Merge pull request #130 from status-im/message-animation
New message animation. Tab switching animation.
Former-commit-id: de0103afcd
This commit is contained in:
commit
12d070e44f
|
@ -22,8 +22,6 @@
|
|||
[status-im.chat.handlers.animation :refer [update-response-height
|
||||
get-response-height]]))
|
||||
|
||||
(def delta 1)
|
||||
|
||||
(register-handler :set-show-actions
|
||||
(fn [db [_ show-actions]]
|
||||
(assoc db :show-actions show-actions)))
|
||||
|
@ -54,14 +52,18 @@
|
|||
(dispatch [:animate-cancel-command])
|
||||
(dispatch [:cancel-command])))))
|
||||
|
||||
(defn animate-set-chat-command-content [db _]
|
||||
(when (commands/get-chat-command-to-msg-id db)
|
||||
(dispatch [:animate-response-resize])))
|
||||
|
||||
(register-handler :set-chat-command-content
|
||||
(after animate-set-chat-command-content)
|
||||
(fn [{:keys [current-chat-id] :as db} [_ content]]
|
||||
(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))
|
||||
(update-response-height db)
|
||||
db))))
|
||||
|
||||
(defn update-input-text
|
||||
|
@ -82,13 +84,6 @@
|
|||
(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 _]
|
||||
|
@ -135,7 +130,21 @@
|
|||
(defn add-message-to-db
|
||||
[db chat-id message]
|
||||
(let [messages [:chats chat-id :messages]]
|
||||
(update-in db messages conj message)))
|
||||
(update-in db messages conj (assoc message :chat-id chat-id
|
||||
:new? true))))
|
||||
|
||||
(defn set-message-shown
|
||||
[db chat-id msg-id]
|
||||
(update-in db [:chats chat-id :messages] (fn [messages]
|
||||
(map (fn [msg]
|
||||
(if (= msg-id (:msg-id msg))
|
||||
(assoc msg :new? false)
|
||||
msg))
|
||||
messages))))
|
||||
|
||||
(register-handler :set-message-shown
|
||||
(fn [db [_ {:keys [chat-id msg-id]}]]
|
||||
(set-message-shown db chat-id msg-id)))
|
||||
|
||||
(defn prepare-message
|
||||
[{:keys [identity current-chat-id] :as db} _]
|
||||
|
|
|
@ -10,12 +10,16 @@
|
|||
|
||||
(def zero-height input-height)
|
||||
|
||||
(register-handler :finish-animate-cancel-command
|
||||
(fn [db _]
|
||||
(assoc-in db [:animations :commands-input-is-switching?] false)))
|
||||
(defn animation-handler
|
||||
([name handler] (animation-handler name nil handler))
|
||||
([name middleware handler]
|
||||
(register-handler name [(path :animations) middleware] handler)))
|
||||
|
||||
(register-handler :animate-cancel-command
|
||||
(path :animations)
|
||||
(animation-handler :finish-animate-cancel-command
|
||||
(fn [db _]
|
||||
(assoc db :commands-input-is-switching? false)))
|
||||
|
||||
(animation-handler :animate-cancel-command
|
||||
(fn [db _]
|
||||
(if-not (:commands-input-is-switching? db)
|
||||
(assoc db
|
||||
|
@ -26,20 +30,19 @@
|
|||
:messages-offset 0)
|
||||
db)))
|
||||
|
||||
(register-handler :finish-animate-response-resize
|
||||
(animation-handler :finish-animate-response-resize
|
||||
(fn [db _]
|
||||
(let [fixed (get-in db [:animations :to-response-height])]
|
||||
(-> db
|
||||
(assoc-in [:animations :response-height-current] fixed)
|
||||
(assoc-in [:animations :response-resize?] false)))))
|
||||
(let [fixed (:to-response-height db)]
|
||||
(assoc db :response-height-current fixed
|
||||
:response-resize? false))))
|
||||
|
||||
(register-handler :set-response-height
|
||||
(animation-handler :set-response-height
|
||||
(fn [db [_ value]]
|
||||
(assoc-in db [:animations :response-height-current] value)))
|
||||
(assoc db :response-height-current value)))
|
||||
|
||||
(register-handler :animate-response-resize
|
||||
(animation-handler :animate-response-resize
|
||||
(fn [db _]
|
||||
(assoc-in db [:animations :response-resize?] true)))
|
||||
(assoc db :response-resize? true)))
|
||||
|
||||
(defn get-response-height [db]
|
||||
(let [command (commands/get-chat-command db)
|
||||
|
@ -55,10 +58,9 @@
|
|||
(defn update-response-height [db]
|
||||
(assoc-in db [:animations :to-response-height] (get-response-height db)))
|
||||
|
||||
(register-handler :finish-show-response
|
||||
(after #(dispatch [:prepare-message-input]))
|
||||
(animation-handler :finish-show-response
|
||||
(fn [db _]
|
||||
(assoc-in db [:animations :commands-input-is-switching?] false)))
|
||||
(assoc db :commands-input-is-switching? false)))
|
||||
|
||||
(register-handler :animate-show-response
|
||||
(after #(dispatch [:animate-response-resize]))
|
||||
|
@ -71,24 +73,22 @@
|
|||
(assoc-in [:animations :messages-offset] request-info-height)
|
||||
(update-response-height))))
|
||||
|
||||
(register-handler :set-response-max-height
|
||||
(animation-handler :set-response-max-height
|
||||
(fn [db [_ height]]
|
||||
(let [prev-height (get-in db [:animations :response-height-max])]
|
||||
(let [prev-height (:response-height-max db)]
|
||||
(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))
|
||||
(let [db (assoc db :response-height-max height)]
|
||||
(if (= prev-height (:to-response-height db))
|
||||
(assoc db :to-response-height height
|
||||
:response-height-current height)
|
||||
db))
|
||||
db))))
|
||||
|
||||
(register-handler :on-drag-response
|
||||
(animation-handler :on-drag-response
|
||||
(fn [db [_ dy]]
|
||||
(let [fixed (get-in db [:animations :to-response-height])]
|
||||
(-> db
|
||||
(assoc-in [:animations :response-height-current] (- fixed dy))
|
||||
(assoc-in [:animations :response-resize?] false)))))
|
||||
(let [fixed (:to-response-height db)]
|
||||
(assoc db :response-height-current (- fixed dy)
|
||||
:response-resize? false))))
|
||||
|
||||
(register-handler :fix-response-height
|
||||
(fn [db _]
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[status-im.components.chat-icon.screen :refer [chat-icon-view-action
|
||||
chat-icon-view-menu-item]]
|
||||
[status-im.chat.styles.screen :as st]
|
||||
[status-im.utils.listview :refer [to-datasource]]
|
||||
[status-im.utils.listview :refer [to-datasource-inverted]]
|
||||
[status-im.utils.utils :refer [truncate-str]]
|
||||
[status-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
|
||||
[status-im.components.toolbar :refer [toolbar]]
|
||||
|
@ -61,12 +61,12 @@
|
|||
(for [member ["Geoff" "Justas"]]
|
||||
^{:key member} [typing member])])
|
||||
|
||||
(defn message-row [contact-by-identity group-chat]
|
||||
(defn message-row [contact-by-identity group-chat messages-count]
|
||||
(fn [row _ idx]
|
||||
(let [msg (-> row
|
||||
(add-msg-color contact-by-identity)
|
||||
(assoc :group-chat group-chat)
|
||||
(assoc :last-msg (zero? (js/parseInt idx))))]
|
||||
(assoc :last-msg (= (js/parseInt idx) (dec messages-count))))]
|
||||
(list-item [chat-message msg]))))
|
||||
|
||||
(defn on-action-selected [position]
|
||||
|
@ -222,12 +222,12 @@
|
|||
[messages [:chat :messages]
|
||||
contacts [:chat :contacts]]
|
||||
(let [contacts' (contacts-by-identity contacts)]
|
||||
[list-view {:renderRow (message-row contacts' group-chat)
|
||||
[list-view {:renderRow (message-row contacts' group-chat (count messages))
|
||||
:renderScrollComponent #(invertible-scroll-view (js->clj %))
|
||||
:onEndReached #(dispatch [:load-more-messages])
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps true
|
||||
:dataSource (to-datasource messages)}]))
|
||||
:dataSource (to-datasource-inverted messages)}]))
|
||||
|
||||
(defn messages-container-animation-logic [{:keys [to-value val]}]
|
||||
(fn [_]
|
||||
|
@ -235,11 +235,11 @@
|
|||
(anim/start (anim/spring val {:toValue to-value})
|
||||
(fn [arg]
|
||||
(when (.-finished arg)
|
||||
(dispatch [:set-in [:animations ::messages-offset-current] to-value])))))))
|
||||
(dispatch [:set-animation ::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]])
|
||||
(let [to-messages-offset (subscribe [:animations :messages-offset])
|
||||
cur-messages-offset (subscribe [:animations ::messages-offset-current])
|
||||
messages-offset (anim/create-value (or @cur-messages-offset 0))
|
||||
context {:to-value to-messages-offset
|
||||
:val messages-offset}
|
||||
|
|
|
@ -131,20 +131,27 @@
|
|||
(def command-request-message-view
|
||||
{:borderRadius 14
|
||||
:padding 12
|
||||
:paddingRight 28
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def command-request-from-text
|
||||
(merge style-sub-text {:marginBottom 2}))
|
||||
|
||||
(defn command-request-image-view
|
||||
[command]
|
||||
{:position :absolute
|
||||
:top 12
|
||||
:right 0
|
||||
:width 32
|
||||
(def command-request-image-touchable
|
||||
{:position :absolute
|
||||
:top 4
|
||||
:right -8
|
||||
:alignItems :center
|
||||
:justifyContent :center
|
||||
:width 48
|
||||
:height 48})
|
||||
|
||||
(defn command-request-image-view [command scale]
|
||||
{:width 32
|
||||
:height 32
|
||||
:borderRadius 50
|
||||
:backgroundColor (:color command)})
|
||||
:backgroundColor (:color command)
|
||||
:transform [{:scale scale}]})
|
||||
|
||||
(def command-request-image
|
||||
{:position :absolute
|
||||
|
@ -309,6 +316,9 @@
|
|||
(def message-date-text
|
||||
(assoc style-sub-text :textAlign :center))
|
||||
|
||||
(defn message-container [height]
|
||||
{:height height})
|
||||
|
||||
(def new-message-container
|
||||
{:backgroundColor color-white
|
||||
:elevation 4})
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
[text {:style st/command-text} (:text command)]])
|
||||
|
||||
(defview cancel-button []
|
||||
[commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]]]
|
||||
[commands-input-is-switching? [:animations :commands-input-is-switching?]]
|
||||
[touchable-highlight {:disabled commands-input-is-switching?
|
||||
:on-press cancel-command-input}
|
||||
[view st/cancel-container
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
(ns status-im.chat.views.message
|
||||
(:require [clojure.string :as s]
|
||||
[re-frame.core :refer [subscribe dispatch]]
|
||||
[reagent.core :as r]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
image
|
||||
touchable-highlight]]
|
||||
animated-view
|
||||
text
|
||||
image
|
||||
touchable-highlight]]
|
||||
[status-im.components.animation :as anim]
|
||||
[status-im.chat.views.request-message :refer [message-content-command-request]]
|
||||
[status-im.chat.styles.message :as st]
|
||||
[status-im.models.commands :refer [parse-command-msg-content
|
||||
parse-command-request]]
|
||||
parse-command-request]]
|
||||
[status-im.resources :as res]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.constants :refer [text-content-type
|
||||
content-type-status
|
||||
content-type-command
|
||||
content-type-command-request]]))
|
||||
content-type-status
|
||||
content-type-command
|
||||
content-type-command-request]]))
|
||||
|
||||
(defn message-date [{:keys [date]}]
|
||||
(defn message-date [timestamp]
|
||||
[view {}
|
||||
[view st/message-date-container
|
||||
[text {:style st/message-date-text} date]]])
|
||||
[text {:style st/message-date-text} (time/to-short-str timestamp)]]])
|
||||
|
||||
(defn contact-photo [{:keys [photo-path]}]
|
||||
[view st/contact-photo-container
|
||||
|
@ -69,36 +74,6 @@
|
|||
"******"
|
||||
content)]]))))
|
||||
|
||||
(defn set-chat-command [msg-id command]
|
||||
(dispatch [:set-response-chat-command msg-id (:command command)]))
|
||||
|
||||
(defn label [{:keys [command]}]
|
||||
(->> (name command)
|
||||
(str "request-")))
|
||||
|
||||
(defn message-content-command-request
|
||||
[{:keys [msg-id content from incoming-group]}]
|
||||
(let [commands-atom (subscribe [:get-commands])]
|
||||
(fn [{:keys [msg-id content from incoming-group]}]
|
||||
(let [commands @commands-atom
|
||||
{:keys [command content]} (parse-command-request commands content)]
|
||||
[touchable-highlight {:onPress #(set-chat-command msg-id command)
|
||||
:accessibility-label (label command)}
|
||||
[view st/comand-request-view
|
||||
[view st/command-request-message-view
|
||||
(when incoming-group
|
||||
[text {:style st/command-request-from-text}
|
||||
from])
|
||||
[text {:style st/style-message-text}
|
||||
content]]
|
||||
[view (st/command-request-image-view command)
|
||||
[image {:source (:request-icon command)
|
||||
:style st/command-request-image}]]
|
||||
(when (:request-text command)
|
||||
[view st/command-request-text-view
|
||||
[text {:style st/style-sub-text}
|
||||
(:request-text command)]])]]))))
|
||||
|
||||
(defn message-view
|
||||
[message content]
|
||||
[view (st/message-view message)
|
||||
|
@ -185,12 +160,50 @@
|
|||
(when (and outgoing delivery-status)
|
||||
[message-delivery-status {:delivery-status delivery-status}])]))
|
||||
|
||||
(defn message-container-animation-logic [{:keys [to-value val callback]}]
|
||||
(fn [_]
|
||||
(let [to-value @to-value]
|
||||
(when (< 0 to-value)
|
||||
(anim/start
|
||||
(anim/spring val {:toValue to-value
|
||||
:friction 4
|
||||
:tension 10})
|
||||
(fn [arg]
|
||||
(when (.-finished arg)
|
||||
(callback))))))))
|
||||
|
||||
(defn message-container [message & children]
|
||||
(if (:new? message)
|
||||
(let [layout-height (r/atom 0)
|
||||
anim-value (anim/create-value 1)
|
||||
anim-callback #(dispatch [:set-message-shown message])
|
||||
context {:to-value layout-height
|
||||
:val anim-value
|
||||
:callback anim-callback}
|
||||
on-update (message-container-animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
:component-did-update
|
||||
on-update
|
||||
:reagent-render
|
||||
(fn [message & children]
|
||||
@layout-height
|
||||
[animated-view {:style (st/message-container anim-value)}
|
||||
(into [view {:onLayout (fn [event]
|
||||
(let [height (.. event -nativeEvent -layout -height)]
|
||||
(reset! layout-height height)))}]
|
||||
children)])}))
|
||||
(into [view] children)))
|
||||
|
||||
(defn chat-message
|
||||
[{:keys [outgoing delivery-status date new-day group-chat]
|
||||
[{:keys [outgoing delivery-status timestamp new-day group-chat]
|
||||
:as message}]
|
||||
[view {}
|
||||
(when new-day [message-date {:date date}])
|
||||
[view {}
|
||||
[message-container message
|
||||
;; TODO there is no new-day info in message
|
||||
(when new-day
|
||||
[message-date timestamp])
|
||||
[view
|
||||
(let [incoming-group (and group-chat (not outgoing))]
|
||||
[message-content
|
||||
(if incoming-group
|
||||
|
|
|
@ -19,29 +19,29 @@
|
|||
[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?]]]
|
||||
[commands-input-is-switching? [: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]}]
|
||||
(defn 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])))))))
|
||||
(dispatch [:set-animation ::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]])
|
||||
(let [to-message-input-offset (subscribe [:animations :message-input-offset])
|
||||
cur-message-input-offset (subscribe [: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)]
|
||||
on-update (animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
|
@ -60,7 +60,7 @@
|
|||
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?]]]
|
||||
commands-input-is-switching? [: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?)
|
||||
|
@ -99,7 +99,7 @@
|
|||
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?]]]
|
||||
commands-input-is-switching? [: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?)]
|
||||
|
|
|
@ -28,12 +28,10 @@
|
|||
:request {:input-options {:keyboardType :numeric}}
|
||||
(throw (js/Error. "Uknown command type"))))])
|
||||
|
||||
(defn chat-message-new []
|
||||
(let [command-atom (subscribe [:get-chat-command])
|
||||
staged-commands-atom (subscribe [:get-chat-staged-commands])]
|
||||
(fn []
|
||||
(let [staged-commands @staged-commands-atom]
|
||||
[view st/new-message-container
|
||||
(when (and staged-commands (pos? (count staged-commands)))
|
||||
[staged-commands-view staged-commands])
|
||||
[show-input @command-atom]]))))
|
||||
(defview chat-message-new []
|
||||
[command [:get-chat-command]
|
||||
staged-commands [:get-chat-staged-commands]]
|
||||
[view st/new-message-container
|
||||
(when (and staged-commands (pos? (count staged-commands)))
|
||||
[staged-commands-view staged-commands])
|
||||
[show-input command]])
|
||||
|
|
|
@ -28,7 +28,20 @@
|
|||
(when (message-valid? staged-commands message)
|
||||
(send dismiss-keyboard)))
|
||||
|
||||
(defn commands-button-animation-logic [{:keys [to-value val]}]
|
||||
(defn prepare-message-input [message-input]
|
||||
(when message-input
|
||||
(.clear message-input)
|
||||
(.focus message-input)))
|
||||
|
||||
(defn commands-button-animation-callback [message-input]
|
||||
(fn [arg to-value]
|
||||
(when (.-finished arg)
|
||||
(dispatch [:set-animation ::message-input-buttons-scale-current to-value])
|
||||
(when (<= to-value 0.1)
|
||||
(dispatch [:finish-show-response])
|
||||
(prepare-message-input @message-input)))))
|
||||
|
||||
(defn button-animation-logic [{:keys [to-value val callback]}]
|
||||
(fn [_]
|
||||
(let [to-scale @to-value
|
||||
minimum 0.1
|
||||
|
@ -37,21 +50,22 @@
|
|||
: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]))))))))
|
||||
(when callback
|
||||
(fn [arg]
|
||||
(callback arg to-scale)))))))
|
||||
|
||||
(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]])
|
||||
message-input (subscribe [:get :message-input])
|
||||
animation? (subscribe [:animations :commands-input-is-switching?])
|
||||
to-scale (subscribe [:animations :message-input-buttons-scale])
|
||||
cur-scale (subscribe [:animations ::message-input-buttons-scale-current])
|
||||
buttons-scale (anim/create-value (or @cur-scale 1))
|
||||
anim-callback (commands-button-animation-callback message-input)
|
||||
context {:to-value to-scale
|
||||
:val buttons-scale}
|
||||
on-update (commands-button-animation-logic context)]
|
||||
:val buttons-scale
|
||||
:callback anim-callback}
|
||||
on-update (button-animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
|
@ -70,13 +84,13 @@
|
|||
[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]])
|
||||
(let [animation? (subscribe [:animations :commands-input-is-switching?])
|
||||
to-scale (subscribe [:animations :message-input-buttons-scale])
|
||||
cur-scale (subscribe [: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)]
|
||||
on-update (button-animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
(ns status-im.chat.views.request-message
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[reagent.core :as r]
|
||||
[status-im.components.react :refer [view
|
||||
animated-view
|
||||
text
|
||||
image
|
||||
touchable-highlight]]
|
||||
[status-im.chat.styles.message :as st]
|
||||
[status-im.models.commands :refer [parse-command-request]]
|
||||
[status-im.components.animation :as anim]))
|
||||
|
||||
(def request-message-icon-scale-delay 600)
|
||||
|
||||
(defn set-chat-command [msg-id command]
|
||||
(dispatch [:set-response-chat-command msg-id (:command command)]))
|
||||
|
||||
(defn label [{:keys [command]}]
|
||||
(->> (name command)
|
||||
(str "request-")))
|
||||
|
||||
(defn request-button-animation-logic [{:keys [to-value val loop?]}]
|
||||
(fn [_]
|
||||
(let [loop? @loop?
|
||||
minimum 1
|
||||
maximum 1.3
|
||||
to-scale (if loop?
|
||||
(or @to-value maximum)
|
||||
minimum)]
|
||||
(anim/start
|
||||
(anim/anim-sequence
|
||||
[(anim/anim-delay (if loop? request-message-icon-scale-delay 0))
|
||||
(anim/spring val {:toValue to-scale})])
|
||||
(fn [arg]
|
||||
(when (.-finished arg)
|
||||
(dispatch [:set-animation ::request-button-scale-current to-scale])
|
||||
(when loop?
|
||||
(dispatch [:set-animation ::request-button-scale (if (= to-scale minimum)
|
||||
maximum
|
||||
minimum)]))))))))
|
||||
|
||||
(defn request-button [msg-id command]
|
||||
(let [to-scale (subscribe [:animations ::request-button-scale])
|
||||
cur-scale (subscribe [:animations ::request-button-scale-current])
|
||||
scale-anim-val (anim/create-value (or @cur-scale 1))
|
||||
loop? (r/atom true)
|
||||
context {:to-value to-scale
|
||||
:val scale-anim-val
|
||||
:loop? loop?}
|
||||
on-update (request-button-animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
:component-did-update
|
||||
on-update
|
||||
:reagent-render
|
||||
(fn [msg-id command]
|
||||
@to-scale
|
||||
[touchable-highlight {:on-press (fn []
|
||||
(reset! loop? false)
|
||||
(set-chat-command msg-id command))
|
||||
:style st/command-request-image-touchable
|
||||
:accessibility-label (label command)}
|
||||
[animated-view {:style (st/command-request-image-view command scale-anim-val)}
|
||||
[image {:source (:request-icon command)
|
||||
:style st/command-request-image}]]])})))
|
||||
|
||||
(defn message-content-command-request
|
||||
[{:keys [msg-id content from incoming-group]}]
|
||||
(let [commands-atom (subscribe [:get-commands])]
|
||||
(fn [{:keys [msg-id content from incoming-group]}]
|
||||
(let [commands @commands-atom
|
||||
{:keys [command content]} (parse-command-request commands content)]
|
||||
[view st/comand-request-view
|
||||
[view st/command-request-message-view
|
||||
(when incoming-group
|
||||
[text {:style st/command-request-from-text}
|
||||
from])
|
||||
[text {:style st/style-message-text}
|
||||
content]]
|
||||
[request-button msg-id command]
|
||||
(when (:request-text command)
|
||||
[view st/command-request-text-view
|
||||
[text {:style st/style-sub-text}
|
||||
(:request-text command)]])]))))
|
|
@ -61,7 +61,7 @@
|
|||
(anim/start (anim/spring val {:toValue to-value})
|
||||
(fn [arg]
|
||||
(when (.-finished arg)
|
||||
(dispatch [:set-in [:animations :response-height-current] to-value])
|
||||
(dispatch [:set-animation :response-height-current to-value])
|
||||
(dispatch [:finish-animate-response-resize])
|
||||
(when (= to-value input-height)
|
||||
(dispatch [:finish-animate-cancel-command])
|
||||
|
@ -69,10 +69,10 @@
|
|||
(anim/set-value val @current-value))))
|
||||
|
||||
(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]])
|
||||
(let [commands-input-is-switching? (subscribe [:animations :commands-input-is-switching?])
|
||||
response-resize? (subscribe [:animations :response-resize?])
|
||||
to-response-height (subscribe [:animations :to-response-height])
|
||||
cur-response-height (subscribe [: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
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
(defn spring [anim-value config]
|
||||
(.spring animated anim-value (clj->js config)))
|
||||
|
||||
(defn anim-sequence [animations]
|
||||
(.sequence animated (clj->js animations)))
|
||||
|
||||
(defn anim-delay [duration]
|
||||
(.delay animated duration))
|
||||
|
||||
(defn event [config]
|
||||
(.event animated (clj->js [nil, config])))
|
||||
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
(ns status-im.components.main-tabs
|
||||
(: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 dispatch-sync]]
|
||||
[reagent.core :as r]
|
||||
[status-im.components.react :refer [view
|
||||
animated-view
|
||||
text-input
|
||||
text
|
||||
image
|
||||
touchable-highlight]]
|
||||
touchable-highlight
|
||||
get-dimensions]]
|
||||
[status-im.components.animation :as anim]
|
||||
[status-im.chats-list.screen :refer [chats-list]]
|
||||
[status-im.discovery.screen :refer [discovery]]
|
||||
[status-im.contacts.screen :refer [contact-list]]
|
||||
|
@ -14,33 +19,91 @@
|
|||
[status-im.components.styles :as common-st]
|
||||
[status-im.i18n :refer [label]]))
|
||||
|
||||
(def window-width (:width (get-dimensions "window")))
|
||||
|
||||
(def tab-list
|
||||
[{:view-id :chat-list
|
||||
:title (label :t/chats)
|
||||
:screen chats-list
|
||||
:icon :icon_tab_chats}
|
||||
:icon :icon_tab_chats
|
||||
:index 0}
|
||||
{:view-id :discovery
|
||||
:title (label :t/discovery)
|
||||
:screen discovery
|
||||
:icon :icon_tab_discovery}
|
||||
:icon :icon_tab_discovery
|
||||
:index 1}
|
||||
{:view-id :contact-list
|
||||
:title (label :t/contacts)
|
||||
:screen contact-list
|
||||
:icon :icon_tab_contacts}])
|
||||
:icon :icon_tab_contacts
|
||||
:index 2}])
|
||||
|
||||
(defn show-view? [current-view view-id]
|
||||
(let [key-map {:key view-id}]
|
||||
(if (= current-view view-id)
|
||||
(merge st/show-tab key-map)
|
||||
(merge st/hide-tab key-map))))
|
||||
(defn animation-logic [{:keys [offsets val tab-id to-tab-id]}]
|
||||
(fn [_]
|
||||
(when-let [offsets @offsets]
|
||||
(let [from-value (:from offsets)
|
||||
to-value (:to offsets)
|
||||
to-tab-id @to-tab-id]
|
||||
(anim/set-value val from-value)
|
||||
(when to-value
|
||||
(anim/start
|
||||
(anim/timing val {:toValue to-value
|
||||
:duration 300})
|
||||
(when (= tab-id to-tab-id)
|
||||
(fn [arg]
|
||||
(when (.-finished arg)
|
||||
(dispatch [:on-navigated-to-tab]))))))))))
|
||||
|
||||
(defn tab-view [current-view {:keys [view-id screen]}]
|
||||
[view (show-view? current-view view-id)
|
||||
(defn get-tab-index-by-id [id]
|
||||
(:index (first (filter #(= id (:view-id %)) tab-list))))
|
||||
|
||||
(defn get-offsets [tab-id from-id to-id]
|
||||
(let [tab (get-tab-index-by-id tab-id)
|
||||
from (get-tab-index-by-id from-id)
|
||||
to (get-tab-index-by-id to-id)]
|
||||
(if (or (= tab from) (= tab to))
|
||||
(cond
|
||||
(or (nil? from) (= from to)) {:from 0}
|
||||
(< from to) (if (= tab to)
|
||||
{:from window-width, :to 0}
|
||||
{:from 0, :to (- window-width)})
|
||||
(< to from) (if (= tab to)
|
||||
{:from (- window-width), :to 0}
|
||||
{:from 0, :to window-width}))
|
||||
{:from (- window-width)})))
|
||||
|
||||
(defn tab-view-container [tab-id content]
|
||||
(let [cur-tab-id (subscribe [:get :view-id])
|
||||
prev-tab-id (subscribe [:get :prev-tab-view-id])
|
||||
offsets (reaction (get-offsets tab-id @prev-tab-id @cur-tab-id))
|
||||
anim-value (anim/create-value (- window-width))
|
||||
context {:offsets offsets
|
||||
:val anim-value
|
||||
:tab-id tab-id
|
||||
:to-tab-id cur-tab-id}
|
||||
on-update (animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
:component-did-update
|
||||
on-update
|
||||
:reagent-render
|
||||
(fn [tab-id content]
|
||||
@offsets
|
||||
[animated-view {:style (st/tab-view-container anim-value)}
|
||||
content])})))
|
||||
|
||||
(defn tab-view [{:keys [view-id screen]}]
|
||||
^{:key view-id}
|
||||
[tab-view-container view-id
|
||||
[screen]])
|
||||
|
||||
(defview main-tabs []
|
||||
[view-id [:get :view-id]]
|
||||
[view common-st/flex
|
||||
(doall (map #(tab-view view-id %1) tab-list))
|
||||
[tabs {:selected-view-id view-id
|
||||
:tab-list tab-list}]])
|
||||
[view-id [:get :view-id]
|
||||
tab-animation? [:get :prev-tab-view-id]]
|
||||
[view {:style common-st/flex}
|
||||
[view {:style common-st/flex
|
||||
:pointerEvents (if tab-animation? :none :auto)}
|
||||
(doall (map #(tab-view %) tab-list))]
|
||||
[tabs {:selected-view-id view-id
|
||||
:tab-list tab-list}]])
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
(def toolbar-height 56)
|
||||
|
||||
(def flex
|
||||
{:style {:flex 1}})
|
||||
{:flex 1})
|
||||
|
||||
(def hamburger-icon
|
||||
{:width 16
|
||||
|
|
|
@ -54,17 +54,11 @@
|
|||
:justifyContent :center
|
||||
:alignItems :center})
|
||||
|
||||
(def show-tab
|
||||
{:flex 1
|
||||
:pointerEvents :auto
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom tab-height})
|
||||
|
||||
(def hide-tab
|
||||
{:opacity 0
|
||||
:pointerEvents :none
|
||||
:overflow :hidden})
|
||||
|
||||
(defn tab-view-container [offset-x]
|
||||
{:flex 1
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom tab-height
|
||||
:transform [{:translateX offset-x}]})
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
[status-im.components.tabs.styles :as st]))
|
||||
|
||||
(defview tab [{:keys [view-id title icon selected-view-id]}]
|
||||
[touchable-highlight {:style st/tab
|
||||
:onPress #(dispatch [:navigate-to
|
||||
view-id])}
|
||||
[touchable-highlight {:style st/tab
|
||||
:disabled (= view-id selected-view-id)
|
||||
:onPress #(dispatch [:navigate-to-tab view-id])}
|
||||
[view {:style st/tab-container}
|
||||
[image {:source {:uri icon}
|
||||
:style st/tab-icon}]
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
debug
|
||||
set-in)
|
||||
|
||||
(register-handler :set-animation
|
||||
(fn [db [_ k v]]
|
||||
(assoc-in db [:animations k] v)))
|
||||
|
||||
(register-handler :initialize-db
|
||||
(fn [_ _]
|
||||
(assoc app-db
|
||||
|
|
|
@ -48,9 +48,10 @@
|
|||
|
||||
(defn get-messages [chat-id]
|
||||
(->> (-> (r/get-by-field :msgs :chat-id chat-id)
|
||||
(r/sorted :timestamp :asc)
|
||||
(r/sorted :timestamp :desc)
|
||||
(r/collection->map))
|
||||
(into '())
|
||||
reverse
|
||||
(map (fn [{:keys [content-type] :as message}]
|
||||
(if (command-type? content-type)
|
||||
(update message :content str-to-map)
|
||||
|
|
|
@ -43,6 +43,18 @@
|
|||
(assoc :view-id view-id)
|
||||
(assoc :navigation-stack navigation-stack'))))))
|
||||
|
||||
(register-handler :navigate-to-tab
|
||||
(enrich preload-data!)
|
||||
(fn [db [_ view-id]]
|
||||
(-> db
|
||||
(assoc :prev-tab-view-id (:view-id db))
|
||||
(replace-view view-id))))
|
||||
|
||||
(register-handler :on-navigated-to-tab
|
||||
(enrich preload-data!)
|
||||
(fn [db [_]]
|
||||
(assoc db :prev-tab-view-id nil)))
|
||||
|
||||
(register-handler :show-group-new
|
||||
(debug
|
||||
(fn [db _]
|
||||
|
|
|
@ -15,3 +15,7 @@
|
|||
(register-sub :get-in
|
||||
(fn [db [_ path]]
|
||||
(reaction (get-in @db path))))
|
||||
|
||||
(register-sub :animations
|
||||
(fn [db [_ k]]
|
||||
(reaction (get-in @db [:animations k]))))
|
||||
|
|
|
@ -7,3 +7,12 @@
|
|||
|
||||
(defn to-datasource [items]
|
||||
(clone-with-rows (data-source {:rowHasChanged not=}) items))
|
||||
|
||||
(defn clone-with-rows-inverted [ds rows]
|
||||
(let [rows (reduce (fn [ac el] (.push ac el) ac)
|
||||
(clj->js []) (reverse rows))
|
||||
row-ids (.reverse (.map rows (fn [_ index] index)))]
|
||||
(.cloneWithRows ds rows row-ids)))
|
||||
|
||||
(defn to-datasource-inverted [items]
|
||||
(clone-with-rows-inverted (data-source {:rowHasChanged not=}) items))
|
||||
|
|
Loading…
Reference in New Issue