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