From 00145a8c6f8e72c9e4e0816a23fa072dc0f1b852 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 23 May 2016 15:08:22 +0300 Subject: [PATCH 01/25] Fix suggestions tapping issue. Fix command input position. --- src/status_im/chat/styles/input.cljs | 3 ++- src/status_im/chat/views/content_suggestions.cljs | 5 +++-- src/status_im/chat/views/suggestions.cljs | 7 ++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/status_im/chat/styles/input.cljs b/src/status_im/chat/styles/input.cljs index 474cd2a115..53e02cb16e 100644 --- a/src/status_im/chat/styles/input.cljs +++ b/src/status_im/chat/styles/input.cljs @@ -37,7 +37,8 @@ (def command-input {:flex 1 :marginLeft 8 - :marginTop 7 + :marginTop -2 + :padding 0 :fontSize 14 :fontFamily font :color text1-color}) diff --git a/src/status_im/chat/views/content_suggestions.cljs b/src/status_im/chat/views/content_suggestions.cljs index 20fb1df9e5..25661ff11d 100644 --- a/src/status_im/chat/views/content_suggestions.cljs +++ b/src/status_im/chat/views/content_suggestions.cljs @@ -32,5 +32,6 @@ :onPress (fn [])} [view [icon :drag_down st/drag-down-icon]]] [view (st/suggestions-container (count suggestions)) - [list-view {:dataSource (to-datasource suggestions) - :renderRow render-row}]]])) + [list-view {:dataSource (to-datasource suggestions) + :keyboardShouldPersistTaps true + :renderRow render-row}]]])) diff --git a/src/status_im/chat/views/suggestions.cljs b/src/status_im/chat/views/suggestions.cljs index 9a170cd5a5..acf45f0967 100644 --- a/src/status_im/chat/views/suggestions.cljs +++ b/src/status_im/chat/views/suggestions.cljs @@ -41,6 +41,7 @@ [view [icon :drag_down st/drag-down-icon]]] [view (st/suggestions-container (count suggestions)) - [list-view {:dataSource (to-datasource suggestions) - :enableEmptySections true - :renderRow render-row}]]]))))) + [list-view {:dataSource (to-datasource suggestions) + :enableEmptySections true + :keyboardShouldPersistTaps true + :renderRow render-row}]]]))))) From 5a901e3b9a62ae00c0f82cf02b3d98f4ffb9d537 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 23 May 2016 17:24:27 +0300 Subject: [PATCH 02/25] Start single input --- src/status_im/chat/views/command.cljs | 28 ++++-- .../chat/views/confirmation_code.cljs | 4 +- src/status_im/chat/views/money.cljs | 4 +- src/status_im/chat/views/new_message.cljs | 53 +++++++---- src/status_im/chat/views/password.cljs | 4 +- src/status_im/chat/views/phone.cljs | 4 +- src/status_im/chat/views/plain_input.cljs | 95 +++++++++++++------ 7 files changed, 129 insertions(+), 63 deletions(-) diff --git a/src/status_im/chat/views/command.cljs b/src/status_im/chat/views/command.cljs index ab90de0426..b587e0ab80 100644 --- a/src/status_im/chat/views/command.cljs +++ b/src/status_im/chat/views/command.cljs @@ -1,10 +1,10 @@ (ns status-im.chat.views.command (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view - icon - text - text-input - touchable-highlight]] + icon + text + text-input + touchable-highlight]] [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] [status-im.chat.styles.input :as st])) @@ -13,7 +13,8 @@ (dispatch [:cancel-command])) (defn set-input-message [message] - (dispatch [:set-chat-command-content message])) + (dispatch [:set-chat-command-content message]) + (dispatch [:set-chat-input-text message])) (defn send-command [] (dispatch [:stage-command]) @@ -24,6 +25,10 @@ (validator message) (pos? (count message)))) +(defn command-icon [command] + [view (st/command-text-container command) + [text {:style st/command-text} (:text command)]]) + (defn simple-command-input-view [command input-options & {:keys [validator]}] (let [message-atom (subscribe [:get-chat-command-content])] (fn [command input-options & {:keys [validator]}] @@ -31,8 +36,7 @@ [view st/command-input-and-suggestions-container [content-suggestions-view] [view st/command-input-container - [view (st/command-text-container command) - [text {:style st/command-text} (:text command)]] + [command-icon command] [text-input (merge {:style st/command-input :autoFocus true :onChangeText set-input-message @@ -47,3 +51,13 @@ [touchable-highlight {:on-press cancel-command-input} [view st/cancel-container [icon :close-gray st/cancel-icon]]])]])))) + + +(comment [text-input (merge {:style st/command-input + :autoFocus true + :onChangeText set-input-message + :onSubmitEditing (fn [] + (when (valid? message validator) + (send-command)))} + input-options) + message]) \ No newline at end of file diff --git a/src/status_im/chat/views/confirmation_code.cljs b/src/status_im/chat/views/confirmation_code.cljs index b1d5f4c94e..8b42e446b5 100644 --- a/src/status_im/chat/views/confirmation_code.cljs +++ b/src/status_im/chat/views/confirmation_code.cljs @@ -2,5 +2,5 @@ (:require [status-im.chat.views.command :refer [simple-command-input-view]])) -(defn confirmation-code-input-view [command] - [simple-command-input-view command {:keyboardType :numeric}]) +(defn confirmation-code-input-view [command input] + [simple-command-input-view command input {:keyboardType :numeric}]) diff --git a/src/status_im/chat/views/money.cljs b/src/status_im/chat/views/money.cljs index 0051b597f6..43cde52001 100644 --- a/src/status_im/chat/views/money.cljs +++ b/src/status_im/chat/views/money.cljs @@ -2,6 +2,6 @@ (:require [status-im.chat.views.command :refer [simple-command-input-view]])) -(defn money-input-view [command] - [simple-command-input-view command +(defn money-input-view [command input] + [simple-command-input-view command input {:keyboardType :numeric}]) diff --git a/src/status_im/chat/views/new_message.cljs b/src/status_im/chat/views/new_message.cljs index 29b203a067..7ed07c6ff3 100644 --- a/src/status_im/chat/views/new_message.cljs +++ b/src/status_im/chat/views/new_message.cljs @@ -1,14 +1,16 @@ (ns status-im.chat.views.new-message + (:require-macros [status-im.utils.views :refer [defview]]) (: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.plain-input :refer [plain-message-input-view input]] [status-im.chat.views.command :refer [simple-command-input-view]] [status-im.chat.views.phone :refer [phone-input-view]] [status-im.chat.views.password :refer [password-input-view]] [status-im.chat.views.confirmation-code :refer [confirmation-code-input-view]] [status-im.chat.views.money :refer [money-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])) (defn staged-command-view [stage-command] @@ -19,27 +21,44 @@ (for [command staged-commands] ^{:key command} [staged-command-view command])]) -(defn default-command-input-view [command] - [simple-command-input-view command {}]) -(defn special-input-view [command] - (case (:command command) - :phone [phone-input-view command] - :keypair-password [password-input-view command] - :confirmation-code [confirmation-code-input-view command] - :money [money-input-view command] - :request [money-input-view command] - [default-command-input-view command])) + +(comment + (defn default-command-input-view [command input] + [simple-command-input-view command input {}]) + + (defn special-input-view [input command] + (case (:command command) + :phone [phone-input-view command input] + :keypair-password [password-input-view command input] + :confirmation-code [confirmation-code-input-view command input] + :money [money-input-view command input] + :request [money-input-view command input] + [default-command-input-view command input]))) + +(defn show-input [command] + [plain-message-input-view + (merge {:command command} + (case (:command command) + :phone {:keyboardType :phone-pad + :validator valid-mobile-number?} + :keypair-password {:secureTextEntry true} + :confirmation-code {:keyboardType :numeric} + :money {:keyboardType :numeric} + :request {:keyboardType :numeric} + nil))]) (defn chat-message-new [] - (let [command-atom (subscribe [:get-chat-command]) + (let [command-atom (subscribe [:get-chat-command]) staged-commands-atom (subscribe [:get-chat-staged-commands])] (fn [] - (let [command @command-atom - staged-commands @staged-commands-atom] + (let [staged-commands @staged-commands-atom] [view st/new-message-container (when (and staged-commands (pos? (count staged-commands))) [staged-commands-view staged-commands]) - (if command - [special-input-view command] - [plain-message-input-view])])))) + [show-input @command-atom]])))) + +(comment + (if command + [special-input-view command] + )) \ No newline at end of file diff --git a/src/status_im/chat/views/password.cljs b/src/status_im/chat/views/password.cljs index cc87e05fff..f8db369e3c 100644 --- a/src/status_im/chat/views/password.cljs +++ b/src/status_im/chat/views/password.cljs @@ -3,5 +3,5 @@ [status-im.chat.views.command :refer [simple-command-input-view]])) -(defn password-input-view [command] - [simple-command-input-view command {:secureTextEntry true}]) +(defn password-input-view [command input] + [simple-command-input-view command input {:secureTextEntry true}]) diff --git a/src/status_im/chat/views/phone.cljs b/src/status_im/chat/views/phone.cljs index f74ad65568..f35881fc07 100644 --- a/src/status_im/chat/views/phone.cljs +++ b/src/status_im/chat/views/phone.cljs @@ -4,6 +4,6 @@ :refer [simple-command-input-view]] [status-im.utils.phone-number :refer [valid-mobile-number?]])) -(defn phone-input-view [command] - [simple-command-input-view command {:keyboardType :phone-pad} +(defn phone-input-view [command input] + [simple-command-input-view command input {:keyboardType :phone-pad} :validator valid-mobile-number?]) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index eaece17dfb..f31ff76c48 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -1,53 +1,86 @@ (ns status-im.chat.views.plain-input + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view - icon - touchable-highlight - text-input]] + icon + touchable-highlight + text-input]] [status-im.chat.views.suggestions :refer [suggestions-view]] - [status-im.chat.styles.plain-input :as st])) + [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] + [status-im.chat.views.command :as command] + [status-im.chat.styles.plain-input :as st] + [status-im.chat.styles.input :as st-command])) (defn set-input-message [message] (dispatch [:set-chat-input-text message])) -(defn send [chat input-message] - (let [{:keys [group-chat chat-id]} chat] - (dispatch [:send-chat-msg]))) +(defn send [] + (dispatch [:send-chat-msg])) (defn message-valid? [staged-commands message] (or (and (pos? (count message)) (not= "!" message)) (pos? (count staged-commands)))) -(defn try-send [chat staged-commands message] +(defn try-send [staged-commands message] (when (message-valid? staged-commands message) - (send chat message))) + (send))) -(defn plain-message-input-view [] - (let [chat (subscribe [:get-current-chat]) - input-message-atom (subscribe [:get-chat-input-text]) +(defn plain-message-input-view [{:keys [command input-options validator]}] + (let [chat (subscribe [:get-current-chat]) + input-message-atom (subscribe [:get-chat-input-text]) staged-commands-atom (subscribe [:get-chat-staged-commands]) - typing-command? (subscribe [:typing-command?])] - (fn [] + typing-command? (subscribe [:typing-command?])] + (fn [{:keys [command input-options validator]}] (let [input-message @input-message-atom] [view st/input-container - [suggestions-view] + (if command + [content-suggestions-view] + [suggestions-view]) [view st/input-view - [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) - :style st/switch-commands-touchable} - [view nil - (if @typing-command? - [icon :close-gray st/close-icon] - [icon :list st/list-icon])]] - [text-input {:style st/message-input - :autoFocus (pos? (count @staged-commands-atom)) - :onChangeText set-input-message - :onSubmitEditing #(try-send @chat @staged-commands-atom - input-message)} + (if command + [command/command-icon command] + [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) + :style st/switch-commands-touchable} + [view nil + (if @typing-command? + [icon :close-gray st/close-icon] + [icon :list st/list-icon])]]) + [text-input (if command + (merge {:style st-command/command-input + :autoFocus true + :onChangeText command/set-input-message + :onSubmitEditing (fn [] + (when (command/valid? input-message validator) + (command/send-command)))} + input-options) + ;; plain + {:style st/message-input + :autoFocus (pos? (count @staged-commands-atom)) + :onChangeText set-input-message + :onSubmitEditing #(try-send @staged-commands-atom + input-message)}) input-message] ;; TODO emoticons: not implemented - [icon :smile st/smile-icon] - (when (message-valid? @staged-commands-atom input-message) - [touchable-highlight {:on-press #(send @chat input-message)} - [view st/send-container - [icon :send st/send-icon]]])]])))) + (when (not command) + [icon :smile st/smile-icon]) + (if command + (if (command/valid? input-message validator) + [touchable-highlight {:on-press command/send-command} + [view st/send-container [icon :send st/send-icon]]] + [touchable-highlight {:on-press command/cancel-command-input} + [view st-command/cancel-container + [icon :close-gray st-command/cancel-icon]]]) + (when (message-valid? @staged-commands-atom input-message) + [touchable-highlight {:on-press send} + [view st/send-container + [icon :send st/send-icon]]]))]])))) + +(comment + [text-input {:style st/message-input + :autoFocus (pos? (count @staged-commands-atom)) + ;:keyboardType (if (< 3 (count input-message)) :default :numeric) + :onChangeText set-input-message + :onSubmitEditing #(try-send @chat @staged-commands-atom + input-message)} + input-message]) \ No newline at end of file From 583f424e93b2b15b1a5e6d014db73f61a103b88b Mon Sep 17 00:00:00 2001 From: virvar Date: Tue, 24 May 2016 16:34:46 +0300 Subject: [PATCH 03/25] Single input --- src/status_im/chat/handlers.cljs | 14 ++- src/status_im/chat/screen.cljs | 11 ++- src/status_im/chat/views/command.cljs | 42 +------- .../chat/views/confirmation_code.cljs | 6 -- src/status_im/chat/views/money.cljs | 7 -- src/status_im/chat/views/new_message.cljs | 37 ++----- src/status_im/chat/views/password.cljs | 7 -- src/status_im/chat/views/phone.cljs | 9 -- src/status_im/chat/views/plain_input.cljs | 99 +++++++++---------- 9 files changed, 72 insertions(+), 160 deletions(-) delete mode 100644 src/status_im/chat/views/confirmation_code.cljs delete mode 100644 src/status_im/chat/views/money.cljs delete mode 100644 src/status_im/chat/views/password.cljs delete mode 100644 src/status_im/chat/views/phone.cljs diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 011749f25f..5b8a8bc030 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -42,8 +42,10 @@ (update-in [:chats current-chat-id :input-text] safe-trim)))) (register-handler :set-chat-command-content - (fn [db [_ content]] - (commands/set-chat-command-content db content))) + (fn [{:keys [current-chat-id] :as db} [_ content]] + (-> db + (commands/set-chat-command-content content) + (assoc-in [:chats current-chat-id :input-text] nil)))) (defn update-input-text [{:keys [current-chat-id] :as db} text] @@ -68,8 +70,12 @@ (update-input-text db text)) (defn update-command [db [_ text]] - (let [{:keys [command]} (suggestions/check-suggestion db text)] - (commands/set-chat-command db command))) + (if (not (commands/get-chat-command db)) + (let [{:keys [command]} (suggestions/check-suggestion db text)] + (if command + (commands/set-chat-command db command) + db)) + db)) (register-handler :set-chat-input-text ((enrich update-command) update-text)) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 19723aba22..2ed10ba018 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -220,11 +220,12 @@ [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)}])) + [list-view {:renderRow (message-row contacts' group-chat) + :renderScrollComponent #(invertible-scroll-view (js->clj %)) + :onEndReached #(dispatch [:load-more-messages]) + :enableEmptySections true + :keyboardShouldPersistTaps true + :dataSource (to-datasource messages)}])) (defview chat [] [group-chat [:chat :group-chat] diff --git a/src/status_im/chat/views/command.cljs b/src/status_im/chat/views/command.cljs index b587e0ab80..b15f08673f 100644 --- a/src/status_im/chat/views/command.cljs +++ b/src/status_im/chat/views/command.cljs @@ -5,16 +5,13 @@ text text-input touchable-highlight]] - [status-im.chat.views.content-suggestions :refer - [content-suggestions-view]] [status-im.chat.styles.input :as st])) (defn cancel-command-input [] (dispatch [:cancel-command])) (defn set-input-message [message] - (dispatch [:set-chat-command-content message]) - (dispatch [:set-chat-input-text message])) + (dispatch [:set-chat-command-content message])) (defn send-command [] (dispatch [:stage-command]) @@ -25,39 +22,10 @@ (validator message) (pos? (count message)))) +(defn try-send [message validator] + (when (valid? message validator) + (send-command))) + (defn command-icon [command] [view (st/command-text-container command) [text {:style st/command-text} (:text command)]]) - -(defn simple-command-input-view [command input-options & {:keys [validator]}] - (let [message-atom (subscribe [:get-chat-command-content])] - (fn [command input-options & {:keys [validator]}] - (let [message @message-atom] - [view st/command-input-and-suggestions-container - [content-suggestions-view] - [view st/command-input-container - [command-icon command] - [text-input (merge {:style st/command-input - :autoFocus true - :onChangeText set-input-message - :onSubmitEditing (fn [] - (when (valid? message validator) - (send-command)))} - input-options) - message] - (if (valid? message validator) - [touchable-highlight {:on-press send-command} - [view st/send-container [icon :send st/send-icon]]] - [touchable-highlight {:on-press cancel-command-input} - [view st/cancel-container - [icon :close-gray st/cancel-icon]]])]])))) - - -(comment [text-input (merge {:style st/command-input - :autoFocus true - :onChangeText set-input-message - :onSubmitEditing (fn [] - (when (valid? message validator) - (send-command)))} - input-options) - message]) \ No newline at end of file diff --git a/src/status_im/chat/views/confirmation_code.cljs b/src/status_im/chat/views/confirmation_code.cljs deleted file mode 100644 index 8b42e446b5..0000000000 --- a/src/status_im/chat/views/confirmation_code.cljs +++ /dev/null @@ -1,6 +0,0 @@ -(ns status-im.chat.views.confirmation-code - (:require - [status-im.chat.views.command :refer [simple-command-input-view]])) - -(defn confirmation-code-input-view [command input] - [simple-command-input-view command input {:keyboardType :numeric}]) diff --git a/src/status_im/chat/views/money.cljs b/src/status_im/chat/views/money.cljs deleted file mode 100644 index 43cde52001..0000000000 --- a/src/status_im/chat/views/money.cljs +++ /dev/null @@ -1,7 +0,0 @@ -(ns status-im.chat.views.money - (:require - [status-im.chat.views.command :refer [simple-command-input-view]])) - -(defn money-input-view [command input] - [simple-command-input-view command input - {:keyboardType :numeric}]) diff --git a/src/status_im/chat/views/new_message.cljs b/src/status_im/chat/views/new_message.cljs index 7ed07c6ff3..73e5466344 100644 --- a/src/status_im/chat/views/new_message.cljs +++ b/src/status_im/chat/views/new_message.cljs @@ -3,12 +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 input]] - [status-im.chat.views.command :refer [simple-command-input-view]] - [status-im.chat.views.phone :refer [phone-input-view]] - [status-im.chat.views.password :refer [password-input-view]] - [status-im.chat.views.confirmation-code :refer [confirmation-code-input-view]] - [status-im.chat.views.money :refer [money-input-view]] + [status-im.chat.views.plain-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])) @@ -21,31 +16,16 @@ (for [command staged-commands] ^{:key command} [staged-command-view command])]) - - -(comment - (defn default-command-input-view [command input] - [simple-command-input-view command input {}]) - - (defn special-input-view [input command] - (case (:command command) - :phone [phone-input-view command input] - :keypair-password [password-input-view command input] - :confirmation-code [confirmation-code-input-view command input] - :money [money-input-view command input] - :request [money-input-view command input] - [default-command-input-view command input]))) - (defn show-input [command] [plain-message-input-view (merge {:command command} (case (:command command) - :phone {:keyboardType :phone-pad + :phone {:input-options {:keyboardType :phone-pad} :validator valid-mobile-number?} - :keypair-password {:secureTextEntry true} - :confirmation-code {:keyboardType :numeric} - :money {:keyboardType :numeric} - :request {:keyboardType :numeric} + :keypair-password {:input-options {:secureTextEntry true}} + :confirmation-code {:input-options {:keyboardType :numeric}} + :money {:input-options {:keyboardType :numeric}} + :request {:input-options {:keyboardType :numeric}} nil))]) (defn chat-message-new [] @@ -57,8 +37,3 @@ (when (and staged-commands (pos? (count staged-commands))) [staged-commands-view staged-commands]) [show-input @command-atom]])))) - -(comment - (if command - [special-input-view command] - )) \ No newline at end of file diff --git a/src/status_im/chat/views/password.cljs b/src/status_im/chat/views/password.cljs deleted file mode 100644 index f8db369e3c..0000000000 --- a/src/status_im/chat/views/password.cljs +++ /dev/null @@ -1,7 +0,0 @@ -(ns status-im.chat.views.password - (:require - [status-im.chat.views.command - :refer [simple-command-input-view]])) - -(defn password-input-view [command input] - [simple-command-input-view command input {:secureTextEntry true}]) diff --git a/src/status_im/chat/views/phone.cljs b/src/status_im/chat/views/phone.cljs deleted file mode 100644 index f35881fc07..0000000000 --- a/src/status_im/chat/views/phone.cljs +++ /dev/null @@ -1,9 +0,0 @@ -(ns status-im.chat.views.phone - (:require - [status-im.chat.views.command - :refer [simple-command-input-view]] - [status-im.utils.phone-number :refer [valid-mobile-number?]])) - -(defn phone-input-view [command input] - [simple-command-input-view command input {:keyboardType :phone-pad} - :validator valid-mobile-number?]) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index f31ff76c48..f3ee1f9fa9 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -27,60 +27,51 @@ (send))) (defn plain-message-input-view [{:keys [command input-options validator]}] - (let [chat (subscribe [:get-current-chat]) - input-message-atom (subscribe [:get-chat-input-text]) - staged-commands-atom (subscribe [:get-chat-staged-commands]) + (let [input-message (subscribe [:get-chat-input-text]) + input-command (subscribe [:get-chat-command-content]) + staged-commands (subscribe [:get-chat-staged-commands]) typing-command? (subscribe [:typing-command?])] (fn [{:keys [command input-options validator]}] - (let [input-message @input-message-atom] - [view st/input-container + [view st/input-container + (if command + [content-suggestions-view] + [suggestions-view]) + [view st/input-view + (if command + [command/command-icon command] + [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) + :style st/switch-commands-touchable} + [view nil + (if @typing-command? + [icon :close-gray st/close-icon] + [icon :list st/list-icon])]]) + [text-input (merge {:style (if command st-command/command-input st/message-input) ;; st-command/command-input + :autoFocus false + :onChangeText (fn [text] + ((if command + command/set-input-message + set-input-message) + text)) + :onSubmitEditing (fn [] + (if command + (command/try-send @input-command validator) + (try-send @staged-commands + @input-message)))} + input-options) (if command - [content-suggestions-view] - [suggestions-view]) - [view st/input-view - (if command - [command/command-icon command] - [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) - :style st/switch-commands-touchable} - [view nil - (if @typing-command? - [icon :close-gray st/close-icon] - [icon :list st/list-icon])]]) - [text-input (if command - (merge {:style st-command/command-input - :autoFocus true - :onChangeText command/set-input-message - :onSubmitEditing (fn [] - (when (command/valid? input-message validator) - (command/send-command)))} - input-options) - ;; plain - {:style st/message-input - :autoFocus (pos? (count @staged-commands-atom)) - :onChangeText set-input-message - :onSubmitEditing #(try-send @staged-commands-atom - input-message)}) - input-message] - ;; TODO emoticons: not implemented - (when (not command) - [icon :smile st/smile-icon]) - (if command - (if (command/valid? input-message validator) - [touchable-highlight {:on-press command/send-command} - [view st/send-container [icon :send st/send-icon]]] - [touchable-highlight {:on-press command/cancel-command-input} - [view st-command/cancel-container - [icon :close-gray st-command/cancel-icon]]]) - (when (message-valid? @staged-commands-atom input-message) - [touchable-highlight {:on-press send} - [view st/send-container - [icon :send st/send-icon]]]))]])))) - -(comment - [text-input {:style st/message-input - :autoFocus (pos? (count @staged-commands-atom)) - ;:keyboardType (if (< 3 (count input-message)) :default :numeric) - :onChangeText set-input-message - :onSubmitEditing #(try-send @chat @staged-commands-atom - input-message)} - input-message]) \ No newline at end of file + @input-command + @input-message)] + ;; TODO emoticons: not implemented + (when (not command) + [icon :smile st/smile-icon]) + (if command + (if (command/valid? @input-command validator) + [touchable-highlight {:on-press command/send-command} + [view st/send-container [icon :send st/send-icon]]] + [touchable-highlight {:on-press command/cancel-command-input} + [view st-command/cancel-container + [icon :close-gray st-command/cancel-icon]]]) + (when (message-valid? @staged-commands @input-message) + [touchable-highlight {:on-press send} + [view st/send-container + [icon :send st/send-icon]]]))]]))) From 4d70e318b398d086d206e94c6b2258a51e354c74 Mon Sep 17 00:00:00 2001 From: virvar Date: Wed, 25 May 2016 12:44:00 +0300 Subject: [PATCH 04/25] Chat name validation --- .../chats_list/views/inner_item.cljs | 4 +- src/status_im/constants.cljs | 2 + src/status_im/group_settings/screen.cljs | 12 +++-- .../group_settings/styles/group_settings.cljs | 10 +++- src/status_im/group_settings/subs.cljs | 20 ++++++- src/status_im/navigation/handlers.cljs | 3 +- src/status_im/new_group/screen.cljs | 52 +++++++++++-------- src/status_im/new_group/styles.cljs | 10 ++-- 8 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/status_im/chats_list/views/inner_item.cljs b/src/status_im/chats_list/views/inner_item.cljs index 2035b7f980..2803b5d6e4 100644 --- a/src/status_im/chats_list/views/inner_item.cljs +++ b/src/status_im/chats_list/views/inner_item.cljs @@ -7,14 +7,14 @@ [status-im.utils.datetime :as time])) (defn chat-list-item-inner-view - [{:keys [chat-id name color photo-path new-messages-count + [{:keys [chat-id name color new-messages-count online group-chat contacts] :as chat}] (let [last-message (first (:messages chat))] [view st/chat-container [view st/chat-icon-container [chat-icon-view-chat-list chat-id group-chat name color online]] [view st/item-container - #_[view st/name-view + [view st/name-view [text {:style st/name-text} (truncate-str name 20)] (when group-chat [icon :group st/group-icon]) diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index a684182899..c1c4f35fa5 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -10,3 +10,5 @@ (def content-type-command "command") (def content-type-command-request "command-request") (def content-type-status "status") + +(def max-chat-name-length 20) diff --git a/src/status_im/group_settings/screen.cljs b/src/status_im/group_settings/screen.cljs index 1c49c4f094..97174ea6f3 100644 --- a/src/status_im/group_settings/screen.cljs +++ b/src/status_im/group_settings/screen.cljs @@ -145,7 +145,9 @@ (defview chat-name [] [name [:chat :name] new-name [:get :new-chat-name] - focused? [:get ::name-input-focused]] + validation-messages [:new-chat-name-validation-messages] + focused? [:get ::name-input-focused] + valid? [:new-chat-name-valid?]] [view [text {:style st/chat-name-text} "Chat name"] [view (st/chat-name-value-container focused?) @@ -156,12 +158,14 @@ :on-blur blur} name] (if (or focused? (not= name new-name)) - [touchable-highlight {:style st/chat-name-btn-edit-container + [touchable-highlight {:style (st/chat-name-btn-edit-container valid?) :on-press save} [view [icon :ok-purple st/add-members-icon]]] - [touchable-highlight {:style st/chat-name-btn-edit-container + [touchable-highlight {:style (st/chat-name-btn-edit-container true) :on-press focus} - [text {:style st/chat-name-btn-edit-text} "Edit"]])]]) + [text {:style st/chat-name-btn-edit-text} "Edit"]])] + (when (pos? (count validation-messages)) + [text {:style st/chat-name-validation-message} (first validation-messages)])]) (defview group-settings [] [show-color-picker [:group-settings :show-color-picker]] diff --git a/src/status_im/group_settings/styles/group_settings.cljs b/src/status_im/group_settings/styles/group_settings.cljs index 91d407c604..9950bb2f9c 100644 --- a/src/status_im/group_settings/styles/group_settings.cljs +++ b/src/status_im/group_settings/styles/group_settings.cljs @@ -91,9 +91,15 @@ :fontFamily font :color text1-color}) -(def chat-name-btn-edit-container +(def chat-name-validation-message + {:marginTop 8 + :marginLeft 16 + :color :red}) + +(defn chat-name-btn-edit-container [enabled?] {:padding 16 - :justifyContent :center}) + :justifyContent :center + :opacity (if enabled? 1 0.3)}) (def chat-name-btn-edit-text {:marginTop -1 diff --git a/src/status_im/group_settings/subs.cljs b/src/status_im/group_settings/subs.cljs index f2b6ac1db3..c1bb17da4d 100644 --- a/src/status_im/group_settings/subs.cljs +++ b/src/status_im/group_settings/subs.cljs @@ -1,6 +1,7 @@ (ns status-im.group-settings.subs (:require-macros [reagent.ratom :refer [reaction]]) - (:require [re-frame.core :refer [register-sub]])) + (:require [re-frame.core :refer [register-sub]] + [status-im.constants :refer [max-chat-name-length]])) (register-sub :selected-participant (fn [db _] @@ -11,3 +12,20 @@ (register-sub :group-settings (fn [db [_ k]] (reaction (get-in @db [:group-settings k])))) + +(defn get-chat-name-validation-messages [chat-name] + (filter some? + (list (when (zero? (count chat-name)) + "Chat name can't be empty") + (when (< max-chat-name-length (count chat-name)) + "Chat name is too long")))) + +(register-sub :new-chat-name-validation-messages + (fn [db [_]] + (let [chat-name (reaction (:new-chat-name @db))] + (reaction (get-chat-name-validation-messages @chat-name))))) + +(register-sub :new-chat-name-valid? + (fn [db [_]] + (let [chat-name (reaction (:new-chat-name @db))] + (reaction (zero? (count (get-chat-name-validation-messages @chat-name))))))) diff --git a/src/status_im/navigation/handlers.cljs b/src/status_im/navigation/handlers.cljs index c47134e429..ac5bd9ec12 100644 --- a/src/status_im/navigation/handlers.cljs +++ b/src/status_im/navigation/handlers.cljs @@ -48,7 +48,8 @@ (fn [db _] (-> db (push-view :new-group) - (assoc :new-group #{}))))) + (assoc :new-group #{}) + (assoc :new-chat-name nil))))) (register-handler :show-contacts (fn [db _] diff --git a/src/status_im/new_group/screen.cljs b/src/status_im/new_group/screen.cljs index a620959d50..3a397f0272 100644 --- a/src/status_im/new_group/screen.cljs +++ b/src/status_im/new_group/screen.cljs @@ -3,13 +3,13 @@ (:require [re-frame.core :refer [subscribe dispatch]] [status-im.resources :as res] [status-im.components.react :refer [view - text-input - text - image - icon - touchable-highlight - list-view - list-item]] + text-input + text + image + icon + touchable-highlight + list-view + list-item]] [status-im.components.styles :refer [color-purple]] [status-im.components.toolbar :refer [toolbar]] [status-im.utils.listview :refer [to-datasource]] @@ -18,24 +18,30 @@ (defview new-group-toolbar [] - [group-name [:get ::group-name] - creation-disabled? [:get :disable-group-creation]] - [toolbar - {:title "New group chat" - :action {:image {:source res/v ;; {:uri "icon_search"} - :style st/toolbar-icon} - :handler (when-not creation-disabled? - #(dispatch [:init-group-creation group-name]))}}]) + [group-name [:get :new-chat-name] + creation-disabled? [:get :disable-group-creation] + valid? [:new-chat-name-valid?]] + (let [create-btn-enabled? (and valid? (not creation-disabled?))] + [toolbar + {:title "New group chat" + :action {:image {:source res/v ;; {:uri "icon_search"} + :style (st/toolbar-icon create-btn-enabled?)} + :handler (when create-btn-enabled? + #(dispatch [:init-group-creation group-name]))}}])) (defview group-name-input [] - [group-name [:get ::group-name]] - [text-input - {:underlineColorAndroid color-purple - :style st/group-name-input - :autoFocus true - :placeholder "Group Name" - :onChangeText #(dispatch [:set ::group-name %])} - group-name]) + [group-name [:get :new-chat-name] + validation-messages [:new-chat-name-validation-messages]] + [view nil + [text-input + {:underlineColorAndroid color-purple + :style st/group-name-input + :autoFocus true + :placeholder "Group Name" + :onChangeText #(dispatch [:set :new-chat-name %])} + group-name] + (when (pos? (count validation-messages)) + [text {:style st/group-name-validation-message} (first validation-messages)])]) (defview new-group [] [contacts [:all-contacts]] diff --git a/src/status_im/new_group/styles.cljs b/src/status_im/new_group/styles.cljs index cd16b8dcc8..3d15673453 100644 --- a/src/status_im/new_group/styles.cljs +++ b/src/status_im/new_group/styles.cljs @@ -7,9 +7,10 @@ text2-color toolbar-background1]])) -(def toolbar-icon - {:width 20 - :height 18}) +(defn toolbar-icon [enabled?] + {:width 20 + :height 18 + :opacity (if enabled? 1 0.3)}) (def new-group-container {:flex 1 @@ -33,6 +34,9 @@ :fontFamily font :color text1-color}) +(def group-name-validation-message + {:color :red}) + (def members-text {:marginTop 24 :marginBottom 16 From 49b08e51181249addc5f50f0d0d866836f8e1944 Mon Sep 17 00:00:00 2001 From: virvar Date: Wed, 25 May 2016 14:50:52 +0300 Subject: [PATCH 05/25] Don't dismiss keyboard on command input appear --- src/status_im/chat/views/plain_input.cljs | 100 ++++++++++++---------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index f3ee1f9fa9..7ff822da85 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -4,7 +4,8 @@ [status-im.components.react :refer [view icon touchable-highlight - text-input]] + text-input + dismiss-keyboard!]] [status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] [status-im.chat.views.command :as command] @@ -14,7 +15,9 @@ (defn set-input-message [message] (dispatch [:set-chat-input-text message])) -(defn send [] +(defn send [dismiss-keyboard] + (when dismiss-keyboard + (dismiss-keyboard!)) (dispatch [:send-chat-msg])) (defn message-valid? [staged-commands message] @@ -22,9 +25,9 @@ (not= "!" message)) (pos? (count staged-commands)))) -(defn try-send [staged-commands message] +(defn try-send [staged-commands message dismiss-keyboard] (when (message-valid? staged-commands message) - (send))) + (send dismiss-keyboard))) (defn plain-message-input-view [{:keys [command input-options validator]}] (let [input-message (subscribe [:get-chat-input-text]) @@ -32,46 +35,51 @@ staged-commands (subscribe [:get-chat-staged-commands]) typing-command? (subscribe [:typing-command?])] (fn [{:keys [command input-options validator]}] - [view st/input-container - (if command - [content-suggestions-view] - [suggestions-view]) - [view st/input-view - (if command - [command/command-icon command] - [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) - :style st/switch-commands-touchable} - [view nil - (if @typing-command? - [icon :close-gray st/close-icon] - [icon :list st/list-icon])]]) - [text-input (merge {:style (if command st-command/command-input st/message-input) ;; st-command/command-input - :autoFocus false - :onChangeText (fn [text] - ((if command - command/set-input-message - set-input-message) - text)) - :onSubmitEditing (fn [] - (if command - (command/try-send @input-command validator) - (try-send @staged-commands - @input-message)))} - input-options) + (let [dismiss-keyboard (not (or command @typing-command?))] + [view st/input-container (if command - @input-command - @input-message)] - ;; TODO emoticons: not implemented - (when (not command) - [icon :smile st/smile-icon]) - (if command - (if (command/valid? @input-command validator) - [touchable-highlight {:on-press command/send-command} - [view st/send-container [icon :send st/send-icon]]] - [touchable-highlight {:on-press command/cancel-command-input} - [view st-command/cancel-container - [icon :close-gray st-command/cancel-icon]]]) - (when (message-valid? @staged-commands @input-message) - [touchable-highlight {:on-press send} - [view st/send-container - [icon :send st/send-icon]]]))]]))) + [content-suggestions-view] + [suggestions-view]) + [view st/input-view + (if command + [command/command-icon command] + [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) + :style st/switch-commands-touchable} + [view nil + (if @typing-command? + [icon :close-gray st/close-icon] + [icon :list st/list-icon])]]) + [text-input (merge {:style (if command st-command/command-input st/message-input) ;; st-command/command-input + :autoFocus false + :blurOnSubmit dismiss-keyboard + :onChangeText (fn [text] + ((if command + command/set-input-message + set-input-message) + text)) + :onSubmitEditing (fn [] + (if command + (command/try-send @input-command validator) + (try-send @staged-commands + @input-message + dismiss-keyboard)))} + input-options) + (if command + @input-command + @input-message)] + ;; TODO emoticons: not implemented + (when (not command) + [icon :smile st/smile-icon]) + (if command + (if (command/valid? @input-command validator) + [touchable-highlight {:on-press command/send-command} + [view st/send-container [icon :send st/send-icon]]] + [touchable-highlight {:on-press command/cancel-command-input} + [view st-command/cancel-container + [icon :close-gray st-command/cancel-icon]]]) + (when (message-valid? @staged-commands @input-message) + [touchable-highlight {:on-press #(try-send @staged-commands + @input-message + dismiss-keyboard)} + [view st/send-container + [icon :send st/send-icon]]]))]])))) From 5333eadd67ae2e8d185bfdb0b48f359b3543a1d1 Mon Sep 17 00:00:00 2001 From: virvar Date: Thu, 26 May 2016 16:54:18 +0300 Subject: [PATCH 06/25] Request-info view --- .../res/drawable-hdpi/icon_close_white.png | Bin 0 -> 253 bytes .../res/drawable-hdpi/icon_dollar_green.png | Bin 0 -> 776 bytes .../res/drawable-hdpi/icon_drag_white.png | Bin 0 -> 244 bytes .../res/drawable-mdpi/icon_close_white.png | Bin 0 -> 201 bytes .../res/drawable-mdpi/icon_dollar_green.png | Bin 0 -> 481 bytes .../res/drawable-mdpi/icon_drag_white.png | Bin 0 -> 178 bytes .../res/drawable-xhdpi/icon_close_white.png | Bin 0 -> 329 bytes .../res/drawable-xhdpi/icon_dollar_green.png | Bin 0 -> 1064 bytes .../res/drawable-xhdpi/icon_drag_white.png | Bin 0 -> 250 bytes .../res/drawable-xxhdpi/icon_close_white.png | Bin 0 -> 401 bytes .../res/drawable-xxhdpi/icon_dollar_green.png | Bin 0 -> 1520 bytes .../res/drawable-xxhdpi/icon_drag_white.png | Bin 0 -> 426 bytes .../res/drawable-xxxhdpi/icon_close_white.png | Bin 0 -> 546 bytes .../drawable-xxxhdpi/icon_dollar_green.png | Bin 0 -> 2040 bytes .../res/drawable-xxxhdpi/icon_drag_white.png | Bin 0 -> 482 bytes src/status_im/chat/handlers.cljs | 2 +- src/status_im/chat/styles/response.cljs | 78 ++++++++++++++++++ src/status_im/chat/subs.cljs | 4 + src/status_im/chat/views/new_message.cljs | 17 ++-- src/status_im/chat/views/plain_input.cljs | 30 +++++-- src/status_im/chat/views/response.cljs | 41 +++++++++ 21 files changed, 153 insertions(+), 19 deletions(-) create mode 100644 android/app/src/main/res/drawable-hdpi/icon_close_white.png create mode 100644 android/app/src/main/res/drawable-hdpi/icon_dollar_green.png create mode 100644 android/app/src/main/res/drawable-hdpi/icon_drag_white.png create mode 100644 android/app/src/main/res/drawable-mdpi/icon_close_white.png create mode 100644 android/app/src/main/res/drawable-mdpi/icon_dollar_green.png create mode 100644 android/app/src/main/res/drawable-mdpi/icon_drag_white.png create mode 100644 android/app/src/main/res/drawable-xhdpi/icon_close_white.png create mode 100644 android/app/src/main/res/drawable-xhdpi/icon_dollar_green.png create mode 100644 android/app/src/main/res/drawable-xhdpi/icon_drag_white.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/icon_close_white.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/icon_dollar_green.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/icon_drag_white.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/icon_close_white.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/icon_dollar_green.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/icon_drag_white.png create mode 100644 src/status_im/chat/styles/response.cljs create mode 100644 src/status_im/chat/views/response.cljs diff --git a/android/app/src/main/res/drawable-hdpi/icon_close_white.png b/android/app/src/main/res/drawable-hdpi/icon_close_white.png new file mode 100644 index 0000000000000000000000000000000000000000..79f55e700a669cd3eaf657aec235d71b3c5b7bcb GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|#^NA%Cx&(BWL^R}+dW+zLo5W> zhA{FqC~%b2-Y9>fUlsFygSGfMO{Uz9fqMPIeo9xPjQ_OF|Dep;8&T0{Y_`0-F?=(( z|MVUSi;YR{EJIPQ$ME6bBvdJZvNYuTos>U=E0 zFm%8E%!wJ^Nz0eZ3IFK`-dZ+c)0s8D1f_+h35(xWNNkImwmMF5L3bhJ-h$=39lzZ6 zKV7M`?V4?hig!c$*;^754<0*nsP^lmuLr*|eDpp3@9~0VfPx%!bwCyR5%fBQ(Z_@Q4pRvcXzWND`^QLvL7mfzz|G!-G_(>sRtnf5hHg~$~4P% zr63XXt)N;hEiogvAS02m9wLH-!1V{D2c?J5B7%A`(lmE<_1^8KC~JCaO;cJN}fdFu?u zi;18Nh|(p80^hN@x62!RUx#QY{bFFCCtS@tR5P(&k;^P%A15h{c!S?1ZU&y~4ObWj zHJU<1LV_L=AcR50TO45AZHf^`U>#;hGJ_M23xh4r#LU0j7BNStorw4f(+LRJu#h004bKR_i4^jki;52S0+Kzu30?CL!R^n3C(2#)0A(w zyHmFfBf``IMy5tM94Vg|7`MO-e>B{}tkS=VTb!c=WQnu0 zu?irgh?o17NLsF9j7u$O^98#X)^^tB7x#p-48Su4hM(burXj|in(#dKTpdDx^zLcS zcME~uM0{0Mwpi0G8+w=)pNhZWG2}{sOMl6_0>0#UorklRiBL(jY3Ito=8W=jL7Le~ zi}Oe;U&jv%03GL!Dc^3%<%}(@F(G}y2Y#+V9?8u>wBfK?ODnG=C1z_CMgRlSx8@jr z#`o~7BKaVLeCDr2=wd}SA7#5K=G)_RqPI0W^w|vTpbqVA-_L3ezQLlkiwW!w;-~;D zO*)QC15I0E^NBo8P{Sqdk#Q{UAVHlcy*pmzW4^9(ExP~;lL67ry@DQF2yM; zySnP*Y@;T~j~e)_s{{-&I0_O!uWLn0000lxkigN;cJTnaAom^4Gdw&^NisZZ)=Y6d{r>)ciF^Bh9X#+s zJjv(=lUf)X+jb3CHbKv_9ko*o?%Di5xgq;zZCm|*Nr?mJLa#krKI@@Ed!r1OkuZw} zH~$8~ADkOl%h%VXFjRI&F{Fr{@DX4*&Zx1bOlPP6ZV$F-)}F85&o^%LPj#4Yv0&5U rz#i$Zj9vu^k9*hzw*@!~GBX?r(V6{z@eCiJ%Naaf{an^LB{Ts5G~8Ol literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/icon_close_white.png b/android/app/src/main/res/drawable-mdpi/icon_close_white.png new file mode 100644 index 0000000000000000000000000000000000000000..956a2c04fb6d0a1cabc9d326d2b27cce2edcfbd3 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k#^NA%Cx&(BWL^R}&7LlfAsV7n zgEsOu81Q&oFtWXCa+ln(u;zdu&mDoBgBPZ3Ve$?Owf4KUDl2Vu$Cn3dRPx$n@L1LR45fqQ9VloK@gqUOArI5R0vuG5yVnKViNEdSO{t*Xkv^Ys9XYqSZEuN z7!8)1Tww|=M9`ohsF0i=g&$ZbSfmMJYhjU?+i~{r)M;+^y?5`;&LaG)h`A9YYU~q; zxDnEi9ZEP&>?Z4%By}S2A;{@yDeH4MRLw+reHnpPh{*j%U=0LB^T9*`BW8L~O1faO zq6th&SJM@K)q5n60YvRW6MZg{5K@053S%dzAE=(|ebP*?add_(8Wo_ylR^pPNaS{_ zL-lqc9wOk45O9mDbndE@?{`@?#$b&F$Anbywz`k9UGwS;_TYQ8rxnfW3=8KtqWj0G zDiFqV!NeuTt}|^7KyN;<@T$nj)q1a#GRFDSh*)QvfM{5F2!jL_9 zyu8_2qehlRVUDn4+2MibS>lbK*dix_pJx$BrudvO!b#o1e;-%@0!4}4-T=j!BT(OO X3O=P5mm-2|00000NkvXXu0mjf1V+pz literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/icon_drag_white.png b/android/app/src/main/res/drawable-mdpi/icon_drag_white.png new file mode 100644 index 0000000000000000000000000000000000000000..ee4865dc432938d431338e5b16f1b400614c572d GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|ay(reLo5W7 zWA4=1_BJvdaA}O&a4nEoLL$OJ@u2dNQwqxuo<4BOC1%2(f8YBbUhF;36Mye-o5TYl zz2gTCpZ5xCS@DwFC}&39^hOKqj}pA!4$Yg|f8rCuN)3 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xhdpi/icon_close_white.png b/android/app/src/main/res/drawable-xhdpi/icon_close_white.png new file mode 100644 index 0000000000000000000000000000000000000000..5c8005f904a4aaadbf49206285f7f7aedeae3984 GIT binary patch literal 329 zcmV-P0k-~$P)Px$14%?dR7efQRzVJfFbqR`TwlNu9?!&{F?BX5Q(HA5DVi3^bUpcSX)P6M`7y7ETI1o=I2YMdiC z5|*oR8Qgl*Mxts0&I0(mkC=qTWfUHhVe!I5Yn|8Cd%}0EMkl?QtN)W}rc{f|-=Nu; zxHwY)Xsf1!OZ*{1e_4&{*#X1VMYnj6d!wOXJFd8iA%6ccwZx@WPmbhPYlIldJxsy` zu-qJXV%6_?a>+%4w&A$nP{U+qo7|wwh(C7vxQ;Ee-Spj+w-ZB^D^R{C$EN>_&lY}2 bu<-N&>}@IStlO{$00000NkvXXu0mjf6AO+w literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xhdpi/icon_dollar_green.png b/android/app/src/main/res/drawable-xhdpi/icon_dollar_green.png new file mode 100644 index 0000000000000000000000000000000000000000..cdea0d4af42625a0bd2aa3870d52089675afcac3 GIT binary patch literal 1064 zcmV+@1lRkCP)Px&;z>k7R7eedRBLP$RTRGG&d}Y`HB>D=m+;bPBEcwX`XYn`(fGq3XjC*LyDd;3 zX=O`{(I2uwf0|v`XjClSrHM6`L_^{)LlC9Atr4}FR7o13iBJ#{P^9g;ow>(vMrYfnM1RFkvXoyIBMp3gr|6tc; zUk<`|gzza@+LvNhZ$RFlgXW>H3Q4aWYVJPh>HO2iH!tZG%&$YS*i$aB*CKaMKG6PH zd8GHNqJwiIN|v%)k<5PIkca_1Oj6_*88v4tR;IA6yAky(EX1QaP72zTZ%G|TO*H`d6$Y$ztYR;CH(^q(c$!0ewsk@PL8S*SQM!M|MNq&6$7?Q_Jh) zZzAD;2U1$!HhAy`dGv>?kx*rXn2xR8HXQ)NRQkSWDyZnsz7$ajy0%6hc&K9vSNX$N z2#$>pWu6N7xs)XOE|8L~q`2^3Lo$V1Ux~g%Df4Q2bf6|M2&kB0?uD})O7$i7=L$`! zakpwO7C*S9%u^>(k!1lK6wx`v{fTK%e^2ACUqZTBjNg#$#rEjhjVdTSvwSq z=h5wVdGgRsbe;@;y3n|L*pbicNH=INWgdaU7m&Yao##Z?A+kSZgx2*woH|3DW4Xw+ zOEVqBbUTvT*VB~xO$U4Q&XXT4nyE~7D8+jryU~*)mM;#qc5k7?U^dG_xg&xTF4sis zRye&C0K-&bFtc6|A4gMqZmyvH#!i_NLY6|O*z|%GlwvK!g1o* z%xTEPPV~?_N{sGM6r_OqOvvBG5h-Ga45nt2%N}2={jlJ$YO6y;n3oL@ww^8b&9)oyNK( irQDIGjaJB7WBvu9)@B6AVfZ!x0000@A`ja2t>mNzm!Q3NrRMMn}CGp)tPTo&5+BlE&8CSxlKI;I5LpZ%8HXLCLcF2~JW8Jci oWBSj$Z|%j}{y0^QHx>FVdQ&MBb@0Hr2b;s5{u literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_close_white.png b/android/app/src/main/res/drawable-xxhdpi/icon_close_white.png new file mode 100644 index 0000000000000000000000000000000000000000..32e84becb684c21a652a8362e1f01918fa280ca9 GIT binary patch literal 401 zcmV;C0dD?@P)Px$OG!jQR9Fesm|+gWAPj|x35lM2{`5*7XUT3c-&08#0)w_B*rZOBzW0e8$#DC= zd*mItA~)m%d3A$>9$znd(tAOAhZn-6@x%wWQB2fE(j$$9K%~pX5GWXxV92l%h)Y%q zQz)3!V92l$h&@va6DSy*!I0rWAU0R-|Kx-aDkzAwz|iA!Gj$YnH@a9`Tv)jk)tYL7 z2+mB)LdZfR`fZMl-r9seJ*BBVK%@hSu%ssSt&V#PdgfM5&%W$18oHMqI2)lbtr)6} z^#BtFuxe@a9FaYY0%{zL07?XN2}XZ;74(s4m6{eu023PA9!ddY57h|6RbbXazfw?d z*?ZnbJ#(9SB%LHNkkq8U*|A1gQ)>8Dhk-@(J`Wd|cSLPx)s!2paR9FeMS8Hq(RTREwX11k}5R8bTpfSYY14Uw6`VtA0G!aDzMujNdEd(_U zLbv=-6S2Pj811&;18ZrwXb2V)h#G?!17dgE`XE3gF&J%mM2H1qq{TjV=lI>Jvko(N z#%+lEW9Q!QeCM3G=bU@b9TH>sRdqDXG(~!gAWv&^T*nCX1;mLoDce z6|Tavau)ga?dgK}9+d$mo>txc*3~MR8}rRs54t$8z zKjJ2iX-sh|O|riKPy1W(dBiu_$jTtKBa_%UK<>){}^x#w&Ts8yoi! z62ClNT+^Ge;u=(T#!AWLZOHdbmk1uHv#m5*B5^B>C%YOJC>;svqfqYBAV<~1ZrKIO($^Y;s*$FPcel}wntNaCZ;OmTyf zMD&9a_W@Dz9V!uWI!EG`GbD0AMM7AvRpEY^5fX=0GT6UO;{Sw^dQ>FA=7a6rt}A5< zuqnUh3_^L{Ey6Z9BeBty8OA|3LC&%Kg3ptunp84>j9+%iQo2U3NbKKz*74>(yn&TS z7a1fvKswd77S|kd%T)8K&RBVx`F@-u!=#CJTQB2mb#n8Z6sHncPM*qu#1Q+h@ZX%1 zJK>Y2{3kE@@%-?NGf9XfV=GM4#E}*J!$!Y^POw*Kyz?qSpT$a|e+6rdN-uLJp{iv4 zvNVf0R+!a^kJVnp0koTR(TdG~VAQPo-{VZu!d;EGh;(`@j-Lf;H6N73L5*mWs=Y`J zr8C=9Bw2r-$*3+C^K2}eCszB>_(|i|ymLo&zmp&6%qFf*G|oz~xsu3S>Av*X9QP9r ze-gT}Bwn=sXIqw)Gn*{Cc(|*fgwo<+APB06K3-UT)@eLw98NT#Yoxa$ z#J75QxFUp%(2VA}>w2_sNBzAxm_C)2hp^lZhY>M6w6~7;8y-a;AYQuRyPRC30w+zM zhk_NSMusC2*Kk`{yTvRO9*Ak8 zTPdf}Lej7{We>u=u}rBL03r<+RAQuPyu>w~b>&HpWLL;97nQOf#-^#fq9eSc{Y=lz z>x6QT*8tymuK!%K7gr;7$J%pH`%$%&txqZqtztye=_M5j%YUpgQNJsk+~O^1hr&~d zcc=9Jak>rBu&!(lku}tGqg@WHjVN0`I`S7FFLV1r{Tf=ML1rUVY&o8ZHiOTJ0_eU{IM>K)@`NhfAq?IR^}$w$rHY-@mWr% zUvtZli7)eL+~e+5czKSTsf0FGhpvfg^XmdBNG@Sv!;aFl6LZ;1t=1y?7Cg@(4bW9%`9ednCw#Q}#E< W{Qf88jl1Xo0000Px$WJyFpRA>e5m9a|1KoEvUF(|@uO;BXTMg%)+LG0~(3SY$s@dfPc55Zb26ht`0 za3I%&fZP!fGumXbhf@qoCh$)cva`eY|Nkbtc60rFMFXz&0ki+2LqOjNA^{{|bO1-l zXrOsJ5-?k69DoFj2Aa1c0keh10Z71Tpm{qIFk5IGu(4`?woMcc$21ye)OSSR4PaH) zRJ@i{FJjtAz`^l|PA~Q-+w2=%!q&@Odbpd>`%5Jj1ZBRzMdz2n9Xu1Wq0GjN?Gge` z&UV^sE}y%MLO>px!|%NE@J|9n{K*WfL;~|-#b@qJPnS^$c)b5~h8yE_8HIrP$ATue z1=UM`M~Ru3jTze&-2?oeolPqWN6s#?x8@@IYNP)>M*{dY-+0rfGVXTxMjRoBd@2$I zs1_w|Kmv&kR>va&)uO}=NFcGn>UboeT9mi}2_!aH9ghT5ixM{=fy4%@;|HI>5A4oG U+1{0uod5s;07*qoM6N<$g2}nE?*IS* literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_close_white.png b/android/app/src/main/res/drawable-xxxhdpi/icon_close_white.png new file mode 100644 index 0000000000000000000000000000000000000000..68dbc7fb364667409f872de8f9ca3b08c2fa1715 GIT binary patch literal 546 zcmV+-0^R+IP)Px$+(|@1RA>d|n!#>^Fc3teenoD4ivKme<-a0DJyyNb8CoPn!K}TrI9690g@C>L z#$XExUoMDo9Iwy~dO%O;4h_8a3PF}%CbE%{tk;Q+2haz!j!&FOtqqU?BFj3+eC6oB zudgirf8n^93D$9Tzly?&946SkMjil9-#wnH^EDtf zeX8KBohpE&i-46g+pf?AnjeN~1h}{9;Jg3G*ZpVK?mu*M5>W8vpPx+vPnciRA>d=S!--mMHHShcemRYN<|46#Hdj*sQBR3ts*|6Mo}S>5;elM0+n~W zB}V^XqlpRf*jlNe*lr;)5fC*h1W_W!ZWqKrBw|Pm)?yHR&;kObboY+mTzZ$=yZ6pr zw(!UOGc)IW=iKkkJ#)^?EU`ZPX8!Q*|8OxO|Oz?Pl(uHmE$vsq*Cu@n>`^nkA0M1P*8_rwW9>n#}N}_1hJ=>&T`zI zPmHz@i4XjN!q49uS#jJAXP0{tDsOJ+C;0Jcx)2pu-nZHvc#esk1!gM|TiX<@-r$8- z5(>3MCNiPdBfnhj|}7UWW@QRreM|Uc7JKBtX*dtFEtrSLg@Nyp;#njC)8_( z%9^iVVy z{?>d(iqNdR?-X_Z+u4c$zT8yWTP)=+#%N_O7fV+K!-wp8>-fdk%7LA%^L5PjOsm}9 z$LibFR8l?Kl&1)VV#{WL%zLIHt;MWpjGkyL32#l)DFmK=VavJpXf#;)rF3&Xh6FvU z@Cy~ad7)&aKfL{Fymh_GH{$7KQ-7WiiMvgqy~VWZ{X!M&G#FAo$OAogOar1|jZ0eWfed zP*8_j@2$lw?@^&pAMccUgHU2%;bDeK=w?7d3~|$CDhHv%YOJ_H>J36o*Oi??&T#!C zU^*xikBnD4RBN%d-LFIt`(5e{LOsBJN&{VAId4bZWlD@fc}4z!I9BRGM+ni00HZIY zE=7pAaL+*iB1a87kw|k6AsB8~VV!hxmQU%42eH4p2{YD4dA@DYyXOCGVpD{qpscxe ziq4WBno4y`C$TctXx!h>5S*`EL25s}wY>;QRatD=VqLJ8dc!A$V&`WF3NLveME`N$daub0Z4Wx@d9LZa0{lJdKb9;#@`L@#Qb;I$;AP zG&f^!Iql_~tsYQtWmE>WHy%-?0+q!g59o*!Fzi!eL=Hmmi?{Rp=PrF`_?(lfXDSIv zL%F3rCRjCAMHs^(l`}6L9(IIlw4kv#yxtA#Nys#uy|2Eov!iPU&SSIiNpCde*|aDl zZ|4LGt8rfIw%cb+$ZGgPtae;d=u-s~PeJZcn5~wUK2banD0mX2{;^2aF=Pcg_1BB_ z+NSv7@k}J1MrocTYn~I%O@^7;_E_+mM@p$QX=1XPA=B8}%5>2dkKBuuS&ogvWPH|q ztKO|o#1}V}RHb%|y$HzwKJKT%Lr30mu!inWxH<8X_Z%1&09UCxG?;#Ja_H98qr*mV zHwaDNQ8y%!Osv9NJpzyq1+WvxoVEEyISaj(sp-_I4Siofh;?_p55JE)=}j4qP<7Fg zuzUf=L#@%=M6&y<9wVOt5+V<`92KXIbwy31Y+AYPeJnTxflr^P?2%HQmpmkf^TX|> za%0&l-Q&5&kaFo`H}HpabZ(PR z6j6H>HRU_rx<`$1*M{P?xX9>z<8MXF+yA`6+?`Tp5bAf8Zxvp_I2T!gsXp?Oo=j{m zi!Yy+l4aPzMz0hH%@rQ-tt)Sz-61hXrj{LCaF*j1qCxhRKU8V#0^iLo$oVib-~T+L-u+H6>M>q&!7P4yH9PTY_ex>}T@B1r}~o#R1%;9mfeoUS<{I z1Uv}a5}D)*GV(!e1FmdJO>8ehQW$DpwgTITIVRu|x2=AkRxB5m`JB|r)fAw}&6CAW zb@^ao`_f`%@6Y3Oua%7SmqrK?FJ$HAoEL-C4}E#4n=Qy}pgjLL^Z0DVrF}B1(g@C2 zZ8<9cB78>W5!-6#-lu)U*}|q^c#9iGNys#ki49eMR6?hTC;^jPcL%0{rNsk~PWWch zC>kxUG;)naoz~5Wklm_$SLFI+m%bfx*I7f6e39kykF6I8c0W$zv>0*%*=6$26U5qS zyWBeFf?^j+M%rgZ$ok-m-TxmE66#CLT%YD~$>}_|+0PKsc4wE6;=V}UO}pw9imVCc z1oD^2Y-{%|w-TD>n`M`0I?kF9&g7^2Y5phF8Pj4@$ zO}>;?zO=Uf=zB?~7x^V`pOjoT+y47wu+ky0#rG5I%COr1oRT z+}RdZxAt(^`+HaK`1@FkXLiH2$DbTyW}bFc*nGodHiJvZjH)7r%UhJ!7CE@Iu2g3? i@U_0A#ZHRwFXlap5$=26s9FFcjlt8^&t;ucLK6TbkH}R3 literal 0 HcmV?d00001 diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 5b8a8bc030..a12722e161 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -70,7 +70,7 @@ (update-input-text db text)) (defn update-command [db [_ text]] - (if (not (commands/get-chat-command db)) + (if-not (commands/get-chat-command db) (let [{:keys [command]} (suggestions/check-suggestion db text)] (if command (commands/set-chat-command db command) diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs new file mode 100644 index 0000000000..2e969ae0ef --- /dev/null +++ b/src/status_im/chat/styles/response.cljs @@ -0,0 +1,78 @@ +(ns status-im.chat.styles.response + (:require [status-im.components.styles :refer [font + color-white + color-blue + text1-color + text2-color + chat-background + color-black]])) + +(def drag-touchable + {:height 16 + :alignItems :center}) + +(def drag-down-icon + {:width 16 + :height 16 + :opacity 0.4}) + +(def command-icon-container + {:marginTop 1 + :marginLeft 12 + :width 32 + :height 32 + :alignItems :center + :justifyContent :center + :borderRadius 50 + :backgroundColor color-white}) + +(def command-icon + {:width 9 + :height 15}) + +(def info-container + {:flex 1 + :marginLeft 12}) + +(def command-name + {:marginTop 0 + :fontSize 12 + :fontFamily font + :color color-white}) + +(def message-info + {:marginTop 1 + :fontSize 12 + :fontFamily font + :opacity 0.69 + :color color-white}) + +(defn request-info [color] + {:flexDirection :column + :height 61 + :backgroundColor color}) + +(def inner-container + {:flexDirection :row + :height 45}) + +(def cancel-container + {:marginTop 2.5 + :marginRight 16 + :width 24 + :height 24}) + +(def cancel-icon + {:marginTop 6 + :marginLeft 6 + :width 12 + :height 12}) + +(def command-input + {:flex 1 + :marginLeft 16 + :marginTop -2 + :padding 0 + :fontSize 14 + :fontFamily font + :color text1-color}) diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index d5df5f5716..f29c3527a2 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -70,6 +70,10 @@ (fn [db _] (reaction (commands/get-chat-command-content @db)))) +(register-sub :get-chat-command-to-msg-id + (fn [db _] + (reaction (commands/get-chat-command-to-msg-id @db)))) + (register-sub :chat-command-request (fn [db _] (reaction (commands/get-chat-command-request @db)))) diff --git a/src/status_im/chat/views/new_message.cljs b/src/status_im/chat/views/new_message.cljs index 73e5466344..3f2ec8792a 100644 --- a/src/status_im/chat/views/new_message.cljs +++ b/src/status_im/chat/views/new_message.cljs @@ -18,15 +18,14 @@ (defn show-input [command] [plain-message-input-view - (merge {:command command} - (case (:command command) - :phone {:input-options {:keyboardType :phone-pad} - :validator valid-mobile-number?} - :keypair-password {:input-options {:secureTextEntry true}} - :confirmation-code {:input-options {:keyboardType :numeric}} - :money {:input-options {:keyboardType :numeric}} - :request {:input-options {:keyboardType :numeric}} - nil))]) + (case (:command command) + :phone {:input-options {:keyboardType :phone-pad} + :validator valid-mobile-number?} + :keypair-password {:input-options {:secureTextEntry true}} + :confirmation-code {:input-options {:keyboardType :numeric}} + :money {:input-options {:keyboardType :numeric}} + :request {:input-options {:keyboardType :numeric}} + nil)]) (defn chat-message-new [] (let [command-atom (subscribe [:get-chat-command]) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index 7ff822da85..c67a54de56 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -9,8 +9,10 @@ [status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] [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.input :as st-command] + [status-im.chat.styles.response :as st-response])) (defn set-input-message [message] (dispatch [:set-chat-input-text message])) @@ -29,27 +31,36 @@ (when (message-valid? staged-commands message) (send dismiss-keyboard))) -(defn plain-message-input-view [{:keys [command input-options validator]}] +(defn plain-message-input-view [{:keys [input-options validator]}] (let [input-message (subscribe [:get-chat-input-text]) + command (subscribe [:get-chat-command]) + to-msg-id (subscribe [:get-chat-command-to-msg-id]) input-command (subscribe [:get-chat-command-content]) staged-commands (subscribe [:get-chat-staged-commands]) typing-command? (subscribe [:typing-command?])] - (fn [{:keys [command input-options validator]}] - (let [dismiss-keyboard (not (or command @typing-command?))] + (fn [{:keys [input-options validator]}] + (let [dismiss-keyboard (not (or command @typing-command?)) + command @command + response? (and command @to-msg-id)] [view st/input-container + (if response? [response/request-info command]) (if command [content-suggestions-view] [suggestions-view]) [view st/input-view (if command - [command/command-icon command] + (when-not response? + [command/command-icon command response?]) [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) :style st/switch-commands-touchable} [view nil (if @typing-command? [icon :close-gray st/close-icon] [icon :list st/list-icon])]]) - [text-input (merge {:style (if command st-command/command-input st/message-input) ;; st-command/command-input + [text-input (merge {:style (cond + response? st-response/command-input + command st-command/command-input + :else st/message-input) :autoFocus false :blurOnSubmit dismiss-keyboard :onChangeText (fn [text] @@ -74,9 +85,10 @@ (if (command/valid? @input-command validator) [touchable-highlight {:on-press command/send-command} [view st/send-container [icon :send st/send-icon]]] - [touchable-highlight {:on-press command/cancel-command-input} - [view st-command/cancel-container - [icon :close-gray st-command/cancel-icon]]]) + (when-not response? + [touchable-highlight {:on-press command/cancel-command-input} + [view st-command/cancel-container + [icon :close-gray st-command/cancel-icon]]])) (when (message-valid? @staged-commands @input-message) [touchable-highlight {:on-press #(try-send @staged-commands @input-message diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs new file mode 100644 index 0000000000..47781928b9 --- /dev/null +++ b/src/status_im/chat/views/response.cljs @@ -0,0 +1,41 @@ +(ns status-im.chat.views.response + (:require [re-frame.core :refer [subscribe dispatch]] + [status-im.components.react :refer [view + icon + image + text + text-input + touchable-highlight]] + [status-im.chat.views.command :as command] + [status-im.chat.styles.response :as st])) + +(defn drag-touchable [] + [touchable-highlight {:style st/drag-touchable + :onPress (fn [] + ;; TODO drag up/down + )} + [view nil + [icon :drag-white st/drag-down-icon]]]) + +(defn command-icon [] + [view st/command-icon-container + ;; TODO stub data: command icon + [icon :dollar-green st/command-icon]]) + +(defn info-container [command] + [view st/info-container + [text {:style st/command-name} + (:description command)] + [text {:style st/message-info} + ;; TODO stub data: request message info + "By ???, MMM 1st at HH:mm"]]) + +(defn request-info [command] + [view (st/request-info (:color command)) + [drag-touchable] + [view st/inner-container + [command-icon nil] + [info-container command] + [touchable-highlight {:on-press command/cancel-command-input} + [view st/cancel-container + [icon :close-white st/cancel-icon]]]]]) From a495fa79619bb67fde4ae34fd581521bee7a1683 Mon Sep 17 00:00:00 2001 From: virvar Date: Fri, 27 May 2016 16:27:17 +0300 Subject: [PATCH 07/25] Response suggestions --- .../chat/styles/response_suggestions.cljs | 62 +++++++++++++++++++ .../chat/views/content_suggestions.cljs | 12 ++-- src/status_im/chat/views/plain_input.cljs | 8 ++- .../chat/views/response_suggestions.cljs | 39 ++++++++++++ .../handlers/content_suggestions.cljs | 13 ++-- 5 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 src/status_im/chat/styles/response_suggestions.cljs create mode 100644 src/status_im/chat/views/response_suggestions.cljs diff --git a/src/status_im/chat/styles/response_suggestions.cljs b/src/status_im/chat/styles/response_suggestions.cljs new file mode 100644 index 0000000000..831486cfa4 --- /dev/null +++ b/src/status_im/chat/styles/response_suggestions.cljs @@ -0,0 +1,62 @@ +(ns status-im.chat.styles.response-suggestions + (:require [status-im.components.styles :refer [font + font-medium + color-light-blue-transparent + color-white + color-black + color-blue + color-blue-transparent + selected-message-color + online-color + separator-color + text1-color + text2-color + text3-color]])) + +(def header-height 50) +(def suggestion-height 56) + +(def header-container + {:paddingLeft 16 + :height header-height + :backgroundColor color-white}) + +(def header-text + {:marginTop 18 + :fontSize 13 + :fontFamily font-medium + :color text2-color}) + +(def suggestion-container + {:flexDirection :column + :paddingLeft 16 + :height 56 + :backgroundColor color-white}) + +(def suggestion-sub-container + {:height suggestion-height + :borderBottomWidth 1 + :borderBottomColor separator-color}) + +(def value-text + {:marginTop 10 + :fontSize 12 + :fontFamily font + :color text1-color}) + +(def description-text + {:marginTop 2 + :fontSize 12 + :fontFamily font + :color text2-color}) + +(defn suggestions-container [suggestions] + {:flexDirection :row + :marginVertical 1 + :marginHorizontal 0 + :height (min 150 (reduce + 0 (map #(if (:header %) + header-height + suggestion-height) + suggestions))) + :backgroundColor color-white + :borderRadius 5}) diff --git a/src/status_im/chat/views/content_suggestions.cljs b/src/status_im/chat/views/content_suggestions.cljs index 25661ff11d..a10ae722db 100644 --- a/src/status_im/chat/views/content_suggestions.cljs +++ b/src/status_im/chat/views/content_suggestions.cljs @@ -2,11 +2,11 @@ (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view - icon - text - touchable-highlight - list-view - list-item]] + icon + text + touchable-highlight + list-view + list-item]] [status-im.chat.styles.content-suggestions :as st] [status-im.utils.listview :refer [to-datasource]])) @@ -32,6 +32,6 @@ :onPress (fn [])} [view [icon :drag_down st/drag-down-icon]]] [view (st/suggestions-container (count suggestions)) - [list-view {:dataSource (to-datasource suggestions) + [list-view {:dataSource (to-datasource (filter :value suggestions)) :keyboardShouldPersistTaps true :renderRow render-row}]]])) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index c67a54de56..7843e4dafa 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -8,6 +8,7 @@ dismiss-keyboard!]] [status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] + [status-im.chat.views.response-suggestions :refer [response-suggestions-view]] [status-im.chat.views.command :as command] [status-im.chat.views.response :as response] [status-im.chat.styles.plain-input :as st] @@ -44,9 +45,10 @@ response? (and command @to-msg-id)] [view st/input-container (if response? [response/request-info command]) - (if command - [content-suggestions-view] - [suggestions-view]) + (cond + response? [response-suggestions-view] + command [content-suggestions-view] + :else [suggestions-view]) [view st/input-view (if command (when-not response? diff --git a/src/status_im/chat/views/response_suggestions.cljs b/src/status_im/chat/views/response_suggestions.cljs new file mode 100644 index 0000000000..6946f693ff --- /dev/null +++ b/src/status_im/chat/views/response_suggestions.cljs @@ -0,0 +1,39 @@ +(ns status-im.chat.views.response-suggestions + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :refer [subscribe dispatch]] + [status-im.components.react :refer [view + icon + text + touchable-highlight + list-view + list-item]] + [status-im.chat.styles.response-suggestions :as st] + [status-im.utils.listview :refer [to-datasource]])) + +(defn set-command-content [content] + (dispatch [:set-chat-command-content content])) + +(defn header-list-item [{:keys [header]}] + [view st/header-container + [text {:style st/header-text} header]]) + +(defn suggestion-list-item [{:keys [value description]}] + [touchable-highlight {:onPress #(set-command-content value)} + [view st/suggestion-container + [view st/suggestion-sub-container + [text {:style st/value-text} value] + [text {:style st/description-text} description]]]]) + +(defn render-row [row _ _] + (list-item (if (:header row) + [header-list-item row] + [suggestion-list-item row]))) + +(defview response-suggestions-view [] + [suggestions [:get-content-suggestions]] + (when (seq suggestions) + [view nil + [view (st/suggestions-container suggestions) + [list-view {:dataSource (to-datasource suggestions) + :keyboardShouldPersistTaps true + :renderRow render-row}]]])) diff --git a/src/status_im/handlers/content_suggestions.cljs b/src/status_im/handlers/content_suggestions.cljs index f4457f931f..6fa8d3cec9 100644 --- a/src/status_im/handlers/content_suggestions.cljs +++ b/src/status_im/handlers/content_suggestions.cljs @@ -4,19 +4,22 @@ [status-im.utils.logging :as log] [clojure.string :as s])) +;; TODO stub data? (def suggestions - {:phone [{:value "89171111111" + {:phone [{:header "Phone number formats"} + {:value "89171111111" :description "Number format 1"} - {:value "+79171111111" + {:value "+79171111111" :description "Number format 2"} - {:value "9171111111" + {:value "9171111111" :description "Number format 3"}]}) (defn get-content-suggestions [db command text] (or (when command (when-let [command-suggestions ((:command command) suggestions)] (filterv (fn [s] - (and (.startsWith (:value s) (or text "")) - (not= (:value s) text))) + (or (:header s) + (and (.startsWith (:value s) (or text "")) + (not= (:value s) text)))) command-suggestions))) [])) From b9fcad3df576bfea8592d0cbfa0419005c412266 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 30 May 2016 16:50:23 +0300 Subject: [PATCH 08/25] Response suggestions animation --- src/status_im/chat/handlers.cljs | 22 +++++++++++++- src/status_im/chat/styles/response.cljs | 8 ++++- .../chat/styles/response_suggestions.cljs | 1 + src/status_im/chat/subs.cljs | 27 +++++++++++++++-- src/status_im/chat/views/plain_input.cljs | 4 +-- src/status_im/chat/views/response.cljs | 15 ++++++++-- .../chat/views/response_suggestions.cljs | 9 +++--- src/status_im/chat/views/suggestions.cljs | 10 +++---- src/status_im/components/animation.cljs | 29 +++++++++++++++++++ src/status_im/components/react.cljs | 4 +++ src/status_im/constants.cljs | 3 ++ src/status_im/db.cljs | 9 ++++-- src/status_im/models/commands.cljs | 1 + 13 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 src/status_im/components/animation.cljs diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index a12722e161..841f23ab14 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -2,12 +2,14 @@ (:require [re-frame.core :refer [register-handler enrich after debug dispatch]] [status-im.models.commands :as commands] [clojure.string :as str] + [status-im.components.animation :as anim] [status-im.components.styles :refer [default-chat-color]] [status-im.chat.suggestions :as suggestions] [status-im.protocol.api :as api] [status-im.models.messages :as messages] [status-im.constants :refer [text-content-type - content-type-command]] + content-type-command + response-input-hiding-duration]] [status-im.utils.random :as random] [status-im.chat.sign-up :as sign-up-service] [status-im.models.chats :as chats] @@ -15,6 +17,7 @@ [status-im.utils.handlers :as u] [status-im.persistence.realm :as r] [status-im.handlers.server :as server] + [status-im.handlers.content-suggestions :refer [get-content-suggestions]] [status-im.utils.phone-number :refer [format-phone-number]] [status-im.utils.datetime :as time])) @@ -38,9 +41,26 @@ (register-handler :cancel-command (fn [{:keys [current-chat-id] :as db} _] (-> db + (assoc-in [:animations :response-input-is-hiding?] false) (assoc-in [:chats current-chat-id :command-input] {}) (update-in [:chats current-chat-id :input-text] safe-trim)))) +(defn animate-cancel-command [db height] + (anim/add-listener height (fn [val] + (when (<= (.-value val) 1) + (anim/remove-all-listeners height) + (anim/stop-animation height) + (dispatch [:cancel-command])))) + (anim/start (anim/timing height {:toValue 1, :duration response-input-hiding-duration})) + (assoc-in db [:animations :response-input-is-hiding?] true)) + +(register-handler :start-cancel-command + (fn [{{height :response-suggestions-height + hiding? :response-input-is-hiding?} :animations :as db} _] + (if-not hiding? + (animate-cancel-command db height) + db))) + (register-handler :set-chat-command-content (fn [{:keys [current-chat-id] :as db} [_ content]] (-> db diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index 2e969ae0ef..7d304474e5 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -7,6 +7,8 @@ chat-background color-black]])) +(def request-info-height 61) + (def drag-touchable {:height 16 :alignItems :center}) @@ -47,9 +49,13 @@ :opacity 0.69 :color color-white}) +(defn request-view [height] + {:flexDirection :column + :height height}) + (defn request-info [color] {:flexDirection :column - :height 61 + :height request-info-height :backgroundColor color}) (def inner-container diff --git a/src/status_im/chat/styles/response_suggestions.cljs b/src/status_im/chat/styles/response_suggestions.cljs index 831486cfa4..e8ba2f6c98 100644 --- a/src/status_im/chat/styles/response_suggestions.cljs +++ b/src/status_im/chat/styles/response_suggestions.cljs @@ -13,6 +13,7 @@ text2-color text3-color]])) +(def min-suggestions-height 150) (def header-height 50) (def suggestion-height 56) diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index f29c3527a2..6e669efba4 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -4,8 +4,12 @@ [status-im.db :as db] ;todo handlers in subs?... [status-im.chat.suggestions :refer - [get-suggestions typing-command? get-content-suggestions]] + [get-suggestions typing-command?]] [status-im.models.commands :as commands] + [status-im.components.animation :as anim] + [status-im.constants :refer [response-suggesstion-resize-duration]] + [status-im.chat.styles.response :as response-styles] + [status-im.chat.styles.response-suggestions :as response-suggestions-styles] [status-im.handlers.content-suggestions :refer [get-content-suggestions]])) (register-sub :chat-properties @@ -91,8 +95,25 @@ (fn [db _] (reaction (typing-command? @db)))) +(defn update-response-suggestions-height [db] + (when-not (get-in db [:animations :response-input-is-hiding?]) + (let [command (commands/get-chat-command db) + text (commands/get-chat-command-content db) + suggestions (get-content-suggestions db command text) + suggestions-height (min response-suggestions-styles/min-suggestions-height + (reduce + 0 (map #(if (:header %) + response-suggestions-styles/header-height + response-suggestions-styles/suggestion-height) + suggestions))) + height (+ suggestions-height response-styles/request-info-height) + anim-value (get-in db [:animations :response-suggestions-height])] + (anim/start (anim/timing anim-value {:toValue height, :duration response-suggesstion-resize-duration})))) + db) + (register-sub :get-content-suggestions (fn [db _] (let [command (reaction (commands/get-chat-command @db)) - text (reaction (commands/get-chat-command-content @db))] - (reaction (get-content-suggestions @db @command @text))))) + text (reaction (commands/get-chat-command-content @db)) + suggestions (reaction (get-content-suggestions @db @command @text))] + (reaction (do (update-response-suggestions-height @db) + @suggestions))))) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index 7843e4dafa..ae391edb4f 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -8,7 +8,6 @@ dismiss-keyboard!]] [status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] - [status-im.chat.views.response-suggestions :refer [response-suggestions-view]] [status-im.chat.views.command :as command] [status-im.chat.views.response :as response] [status-im.chat.styles.plain-input :as st] @@ -44,9 +43,8 @@ command @command response? (and command @to-msg-id)] [view st/input-container - (if response? [response/request-info command]) (cond - response? [response-suggestions-view] + response? [response/request-view] command [content-suggestions-view] :else [suggestions-view]) [view st/input-view diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 47781928b9..89e4bb0c1c 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -1,12 +1,14 @@ (ns status-im.chat.views.response + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view + animated-view icon image text text-input touchable-highlight]] - [status-im.chat.views.command :as command] + [status-im.chat.views.response-suggestions :refer [response-suggestions-view]] [status-im.chat.styles.response :as st])) (defn drag-touchable [] @@ -30,12 +32,19 @@ ;; TODO stub data: request message info "By ???, MMM 1st at HH:mm"]]) -(defn request-info [command] +(defview request-info [] + [command [:get-chat-command]] [view (st/request-info (:color command)) [drag-touchable] [view st/inner-container [command-icon nil] [info-container command] - [touchable-highlight {:on-press command/cancel-command-input} + [touchable-highlight {:on-press #(dispatch [:start-cancel-command])} [view st/cancel-container [icon :close-white st/cancel-icon]]]]]) + +(defview request-view [] + [height [:get-in [:animations :response-suggestions-height]]] + [animated-view {:style (st/request-view height)} + [request-info] + [response-suggestions-view]]) diff --git a/src/status_im/chat/views/response_suggestions.cljs b/src/status_im/chat/views/response_suggestions.cljs index 6946f693ff..c2dab90552 100644 --- a/src/status_im/chat/views/response_suggestions.cljs +++ b/src/status_im/chat/views/response_suggestions.cljs @@ -32,8 +32,7 @@ (defview response-suggestions-view [] [suggestions [:get-content-suggestions]] (when (seq suggestions) - [view nil - [view (st/suggestions-container suggestions) - [list-view {:dataSource (to-datasource suggestions) - :keyboardShouldPersistTaps true - :renderRow render-row}]]])) + [view (st/suggestions-container suggestions) + [list-view {:dataSource (to-datasource suggestions) + :keyboardShouldPersistTaps true + :renderRow render-row}]])) diff --git a/src/status_im/chat/views/suggestions.cljs b/src/status_im/chat/views/suggestions.cljs index acf45f0967..157c23b74e 100644 --- a/src/status_im/chat/views/suggestions.cljs +++ b/src/status_im/chat/views/suggestions.cljs @@ -1,11 +1,11 @@ (ns status-im.chat.views.suggestions (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view - text - icon - touchable-highlight - list-view - list-item]] + text + icon + touchable-highlight + list-view + list-item]] [status-im.utils.listview :refer [to-datasource]] [status-im.chat.styles.suggestions :as st])) diff --git a/src/status_im/components/animation.cljs b/src/status_im/components/animation.cljs new file mode 100644 index 0000000000..2ccc4fc216 --- /dev/null +++ b/src/status_im/components/animation.cljs @@ -0,0 +1,29 @@ +(ns status-im.components.animation + (:require [status-im.components.react :refer [animated]])) + +(defn start [anim] + (.start anim)) + +(defn timing [anim-value config] + (.timing animated anim-value (clj->js config))) + +(defn spring [anim-value config] + (.spring animated anim-value (clj->js config))) + +(defn add-listener [anim-value listener] + (.addListener anim-value listener)) + +(defn remove-all-listeners [anim-value] + (.removeAllListeners anim-value)) + +(defn stop-animation [anim-value] + (.stopAnimation anim-value)) + +(defn value [anim-value] + (.-value anim-value)) + +(defn set-value [anim-value value] + (.setValue anim-value value)) + +(defn create-value [value] + (js/React.Animated.Value. value)) diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index 930f6deedf..0f16a6d82b 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -34,6 +34,10 @@ (def picker (r/adapt-react-class (.-Picker js/React))) (def picker-item (r/adapt-react-class (.-Item (.-Picker js/React)))) +(def animated (.-Animated js/React)) +(def animated-view (r/adapt-react-class (.-View animated))) +(def animated-text (r/adapt-react-class (.-Text animated))) + (defn icon ([n] (icon n {})) diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index c1c4f35fa5..ec1ba801e2 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -12,3 +12,6 @@ (def content-type-status "status") (def max-chat-name-length 20) + +(def response-input-hiding-duration 200) +(def response-suggesstion-resize-duration 100) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index a46c61f087..f38d4f870f 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -1,5 +1,7 @@ (ns status-im.db - (:require [schema.core :as s :include-macros true])) + (:require [schema.core :as s :include-macros true] + [status-im.components.react :refer [animated]] + [status-im.components.animation :as anim])) ;; schema of app-db (def schema {:greeting s/Str}) @@ -29,7 +31,10 @@ :email "myemail@gmail.com" :status "Hi, this is my status" :current-tag nil - :disable-group-creation false}) + :disable-group-creation false + :animations {;; mutable data + :response-suggestions-height (anim/create-value 0) + :response-input-is-hiding? false}}) (def protocol-initialized-path [:protocol-initialized]) (defn chat-input-text-path [chat-id] diff --git a/src/status_im/models/commands.cljs b/src/status_im/models/commands.cljs index 4ade2ed196..55428ae3d8 100644 --- a/src/status_im/models/commands.cljs +++ b/src/status_im/models/commands.cljs @@ -3,6 +3,7 @@ [clojure.walk :refer [stringify-keys keywordize-keys]] [re-frame.core :refer [subscribe dispatch]] [status-im.db :as db] + [status-im.components.animation :as anim] [status-im.components.styles :refer [color-blue color-dark-mint]])) ;; todo delete From 8892d13db4ddd5a66c9daaea7e64d70d4e4e578e Mon Sep 17 00:00:00 2001 From: virvar Date: Tue, 31 May 2016 14:23:30 +0300 Subject: [PATCH 09/25] Spring animation --- src/status_im/chat/handlers.cljs | 57 ++++++++++++++----- .../chat/styles/response_suggestions.cljs | 9 +-- src/status_im/chat/subs.cljs | 26 +-------- .../chat/views/content_suggestions.cljs | 6 +- .../chat/views/response_suggestions.cljs | 2 +- .../handlers/content_suggestions.cljs | 2 +- 6 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 841f23ab14..bd9367b91c 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -4,6 +4,8 @@ [clojure.string :as str] [status-im.components.animation :as anim] [status-im.components.styles :refer [default-chat-color]] + [status-im.chat.styles.response :as response-styles] + [status-im.chat.styles.response-suggestions :as response-suggestions-styles] [status-im.chat.suggestions :as suggestions] [status-im.protocol.api :as api] [status-im.models.messages :as messages] @@ -21,6 +23,8 @@ [status-im.utils.phone-number :refer [format-phone-number]] [status-im.utils.datetime :as time])) +(def delta 1) + (register-handler :set-show-actions (fn [db [_ show-actions]] (assoc db :show-actions show-actions))) @@ -45,27 +49,52 @@ (assoc-in [:chats current-chat-id :command-input] {}) (update-in [:chats current-chat-id :input-text] safe-trim)))) -(defn animate-cancel-command [db height] - (anim/add-listener height (fn [val] - (when (<= (.-value val) 1) - (anim/remove-all-listeners height) - (anim/stop-animation height) - (dispatch [:cancel-command])))) - (anim/start (anim/timing height {:toValue 1, :duration response-input-hiding-duration})) - (assoc-in db [:animations :response-input-is-hiding?] true)) +(defn animate-cancel-command [db height-anim-value] + (let [to-value 1] + (anim/add-listener height-anim-value + (fn [val] + (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) + (anim/remove-all-listeners height-anim-value) + (dispatch [:cancel-command])))) + (anim/stop-animation height-anim-value) + (anim/start (anim/spring height-anim-value {:toValue to-value + :speed 10 + :bounciness 1})) + (assoc-in db [:animations :response-input-is-hiding?] true))) (register-handler :start-cancel-command - (fn [{{height :response-suggestions-height - hiding? :response-input-is-hiding?} :animations :as db} _] + (fn [{{height-anim-value :response-suggestions-height + hiding? :response-input-is-hiding?} :animations :as db} _] (if-not hiding? - (animate-cancel-command db height) + (animate-cancel-command db height-anim-value) db))) +(defn update-response-suggestions-height [db] + (when (and (not (get-in db [:animations :response-input-is-hiding?])) + (commands/get-chat-command-to-msg-id db)) + (let [command (commands/get-chat-command db) + text (commands/get-chat-command-content db) + suggestions (get-content-suggestions command text) + suggestions-height (min response-suggestions-styles/max-suggestions-height + (reduce + 0 (map #(if (:header %) + response-suggestions-styles/header-height + response-suggestions-styles/suggestion-height) + suggestions))) + height (+ suggestions-height response-styles/request-info-height) + anim-value (get-in db [:animations :response-suggestions-height])] + (anim/stop-animation anim-value) + (anim/start + (anim/spring anim-value {:toValue height + :speed 10 + :bounciness 10})))) + db) + (register-handler :set-chat-command-content (fn [{:keys [current-chat-id] :as db} [_ content]] (-> db (commands/set-chat-command-content content) - (assoc-in [:chats current-chat-id :input-text] nil)))) + (assoc-in [:chats current-chat-id :input-text] nil) + (update-response-suggestions-height)))) (defn update-input-text [{:keys [current-chat-id] :as db} text] @@ -83,7 +112,9 @@ (register-handler :set-response-chat-command (fn [db [_ to-msg-id command-key]] - (commands/set-response-chat-command db to-msg-id command-key))) + (-> db + (commands/set-response-chat-command to-msg-id command-key) + (update-response-suggestions-height)))) (defn update-text [db [_ text]] diff --git a/src/status_im/chat/styles/response_suggestions.cljs b/src/status_im/chat/styles/response_suggestions.cljs index e8ba2f6c98..e039264a06 100644 --- a/src/status_im/chat/styles/response_suggestions.cljs +++ b/src/status_im/chat/styles/response_suggestions.cljs @@ -13,7 +13,7 @@ text2-color text3-color]])) -(def min-suggestions-height 150) +(def max-suggestions-height 250) (def header-height 50) (def suggestion-height 56) @@ -51,13 +51,10 @@ :fontFamily font :color text2-color}) -(defn suggestions-container [suggestions] +(def suggestions-container {:flexDirection :row + :flex 1 :marginVertical 1 :marginHorizontal 0 - :height (min 150 (reduce + 0 (map #(if (:header %) - header-height - suggestion-height) - suggestions))) :backgroundColor color-white :borderRadius 5}) diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index 6e669efba4..9b11d29fd0 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -1,15 +1,12 @@ (ns status-im.chat.subs (:require-macros [reagent.ratom :refer [reaction]]) - (:require [re-frame.core :refer [register-sub]] + (:require [re-frame.core :refer [register-sub dispatch]] [status-im.db :as db] ;todo handlers in subs?... [status-im.chat.suggestions :refer [get-suggestions typing-command?]] [status-im.models.commands :as commands] - [status-im.components.animation :as anim] [status-im.constants :refer [response-suggesstion-resize-duration]] - [status-im.chat.styles.response :as response-styles] - [status-im.chat.styles.response-suggestions :as response-suggestions-styles] [status-im.handlers.content-suggestions :refer [get-content-suggestions]])) (register-sub :chat-properties @@ -95,25 +92,8 @@ (fn [db _] (reaction (typing-command? @db)))) -(defn update-response-suggestions-height [db] - (when-not (get-in db [:animations :response-input-is-hiding?]) - (let [command (commands/get-chat-command db) - text (commands/get-chat-command-content db) - suggestions (get-content-suggestions db command text) - suggestions-height (min response-suggestions-styles/min-suggestions-height - (reduce + 0 (map #(if (:header %) - response-suggestions-styles/header-height - response-suggestions-styles/suggestion-height) - suggestions))) - height (+ suggestions-height response-styles/request-info-height) - anim-value (get-in db [:animations :response-suggestions-height])] - (anim/start (anim/timing anim-value {:toValue height, :duration response-suggesstion-resize-duration})))) - db) - (register-sub :get-content-suggestions (fn [db _] (let [command (reaction (commands/get-chat-command @db)) - text (reaction (commands/get-chat-command-content @db)) - suggestions (reaction (get-content-suggestions @db @command @text))] - (reaction (do (update-response-suggestions-height @db) - @suggestions))))) + text (reaction (commands/get-chat-command-content @db))] + (reaction (get-content-suggestions @command @text))))) diff --git a/src/status_im/chat/views/content_suggestions.cljs b/src/status_im/chat/views/content_suggestions.cljs index a10ae722db..e200aee8db 100644 --- a/src/status_im/chat/views/content_suggestions.cljs +++ b/src/status_im/chat/views/content_suggestions.cljs @@ -25,13 +25,13 @@ (defview content-suggestions-view [] [suggestions [:get-content-suggestions]] - (when (seq suggestions) + (when-let [values (not-empty (filter :value suggestions))] [view [touchable-highlight {:style st/drag-down-touchable ;; TODO hide suggestions? :onPress (fn [])} [view [icon :drag_down st/drag-down-icon]]] - [view (st/suggestions-container (count suggestions)) - [list-view {:dataSource (to-datasource (filter :value suggestions)) + [view (st/suggestions-container (count values)) + [list-view {:dataSource (to-datasource values) :keyboardShouldPersistTaps true :renderRow render-row}]]])) diff --git a/src/status_im/chat/views/response_suggestions.cljs b/src/status_im/chat/views/response_suggestions.cljs index c2dab90552..54eed3bb7d 100644 --- a/src/status_im/chat/views/response_suggestions.cljs +++ b/src/status_im/chat/views/response_suggestions.cljs @@ -32,7 +32,7 @@ (defview response-suggestions-view [] [suggestions [:get-content-suggestions]] (when (seq suggestions) - [view (st/suggestions-container suggestions) + [view st/suggestions-container [list-view {:dataSource (to-datasource suggestions) :keyboardShouldPersistTaps true :renderRow render-row}]])) diff --git a/src/status_im/handlers/content_suggestions.cljs b/src/status_im/handlers/content_suggestions.cljs index 6fa8d3cec9..d43801cff3 100644 --- a/src/status_im/handlers/content_suggestions.cljs +++ b/src/status_im/handlers/content_suggestions.cljs @@ -14,7 +14,7 @@ {:value "9171111111" :description "Number format 3"}]}) -(defn get-content-suggestions [db command text] +(defn get-content-suggestions [command text] (or (when command (when-let [command-suggestions ((:command command) suggestions)] (filterv (fn [s] From 96ef6c34a8a4e33cf0c470075c4db4a23405e397 Mon Sep 17 00:00:00 2001 From: virvar Date: Tue, 31 May 2016 14:39:38 +0300 Subject: [PATCH 10/25] Fix drag icon --- .../main/res/drawable-hdpi/icon_drag_white.png | Bin 244 -> 151 bytes .../main/res/drawable-mdpi/icon_drag_white.png | Bin 178 -> 120 bytes .../main/res/drawable-xhdpi/icon_drag_white.png | Bin 250 -> 145 bytes .../res/drawable-xxhdpi/icon_drag_white.png | Bin 426 -> 187 bytes .../res/drawable-xxxhdpi/icon_drag_white.png | Bin 482 -> 223 bytes src/status_im/chat/styles/response.cljs | 14 ++++++++++---- src/status_im/chat/views/response.cljs | 4 ++-- 7 files changed, 12 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/res/drawable-hdpi/icon_drag_white.png b/android/app/src/main/res/drawable-hdpi/icon_drag_white.png index 0e00adb5c10efa4af255199c17be50ce214139e8..6a079b6f6fb5559908a6104e85d2eafa2bbbfd6f 100644 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^qCm{b!3HE(9bC=}q!^2X+?^QKos)S92Uw2eKC$n0p+Yof~+vBshvMSgR>?vmaY5be7rZi`rD4X365o xf=8Ix8kr^tu_YPEdrW5j$85ScH6^8nfx+Uuph;Gc!EB)644$rjF6*2UngB*TDjNU* literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|)_J-(hIsHM z$K0v2?QLvp=xj@C?v>lxkigN;cJTnaAom^4Gdw&^NisZZ)=Y6d{r>)ciF^Bh9X#+s zJjv(=lUf)X+jb3CHbKv_9ko*o?%Di5xgq;zZCm|*Nr?mJLa#krKI@@Ed!r1OkuZw} zH~$8~ADkOl%h%VXFjRI&F{Fr{@DX4*&Zx1bOlPP6ZV$F-)}F85&o^%LPj#4Yv0&5U rz#i$Zj9vu^k9*hzw*@!~GBX?r(V6{z@eCiJ%Naaf{an^LB{Ts5G~8Ol diff --git a/android/app/src/main/res/drawable-mdpi/icon_drag_white.png b/android/app/src/main/res/drawable-mdpi/icon_drag_white.png index ee4865dc432938d431338e5b16f1b400614c572d..7845600020bd2775aba0a38991a6943317d4a02a 100644 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^d_c_1!3HE3U$f%}QjEnx?oJHr&dIz4a*RA(978x{ zlmGnxzh9D>xmixYn9uN)3 diff --git a/android/app/src/main/res/drawable-xhdpi/icon_drag_white.png b/android/app/src/main/res/drawable-xhdpi/icon_drag_white.png index 9d42716db7c428f54742da39ca13b92ba526a3db..2b200673bb0d4a0720da1e2ad8ffb61033c83c04 100644 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^GC<76!3HERIQ+{5QjEnx?oJHr&dIz4a=blV978lj zlmGnxZ*R=Z+-xbZn$b{N;4;%6CaEg!4u2yi-7QQ;B^im_V#ezY7+D?d7K;ZkM|y-a rY!VRJ_JwJCM1$GfmRoMqU6>gTm-Am+WzsGHG?u~B)z4*}Q$iB}6E!Fx literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}TRdGHLn1hn zWA4=1_9ikgUS_z(yRGU9<6=bvDJC$%EXSm?VOK-v%*KN!BIh_p&Ys^mb*|aFUw=Q# zAHI89Uh>@A`ja2t>mNzm!Q3NrRMMn}CGp)tPTo&5+BlE&8CSxlKI;I5LpZ%8HXLCLcF2~JW8Jci oWBSj$Z|%j}{y0^QHx>FVdQ&MBb@0Hr2b;s5{u diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_drag_white.png b/android/app/src/main/res/drawable-xxhdpi/icon_drag_white.png index ac17612846227adddeab33bce39613962dcc5e9a..23fa971c5e6c99e3b6bf8a522bd8b528b6183aa3 100644 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^T0qRn!3HEVa+Fwp3rXut5EtfmB4^K@cTVlrcfYZie^aik;OB79*+2&{c)I$ztaD0e0sve=MneDq literal 426 zcmV;b0agBqP)Px$WJyFpRA>e5m9a|1KoEvUF(|@uO;BXTMg%)+LG0~(3SY$s@dfPc55Zb26ht`0 za3I%&fZP!fGumXbhf@qoCh$)cva`eY|Nkbtc60rFMFXz&0ki+2LqOjNA^{{|bO1-l zXrOsJ5-?k69DoFj2Aa1c0keh10Z71Tpm{qIFk5IGu(4`?woMcc$21ye)OSSR4PaH) zRJ@i{FJjtAz`^l|PA~Q-+w2=%!q&@Odbpd>`%5Jj1ZBRzMdz2n9Xu1Wq0GjN?Gge` z&UV^sE}y%MLO>px!|%NE@J|9n{K*WfL;~|-#b@qJPnS^$c)b5~h8yE_8HIrP$ATue z1=UM`M~Ru3jTze&-2?oeolPqWN6s#?x8@@IYNP)>M*{dY-+0rfGVXTxMjRoBd@2$I zs1_w|Kmv&kR>va&)uO}=NFcGn>UboeT9mi}2_!aH9ghT5ixM{=fy4%@;|HI>5A4oG U+1{0uod5s;07*qoM6N<$g2}nE?*IS* diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_drag_white.png b/android/app/src/main/res/drawable-xxxhdpi/icon_drag_white.png index dced659cf485c8d0ecd8c527d648fffb7bcd95fc..fd3f08e9ae1a5182456afe2421881b61b47156d7 100644 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^7C_9y!3HGFbL*A@DaPU;cPEB*=VV?2IWs+7978;K z?@rq&cvwMzpb%&#U06dOvwt_oS(j zm0JIggwI}kYTcBMj2t@&mG76*L+`EO{c$33@{@^fPv<;Y!QUEH=soL0^sW#;EprQ9 zj-qEVCpn51?l4l$;BAUoyDo&~rS!Tt9Ad5e9hF8Pj4@$ zO}>;?zO=Uf=zB?~7x^V`pOjoT+y47wu+ky0#rG5I%COr1oRT z+}RdZxAt(^`+HaK`1@FkXLiH2$DbTyW}bFc*nGodHiJvZjH)7r%UhJ!7CE@Iu2g3? i@U_0A#ZHRwFXlap5$=26s9FFcjlt8^&t;ucLK6TbkH}R3 diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index 7d304474e5..8849708630 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -13,10 +13,16 @@ {:height 16 :alignItems :center}) -(def drag-down-icon - {:width 16 - :height 16 - :opacity 0.4}) +(def drag-container + {:width 16 + :height 16}) + +(def drag-icon + {:position :absolute + :top 6.5 + :left 1 + :width 14 + :height 3}) (def command-icon-container {:marginTop 1 diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 89e4bb0c1c..27c997317b 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -16,8 +16,8 @@ :onPress (fn [] ;; TODO drag up/down )} - [view nil - [icon :drag-white st/drag-down-icon]]]) + [view st/drag-container + [icon :drag-white st/drag-icon]]]) (defn command-icon [] [view st/command-icon-container From 5c83b09db623bfb36add56ab70f27ee54ef914aa Mon Sep 17 00:00:00 2001 From: virvar Date: Tue, 31 May 2016 17:05:31 +0300 Subject: [PATCH 11/25] Animation refactoring --- src/status_im/chat/handlers.cljs | 36 +++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index bd9367b91c..d0a25712fc 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -49,27 +49,28 @@ (assoc-in [:chats current-chat-id :command-input] {}) (update-in [:chats current-chat-id :input-text] safe-trim)))) -(defn animate-cancel-command [db height-anim-value] - (let [to-value 1] +(defn animate-cancel-command! [db] + (let [height-anim-value (get-in db [:animations :response-suggestions-height]) + to-value 1] (anim/add-listener height-anim-value (fn [val] (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) (anim/remove-all-listeners height-anim-value) (dispatch [:cancel-command])))) - (anim/stop-animation height-anim-value) (anim/start (anim/spring height-anim-value {:toValue to-value :speed 10 - :bounciness 1})) - (assoc-in db [:animations :response-input-is-hiding?] true))) + :bounciness 1})))) (register-handler :start-cancel-command - (fn [{{height-anim-value :response-suggestions-height - hiding? :response-input-is-hiding?} :animations :as db} _] - (if-not hiding? - (animate-cancel-command db height-anim-value) - db))) + (after animate-cancel-command!) + (fn [db _] + (let [current-chat-id (:current-chat-id db) + hiding? (get-in db [:animations :response-input-is-hiding?])] + (if-not hiding? + (assoc-in db [:animations :response-input-is-hiding?] true) + db)))) -(defn update-response-suggestions-height [db] +(defn update-response-suggestions-height! [db] (when (and (not (get-in db [:animations :response-input-is-hiding?])) (commands/get-chat-command-to-msg-id db)) (let [command (commands/get-chat-command db) @@ -82,19 +83,17 @@ suggestions))) height (+ suggestions-height response-styles/request-info-height) anim-value (get-in db [:animations :response-suggestions-height])] - (anim/stop-animation anim-value) (anim/start (anim/spring anim-value {:toValue height :speed 10 - :bounciness 10})))) - db) + :bounciness 10}))))) (register-handler :set-chat-command-content + (after update-response-suggestions-height!) (fn [{:keys [current-chat-id] :as db} [_ content]] (-> db (commands/set-chat-command-content content) - (assoc-in [:chats current-chat-id :input-text] nil) - (update-response-suggestions-height)))) + (assoc-in [:chats current-chat-id :input-text] nil)))) (defn update-input-text [{:keys [current-chat-id] :as db} text] @@ -111,10 +110,9 @@ (commands/stage-command db command-info)))) (register-handler :set-response-chat-command + (after update-response-suggestions-height!) (fn [db [_ to-msg-id command-key]] - (-> db - (commands/set-response-chat-command to-msg-id command-key) - (update-response-suggestions-height)))) + (commands/set-response-chat-command db to-msg-id command-key))) (defn update-text [db [_ text]] From 572fc0e554741f2cd1c3c81d3a112d0cb38ff1cd Mon Sep 17 00:00:00 2001 From: virvar Date: Wed, 1 Jun 2016 14:09:25 +0300 Subject: [PATCH 12/25] Input text and buttons animation --- src/status_im/chat/handlers.cljs | 60 +++++--- src/status_im/chat/styles/plain_input.cljs | 14 +- src/status_im/chat/styles/response.cljs | 15 +- src/status_im/chat/views/plain_input.cljs | 154 ++++++++++++--------- src/status_im/constants.cljs | 2 +- src/status_im/db.cljs | 7 +- 6 files changed, 158 insertions(+), 94 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index d0a25712fc..8169e91b67 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -49,23 +49,28 @@ (assoc-in [:chats current-chat-id :command-input] {}) (update-in [:chats current-chat-id :input-text] safe-trim)))) -(defn animate-cancel-command! [db] - (let [height-anim-value (get-in db [:animations :response-suggestions-height]) - to-value 1] - (anim/add-listener height-anim-value +(defn animate-cancel-command! [{{:keys [response-suggestions-height + message-input-buttons-scale + message-input-offset]} :animations}] + (let [height-to-value 1] + (anim/add-listener response-suggestions-height (fn [val] - (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) - (anim/remove-all-listeners height-anim-value) + (when (<= (- height-to-value delta) (anim/value val) (+ height-to-value delta)) + (anim/remove-all-listeners response-suggestions-height) (dispatch [:cancel-command])))) - (anim/start (anim/spring height-anim-value {:toValue to-value - :speed 10 - :bounciness 1})))) + (anim/start (anim/spring response-suggestions-height {:toValue height-to-value + :velocity 1 + :tension 1 + :friction 5})) + (anim/start (anim/timing message-input-buttons-scale {:toValue 1 + :duration response-input-hiding-duration})) + (anim/start (anim/timing message-input-offset {:toValue 0 + :duration response-input-hiding-duration})))) (register-handler :start-cancel-command (after animate-cancel-command!) (fn [db _] - (let [current-chat-id (:current-chat-id db) - hiding? (get-in db [:animations :response-input-is-hiding?])] + (let [hiding? (get-in db [:animations :response-input-is-hiding?])] (if-not hiding? (assoc-in db [:animations :response-input-is-hiding?] true) db)))) @@ -85,8 +90,8 @@ anim-value (get-in db [:animations :response-suggestions-height])] (anim/start (anim/spring anim-value {:toValue height - :speed 10 - :bounciness 10}))))) + :speed 1 + :bounciness 0.2}))))) (register-handler :set-chat-command-content (after update-response-suggestions-height!) @@ -109,10 +114,33 @@ :handler (:handler command)}] (commands/stage-command db command-info)))) +(register-handler :finish-show-response! + (fn [db _] + (assoc-in db [:animations :commands-input-is-switching?] false))) + +(defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale + offset-anim-value :message-input-offset} :animations}] + (let [to-value 0.1 + delta 0.02] + (anim/add-listener scale-anim-value + (fn [val] + (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) + (anim/remove-all-listeners scale-anim-value) + (dispatch [:finish-show-response!])))) + (anim/start (anim/timing scale-anim-value {:toValue to-value + :duration response-input-hiding-duration})) + (anim/start (anim/timing offset-anim-value {:toValue -40 + :duration response-input-hiding-duration})))) + +(defn set-reponse-chat-command [db [_ to-msg-id command-key]] + (-> db + (commands/set-response-chat-command to-msg-id command-key) + (assoc-in [:animations :commands-input-is-switching?] true))) + (register-handler :set-response-chat-command - (after update-response-suggestions-height!) - (fn [db [_ to-msg-id command-key]] - (commands/set-response-chat-command db to-msg-id command-key))) + (-> set-reponse-chat-command + ((after animate-show-response!)) + ((after update-response-suggestions-height!)))) (defn update-text [db [_ text]] diff --git a/src/status_im/chat/styles/plain_input.cljs b/src/status_im/chat/styles/plain_input.cljs index b8806518dd..dc2883a7f2 100644 --- a/src/status_im/chat/styles/plain_input.cljs +++ b/src/status_im/chat/styles/plain_input.cljs @@ -12,12 +12,20 @@ :height 56 :backgroundColor color-white}) -(def switch-commands-touchable +(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}) @@ -35,9 +43,7 @@ :color text2-color}) (def smile-icon - {:marginTop 18 - :marginRight 18 - :width 20 + {:width 20 :height 20}) (def send-icon diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index 8849708630..a9293b78c5 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -81,10 +81,11 @@ :height 12}) (def command-input - {:flex 1 - :marginLeft 16 - :marginTop -2 - :padding 0 - :fontSize 14 - :fontFamily font - :color text1-color}) + {:flex 1 + :marginLeft 56 + :marginRight 16 + :marginTop -2 + :padding 0 + :fontSize 14 + :fontFamily font + :color text1-color}) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index ae391edb4f..94b9144f9a 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -2,6 +2,7 @@ (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view + animated-view icon touchable-highlight text-input @@ -31,67 +32,92 @@ (when (message-valid? staged-commands message) (send dismiss-keyboard))) -(defn plain-message-input-view [{:keys [input-options validator]}] - (let [input-message (subscribe [:get-chat-input-text]) - command (subscribe [:get-chat-command]) - to-msg-id (subscribe [:get-chat-command-to-msg-id]) - input-command (subscribe [:get-chat-command-content]) - staged-commands (subscribe [:get-chat-staged-commands]) - typing-command? (subscribe [:typing-command?])] - (fn [{:keys [input-options validator]}] - (let [dismiss-keyboard (not (or command @typing-command?)) - command @command - response? (and command @to-msg-id)] - [view st/input-container - (cond - response? [response/request-view] - command [content-suggestions-view] - :else [suggestions-view]) - [view st/input-view - (if command - (when-not response? - [command/command-icon command response?]) - [touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) - :style st/switch-commands-touchable} - [view nil - (if @typing-command? - [icon :close-gray st/close-icon] - [icon :list st/list-icon])]]) - [text-input (merge {:style (cond - response? st-response/command-input - command st-command/command-input - :else st/message-input) - :autoFocus false - :blurOnSubmit dismiss-keyboard - :onChangeText (fn [text] - ((if command - command/set-input-message - set-input-message) - text)) - :onSubmitEditing (fn [] - (if command - (command/try-send @input-command validator) - (try-send @staged-commands - @input-message - dismiss-keyboard)))} - input-options) - (if command - @input-command - @input-message)] - ;; TODO emoticons: not implemented - (when (not command) - [icon :smile st/smile-icon]) - (if command - (if (command/valid? @input-command validator) - [touchable-highlight {:on-press command/send-command} - [view st/send-container [icon :send st/send-icon]]] - (when-not response? - [touchable-highlight {:on-press command/cancel-command-input} - [view st-command/cancel-container - [icon :close-gray st-command/cancel-icon]]])) - (when (message-valid? @staged-commands @input-message) - [touchable-highlight {:on-press #(try-send @staged-commands - @input-message - dismiss-keyboard)} - [view st/send-container - [icon :send st/send-icon]]]))]])))) +(defview commands-button [animation?] + [typing-command? [:typing-command?] + buttons-scale [:get-in [:animations :message-input-buttons-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])]]) + +(defview smile-button [animation?] + [buttons-scale [:get-in [:animations :message-input-buttons-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)} + [icon :smile st/smile-icon]]]) + +(defview message-input-container [input] + [message-input-offset [:get-in [:animations :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?] + response-input-is-hiding? [:get-in [:animations :response-input-is-hiding?]] + 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) response-input-is-hiding? commands-button-is-switching?) + animation? (or response-input-is-hiding? commands-button-is-switching?)] + [view st/input-container + (cond + response? [response/request-view] + command [content-suggestions-view] + :else [suggestions-view]) + [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) + :autoFocus false + :blurOnSubmit dismiss-keyboard + :onChangeText (fn [text] + ((if message-input? + set-input-message + command/set-input-message) + text)) + :editable (not animation?) + :onSubmitEditing #(if message-input? + (try-send staged-commands + input-message + dismiss-keyboard) + (command/try-send input-command validator))} + 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)} + [view st/send-container + [icon :send st/send-icon]]]) + (if (command/valid? input-command validator) + [touchable-highlight {:disabled animation? + :on-press command/send-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/constants.cljs b/src/status_im/constants.cljs index ec1ba801e2..556f9b7898 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -13,5 +13,5 @@ (def max-chat-name-length 20) -(def response-input-hiding-duration 200) +(def response-input-hiding-duration 300) (def response-suggesstion-resize-duration 100) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index f38d4f870f..2ffdc70d88 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -33,8 +33,11 @@ :current-tag nil :disable-group-creation false :animations {;; mutable data - :response-suggestions-height (anim/create-value 0) - :response-input-is-hiding? false}}) + :message-input-offset (anim/create-value 0) + :message-input-buttons-scale (anim/create-value 1) + :commands-input-is-switching? false + :response-suggestions-height (anim/create-value 0) + :response-input-is-hiding? false}}) (def protocol-initialized-path [:protocol-initialized]) (defn chat-input-text-path [chat-id] From 547c73d130fc960cca6e17e91e1a1337eb7dd676 Mon Sep 17 00:00:00 2001 From: virvar Date: Wed, 1 Jun 2016 16:36:43 +0300 Subject: [PATCH 13/25] Start response suggestions dragging --- src/status_im/chat/handlers.cljs | 22 +++++++++++++++++++--- src/status_im/chat/views/response.cljs | 10 ++++++++-- src/status_im/components/animation.cljs | 15 +++++++++++++++ src/status_im/components/drag_drop.cljs | 12 ++++++++++++ src/status_im/components/react.cljs | 1 + src/status_im/db.cljs | 2 ++ 6 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/status_im/components/drag_drop.cljs diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 8169e91b67..481e5372fc 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -2,6 +2,7 @@ (:require [re-frame.core :refer [register-handler enrich after debug dispatch]] [status-im.models.commands :as commands] [clojure.string :as str] + [status-im.components.drag-drop :as drag] [status-im.components.animation :as anim] [status-im.components.styles :refer [default-chat-color]] [status-im.chat.styles.response :as response-styles] @@ -132,13 +133,13 @@ (anim/start (anim/timing offset-anim-value {:toValue -40 :duration response-input-hiding-duration})))) -(defn set-reponse-chat-command [db [_ to-msg-id command-key]] +(defn set-response-chat-command [db [_ to-msg-id command-key]] (-> db (commands/set-response-chat-command to-msg-id command-key) (assoc-in [:animations :commands-input-is-switching?] true))) (register-handler :set-response-chat-command - (-> set-reponse-chat-command + (-> set-response-chat-command ((after animate-show-response!)) ((after update-response-suggestions-height!)))) @@ -328,10 +329,25 @@ messages/get-messages (assoc db :messages)))) +(defn create-response-pan-responder [pan] + (drag/create-pan-responder + {:on-move (anim/event {:dy (anim/y pan)}) + :on-release (fn [e gesture] + (anim/start (anim/spring pan + {:toValue {:x 0, :y 0}})))})) + +(defn init-response-dragging [db] + (let [pan (anim/create-value-xy 0 0)] + (-> db + (assoc-in [:animations :response-pan] pan) + (assoc-in [:animations :response-pan-responder] (create-response-pan-responder pan))))) + (defn init-chat ([db] (init-chat db nil)) ([{:keys [messages current-chat-id] :as db} _] - (assoc-in db [:chats current-chat-id :messages] messages))) + (-> db + (assoc-in [:chats current-chat-id :messages] messages) + (init-response-dragging)))) (register-handler :init-chat (-> load-messages! diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 27c997317b..4dd39ab9e9 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -8,6 +8,8 @@ text text-input touchable-highlight]] + [status-im.components.animation :as anim] + [status-im.components.drag-drop :as drag] [status-im.chat.views.response-suggestions :refer [response-suggestions-view]] [status-im.chat.styles.response :as st])) @@ -44,7 +46,11 @@ [icon :close-white st/cancel-icon]]]]]) (defview request-view [] - [height [:get-in [:animations :response-suggestions-height]]] - [animated-view {:style (st/request-view height)} + [height [:get-in [:animations :response-suggestions-height]] + pan-responder [:get-in [:animations :response-pan-responder]] + pan [:get-in [:animations :response-pan]]] + [animated-view (merge (drag/pan-handlers pan-responder) + {:style (merge (anim/get-layout pan) + (st/request-view height))}) [request-info] [response-suggestions-view]]) diff --git a/src/status_im/components/animation.cljs b/src/status_im/components/animation.cljs index 2ccc4fc216..dac71685fd 100644 --- a/src/status_im/components/animation.cljs +++ b/src/status_im/components/animation.cljs @@ -10,6 +10,9 @@ (defn spring [anim-value config] (.spring animated anim-value (clj->js config))) +(defn event [config] + (.event animated (clj->js [nil, config]))) + (defn add-listener [anim-value listener] (.addListener anim-value listener)) @@ -27,3 +30,15 @@ (defn create-value [value] (js/React.Animated.Value. value)) + +(defn x [value-xy] + (.-x value-xy)) + +(defn y [value-xy] + (.-y value-xy)) + +(defn get-layout [value-xy] + (js->clj (.getLayout value-xy))) + +(defn create-value-xy [x y] + (js/React.Animated.ValueXY. (clj->js {:x x, :y y}))) diff --git a/src/status_im/components/drag_drop.cljs b/src/status_im/components/drag_drop.cljs new file mode 100644 index 0000000000..708efdfb12 --- /dev/null +++ b/src/status_im/components/drag_drop.cljs @@ -0,0 +1,12 @@ +(ns status-im.components.drag-drop + (:require [status-im.components.react :refer [animated pan-responder]] + [status-im.components.animation :as anim])) + +(defn pan-handlers [pan-responder] + (js->clj (.-panHandlers pan-responder))) + +(defn create-pan-responder [{:keys [on-move on-release]}] + (.create pan-responder + (clj->js {:onStartShouldSetPanResponder (fn [] true) + :onPanResponderMove on-move + :onPanResponderRelease on-release}))) diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index 0f16a6d82b..1967c91801 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -34,6 +34,7 @@ (def picker (r/adapt-react-class (.-Picker js/React))) (def picker-item (r/adapt-react-class (.-Item (.-Picker js/React)))) +(def pan-responder (.-PanResponder js/React)) (def animated (.-Animated js/React)) (def animated-view (r/adapt-react-class (.-View animated))) (def animated-text (r/adapt-react-class (.-Text animated))) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index 2ffdc70d88..af852299af 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -33,6 +33,8 @@ :current-tag nil :disable-group-creation false :animations {;; mutable data + :response-pan nil + :response-pan-responder nil :message-input-offset (anim/create-value 0) :message-input-buttons-scale (anim/create-value 1) :commands-input-is-switching? false From cad5cbaf10aaf835a4cb321993930c7a943be8c9 Mon Sep 17 00:00:00 2001 From: virvar Date: Thu, 2 Jun 2016 15:53:13 +0300 Subject: [PATCH 14/25] Response suggestions dragging (minimize/maximize) --- src/status_im/chat/handlers.cljs | 83 ++++++++++++++----- src/status_im/chat/screen.cljs | 11 ++- .../chat/styles/content_suggestions.cljs | 3 + src/status_im/chat/styles/response.cljs | 31 ++++--- .../chat/styles/response_suggestions.cljs | 2 +- src/status_im/chat/styles/suggestions.cljs | 3 + .../chat/views/content_suggestions.cljs | 2 +- src/status_im/chat/views/plain_input.cljs | 11 +-- src/status_im/chat/views/response.cljs | 34 ++++---- src/status_im/chat/views/suggestions.cljs | 2 +- src/status_im/components/react.cljs | 3 + src/status_im/db.cljs | 7 +- 12 files changed, 128 insertions(+), 64 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 481e5372fc..2f1fd3288c 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -46,23 +46,23 @@ (register-handler :cancel-command (fn [{:keys [current-chat-id] :as db} _] (-> db - (assoc-in [:animations :response-input-is-hiding?] false) + (assoc-in [:animations :commands-input-is-switching?] false) (assoc-in [:chats current-chat-id :command-input] {}) (update-in [:chats current-chat-id :input-text] safe-trim)))) -(defn animate-cancel-command! [{{:keys [response-suggestions-height +(defn animate-cancel-command! [{{:keys [response-height-anim-value message-input-buttons-scale message-input-offset]} :animations}] (let [height-to-value 1] - (anim/add-listener response-suggestions-height + (anim/add-listener response-height-anim-value (fn [val] (when (<= (- height-to-value delta) (anim/value val) (+ height-to-value delta)) - (anim/remove-all-listeners response-suggestions-height) + (anim/remove-all-listeners response-height-anim-value) (dispatch [:cancel-command])))) - (anim/start (anim/spring response-suggestions-height {:toValue height-to-value - :velocity 1 - :tension 1 - :friction 5})) + (anim/start (anim/spring response-height-anim-value {:toValue height-to-value + :velocity 1 + :tension 1 + :friction 5})) (anim/start (anim/timing message-input-buttons-scale {:toValue 1 :duration response-input-hiding-duration})) (anim/start (anim/timing message-input-offset {:toValue 0 @@ -71,14 +71,13 @@ (register-handler :start-cancel-command (after animate-cancel-command!) (fn [db _] - (let [hiding? (get-in db [:animations :response-input-is-hiding?])] + (let [hiding? (get-in db [:animations :commands-input-is-switching?])] (if-not hiding? - (assoc-in db [:animations :response-input-is-hiding?] true) + (assoc-in db [:animations :commands-input-is-switching?] true) db)))) (defn update-response-suggestions-height! [db] - (when (and (not (get-in db [:animations :response-input-is-hiding?])) - (commands/get-chat-command-to-msg-id db)) + (when (commands/get-chat-command-to-msg-id db) (let [command (commands/get-chat-command db) text (commands/get-chat-command-content db) suggestions (get-content-suggestions command text) @@ -88,7 +87,7 @@ response-suggestions-styles/suggestion-height) suggestions))) height (+ suggestions-height response-styles/request-info-height) - anim-value (get-in db [:animations :response-suggestions-height])] + anim-value (get-in db [:animations :response-height-anim-value])] (anim/start (anim/spring anim-value {:toValue height :speed 1 @@ -329,18 +328,62 @@ messages/get-messages (assoc db :messages)))) -(defn create-response-pan-responder [pan] +(register-handler :set-response-max-height + (fn [db [_ height]] + (assoc-in db [:animations :response-height-max] height))) + +(register-handler :on-drag-response + (fn [db [_ dy]] + (let [fixed (get-in db [:animations :response-height-fixed])] + (assoc-in db [:animations :response-height] (- fixed dy))))) + +(register-handler :finish-animate-fix-response-height! + (fn [db _] + (let [fixed (get-in db [:animations :response-height-fixed])] + (-> db + (assoc-in [:animations :response-height] fixed) + (assoc-in [:animations :response-resize?] false))))) + +(defn animate-fix-response-height! [{{height-anim-value :response-height-anim-value + from :response-height + to :response-height-fixed} :animations}] + (let [delta 5] + (anim/set-value height-anim-value from) + (anim/add-listener height-anim-value + (fn [val] + (when (<= (- to delta) (anim/value val) (+ to delta)) + (anim/remove-all-listeners height-anim-value) + (dispatch [:finish-animate-fix-response-height!])))) + (anim/start (anim/spring height-anim-value {:toValue to})))) + +(register-handler :fix-response-height + (after animate-fix-response-height!) + (fn [db _] + (let [current (get-in db [:animations :response-height]) + normal-height response-styles/response-height-normal + max-height (get-in db [:animations :response-height-max]) + delta (/ normal-height 2) + new-fixed (cond + (<= current delta) response-styles/request-info-height + (<= current (+ normal-height delta)) normal-height + :else max-height)] + (-> db + (assoc-in [:animations :response-height-fixed] new-fixed) + (assoc-in [:animations :response-resize?] true))))) + +(defn create-response-pan-responder [] (drag/create-pan-responder - {:on-move (anim/event {:dy (anim/y pan)}) + {:on-move (fn [e gesture] + (dispatch [:on-drag-response (.-dy gesture)])) :on-release (fn [e gesture] - (anim/start (anim/spring pan - {:toValue {:x 0, :y 0}})))})) + (dispatch [:fix-response-height]))})) (defn init-response-dragging [db] - (let [pan (anim/create-value-xy 0 0)] + (let [height response-suggestions-styles/max-suggestions-height] (-> db - (assoc-in [:animations :response-pan] pan) - (assoc-in [:animations :response-pan-responder] (create-response-pan-responder pan))))) + (assoc-in [:animations :response-height-fixed] height) + (assoc-in [:animations :response-height] height) + (assoc-in [:animations :response-pan-responder] (create-response-pan-responder))))) (defn init-chat ([db] (init-chat db nil)) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 2ed10ba018..a43f16763c 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -17,6 +17,9 @@ [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.content-suggestions :refer [content-suggestions-view]] + [status-im.chat.views.suggestions :refer [suggestions-view]] + [status-im.chat.views.response :refer [request-view]] [status-im.chat.views.new-message :refer [chat-message-new]])) @@ -229,10 +232,16 @@ (defview chat [] [group-chat [:chat :group-chat] - show-actions-atom [:show-actions]] + show-actions-atom [:show-actions] + command [:get-chat-command] + to-msg-id [:get-chat-command-to-msg-id]] [view st/chat-view [chat-toolbar] [messages-view group-chat] (when group-chat [typing-all]) + (cond + (and command to-msg-id) [request-view] + command [content-suggestions-view] + :else [suggestions-view]) [chat-message-new] (when show-actions-atom [actions-view])]) diff --git a/src/status_im/chat/styles/content_suggestions.cljs b/src/status_im/chat/styles/content_suggestions.cljs index 198468a549..47ee5fc1fb 100644 --- a/src/status_im/chat/styles/content_suggestions.cljs +++ b/src/status_im/chat/styles/content_suggestions.cljs @@ -44,6 +44,9 @@ :backgroundColor color-white :borderRadius 5}) +(def container + {:backgroundColor color-white}) + (def drag-down-touchable {:height 22 :alignItems :center diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index a9293b78c5..7125ee4f03 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -7,21 +7,16 @@ chat-background color-black]])) +(def response-height-normal 211) (def request-info-height 61) -(def drag-touchable - {:height 16 - :alignItems :center}) - (def drag-container - {:width 16 - :height 16}) + {:height 16 + :alignItems :center + :justifyContent :center}) (def drag-icon - {:position :absolute - :top 6.5 - :left 1 - :width 14 + {:width 14 :height 3}) (def command-icon-container @@ -55,9 +50,21 @@ :opacity 0.69 :color color-white}) +(def container + {:flexDirection :column + :justifyContent :flex-end + :position :absolute + :left 0 + :right 0 + :top 0 + :bottom 56 + :backgroundColor :transparent + :elevation 2}) + (defn request-view [height] - {:flexDirection :column - :height height}) + {:flexDirection :column + :height height + :backgroundColor color-white}) (defn request-info [color] {:flexDirection :column diff --git a/src/status_im/chat/styles/response_suggestions.cljs b/src/status_im/chat/styles/response_suggestions.cljs index e039264a06..f17a095863 100644 --- a/src/status_im/chat/styles/response_suggestions.cljs +++ b/src/status_im/chat/styles/response_suggestions.cljs @@ -31,7 +31,7 @@ (def suggestion-container {:flexDirection :column :paddingLeft 16 - :height 56 + :height suggestion-height :backgroundColor color-white}) (def suggestion-sub-container diff --git a/src/status_im/chat/styles/suggestions.cljs b/src/status_im/chat/styles/suggestions.cljs index 2d5eaaab8e..0c35347f79 100644 --- a/src/status_im/chat/styles/suggestions.cljs +++ b/src/status_im/chat/styles/suggestions.cljs @@ -59,6 +59,9 @@ :backgroundColor color-white :borderRadius 5}) +(def container + {:backgroundColor color-white}) + (def drag-down-touchable {:height 22 :alignItems :center diff --git a/src/status_im/chat/views/content_suggestions.cljs b/src/status_im/chat/views/content_suggestions.cljs index e200aee8db..4dfefe2cf4 100644 --- a/src/status_im/chat/views/content_suggestions.cljs +++ b/src/status_im/chat/views/content_suggestions.cljs @@ -26,7 +26,7 @@ (defview content-suggestions-view [] [suggestions [:get-content-suggestions]] (when-let [values (not-empty (filter :value suggestions))] - [view + [view st/container [touchable-highlight {:style st/drag-down-touchable ;; TODO hide suggestions? :onPress (fn [])} diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index 94b9144f9a..509e961456 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -7,8 +7,6 @@ touchable-highlight text-input dismiss-keyboard!]] - [status-im.chat.views.suggestions :refer [suggestions-view]] - [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] [status-im.chat.views.command :as command] [status-im.chat.views.response :as response] [status-im.chat.styles.plain-input :as st] @@ -63,17 +61,12 @@ input-command [:get-chat-command-content] staged-commands [:get-chat-staged-commands] typing-command? [:typing-command?] - response-input-is-hiding? [:get-in [:animations :response-input-is-hiding?]] 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) response-input-is-hiding? commands-button-is-switching?) - animation? (or response-input-is-hiding? commands-button-is-switching?)] + message-input? (or (not command) commands-button-is-switching?) + animation? commands-button-is-switching?] [view st/input-container - (cond - response? [response/request-view] - command [content-suggestions-view] - :else [suggestions-view]) [view st/input-view (if message-input? [commands-button animation?] diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 4dd39ab9e9..8ca97f69ad 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -8,18 +8,13 @@ text text-input touchable-highlight]] - [status-im.components.animation :as anim] [status-im.components.drag-drop :as drag] [status-im.chat.views.response-suggestions :refer [response-suggestions-view]] [status-im.chat.styles.response :as st])) -(defn drag-touchable [] - [touchable-highlight {:style st/drag-touchable - :onPress (fn [] - ;; TODO drag up/down - )} - [view st/drag-container - [icon :drag-white st/drag-icon]]]) +(defn drag-icon [] + [view st/drag-container + [icon :drag-white st/drag-icon]]) (defn command-icon [] [view st/command-icon-container @@ -37,7 +32,7 @@ (defview request-info [] [command [:get-chat-command]] [view (st/request-info (:color command)) - [drag-touchable] + [drag-icon] [view st/inner-container [command-icon nil] [info-container command] @@ -46,11 +41,18 @@ [icon :close-white st/cancel-icon]]]]]) (defview request-view [] - [height [:get-in [:animations :response-suggestions-height]] + [height [:get-in [:animations :response-height-anim-value]] pan-responder [:get-in [:animations :response-pan-responder]] - pan [:get-in [:animations :response-pan]]] - [animated-view (merge (drag/pan-handlers pan-responder) - {:style (merge (anim/get-layout pan) - (st/request-view height))}) - [request-info] - [response-suggestions-view]]) + response-height [:get-in [:animations :response-height]] + commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]] + response-resize? [:get-in [:animations :response-resize?]]] + [view {:style st/container + :onLayout (fn [event] + (let [height (.. event -nativeEvent -layout -height)] + (dispatch [:set-response-max-height height])))} + [animated-view (merge (drag/pan-handlers pan-responder) + {:style (st/request-view (if (or commands-input-is-switching? response-resize?) + height + response-height))}) + [request-info] + [response-suggestions-view]]]) diff --git a/src/status_im/chat/views/suggestions.cljs b/src/status_im/chat/views/suggestions.cljs index 157c23b74e..e0f261542a 100644 --- a/src/status_im/chat/views/suggestions.cljs +++ b/src/status_im/chat/views/suggestions.cljs @@ -33,7 +33,7 @@ (fn [] (let [suggestions @suggestions-atom] (when (seq suggestions) - [view + [view st/container [touchable-highlight {:style st/drag-down-touchable :onPress (fn [] ;; TODO hide suggestions? diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index 1967c91801..bd534c2ec1 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -39,6 +39,9 @@ (def animated-view (r/adapt-react-class (.-View animated))) (def animated-text (r/adapt-react-class (.-Text animated))) +(def dimensions (.-Dimensions js/React)) +(defn get-dimensions [name] + (js->clj (.get dimensions name) :keywordize-keys true)) (defn icon ([n] (icon n {})) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index af852299af..dbaba99eaf 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -33,13 +33,14 @@ :current-tag nil :disable-group-creation false :animations {;; mutable data - :response-pan nil + :response-height nil + :response-height-fixed nil :response-pan-responder nil :message-input-offset (anim/create-value 0) :message-input-buttons-scale (anim/create-value 1) :commands-input-is-switching? false - :response-suggestions-height (anim/create-value 0) - :response-input-is-hiding? false}}) + :response-height-anim-value (anim/create-value 0) + :response-resize? false}}) (def protocol-initialized-path [:protocol-initialized]) (defn chat-input-text-path [chat-id] From 7f7ab514cab23c0493f3052b82d0e8955ceb443e Mon Sep 17 00:00:00 2001 From: virvar Date: Thu, 2 Jun 2016 16:23:50 +0300 Subject: [PATCH 15/25] Messages animation --- src/status_im/chat/handlers.cljs | 24 +++++++++++++--------- src/status_im/chat/screen.cljs | 29 +++++++++++++++------------ src/status_im/chat/styles/screen.cljs | 4 ++++ src/status_im/db.cljs | 1 + 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 2f1fd3288c..4966dbcadd 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -5,7 +5,7 @@ [status-im.components.drag-drop :as drag] [status-im.components.animation :as anim] [status-im.components.styles :refer [default-chat-color]] - [status-im.chat.styles.response :as response-styles] + [status-im.chat.styles.response :refer [request-info-height response-height-normal]] [status-im.chat.styles.response-suggestions :as response-suggestions-styles] [status-im.chat.suggestions :as suggestions] [status-im.protocol.api :as api] @@ -52,7 +52,8 @@ (defn animate-cancel-command! [{{:keys [response-height-anim-value message-input-buttons-scale - message-input-offset]} :animations}] + message-input-offset + messages-offset-anim-value]} :animations}] (let [height-to-value 1] (anim/add-listener response-height-anim-value (fn [val] @@ -66,7 +67,8 @@ (anim/start (anim/timing message-input-buttons-scale {:toValue 1 :duration response-input-hiding-duration})) (anim/start (anim/timing message-input-offset {:toValue 0 - :duration response-input-hiding-duration})))) + :duration response-input-hiding-duration})) + (anim/start (anim/spring messages-offset-anim-value {:toValue 0})))) (register-handler :start-cancel-command (after animate-cancel-command!) @@ -86,7 +88,7 @@ response-suggestions-styles/header-height response-suggestions-styles/suggestion-height) suggestions))) - height (+ suggestions-height response-styles/request-info-height) + height (+ suggestions-height request-info-height) anim-value (get-in db [:animations :response-height-anim-value])] (anim/start (anim/spring anim-value {:toValue height @@ -118,8 +120,9 @@ (fn [db _] (assoc-in db [:animations :commands-input-is-switching?] false))) -(defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale - offset-anim-value :message-input-offset} :animations}] +(defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale + input-offset-anim-value :message-input-offset + messages-offset-anim-value :messages-offset-anim-value} :animations}] (let [to-value 0.1 delta 0.02] (anim/add-listener scale-anim-value @@ -129,8 +132,9 @@ (dispatch [:finish-show-response!])))) (anim/start (anim/timing scale-anim-value {:toValue to-value :duration response-input-hiding-duration})) - (anim/start (anim/timing offset-anim-value {:toValue -40 - :duration response-input-hiding-duration})))) + (anim/start (anim/timing input-offset-anim-value {:toValue -40 + :duration response-input-hiding-duration})) + (anim/start (anim/spring messages-offset-anim-value {:toValue request-info-height})))) (defn set-response-chat-command [db [_ to-msg-id command-key]] (-> db @@ -360,11 +364,11 @@ (after animate-fix-response-height!) (fn [db _] (let [current (get-in db [:animations :response-height]) - normal-height response-styles/response-height-normal + normal-height response-height-normal max-height (get-in db [:animations :response-height-max]) delta (/ normal-height 2) new-fixed (cond - (<= current delta) response-styles/request-info-height + (<= current delta) request-info-height (<= current (+ normal-height delta)) normal-height :else max-height)] (-> db diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index a43f16763c..9332a6fd28 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -3,12 +3,13 @@ (:require [re-frame.core :refer [subscribe dispatch]] [clojure.string :as s] [status-im.components.react :refer [view - text - image - icon - touchable-highlight - list-view - list-item]] + animated-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] @@ -221,14 +222,16 @@ (defview messages-view [group-chat] [messages [:chat :messages] - contacts [:chat :contacts]] + contacts [:chat :contacts] + messages-offset [:get-in [:animations :messages-offset-anim-value]]] (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 - :keyboardShouldPersistTaps true - :dataSource (to-datasource messages)}])) + [animated-view {:style (st/messages-container messages-offset)} + [list-view {:renderRow (message-row contacts' group-chat) + :renderScrollComponent #(invertible-scroll-view (js->clj %)) + :onEndReached #(dispatch [:load-more-messages]) + :enableEmptySections true + :keyboardShouldPersistTaps true + :dataSource (to-datasource messages)}]])) (defview chat [] [group-chat [:chat :group-chat] diff --git a/src/status_im/chat/styles/screen.cljs b/src/status_im/chat/styles/screen.cljs index 35e4d0b3d7..49133f8d32 100644 --- a/src/status_im/chat/styles/screen.cljs +++ b/src/status_im/chat/styles/screen.cljs @@ -14,6 +14,10 @@ {:flex 1 :backgroundColor chat-background}) +(defn messages-container [bottom] + {:flex 1 + :bottom bottom}) + (def toolbar-view {:flexDirection :row :height 56 diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index dbaba99eaf..2f6a31549d 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -40,6 +40,7 @@ :message-input-buttons-scale (anim/create-value 1) :commands-input-is-switching? false :response-height-anim-value (anim/create-value 0) + :messages-offset-anim-value (anim/create-value 0) :response-resize? false}}) (def protocol-initialized-path [:protocol-initialized]) From 2d62d21b892329807563287bc16dd3a721ef4168 Mon Sep 17 00:00:00 2001 From: virvar Date: Fri, 3 Jun 2016 11:16:38 +0300 Subject: [PATCH 16/25] Response suggestion resize on type --- src/status_im/chat/handlers.cljs | 94 +++++++++---------- .../chat/styles/response_suggestions.cljs | 1 - 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 4966dbcadd..8e7ed1c8df 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -78,29 +78,52 @@ (assoc-in db [:animations :commands-input-is-switching?] true) db)))) -(defn update-response-suggestions-height! [db] +(register-handler :finish-animate-response-resize + (fn [db _] + (let [fixed (get-in db [:animations :response-height-fixed])] + (-> db + (assoc-in [:animations :response-height] fixed) + (assoc-in [:animations :response-resize?] false))))) + +(defn animate-response-resize! [{{height-anim-value :response-height-anim-value + from :response-height + to :response-height-fixed} :animations}] + (let [delta 5] + (anim/set-value height-anim-value from) + (anim/add-listener height-anim-value + (fn [val] + (when (<= (- to delta) (anim/value val) (+ to delta)) + (anim/remove-all-listeners height-anim-value) + (dispatch [:finish-animate-response-resize])))) + (anim/start (anim/spring height-anim-value {:toValue to})))) + +(register-handler :animate-response-resize + (after animate-response-resize!) + (fn [db _] + (assoc-in db [:animations :response-resize?] true))) + +(defn get-response-height [db] (when (commands/get-chat-command-to-msg-id db) (let [command (commands/get-chat-command db) text (commands/get-chat-command-content db) suggestions (get-content-suggestions command text) - suggestions-height (min response-suggestions-styles/max-suggestions-height - (reduce + 0 (map #(if (:header %) - response-suggestions-styles/header-height - response-suggestions-styles/suggestion-height) - suggestions))) - height (+ suggestions-height request-info-height) - anim-value (get-in db [:animations :response-height-anim-value])] - (anim/start - (anim/spring anim-value {:toValue height - :speed 1 - :bounciness 0.2}))))) + suggestions-height (reduce + 0 (map #(if (:header %) + response-suggestions-styles/header-height + response-suggestions-styles/suggestion-height) + suggestions))] + (min response-height-normal (+ suggestions-height request-info-height))))) + +(defn update-response-height [db] + (when (commands/get-chat-command-to-msg-id db) + (assoc-in db [:animations :response-height-fixed] (get-response-height db)))) (register-handler :set-chat-command-content - (after update-response-suggestions-height!) (fn [{:keys [current-chat-id] :as db} [_ content]] + (dispatch [:animate-response-resize]) (-> db (commands/set-chat-command-content content) - (assoc-in [:chats current-chat-id :input-text] nil)))) + (assoc-in [:chats current-chat-id :input-text] nil) + (update-response-height)))) (defn update-input-text [{:keys [current-chat-id] :as db} text] @@ -137,14 +160,16 @@ (anim/start (anim/spring messages-offset-anim-value {:toValue request-info-height})))) (defn set-response-chat-command [db [_ to-msg-id command-key]] + (dispatch [:animate-response-resize]) (-> db (commands/set-response-chat-command to-msg-id command-key) - (assoc-in [:animations :commands-input-is-switching?] true))) + (assoc-in [:animations :commands-input-is-switching?] true) + (assoc-in [:animations :response-height] 0) + (update-response-height))) (register-handler :set-response-chat-command - (-> set-response-chat-command - ((after animate-show-response!)) - ((after update-response-suggestions-height!)))) + (after animate-show-response!) + set-response-chat-command) (defn update-text [db [_ text]] @@ -341,27 +366,7 @@ (let [fixed (get-in db [:animations :response-height-fixed])] (assoc-in db [:animations :response-height] (- fixed dy))))) -(register-handler :finish-animate-fix-response-height! - (fn [db _] - (let [fixed (get-in db [:animations :response-height-fixed])] - (-> db - (assoc-in [:animations :response-height] fixed) - (assoc-in [:animations :response-resize?] false))))) - -(defn animate-fix-response-height! [{{height-anim-value :response-height-anim-value - from :response-height - to :response-height-fixed} :animations}] - (let [delta 5] - (anim/set-value height-anim-value from) - (anim/add-listener height-anim-value - (fn [val] - (when (<= (- to delta) (anim/value val) (+ to delta)) - (anim/remove-all-listeners height-anim-value) - (dispatch [:finish-animate-fix-response-height!])))) - (anim/start (anim/spring height-anim-value {:toValue to})))) - (register-handler :fix-response-height - (after animate-fix-response-height!) (fn [db _] (let [current (get-in db [:animations :response-height]) normal-height response-height-normal @@ -369,11 +374,10 @@ delta (/ normal-height 2) new-fixed (cond (<= current delta) request-info-height - (<= current (+ normal-height delta)) normal-height + (<= current (+ normal-height delta)) (get-response-height db) :else max-height)] - (-> db - (assoc-in [:animations :response-height-fixed] new-fixed) - (assoc-in [:animations :response-resize?] true))))) + (dispatch [:animate-response-resize]) + (assoc-in db [:animations :response-height-fixed] new-fixed)))) (defn create-response-pan-responder [] (drag/create-pan-responder @@ -383,11 +387,7 @@ (dispatch [:fix-response-height]))})) (defn init-response-dragging [db] - (let [height response-suggestions-styles/max-suggestions-height] - (-> db - (assoc-in [:animations :response-height-fixed] height) - (assoc-in [:animations :response-height] height) - (assoc-in [:animations :response-pan-responder] (create-response-pan-responder))))) + (assoc-in db [:animations :response-pan-responder] (create-response-pan-responder))) (defn init-chat ([db] (init-chat db nil)) diff --git a/src/status_im/chat/styles/response_suggestions.cljs b/src/status_im/chat/styles/response_suggestions.cljs index f17a095863..2561f2ae53 100644 --- a/src/status_im/chat/styles/response_suggestions.cljs +++ b/src/status_im/chat/styles/response_suggestions.cljs @@ -13,7 +13,6 @@ text2-color text3-color]])) -(def max-suggestions-height 250) (def header-height 50) (def suggestion-height 56) From 408d9c8b3f27e809eeee96a87bfc7e47cc4c0822 Mon Sep 17 00:00:00 2001 From: virvar Date: Fri, 3 Jun 2016 13:54:17 +0300 Subject: [PATCH 17/25] Move response animation to separate handler --- src/status_im/chat/handlers.cljs | 159 +++------------------ src/status_im/chat/handlers/animation.cljs | 148 +++++++++++++++++++ src/status_im/chat/views/command.cljs | 2 +- src/status_im/chat/views/response.cljs | 6 +- 4 files changed, 172 insertions(+), 143 deletions(-) create mode 100644 src/status_im/chat/handlers/animation.cljs diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 8e7ed1c8df..c291015f26 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -2,17 +2,13 @@ (:require [re-frame.core :refer [register-handler enrich after debug dispatch]] [status-im.models.commands :as commands] [clojure.string :as str] - [status-im.components.drag-drop :as drag] - [status-im.components.animation :as anim] [status-im.components.styles :refer [default-chat-color]] [status-im.chat.styles.response :refer [request-info-height response-height-normal]] - [status-im.chat.styles.response-suggestions :as response-suggestions-styles] [status-im.chat.suggestions :as suggestions] [status-im.protocol.api :as api] [status-im.models.messages :as messages] [status-im.constants :refer [text-content-type - content-type-command - response-input-hiding-duration]] + content-type-command]] [status-im.utils.random :as random] [status-im.chat.sign-up :as sign-up-service] [status-im.models.chats :as chats] @@ -22,7 +18,10 @@ [status-im.handlers.server :as server] [status-im.handlers.content-suggestions :refer [get-content-suggestions]] [status-im.utils.phone-number :refer [format-phone-number]] - [status-im.utils.datetime :as time])) + [status-im.utils.datetime :as time] + [status-im.chat.handlers.animation :refer [update-response-height + get-response-height + init-response-dragging]])) (def delta 1) @@ -46,84 +45,25 @@ (register-handler :cancel-command (fn [{:keys [current-chat-id] :as db} _] (-> db - (assoc-in [:animations :commands-input-is-switching?] false) (assoc-in [:chats current-chat-id :command-input] {}) (update-in [:chats current-chat-id :input-text] safe-trim)))) -(defn animate-cancel-command! [{{:keys [response-height-anim-value - message-input-buttons-scale - message-input-offset - messages-offset-anim-value]} :animations}] - (let [height-to-value 1] - (anim/add-listener response-height-anim-value - (fn [val] - (when (<= (- height-to-value delta) (anim/value val) (+ height-to-value delta)) - (anim/remove-all-listeners response-height-anim-value) - (dispatch [:cancel-command])))) - (anim/start (anim/spring response-height-anim-value {:toValue height-to-value - :velocity 1 - :tension 1 - :friction 5})) - (anim/start (anim/timing message-input-buttons-scale {:toValue 1 - :duration response-input-hiding-duration})) - (anim/start (anim/timing message-input-offset {:toValue 0 - :duration response-input-hiding-duration})) - (anim/start (anim/spring messages-offset-anim-value {:toValue 0})))) - (register-handler :start-cancel-command - (after animate-cancel-command!) (fn [db _] - (let [hiding? (get-in db [:animations :commands-input-is-switching?])] - (if-not hiding? - (assoc-in db [:animations :commands-input-is-switching?] true) - db)))) - -(register-handler :finish-animate-response-resize - (fn [db _] - (let [fixed (get-in db [:animations :response-height-fixed])] - (-> db - (assoc-in [:animations :response-height] fixed) - (assoc-in [:animations :response-resize?] false))))) - -(defn animate-response-resize! [{{height-anim-value :response-height-anim-value - from :response-height - to :response-height-fixed} :animations}] - (let [delta 5] - (anim/set-value height-anim-value from) - (anim/add-listener height-anim-value - (fn [val] - (when (<= (- to delta) (anim/value val) (+ to delta)) - (anim/remove-all-listeners height-anim-value) - (dispatch [:finish-animate-response-resize])))) - (anim/start (anim/spring height-anim-value {:toValue to})))) - -(register-handler :animate-response-resize - (after animate-response-resize!) - (fn [db _] - (assoc-in db [:animations :response-resize?] true))) - -(defn get-response-height [db] - (when (commands/get-chat-command-to-msg-id db) - (let [command (commands/get-chat-command db) - text (commands/get-chat-command-content db) - suggestions (get-content-suggestions command text) - suggestions-height (reduce + 0 (map #(if (:header %) - response-suggestions-styles/header-height - response-suggestions-styles/suggestion-height) - suggestions))] - (min response-height-normal (+ suggestions-height request-info-height))))) - -(defn update-response-height [db] - (when (commands/get-chat-command-to-msg-id db) - (assoc-in db [:animations :response-height-fixed] (get-response-height db)))) + (if (commands/get-chat-command-to-msg-id db) + (dispatch [:animate-cancel-command #(dispatch [:cancel-command])]) + (dispatch [:cancel-command #(dispatch [:cancel-command])])) + db)) (register-handler :set-chat-command-content (fn [{:keys [current-chat-id] :as db} [_ content]] - (dispatch [:animate-response-resize]) - (-> db - (commands/set-chat-command-content content) - (assoc-in [:chats current-chat-id :input-text] nil) - (update-response-height)))) + (as-> db db + (commands/set-chat-command-content db content) + (assoc-in db [:chats current-chat-id :input-text] nil) + (if (commands/get-chat-command-to-msg-id db) + (do (dispatch [:animate-response-resize]) + (update-response-height db)) + db)))) (defn update-input-text [{:keys [current-chat-id] :as db} text] @@ -131,7 +71,7 @@ (register-handler :stage-command (fn [{:keys [current-chat-id] :as db} _] - (let [db (update-input-text db nil) + (let [db (update-input-text db nil) {:keys [command content]} (get-in db [:chats current-chat-id :command-input]) command-info {:command command @@ -139,37 +79,10 @@ :handler (:handler command)}] (commands/stage-command db command-info)))) -(register-handler :finish-show-response! - (fn [db _] - (assoc-in db [:animations :commands-input-is-switching?] false))) - -(defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale - input-offset-anim-value :message-input-offset - messages-offset-anim-value :messages-offset-anim-value} :animations}] - (let [to-value 0.1 - delta 0.02] - (anim/add-listener scale-anim-value - (fn [val] - (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) - (anim/remove-all-listeners scale-anim-value) - (dispatch [:finish-show-response!])))) - (anim/start (anim/timing scale-anim-value {:toValue to-value - :duration response-input-hiding-duration})) - (anim/start (anim/timing input-offset-anim-value {:toValue -40 - :duration response-input-hiding-duration})) - (anim/start (anim/spring messages-offset-anim-value {:toValue request-info-height})))) - -(defn set-response-chat-command [db [_ to-msg-id command-key]] - (dispatch [:animate-response-resize]) - (-> db - (commands/set-response-chat-command to-msg-id command-key) - (assoc-in [:animations :commands-input-is-switching?] true) - (assoc-in [:animations :response-height] 0) - (update-response-height))) - (register-handler :set-response-chat-command - (after animate-show-response!) - set-response-chat-command) + (fn [db [_ to-msg-id command-key]] + (dispatch [:animate-show-response]) + (commands/set-response-chat-command db to-msg-id command-key))) (defn update-text [db [_ text]] @@ -357,38 +270,6 @@ messages/get-messages (assoc db :messages)))) -(register-handler :set-response-max-height - (fn [db [_ height]] - (assoc-in db [:animations :response-height-max] height))) - -(register-handler :on-drag-response - (fn [db [_ dy]] - (let [fixed (get-in db [:animations :response-height-fixed])] - (assoc-in db [:animations :response-height] (- fixed dy))))) - -(register-handler :fix-response-height - (fn [db _] - (let [current (get-in db [:animations :response-height]) - normal-height response-height-normal - max-height (get-in db [:animations :response-height-max]) - delta (/ normal-height 2) - new-fixed (cond - (<= current delta) request-info-height - (<= current (+ normal-height delta)) (get-response-height db) - :else max-height)] - (dispatch [:animate-response-resize]) - (assoc-in db [:animations :response-height-fixed] new-fixed)))) - -(defn create-response-pan-responder [] - (drag/create-pan-responder - {:on-move (fn [e gesture] - (dispatch [:on-drag-response (.-dy gesture)])) - :on-release (fn [e gesture] - (dispatch [:fix-response-height]))})) - -(defn init-response-dragging [db] - (assoc-in db [:animations :response-pan-responder] (create-response-pan-responder))) - (defn init-chat ([db] (init-chat db nil)) ([{:keys [messages current-chat-id] :as db} _] diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs new file mode 100644 index 0000000000..91f72309c1 --- /dev/null +++ b/src/status_im/chat/handlers/animation.cljs @@ -0,0 +1,148 @@ +(ns status-im.chat.handlers.animation + (:require [re-frame.core :refer [register-handler after dispatch]] + [status-im.components.animation :as anim] + [status-im.components.drag-drop :as drag] + [status-im.models.commands :as commands] + [status-im.handlers.content-suggestions :refer [get-content-suggestions]] + [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]])) + +(register-handler :finish-animate-cancel-command + (fn [db _] + (assoc-in db [:animations :commands-input-is-switching?] false))) + +(defn animate-cancel-command! [{{:keys [response-height-anim-value + message-input-buttons-scale + message-input-offset + messages-offset-anim-value]} :animations} + [_ on-animation-stop]] + (let [height-to-value 1 + delta 1] + (anim/add-listener response-height-anim-value + (fn [val] + (when (<= (- height-to-value delta) (anim/value val) (+ height-to-value delta)) + (anim/remove-all-listeners response-height-anim-value) + (dispatch [:finish-animate-cancel-command]) + (on-animation-stop)))) + (anim/start (anim/spring response-height-anim-value {:toValue height-to-value + :velocity 1 + :tension 1 + :friction 5})) + (anim/start (anim/timing message-input-buttons-scale {:toValue 1 + :duration response-input-hiding-duration})) + (anim/start (anim/timing message-input-offset {:toValue 0 + :duration response-input-hiding-duration})) + (anim/start (anim/spring messages-offset-anim-value {:toValue 0})))) + +(register-handler :animate-cancel-command + (after animate-cancel-command!) + (fn [db _] + (let [hiding? (get-in db [:animations :commands-input-is-switching?])] + (if-not hiding? + (assoc-in db [:animations :commands-input-is-switching?] true) + db)))) + +(register-handler :finish-animate-response-resize + (fn [db _] + (let [fixed (get-in db [:animations :response-height-fixed])] + (-> db + (assoc-in [:animations :response-height] fixed) + (assoc-in [:animations :response-resize?] false))))) + +(register-handler :set-response-height + (fn [db [_ value]] + (assoc-in db [:animations :response-height] value))) + +(defn animate-response-resize! [{{height-anim-value :response-height-anim-value + from :response-height + to :response-height-fixed} :animations}] + (let [delta 5] + (anim/remove-all-listeners height-anim-value) + (anim/set-value height-anim-value from) + (anim/add-listener height-anim-value + (fn [val] + (dispatch [:set-response-height (anim/value val)]) + (when (<= (- to delta) (anim/value val) (+ to delta)) + (anim/remove-all-listeners height-anim-value) + (dispatch [:finish-animate-response-resize])))) + (anim/start (anim/spring height-anim-value {:toValue to})))) + +(register-handler :animate-response-resize + (after animate-response-resize!) + (fn [db _] + (assoc-in db [:animations :response-resize?] true))) + +(defn get-response-height [db] + (let [command (commands/get-chat-command db) + text (commands/get-chat-command-content db) + suggestions (get-content-suggestions command text) + suggestions-height (reduce + 0 (map #(if (:header %) + response-suggestions-styles/header-height + response-suggestions-styles/suggestion-height) + suggestions))] + (min response-height-normal (+ suggestions-height request-info-height)))) + +(defn update-response-height [db] + (assoc-in db [:animations :response-height-fixed] (get-response-height db))) + +(register-handler :finish-show-response! + (fn [db _] + (assoc-in db [:animations :commands-input-is-switching?] false))) + +(defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale + input-offset-anim-value :message-input-offset + messages-offset-anim-value :messages-offset-anim-value} :animations}] + (let [to-value 0.1 + delta 0.02] + (anim/add-listener scale-anim-value + (fn [val] + (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) + (anim/remove-all-listeners scale-anim-value) + (dispatch [:finish-show-response!])))) + (anim/start (anim/timing scale-anim-value {:toValue to-value + :duration response-input-hiding-duration})) + (anim/start (anim/timing input-offset-anim-value {:toValue -40 + :duration response-input-hiding-duration})) + (anim/start (anim/spring messages-offset-anim-value {:toValue request-info-height})))) + +(register-handler :animate-show-response + (after animate-show-response!) + (fn [db _] + (dispatch [:animate-response-resize]) + (-> db + (assoc-in [:animations :commands-input-is-switching?] true) + (assoc-in [:animations :response-height] 0) + (update-response-height)))) + +(register-handler :set-response-max-height + (fn [db [_ height]] + (assoc-in db [:animations :response-height-max] height))) + +(register-handler :on-drag-response + (fn [db [_ dy]] + (let [fixed (get-in db [:animations :response-height-fixed])] + (assoc-in db [:animations :response-height] (- fixed dy))))) + +(register-handler :fix-response-height + (fn [db _] + (let [current (get-in db [:animations :response-height]) + normal-height response-height-normal + max-height (get-in db [:animations :response-height-max]) + delta (/ normal-height 2) + new-fixed (cond + (<= current delta) request-info-height + (<= current (+ normal-height delta)) (get-response-height db) + :else max-height)] + (dispatch [:animate-response-resize]) + (assoc-in db [:animations :response-height-fixed] new-fixed)))) + +(defn create-response-pan-responder [] + (drag/create-pan-responder + {:on-move (fn [e gesture] + (dispatch [:on-drag-response (.-dy gesture)])) + :on-release (fn [e gesture] + (dispatch [:fix-response-height]))})) + +(defn init-response-dragging [db] + (assoc-in db [:animations :response-pan-responder] (create-response-pan-responder))) diff --git a/src/status_im/chat/views/command.cljs b/src/status_im/chat/views/command.cljs index b15f08673f..70cd1b5841 100644 --- a/src/status_im/chat/views/command.cljs +++ b/src/status_im/chat/views/command.cljs @@ -8,7 +8,7 @@ [status-im.chat.styles.input :as st])) (defn cancel-command-input [] - (dispatch [:cancel-command])) + (dispatch [:start-cancel-command])) (defn set-input-message [message] (dispatch [:set-chat-command-content message])) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 8ca97f69ad..590b2516f1 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -41,9 +41,9 @@ [icon :close-white st/cancel-icon]]]]]) (defview request-view [] - [height [:get-in [:animations :response-height-anim-value]] - pan-responder [:get-in [:animations :response-pan-responder]] + [pan-responder [:get-in [:animations :response-pan-responder]] response-height [:get-in [:animations :response-height]] + anim-height [:get-in [:animations :response-height-anim-value]] commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]] response-resize? [:get-in [:animations :response-resize?]]] [view {:style st/container @@ -52,7 +52,7 @@ (dispatch [:set-response-max-height height])))} [animated-view (merge (drag/pan-handlers pan-responder) {:style (st/request-view (if (or commands-input-is-switching? response-resize?) - height + anim-height response-height))}) [request-info] [response-suggestions-view]]]) From 06dd295ef5a4a55b6ffb539ed18ae5db86b31c8c Mon Sep 17 00:00:00 2001 From: virvar Date: Fri, 3 Jun 2016 14:09:34 +0300 Subject: [PATCH 18/25] Rename request-view to response-view --- src/status_im/chat/screen.cljs | 4 ++-- src/status_im/chat/styles/response.cljs | 2 +- src/status_im/chat/views/response.cljs | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 9332a6fd28..0f42b33f65 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -20,7 +20,7 @@ [status-im.chat.views.message :refer [chat-message]] [status-im.chat.views.content-suggestions :refer [content-suggestions-view]] [status-im.chat.views.suggestions :refer [suggestions-view]] - [status-im.chat.views.response :refer [request-view]] + [status-im.chat.views.response :refer [response-view]] [status-im.chat.views.new-message :refer [chat-message-new]])) @@ -243,7 +243,7 @@ [messages-view group-chat] (when group-chat [typing-all]) (cond - (and command to-msg-id) [request-view] + (and command to-msg-id) [response-view] command [content-suggestions-view] :else [suggestions-view]) [chat-message-new] diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index 7125ee4f03..1974517bb2 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -61,7 +61,7 @@ :backgroundColor :transparent :elevation 2}) -(defn request-view [height] +(defn response-view [height] {:flexDirection :column :height height :backgroundColor color-white}) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 590b2516f1..848c49e078 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -40,19 +40,19 @@ [view st/cancel-container [icon :close-white st/cancel-icon]]]]]) -(defview request-view [] +(defview response-view [] [pan-responder [:get-in [:animations :response-pan-responder]] response-height [:get-in [:animations :response-height]] anim-height [:get-in [:animations :response-height-anim-value]] commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]] response-resize? [:get-in [:animations :response-resize?]]] - [view {:style st/container + [view {:style st/container :onLayout (fn [event] (let [height (.. event -nativeEvent -layout -height)] (dispatch [:set-response-max-height height])))} [animated-view (merge (drag/pan-handlers pan-responder) - {:style (st/request-view (if (or commands-input-is-switching? response-resize?) - anim-height - response-height))}) + {:style (st/response-view (if (or commands-input-is-switching? response-resize?) + anim-height + response-height))}) [request-info] [response-suggestions-view]]]) From 72bdf34348a164f2b77400f7f0e77e3ba594451e Mon Sep 17 00:00:00 2001 From: virvar Date: Fri, 3 Jun 2016 14:46:32 +0300 Subject: [PATCH 19/25] Replace animation listeners to callbacks. Handle height < 0. --- src/status_im/chat/handlers/animation.cljs | 59 +++++++++------------- src/status_im/chat/styles/plain_input.cljs | 4 +- src/status_im/chat/styles/response.cljs | 8 ++- src/status_im/chat/views/response.cljs | 3 +- src/status_im/components/animation.cljs | 5 +- 5 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index 91f72309c1..8dddfaa967 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -4,10 +4,13 @@ [status-im.components.drag-drop :as drag] [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.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]])) +(def zero-height input-height) + (register-handler :finish-animate-cancel-command (fn [db _] (assoc-in db [:animations :commands-input-is-switching?] false))) @@ -17,18 +20,11 @@ message-input-offset messages-offset-anim-value]} :animations} [_ on-animation-stop]] - (let [height-to-value 1 - delta 1] - (anim/add-listener response-height-anim-value - (fn [val] - (when (<= (- height-to-value delta) (anim/value val) (+ height-to-value delta)) - (anim/remove-all-listeners response-height-anim-value) - (dispatch [:finish-animate-cancel-command]) - (on-animation-stop)))) - (anim/start (anim/spring response-height-anim-value {:toValue height-to-value - :velocity 1 - :tension 1 - :friction 5})) + (let [height-to-value zero-height] + (anim/start (anim/spring response-height-anim-value {:toValue height-to-value}) + (fn [] + (dispatch [:finish-animate-cancel-command]) + (on-animation-stop))) (anim/start (anim/timing message-input-buttons-scale {:toValue 1 :duration response-input-hiding-duration})) (anim/start (anim/timing message-input-offset {:toValue 0 @@ -57,16 +53,15 @@ (defn animate-response-resize! [{{height-anim-value :response-height-anim-value from :response-height to :response-height-fixed} :animations}] - (let [delta 5] - (anim/remove-all-listeners height-anim-value) - (anim/set-value height-anim-value from) - (anim/add-listener height-anim-value - (fn [val] - (dispatch [:set-response-height (anim/value val)]) - (when (<= (- to delta) (anim/value val) (+ to delta)) - (anim/remove-all-listeners height-anim-value) - (dispatch [:finish-animate-response-resize])))) - (anim/start (anim/spring height-anim-value {:toValue to})))) + (anim/remove-all-listeners height-anim-value) + (anim/set-value height-anim-value from) + (anim/add-listener height-anim-value + (fn [val] + (dispatch [:set-response-height (anim/value val)]))) + (anim/start (anim/spring height-anim-value {:toValue to}) + (fn [] + (anim/remove-all-listeners height-anim-value) + (dispatch [:finish-animate-response-resize])))) (register-handler :animate-response-resize (after animate-response-resize!) @@ -81,7 +76,8 @@ response-suggestions-styles/header-height response-suggestions-styles/suggestion-height) suggestions))] - (min response-height-normal (+ suggestions-height request-info-height)))) + (+ zero-height + (min response-height-normal (+ suggestions-height request-info-height))))) (defn update-response-height [db] (assoc-in db [:animations :response-height-fixed] (get-response-height db))) @@ -93,15 +89,10 @@ (defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale input-offset-anim-value :message-input-offset messages-offset-anim-value :messages-offset-anim-value} :animations}] - (let [to-value 0.1 - delta 0.02] - (anim/add-listener scale-anim-value - (fn [val] - (when (<= (- to-value delta) (anim/value val) (+ to-value delta)) - (anim/remove-all-listeners scale-anim-value) - (dispatch [:finish-show-response!])))) + (let [to-value 0.1] (anim/start (anim/timing scale-anim-value {:toValue to-value - :duration response-input-hiding-duration})) + :duration response-input-hiding-duration}) + #(dispatch [:finish-show-response!])) (anim/start (anim/timing input-offset-anim-value {:toValue -40 :duration response-input-hiding-duration})) (anim/start (anim/spring messages-offset-anim-value {:toValue request-info-height})))) @@ -112,7 +103,7 @@ (dispatch [:animate-response-resize]) (-> db (assoc-in [:animations :commands-input-is-switching?] true) - (assoc-in [:animations :response-height] 0) + (assoc-in [:animations :response-height] zero-height) (update-response-height)))) (register-handler :set-response-max-height @@ -131,8 +122,8 @@ max-height (get-in db [:animations :response-height-max]) delta (/ normal-height 2) new-fixed (cond - (<= current delta) request-info-height - (<= current (+ normal-height delta)) (get-response-height db) + (<= current (+ zero-height delta)) (+ zero-height request-info-height) + (<= current (+ zero-height normal-height delta)) (get-response-height db) :else max-height)] (dispatch [:animate-response-resize]) (assoc-in db [:animations :response-height-fixed] new-fixed)))) diff --git a/src/status_im/chat/styles/plain_input.cljs b/src/status_im/chat/styles/plain_input.cljs index dc2883a7f2..da4168fae8 100644 --- a/src/status_im/chat/styles/plain_input.cljs +++ b/src/status_im/chat/styles/plain_input.cljs @@ -4,12 +4,14 @@ color-white color-blue]])) +(def input-height 56) + (def input-container {:flexDirection :column}) (def input-view {:flexDirection :row - :height 56 + :height input-height :backgroundColor color-white}) (def message-input-button-touchable diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index 1974517bb2..c01fb16c95 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -5,7 +5,8 @@ text1-color text2-color chat-background - color-black]])) + color-black]] + [status-im.chat.styles.plain-input :refer [input-height]])) (def response-height-normal 211) (def request-info-height 61) @@ -57,7 +58,7 @@ :left 0 :right 0 :top 0 - :bottom 56 + :bottom 0 :backgroundColor :transparent :elevation 2}) @@ -66,6 +67,9 @@ :height height :backgroundColor color-white}) +(def input-placeholder + {:height input-height}) + (defn request-info [color] {:flexDirection :column :height request-info-height diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 848c49e078..489a08e07f 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -55,4 +55,5 @@ anim-height response-height))}) [request-info] - [response-suggestions-view]]]) + [response-suggestions-view] + [view st/input-placeholder]]]) diff --git a/src/status_im/components/animation.cljs b/src/status_im/components/animation.cljs index dac71685fd..677223b338 100644 --- a/src/status_im/components/animation.cljs +++ b/src/status_im/components/animation.cljs @@ -1,8 +1,9 @@ (ns status-im.components.animation (:require [status-im.components.react :refer [animated]])) -(defn start [anim] - (.start anim)) +(defn start + ([anim] (.start anim)) + ([anim callback] (.start anim callback))) (defn timing [anim-value config] (.timing animated anim-value (clj->js config))) From c229902a77da83919761eb3735bc74c4c6ede8c7 Mon Sep 17 00:00:00 2001 From: virvar Date: Fri, 3 Jun 2016 22:34:24 +0300 Subject: [PATCH 20/25] Move animation to views --- src/status_im/chat/handlers.cljs | 2 +- src/status_im/chat/handlers/animation.cljs | 74 ++++---------- src/status_im/chat/screen.cljs | 53 +++++++--- src/status_im/chat/views/plain_input.cljs | 113 +++++++++++++++++---- src/status_im/chat/views/response.cljs | 68 ++++++++++--- src/status_im/db.cljs | 11 +- 6 files changed, 209 insertions(+), 112 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index d25304749d..abcf1e4393 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -51,7 +51,7 @@ (register-handler :start-cancel-command (fn [db _] (if (commands/get-chat-command-to-msg-id db) - (dispatch [:animate-cancel-command #(dispatch [:cancel-command])]) + (dispatch [:animate-cancel-command]) (dispatch [:cancel-command #(dispatch [:cancel-command])])) db)) diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index 8dddfaa967..900bfb9a19 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -1,6 +1,5 @@ (ns status-im.chat.handlers.animation (:require [re-frame.core :refer [register-handler after dispatch]] - [status-im.components.animation :as anim] [status-im.components.drag-drop :as drag] [status-im.models.commands :as commands] [status-im.handlers.content-suggestions :refer [get-content-suggestions]] @@ -15,56 +14,30 @@ (fn [db _] (assoc-in db [:animations :commands-input-is-switching?] false))) -(defn animate-cancel-command! [{{:keys [response-height-anim-value - message-input-buttons-scale - message-input-offset - messages-offset-anim-value]} :animations} - [_ on-animation-stop]] - (let [height-to-value zero-height] - (anim/start (anim/spring response-height-anim-value {:toValue height-to-value}) - (fn [] - (dispatch [:finish-animate-cancel-command]) - (on-animation-stop))) - (anim/start (anim/timing message-input-buttons-scale {:toValue 1 - :duration response-input-hiding-duration})) - (anim/start (anim/timing message-input-offset {:toValue 0 - :duration response-input-hiding-duration})) - (anim/start (anim/spring messages-offset-anim-value {:toValue 0})))) - (register-handler :animate-cancel-command - (after animate-cancel-command!) (fn [db _] (let [hiding? (get-in db [:animations :commands-input-is-switching?])] (if-not hiding? - (assoc-in db [:animations :commands-input-is-switching?] true) + (-> db + (assoc-in [:animations :commands-input-is-switching?] true) + (assoc-in [:animations :message-input-buttons-scale] 1) + (assoc-in [:animations :message-input-offset] 0) + (assoc-in [:animations :to-response-height] zero-height) + (assoc-in [:animations :messages-offset] 0)) db)))) (register-handler :finish-animate-response-resize (fn [db _] - (let [fixed (get-in db [:animations :response-height-fixed])] + (let [fixed (get-in db [:animations :to-response-height])] (-> db - (assoc-in [:animations :response-height] fixed) + (assoc-in [:animations :response-height-current] fixed) (assoc-in [:animations :response-resize?] false))))) (register-handler :set-response-height (fn [db [_ value]] - (assoc-in db [:animations :response-height] value))) - -(defn animate-response-resize! [{{height-anim-value :response-height-anim-value - from :response-height - to :response-height-fixed} :animations}] - (anim/remove-all-listeners height-anim-value) - (anim/set-value height-anim-value from) - (anim/add-listener height-anim-value - (fn [val] - (dispatch [:set-response-height (anim/value val)]))) - (anim/start (anim/spring height-anim-value {:toValue to}) - (fn [] - (anim/remove-all-listeners height-anim-value) - (dispatch [:finish-animate-response-resize])))) + (assoc-in db [:animations :response-height-current] value))) (register-handler :animate-response-resize - (after animate-response-resize!) (fn [db _] (assoc-in db [:animations :response-resize?] true))) @@ -80,30 +53,21 @@ (min response-height-normal (+ suggestions-height request-info-height))))) (defn update-response-height [db] - (assoc-in db [:animations :response-height-fixed] (get-response-height db))) + (assoc-in db [:animations :to-response-height] (get-response-height db))) -(register-handler :finish-show-response! +(register-handler :finish-show-response (fn [db _] (assoc-in db [:animations :commands-input-is-switching?] false))) -(defn animate-show-response! [{{scale-anim-value :message-input-buttons-scale - input-offset-anim-value :message-input-offset - messages-offset-anim-value :messages-offset-anim-value} :animations}] - (let [to-value 0.1] - (anim/start (anim/timing scale-anim-value {:toValue to-value - :duration response-input-hiding-duration}) - #(dispatch [:finish-show-response!])) - (anim/start (anim/timing input-offset-anim-value {:toValue -40 - :duration response-input-hiding-duration})) - (anim/start (anim/spring messages-offset-anim-value {:toValue request-info-height})))) - (register-handler :animate-show-response - (after animate-show-response!) (fn [db _] (dispatch [:animate-response-resize]) (-> db (assoc-in [:animations :commands-input-is-switching?] true) - (assoc-in [:animations :response-height] zero-height) + (assoc-in [:animations :response-height-current] zero-height) + (assoc-in [:animations :message-input-buttons-scale] 0.1) + (assoc-in [:animations :message-input-offset] -40) + (assoc-in [:animations :messages-offset] request-info-height) (update-response-height)))) (register-handler :set-response-max-height @@ -112,12 +76,12 @@ (register-handler :on-drag-response (fn [db [_ dy]] - (let [fixed (get-in db [:animations :response-height-fixed])] - (assoc-in db [:animations :response-height] (- fixed dy))))) + (let [fixed (get-in db [:animations :to-response-height])] + (assoc-in db [:animations :response-height-current] (- fixed dy))))) (register-handler :fix-response-height (fn [db _] - (let [current (get-in db [:animations :response-height]) + (let [current (get-in db [:animations :response-height-current]) normal-height response-height-normal max-height (get-in db [:animations :response-height-max]) delta (/ normal-height 2) @@ -126,7 +90,7 @@ (<= current (+ zero-height normal-height delta)) (get-response-height db) :else max-height)] (dispatch [:animate-response-resize]) - (assoc-in db [:animations :response-height-fixed] new-fixed)))) + (assoc-in db [:animations :to-response-height] new-fixed)))) (defn create-response-pan-responder [] (drag/create-pan-responder diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 10e5bd3754..7b921803bc 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -22,7 +22,9 @@ [status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.response :refer [response-view]] [status-im.chat.views.new-message :refer [chat-message-new]] - [status-im.i18n :refer [label label-pluralize]])) + [status-im.i18n :refer [label label-pluralize]] + [status-im.components.animation :as anim] + [reagent.core :as r])) (defn contacts-by-identity [contacts] @@ -217,17 +219,41 @@ :custom-action [toolbar-action]}]))) (defview messages-view [group-chat] - [messages [:chat :messages] - contacts [:chat :contacts] - messages-offset [:get-in [:animations :messages-offset-anim-value]]] - (let [contacts' (contacts-by-identity contacts)] - [animated-view {:style (st/messages-container messages-offset)} - [list-view {:renderRow (message-row contacts' group-chat) - :renderScrollComponent #(invertible-scroll-view (js->clj %)) - :onEndReached #(dispatch [:load-more-messages]) - :enableEmptySections true - :keyboardShouldPersistTaps true - :dataSource (to-datasource messages)}]])) + [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 + :keyboardShouldPersistTaps true + :dataSource (to-datasource messages)}])) + +(defn messages-container-animation-logic [{:keys [to-value val]}] + (fn [_] + (let [to-value @to-value] + (anim/start (anim/spring val {:toValue to-value}) + (fn [arg] + (when (.-finished arg) + (dispatch [:set-in [:animations ::messages-offset-current] to-value]))))))) + +(defn messages-container [messages] + (let [to-messages-offset (subscribe [:get-in [:animations :messages-offset]]) + cur-messages-offset (subscribe [:get-in [:animations ::messages-offset-current]]) + messages-offset (anim/create-value (or @cur-messages-offset 0)) + context {:to-value to-messages-offset + :val messages-offset} + on-update (messages-container-animation-logic context)] + (r/create-class + {:component-did-mount + on-update + :component-did-update + on-update + :reagent-render + (fn [messages] + @to-messages-offset + [animated-view {:style (st/messages-container messages-offset)} + messages])}))) (defview chat [] [group-chat [:chat :group-chat] @@ -236,7 +262,8 @@ to-msg-id [:get-chat-command-to-msg-id]] [view st/chat-view [chat-toolbar] - [messages-view group-chat] + [messages-container + [messages-view group-chat]] (when group-chat [typing-all]) (cond (and command to-msg-id) [response-view] diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index 9c03cf12a9..b92c7f6521 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -1,17 +1,20 @@ (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.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])) @@ -30,29 +33,95 @@ (when (message-valid? staged-commands message) (send dismiss-keyboard))) -(defview commands-button [animation?] - [typing-command? [:typing-command?] - buttons-scale [:get-in [:animations :message-input-buttons-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 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])))))))) -(defview smile-button [animation?] - [buttons-scale [:get-in [:animations :message-input-buttons-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)} - [icon :smile st/smile-icon]]]) +(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])]]))}))) -(defview message-input-container [input] - [message-input-offset [:get-in [:animations :message-input-offset]]] - [animated-view {:style (st/message-input-container message-input-offset)} - input]) +(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] diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 489a08e07f..37bc12385a 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -1,6 +1,8 @@ (ns status-im.chat.views.response - (:require-macros [status-im.utils.views :refer [defview]]) + (:require-macros [reagent.ratom :refer [reaction]] + [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 @@ -10,7 +12,9 @@ touchable-highlight]] [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.response :as st] + [status-im.chat.styles.plain-input :refer [input-height]] + [status-im.components.animation :as anim])) (defn drag-icon [] [view st/drag-container @@ -40,20 +44,54 @@ [view st/cancel-container [icon :close-white st/cancel-icon]]]]]) -(defview response-view [] - [pan-responder [:get-in [:animations :response-pan-responder]] - response-height [:get-in [:animations :response-height]] - anim-height [:get-in [:animations :response-height-anim-value]] - commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]] - response-resize? [:get-in [:animations :response-resize?]]] +(defn inner-container-animation-logic [{:keys [animation? to-value current-value val]}] + (fn [_] + (if @animation? + (let [to-value @to-value] + (anim/start (anim/spring val {:toValue to-value}) + (fn [arg] + (when (.-finished arg) + (dispatch [:set-in [:animations :response-height-current] to-value]) + (dispatch [:finish-animate-response-resize]) + (when (= to-value input-height) + (dispatch [:finish-animate-cancel-command]) + (dispatch [:cancel-command])))))) + (anim/set-value val @current-value)))) + +(defn inner-container [content] + (let [pan-responder (subscribe [:get-in [:animations :response-pan-responder]]) + commands-input-is-switching? (subscribe [:get-in [:animations :commands-input-is-switching?]]) + response-resize? (subscribe [:get-in [:animations :response-resize?]]) + + to-response-height (subscribe [:get-in [:animations :to-response-height]]) + cur-response-height (subscribe [:get-in [:animations :response-height-current]]) + response-height (anim/create-value (or @cur-response-height 0)) + context {:animation? (reaction (or @commands-input-is-switching? @response-resize?)) + :to-value to-response-height + :current-value cur-response-height + :val response-height} + on-update (inner-container-animation-logic context)] + (r/create-class + {:component-did-mount + on-update + :component-did-update + on-update + :reagent-render + (fn [content] + @to-response-height + [animated-view (merge (drag/pan-handlers @pan-responder) + {:style (st/response-view (if (or @commands-input-is-switching? @response-resize?) + response-height + (or @cur-response-height 0)))}) + content])}))) + +(defn response-view [] [view {:style st/container :onLayout (fn [event] (let [height (.. event -nativeEvent -layout -height)] (dispatch [:set-response-max-height height])))} - [animated-view (merge (drag/pan-handlers pan-responder) - {:style (st/response-view (if (or commands-input-is-switching? response-resize?) - anim-height - response-height))}) - [request-info] - [response-suggestions-view] - [view st/input-placeholder]]]) + [inner-container + [view + [request-info] + [response-suggestions-view] + [view st/input-placeholder]]]]) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index 2f6a31549d..5fa2ad7f22 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -33,14 +33,13 @@ :current-tag nil :disable-group-creation false :animations {;; mutable data - :response-height nil - :response-height-fixed nil + :to-response-height nil + :response-height-current nil :response-pan-responder nil - :message-input-offset (anim/create-value 0) - :message-input-buttons-scale (anim/create-value 1) + :message-input-offset 0 + :message-input-buttons-scale 1 :commands-input-is-switching? false - :response-height-anim-value (anim/create-value 0) - :messages-offset-anim-value (anim/create-value 0) + :messages-offset 0 :response-resize? false}}) (def protocol-initialized-path [:protocol-initialized]) From 161be555b5c7ee827c57065cffc2299ee6311253 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 6 Jun 2016 09:12:55 +0300 Subject: [PATCH 21/25] Move PanResponder to view --- src/status_im/chat/handlers.cljs | 7 ++----- src/status_im/chat/handlers/animation.cljs | 11 ----------- src/status_im/chat/views/response.cljs | 12 +++++++++--- src/status_im/db.cljs | 3 +-- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index abcf1e4393..4af77d29ba 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -20,8 +20,7 @@ [status-im.utils.phone-number :refer [format-phone-number]] [status-im.utils.datetime :as time] [status-im.chat.handlers.animation :refer [update-response-height - get-response-height - init-response-dragging]])) + get-response-height]])) (def delta 1) @@ -273,9 +272,7 @@ (defn init-chat ([db] (init-chat db nil)) ([{:keys [messages current-chat-id] :as db} _] - (-> db - (assoc-in [:chats current-chat-id :messages] messages) - (init-response-dragging)))) + (assoc-in db [:chats current-chat-id :messages] messages))) (register-handler :init-chat (-> load-messages! diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index 900bfb9a19..5f0c918da0 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -1,6 +1,5 @@ (ns status-im.chat.handlers.animation (:require [re-frame.core :refer [register-handler after dispatch]] - [status-im.components.drag-drop :as drag] [status-im.models.commands :as commands] [status-im.handlers.content-suggestions :refer [get-content-suggestions]] [status-im.chat.styles.plain-input :refer [input-height]] @@ -91,13 +90,3 @@ :else max-height)] (dispatch [:animate-response-resize]) (assoc-in db [:animations :to-response-height] new-fixed)))) - -(defn create-response-pan-responder [] - (drag/create-pan-responder - {:on-move (fn [e gesture] - (dispatch [:on-drag-response (.-dy gesture)])) - :on-release (fn [e gesture] - (dispatch [:fix-response-height]))})) - -(defn init-response-dragging [db] - (assoc-in db [:animations :response-pan-responder] (create-response-pan-responder))) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 37bc12385a..e1f1a0f74c 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -58,11 +58,17 @@ (dispatch [:cancel-command])))))) (anim/set-value val @current-value)))) +(defn create-response-pan-responder [] + (drag/create-pan-responder + {:on-move (fn [e gesture] + (dispatch [:on-drag-response (.-dy gesture)])) + :on-release (fn [e gesture] + (dispatch [:fix-response-height]))})) + (defn inner-container [content] - (let [pan-responder (subscribe [:get-in [:animations :response-pan-responder]]) + (let [pan-responder (create-response-pan-responder) commands-input-is-switching? (subscribe [:get-in [:animations :commands-input-is-switching?]]) response-resize? (subscribe [:get-in [:animations :response-resize?]]) - to-response-height (subscribe [:get-in [:animations :to-response-height]]) cur-response-height (subscribe [:get-in [:animations :response-height-current]]) response-height (anim/create-value (or @cur-response-height 0)) @@ -79,7 +85,7 @@ :reagent-render (fn [content] @to-response-height - [animated-view (merge (drag/pan-handlers @pan-responder) + [animated-view (merge (drag/pan-handlers pan-responder) {:style (st/response-view (if (or @commands-input-is-switching? @response-resize?) response-height (or @cur-response-height 0)))}) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index 5fa2ad7f22..c79babb995 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -35,11 +35,10 @@ :animations {;; mutable data :to-response-height nil :response-height-current nil - :response-pan-responder nil :message-input-offset 0 :message-input-buttons-scale 1 - :commands-input-is-switching? false :messages-offset 0 + :commands-input-is-switching? false :response-resize? false}}) (def protocol-initialized-path [:protocol-initialized]) From a7e694cb4689b572a0d6fa8a10091ae5419d4502 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 6 Jun 2016 15:05:35 +0300 Subject: [PATCH 22/25] Fix response suggestions: Fix scrolling messages when response view is shown. Empty suggestions can't be fully opened. Fix UI delays after animation. Code improvements. --- src/status_im/chat/handlers.cljs | 12 ++-- src/status_im/chat/handlers/animation.cljs | 60 ++++++++++++------- src/status_im/chat/screen.cljs | 5 +- src/status_im/chat/styles/response.cljs | 12 +--- src/status_im/chat/views/new_message.cljs | 17 +++--- src/status_im/chat/views/response.cljs | 70 ++++++++++------------ src/status_im/new_group/screen.cljs | 2 +- 7 files changed, 95 insertions(+), 83 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 4af77d29ba..64273fe406 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -48,11 +48,11 @@ (update-in [:chats current-chat-id :input-text] safe-trim)))) (register-handler :start-cancel-command - (fn [db _] - (if (commands/get-chat-command-to-msg-id db) - (dispatch [:animate-cancel-command]) - (dispatch [:cancel-command #(dispatch [:cancel-command])])) - db)) + (u/side-effect! + (fn [db _] + (if (commands/get-chat-command-to-msg-id db) + (dispatch [:animate-cancel-command]) + (dispatch [:cancel-command]))))) (register-handler :set-chat-command-content (fn [{:keys [current-chat-id] :as db} [_ content]] @@ -79,8 +79,8 @@ (commands/stage-command db command-info)))) (register-handler :set-response-chat-command + (after #(dispatch [:animate-show-response])) (fn [db [_ to-msg-id command-key]] - (dispatch [:animate-show-response]) (commands/set-response-chat-command db to-msg-id command-key))) (defn update-text diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index 5f0c918da0..3afb86c24b 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -1,5 +1,6 @@ (ns status-im.chat.handlers.animation (:require [re-frame.core :refer [register-handler after dispatch]] + [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]] @@ -14,16 +15,16 @@ (assoc-in db [:animations :commands-input-is-switching?] false))) (register-handler :animate-cancel-command + (path :animations) (fn [db _] - (let [hiding? (get-in db [:animations :commands-input-is-switching?])] - (if-not hiding? - (-> db - (assoc-in [:animations :commands-input-is-switching?] true) - (assoc-in [:animations :message-input-buttons-scale] 1) - (assoc-in [:animations :message-input-offset] 0) - (assoc-in [:animations :to-response-height] zero-height) - (assoc-in [:animations :messages-offset] 0)) - db)))) + (if-not (:commands-input-is-switching? db) + (assoc db + :commands-input-is-switching? true + :message-input-buttons-scale 1 + :message-input-offset 0 + :to-response-height zero-height + :messages-offset 0) + db))) (register-handler :finish-animate-response-resize (fn [db _] @@ -71,22 +72,39 @@ (register-handler :set-response-max-height (fn [db [_ height]] - (assoc-in db [:animations :response-height-max] height))) + (let [prev-height (get-in db [:animations :response-height-max])] + (if (not= height prev-height) + (let [db (assoc-in db [:animations :response-height-max] height)] + (if (= prev-height (get-in db [:animations :to-response-height])) + (-> db + (assoc-in [:animations :to-response-height] height) + (assoc-in [:animations :response-height-current] height)) + db)) + db)))) (register-handler :on-drag-response (fn [db [_ dy]] (let [fixed (get-in db [:animations :to-response-height])] - (assoc-in db [:animations :response-height-current] (- fixed dy))))) + (-> db + (assoc-in [:animations :response-height-current] (- fixed dy)) + (assoc-in [:animations :response-resize?] false))))) (register-handler :fix-response-height (fn [db _] - (let [current (get-in db [:animations :response-height-current]) - normal-height response-height-normal - max-height (get-in db [:animations :response-height-max]) - delta (/ normal-height 2) - new-fixed (cond - (<= current (+ zero-height delta)) (+ zero-height request-info-height) - (<= current (+ zero-height normal-height delta)) (get-response-height db) - :else max-height)] - (dispatch [:animate-response-resize]) - (assoc-in db [:animations :to-response-height] new-fixed)))) + (if (and (commands/get-chat-command-to-msg-id db) + (not (get-in db [:animations :commands-input-is-switching?]))) + (let [current (get-in db [:animations :response-height-current]) + normal-height response-height-normal + command (commands/get-chat-command db) + text (commands/get-chat-command-content db) + suggestions (get-content-suggestions command text) + max-height (get-in db [:animations :response-height-max]) + delta (/ normal-height 2) + new-fixed (cond + (or (<= current (+ zero-height delta)) + (empty? suggestions)) (+ zero-height request-info-height) + (<= current (+ zero-height normal-height delta)) (get-response-height db) + :else max-height)] + (dispatch [:animate-response-resize]) + (assoc-in db [:animations :to-response-height] new-fixed)) + db))) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 7b921803bc..a2fc957b1e 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -260,7 +260,10 @@ show-actions-atom [:show-actions] command [:get-chat-command] to-msg-id [:get-chat-command-to-msg-id]] - [view st/chat-view + [view {:style st/chat-view + :onLayout (fn [event] + (let [height (.. event -nativeEvent -layout -height)] + (dispatch [:set-response-max-height height])))} [chat-toolbar] [messages-container [messages-view group-chat]] diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index c01fb16c95..c9612e3e35 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -51,21 +51,15 @@ :opacity 0.69 :color color-white}) -(def container +(defn response-view [height] {:flexDirection :column - :justifyContent :flex-end :position :absolute :left 0 :right 0 - :top 0 :bottom 0 - :backgroundColor :transparent - :elevation 2}) - -(defn response-view [height] - {:flexDirection :column :height height - :backgroundColor color-white}) + :backgroundColor color-white + :elevation 2}) (def input-placeholder {:height input-height}) diff --git a/src/status_im/chat/views/new_message.cljs b/src/status_im/chat/views/new_message.cljs index 3f2ec8792a..fa8b5ab74b 100644 --- a/src/status_im/chat/views/new_message.cljs +++ b/src/status_im/chat/views/new_message.cljs @@ -18,14 +18,15 @@ (defn show-input [command] [plain-message-input-view - (case (:command command) - :phone {:input-options {:keyboardType :phone-pad} - :validator valid-mobile-number?} - :keypair-password {:input-options {:secureTextEntry true}} - :confirmation-code {:input-options {:keyboardType :numeric}} - :money {:input-options {:keyboardType :numeric}} - :request {:input-options {:keyboardType :numeric}} - nil)]) + (when command + (case (:command command) + :phone {:input-options {:keyboardType :phone-pad} + :validator valid-mobile-number?} + :keypair-password {:input-options {:secureTextEntry true}} + :confirmation-code {:input-options {:keyboardType :numeric}} + :money {:input-options {:keyboardType :numeric}} + :request {:input-options {:keyboardType :numeric}} + (throw (js/Error. "Uknown command type"))))]) (defn chat-message-new [] (let [command-atom (subscribe [:get-chat-command]) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index e1f1a0f74c..9d2b84a490 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -33,18 +33,28 @@ ;; TODO stub data: request message info "By ???, MMM 1st at HH:mm"]]) -(defview request-info [] - [command [:get-chat-command]] - [view (st/request-info (:color command)) - [drag-icon] - [view st/inner-container - [command-icon nil] - [info-container command] - [touchable-highlight {:on-press #(dispatch [:start-cancel-command])} - [view st/cancel-container - [icon :close-white st/cancel-icon]]]]]) +(defn create-response-pan-responder [] + (drag/create-pan-responder + {:on-move (fn [e gesture] + (dispatch [:on-drag-response (.-dy gesture)])) + :on-release (fn [e gesture] + (dispatch [:fix-response-height]))})) -(defn inner-container-animation-logic [{:keys [animation? to-value current-value val]}] +(defn request-info [] + (let [pan-responder (create-response-pan-responder) + command (subscribe [:get-chat-command])] + (fn [] + [view (merge (drag/pan-handlers pan-responder) + {:style (st/request-info (:color @command))}) + [drag-icon] + [view st/inner-container + [command-icon nil] + [info-container @command] + [touchable-highlight {:on-press #(dispatch [:start-cancel-command])} + [view st/cancel-container + [icon :close-white st/cancel-icon]]]]]))) + +(defn container-animation-logic [{:keys [animation? to-value current-value val]}] (fn [_] (if @animation? (let [to-value @to-value] @@ -58,16 +68,8 @@ (dispatch [:cancel-command])))))) (anim/set-value val @current-value)))) -(defn create-response-pan-responder [] - (drag/create-pan-responder - {:on-move (fn [e gesture] - (dispatch [:on-drag-response (.-dy gesture)])) - :on-release (fn [e gesture] - (dispatch [:fix-response-height]))})) - -(defn inner-container [content] - (let [pan-responder (create-response-pan-responder) - commands-input-is-switching? (subscribe [:get-in [:animations :commands-input-is-switching?]]) +(defn container [& children] + (let [commands-input-is-switching? (subscribe [:get-in [:animations :commands-input-is-switching?]]) response-resize? (subscribe [:get-in [:animations :response-resize?]]) to-response-height (subscribe [:get-in [:animations :to-response-height]]) cur-response-height (subscribe [:get-in [:animations :response-height-current]]) @@ -76,28 +78,22 @@ :to-value to-response-height :current-value cur-response-height :val response-height} - on-update (inner-container-animation-logic context)] + on-update (container-animation-logic context)] (r/create-class {:component-did-mount on-update :component-did-update on-update :reagent-render - (fn [content] + (fn [& children] @to-response-height - [animated-view (merge (drag/pan-handlers pan-responder) - {:style (st/response-view (if (or @commands-input-is-switching? @response-resize?) - response-height - (or @cur-response-height 0)))}) - content])}))) + (into [animated-view {:style (st/response-view (if (or @commands-input-is-switching? @response-resize?) + response-height + (or @cur-response-height 0)))}] + children))}))) (defn response-view [] - [view {:style st/container - :onLayout (fn [event] - (let [height (.. event -nativeEvent -layout -height)] - (dispatch [:set-response-max-height height])))} - [inner-container - [view - [request-info] - [response-suggestions-view] - [view st/input-placeholder]]]]) + [container + [request-info] + [response-suggestions-view] + [view st/input-placeholder]]) diff --git a/src/status_im/new_group/screen.cljs b/src/status_im/new_group/screen.cljs index 97da481782..9e81f77b89 100644 --- a/src/status_im/new_group/screen.cljs +++ b/src/status_im/new_group/screen.cljs @@ -33,7 +33,7 @@ (defview group-name-input [] [group-name [:get :new-chat-name] validation-messages [:new-chat-name-validation-messages]] - [view nil + [view [text-input {:underlineColorAndroid color-purple :style st/group-name-input From df8c7f2fe74f1ad2f0ece88d220944bbb229cfa6 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 6 Jun 2016 17:33:04 +0300 Subject: [PATCH 23/25] Fix keyboard hiding. Focus on input when response view is shown. --- src/status_im/chat/handlers.cljs | 17 ++++++++++++++++ src/status_im/chat/handlers/animation.cljs | 23 +++++++++++----------- src/status_im/chat/views/plain_input.cljs | 23 ++++++++++++---------- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 64273fe406..1ddb552cc0 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -78,6 +78,23 @@ :handler (:handler command)}] (commands/stage-command db command-info)))) +(register-handler :set-message-input [] + (fn [db [_ input]] + (assoc db :message-input input))) + +(register-handler :prepare-message-input + (u/side-effect! + (fn [db _] + (when-let [message-input (:message-input db)] + (.clear message-input) + (.focus message-input))))) + +(register-handler :blur-message-input + (u/side-effect! + (fn [db _] + (when-let [message-input (:message-input db)] + (.blur message-input))))) + (register-handler :set-response-chat-command (after #(dispatch [:animate-show-response])) (fn [db [_ to-msg-id command-key]] diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index 3afb86c24b..b3f540282a 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -15,16 +15,16 @@ (assoc-in db [:animations :commands-input-is-switching?] false))) (register-handler :animate-cancel-command - (path :animations) - (fn [db _] - (if-not (:commands-input-is-switching? db) - (assoc db - :commands-input-is-switching? true - :message-input-buttons-scale 1 - :message-input-offset 0 - :to-response-height zero-height - :messages-offset 0) - db))) + (path :animations) + (fn [db _] + (if-not (:commands-input-is-switching? db) + (assoc db + :commands-input-is-switching? true + :message-input-buttons-scale 1 + :message-input-offset 0 + :to-response-height zero-height + :messages-offset 0) + db))) (register-handler :finish-animate-response-resize (fn [db _] @@ -56,12 +56,13 @@ (assoc-in db [:animations :to-response-height] (get-response-height db))) (register-handler :finish-show-response + (after #(dispatch [:prepare-message-input])) (fn [db _] (assoc-in db [:animations :commands-input-is-switching?] false))) (register-handler :animate-show-response + (after #(dispatch [:animate-response-resize])) (fn [db _] - (dispatch [:animate-response-resize]) (-> db (assoc-in [:animations :commands-input-is-switching?] true) (assoc-in [:animations :response-height-current] zero-height) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs index b92c7f6521..da0e88648d 100644 --- a/src/status_im/chat/views/plain_input.cljs +++ b/src/status_im/chat/views/plain_input.cljs @@ -146,19 +146,22 @@ 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] - ((if message-input? - set-input-message - command/set-input-message) - text)) - :editable (not animation?) - :onSubmitEditing #(if message-input? - (try-send staged-commands - input-message - dismiss-keyboard) - (command/try-send input-command validator))} + (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) From 89051ce50b1ecb78b0b994287d6649097a981585 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 6 Jun 2016 18:47:11 +0300 Subject: [PATCH 24/25] Message input refactoring --- 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 [] From 0ef09b57e857d1e4c27b6eb00cf1d1ed8b002d33 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 6 Jun 2016 18:59:52 +0300 Subject: [PATCH 25/25] Fix message input view --- src/status_im/chat/views/message_input.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/status_im/chat/views/message_input.cljs b/src/status_im/chat/views/message_input.cljs index 0d170c83d3..c8d81a30b6 100644 --- a/src/status_im/chat/views/message_input.cljs +++ b/src/status_im/chat/views/message_input.cljs @@ -53,7 +53,7 @@ [animated-view {:style (st/message-input-container message-input-offset)} input])}))) -(defview message-input [] +(defview message-input [input-options validator] [input-message [:get-chat-input-text] command [:get-chat-command] to-msg-id [:get-chat-command-to-msg-id] @@ -110,7 +110,7 @@ (when (and command (not response?)) [command/command-icon command response?])) [message-input-container - [message-input]] + [message-input input-options validator]] ;; TODO emoticons: not implemented (when message-input? [plain-message/smile-button])