Input text and buttons animation

This commit is contained in:
virvar 2016-06-01 14:09:25 +03:00
parent 5c83b09db6
commit 572fc0e554
6 changed files with 158 additions and 94 deletions

View File

@ -49,23 +49,28 @@
(assoc-in [:chats current-chat-id :command-input] {}) (assoc-in [:chats current-chat-id :command-input] {})
(update-in [:chats current-chat-id :input-text] safe-trim)))) (update-in [:chats current-chat-id :input-text] safe-trim))))
(defn animate-cancel-command! [db] (defn animate-cancel-command! [{{:keys [response-suggestions-height
(let [height-anim-value (get-in db [:animations :response-suggestions-height]) message-input-buttons-scale
to-value 1] message-input-offset]} :animations}]
(anim/add-listener height-anim-value (let [height-to-value 1]
(anim/add-listener response-suggestions-height
(fn [val] (fn [val]
(when (<= (- to-value delta) (anim/value val) (+ to-value delta)) (when (<= (- height-to-value delta) (anim/value val) (+ height-to-value delta))
(anim/remove-all-listeners height-anim-value) (anim/remove-all-listeners response-suggestions-height)
(dispatch [:cancel-command])))) (dispatch [:cancel-command]))))
(anim/start (anim/spring height-anim-value {:toValue to-value (anim/start (anim/spring response-suggestions-height {:toValue height-to-value
:speed 10 :velocity 1
:bounciness 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 (register-handler :start-cancel-command
(after animate-cancel-command!) (after animate-cancel-command!)
(fn [db _] (fn [db _]
(let [current-chat-id (:current-chat-id db) (let [hiding? (get-in db [:animations :response-input-is-hiding?])]
hiding? (get-in db [:animations :response-input-is-hiding?])]
(if-not hiding? (if-not hiding?
(assoc-in db [:animations :response-input-is-hiding?] true) (assoc-in db [:animations :response-input-is-hiding?] true)
db)))) db))))
@ -85,8 +90,8 @@
anim-value (get-in db [:animations :response-suggestions-height])] anim-value (get-in db [:animations :response-suggestions-height])]
(anim/start (anim/start
(anim/spring anim-value {:toValue height (anim/spring anim-value {:toValue height
:speed 10 :speed 1
:bounciness 10}))))) :bounciness 0.2})))))
(register-handler :set-chat-command-content (register-handler :set-chat-command-content
(after update-response-suggestions-height!) (after update-response-suggestions-height!)
@ -109,10 +114,33 @@
:handler (:handler command)}] :handler (:handler command)}]
(commands/stage-command db command-info)))) (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 (register-handler :set-response-chat-command
(after update-response-suggestions-height!) (-> set-reponse-chat-command
(fn [db [_ to-msg-id command-key]] ((after animate-show-response!))
(commands/set-response-chat-command db to-msg-id command-key))) ((after update-response-suggestions-height!))))
(defn update-text (defn update-text
[db [_ text]] [db [_ text]]

View File

@ -12,12 +12,20 @@
:height 56 :height 56
:backgroundColor color-white}) :backgroundColor color-white})
(def switch-commands-touchable (def message-input-button-touchable
{:width 56 {:width 56
:height 56 :height 56
:alignItems :center :alignItems :center
:justifyContent :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 (def list-icon
{:width 13 {:width 13
:height 12}) :height 12})
@ -35,9 +43,7 @@
:color text2-color}) :color text2-color})
(def smile-icon (def smile-icon
{:marginTop 18 {:width 20
:marginRight 18
:width 20
:height 20}) :height 20})
(def send-icon (def send-icon

View File

@ -81,10 +81,11 @@
:height 12}) :height 12})
(def command-input (def command-input
{:flex 1 {:flex 1
:marginLeft 16 :marginLeft 56
:marginTop -2 :marginRight 16
:padding 0 :marginTop -2
:fontSize 14 :padding 0
:fontFamily font :fontSize 14
:color text1-color}) :fontFamily font
:color text1-color})

View File

@ -2,6 +2,7 @@
(:require-macros [status-im.utils.views :refer [defview]]) (:require-macros [status-im.utils.views :refer [defview]])
(:require [re-frame.core :refer [subscribe dispatch]] (:require [re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :refer [view [status-im.components.react :refer [view
animated-view
icon icon
touchable-highlight touchable-highlight
text-input text-input
@ -31,67 +32,92 @@
(when (message-valid? staged-commands message) (when (message-valid? staged-commands message)
(send dismiss-keyboard))) (send dismiss-keyboard)))
(defn plain-message-input-view [{:keys [input-options validator]}] (defview commands-button [animation?]
(let [input-message (subscribe [:get-chat-input-text]) [typing-command? [:typing-command?]
command (subscribe [:get-chat-command]) buttons-scale [:get-in [:animations :message-input-buttons-scale]]]
to-msg-id (subscribe [:get-chat-command-to-msg-id]) [touchable-highlight {:disabled animation?
input-command (subscribe [:get-chat-command-content]) :on-press #(dispatch [:switch-command-suggestions])
staged-commands (subscribe [:get-chat-staged-commands]) :style st/message-input-button-touchable}
typing-command? (subscribe [:typing-command?])] [animated-view {:style (st/message-input-button buttons-scale)}
(fn [{:keys [input-options validator]}] (if typing-command?
(let [dismiss-keyboard (not (or command @typing-command?)) [icon :close-gray st/close-icon]
command @command [icon :list st/list-icon])]])
response? (and command @to-msg-id)]
[view st/input-container (defview smile-button [animation?]
(cond [buttons-scale [:get-in [:animations :message-input-buttons-scale]]]
response? [response/request-view] [touchable-highlight {:disabled animation?
command [content-suggestions-view] :on-press #(dispatch [:switch-command-suggestions])
:else [suggestions-view]) :style st/message-input-button-touchable}
[view st/input-view [animated-view {:style (st/message-input-button buttons-scale)}
(if command [icon :smile st/smile-icon]]])
(when-not response?
[command/command-icon command response?]) (defview message-input-container [input]
[touchable-highlight {:on-press #(dispatch [:switch-command-suggestions]) [message-input-offset [:get-in [:animations :message-input-offset]]]
:style st/switch-commands-touchable} [animated-view {:style (st/message-input-container message-input-offset)}
[view nil input])
(if @typing-command?
[icon :close-gray st/close-icon] (defview plain-message-input-view [{:keys [input-options validator]}]
[icon :list st/list-icon])]]) [input-message [:get-chat-input-text]
[text-input (merge {:style (cond command [:get-chat-command]
response? st-response/command-input to-msg-id [:get-chat-command-to-msg-id]
command st-command/command-input input-command [:get-chat-command-content]
:else st/message-input) staged-commands [:get-chat-staged-commands]
:autoFocus false typing-command? [:typing-command?]
:blurOnSubmit dismiss-keyboard response-input-is-hiding? [:get-in [:animations :response-input-is-hiding?]]
:onChangeText (fn [text] commands-button-is-switching? [:get-in [:animations :commands-input-is-switching?]]]
((if command (let [dismiss-keyboard (not (or command typing-command?))
command/set-input-message response? (and command to-msg-id)
set-input-message) message-input? (or (not command) response-input-is-hiding? commands-button-is-switching?)
text)) animation? (or response-input-is-hiding? commands-button-is-switching?)]
:onSubmitEditing (fn [] [view st/input-container
(if command (cond
(command/try-send @input-command validator) response? [response/request-view]
(try-send @staged-commands command [content-suggestions-view]
@input-message :else [suggestions-view])
dismiss-keyboard)))} [view st/input-view
input-options) (if message-input?
(if command [commands-button animation?]
@input-command (when (and command (not response?))
@input-message)] [command/command-icon command response?]))
;; TODO emoticons: not implemented [message-input-container
(when (not command) [text-input (merge {:style (cond
[icon :smile st/smile-icon]) message-input? st/message-input
(if command response? st-response/command-input
(if (command/valid? @input-command validator) command st-command/command-input)
[touchable-highlight {:on-press command/send-command} :autoFocus false
[view st/send-container [icon :send st/send-icon]]] :blurOnSubmit dismiss-keyboard
(when-not response? :onChangeText (fn [text]
[touchable-highlight {:on-press command/cancel-command-input} ((if message-input?
[view st-command/cancel-container set-input-message
[icon :close-gray st-command/cancel-icon]]])) command/set-input-message)
(when (message-valid? @staged-commands @input-message) text))
[touchable-highlight {:on-press #(try-send @staged-commands :editable (not animation?)
@input-message :onSubmitEditing #(if message-input?
dismiss-keyboard)} (try-send staged-commands
[view st/send-container input-message
[icon :send st/send-icon]]]))]])))) 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]]])))]]))

View File

@ -13,5 +13,5 @@
(def max-chat-name-length 20) (def max-chat-name-length 20)
(def response-input-hiding-duration 200) (def response-input-hiding-duration 300)
(def response-suggesstion-resize-duration 100) (def response-suggesstion-resize-duration 100)

View File

@ -33,8 +33,11 @@
:current-tag nil :current-tag nil
:disable-group-creation false :disable-group-creation false
:animations {;; mutable data :animations {;; mutable data
:response-suggestions-height (anim/create-value 0) :message-input-offset (anim/create-value 0)
:response-input-is-hiding? false}}) :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]) (def protocol-initialized-path [:protocol-initialized])
(defn chat-input-text-path [chat-id] (defn chat-input-text-path [chat-id]