Fix chat text input animation lags

Remove picker panel from input

Clean pan state

Fixes #11031

Do not use pan state on android

iOs panel switching do not change height

Revert "Remove picker panel from input"

This reverts commit 0ab2c1544b70f8c491424376268f572696bd284a.

Change reactions space keeper method

Audio

Do not use accessory view on Android

Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
Gheorghe Pinzaru 2020-08-04 12:16:20 +03:00
parent eeff44eea7
commit 7bb7b48db7
No known key found for this signature in database
GPG Key ID: C9A094959935A952
5 changed files with 119 additions and 63 deletions

View File

@ -11,23 +11,29 @@
[quo.components.safe-area :refer [use-safe-area]]))
(def tabbar-height tabs.styles/minimized-tabs-height)
(def duration 250)
(defn create-pan-responder [y pan-active]
(js->clj (.-panHandlers
^js (.create
^js rn/pan-responder
#js {:onPanResponderGrant (fn []
(animated/set-value pan-active 1))
:onPanResponderMove (fn [_ ^js state]
(animated/set-value y (.-moveY state)))
:onPanResponderRelease (fn []
(js/setTimeout
#(animated/set-value y 0)
100))
:onPanResponderEnd (fn []
(animated/set-value pan-active 0))}))))
(when-not platform/android?
(js->clj (.-panHandlers
^js (.create
^js rn/pan-responder
#js {:onPanResponderGrant (fn []
(animated/set-value pan-active 1))
:onPanResponderMove (fn [_ ^js state]
(animated/set-value y (.-moveY state)))
:onPanResponderRelease (fn []
(animated/set-value pan-active 0)
(js/setTimeout
#(animated/set-value y 0)
100))
:onPanResponderTerminate (fn []
(animated/set-value pan-active 0)
(js/setTimeout
#(animated/set-value y 0)
100))})))))
(def view
(def ios-view
(reagent/adapt-react-class
(react/memo
(fn [props]
@ -39,7 +45,6 @@
children :children} (bean/bean props)
{keyboard-height :height
keyboard-max-height :max-height
duration :duration
keyboard-end-position :end-position} (use-keyboard-dimension)
{:keys [bottom]} (use-safe-area)
{on-layout :on-layout
@ -64,15 +69,13 @@
:easing (:keyboard animated/easings)})
0
panel-on-screen))
[duration panel-on-screen])
[panel-on-screen])
delta-y (animated/clamp (animated/add drag-diff animated-y) max-delta 0)
on-update (react/callback
(fn []
(when on-update-inset
(on-update-inset (+ bar-height panel-height))))
[panel-height bar-height])
on-update (fn []
(when on-update-inset
(on-update-inset (+ bar-height panel-height))))
children (react/get-children children)]
(react/effect! on-update)
(react/effect! on-update [panel-height bar-height])
(animated/code!
(fn []
(when has-panel
@ -86,12 +89,7 @@
(animated/delay
(animated/set anim-visible (if visible 1 0))
(if visible delay 0)))
[visible keyboard-max-height duration])
(rn/use-back-handler
(fn []
(when visible
(on-close))
visible))
[visible keyboard-max-height delay])
(reagent/as-element
[animated/view {:style {:position :absolute
:left 0
@ -104,3 +102,44 @@
[rn/view {:style {:flex 1
:height (when (pos? panel-height) panel-height)}}
(second children)]]))))))
(def android-view
(reagent/adapt-react-class
(react/memo
(fn [props]
(let [{on-update-inset :onUpdateInset
on-close :onClose
has-panel :hasPanel
children :children} (bean/bean props)
{keyboard-max-height :max-height} (use-keyboard-dimension)
{:keys [bottom]} (use-safe-area)
{on-layout :on-layout
bar-height :height} (rn/use-layout)
visible has-panel
panel-on-screen (* -1 (- keyboard-max-height bottom tabbar-height))
max-delta (min 0 (if has-panel panel-on-screen 0))
panel-height (* -1 max-delta)
on-update (fn []
(when on-update-inset
(on-update-inset (+ bar-height panel-height))))
children (react/get-children children)]
(react/effect! on-update [panel-height bar-height])
(rn/use-back-handler
(fn []
(when visible
(on-close))
visible))
(reagent/as-element
[animated/view {:style {:position :absolute
:left 0
:right 0
:bottom 0
:background-color (:ui-background @colors/theme)}}
[rn/view {:on-layout on-layout}
(first children)]
[rn/view {:style {:flex 1
:height (when (pos? panel-height) panel-height)}}
(second children)]]))))))
(def view (if platform/android? android-view ios-view))

View File

@ -15,8 +15,7 @@
[clojure.string :as string]))
(def panel->icons {:extensions :main-icons/commands
:images :main-icons/photo
:audio :main-icons/speech})
:images :main-icons/photo})
(defn touchable-icon [{:keys [panel active set-active accessibility-label]}]
[pressable/pressable {:type :scale
@ -38,6 +37,8 @@
[icons/icon :main-icons/keyboard (styles/icon false)]
[icons/icon :main-icons/stickers (styles/icon false)])]])
;; TODO(Ferossgp): Move this into audio panel.
;; Instead of not changing panel we can show a placeholder with no permission
(defn- request-record-audio-permission [set-active panel]
(re-frame/dispatch
[:request-permissions
@ -58,9 +59,9 @@
(input-focus)
(request-record-audio-permission set-active panel))}
[rn/view {:style (styles/in-input-touchable-icon)}
[icons/icon
(panel->icons panel)
(styles/icon (= active panel))]]])
(if (= active panel)
[icons/icon :main-icons/keyboard (styles/icon false)]
[icons/icon :main-icons/speech (styles/icon false)])]])
(defn send-button [{:keys [on-send-press]}]
[pressable/pressable {:type :scale

View File

@ -104,7 +104,8 @@
(defn in-input-buttons []
{:flex-direction :row
:height 34})
:height 34
:overflow :hidden})
(defn send-icon-color []
colors/white)

View File

@ -2,7 +2,6 @@
(:require [re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.i18n :as i18n]
[quo.platform :as platform]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.react :as react]
@ -341,17 +340,14 @@
[message-content-wrapper message
[unknown-content-type message]])
(defn chat-message [message set-active-panel]
(defn chat-message [message space-keeper]
[reactions/with-reaction-picker
{:message message
:reactions @(re-frame/subscribe [:chats/message-reactions (:message-id message)])
:picker-on-open (fn []
;; NOTE(Ferossgp): Because of soft-input adjustResize there are some problems on android
(when (and platform/ios? (pos? @(re-frame/subscribe [:keyboard-height])))
(set-active-panel :keep-space)))
(space-keeper true))
:picker-on-close (fn []
(when platform/ios?
(set-active-panel nil)))
(space-keeper false))
:send-emoji (fn [{:keys [emoji-id]}]
(re-frame/dispatch [::models.reactions/send-emoji-reaction
{:message-id (:message-id message)

View File

@ -11,6 +11,7 @@
[status-im.ui.screens.chat.sheets :as sheets]
[quo.animated :as animated]
[quo.react-native :as rn]
[quo.platform :as platform]
[status-im.ui.screens.chat.audio-message.views :as audio-message]
[quo.react :as quo.react]
[status-im.ui.screens.chat.message.message :as message]
@ -27,8 +28,7 @@
[status-im.ui.components.invite.chat :as invite.chat]
[status-im.ui.screens.chat.components.accessory :as accessory]
[status-im.ui.screens.chat.components.input :as components]
[status-im.ui.screens.chat.message.datemark :as message-datemark])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
[status-im.ui.screens.chat.message.datemark :as message-datemark]))
(defn topbar [current-chat]
[topbar/topbar
@ -137,14 +137,16 @@
first-not-visible)))))
(debounce/debounce-and-dispatch [:chat.ui/message-visibility-changed e] 5000))
(defview messages-view
[{:keys [group-chat chat-id public?] :as chat} bottom-space pan-handler set-active-panel]
(letsubs [messages [:chats/current-chat-messages-stream]
no-messages? [:chats/current-chat-no-messages?]
current-public-key [:multiaccount/public-key]]
(defn messages-view
[{:keys [chat bottom-space pan-responder space-keeper]}]
(let [{:keys [group-chat chat-id public?]} chat
messages @(re-frame/subscribe [:chats/current-chat-messages-stream])
no-messages? @(re-frame/subscribe [:chats/current-chat-no-messages?])
current-public-key @(re-frame/subscribe [:multiaccount/public-key])]
[list/flat-list
(merge
pan-handler
pan-responder
{:key-fn #(or (:message-id %) (:value %))
:ref #(reset! messages-list-ref %)
:header (when (and group-chat (not public?))
@ -167,13 +169,13 @@
:group-chat group-chat
:public? public?
:current-public-key current-public-key)
set-active-panel])))
space-keeper])))
:on-viewable-items-changed on-viewable-items-changed
:on-end-reached #(re-frame/dispatch [:chat.ui/load-more-messages])
:on-scroll-to-index-failed #() ;;don't remove this
:content-container-style {:padding-top (+ @bottom-space 16)
:content-container-style {:padding-top (+ bottom-space 16)
:padding-bottom 16}
:scrollIndicatorInsets {:top @bottom-space}
:scrollIndicatorInsets {:top bottom-space}
:keyboardDismissMode "interactive"
:keyboard-should-persist-taps :handled})]))
@ -190,20 +192,34 @@
nil))
(defn chat []
(let [bottom-space (reagent/atom 0)
active-panel (reagent/atom nil)
position-y (animated/value 0)
pan-state (animated/value 0)
text-input-ref (quo.react/create-ref)
on-update (partial reset! bottom-space)
pan-responder (accessory/create-pan-responder position-y pan-state)
(let [bottom-space (reagent/atom 0)
panel-space (reagent/atom 0)
active-panel (reagent/atom nil)
position-y (animated/value 0)
pan-state (animated/value 0)
text-input-ref (quo.react/create-ref)
on-update (partial reset! panel-space)
pan-responder (accessory/create-pan-responder position-y pan-state)
space-keeper (fn [state]
;; NOTE: Only iOs now because we use soft input resize screen on android
(when platform/ios?
(cond
(and state
(< @bottom-space @panel-space)
(not @active-panel))
(reset! bottom-space @panel-space)
(and (not state)
(< @panel-space @bottom-space))
(do
(some-> ^js (quo.react/current-ref text-input-ref) .focus)
(reset! panel-space @bottom-space)
(reset! bottom-space 0)))))
set-active-panel (fn [panel]
(rn/configure-next
(:ease-opacity-200 rn/custom-animations))
(when (and (not panel)
(= :keep-space @active-panel))
(some-> ^js (quo.react/current-ref text-input-ref) .focus))
(reset! active-panel panel)
(reagent/flush)
(when panel
(js/setTimeout #(react/dismiss-keyboard!) 100)))]
(fn []
@ -215,7 +231,10 @@
[react/view {:style {:flex 1}}
(when-not group-chat
[add-contact-bar chat-id])
[messages-view current-chat bottom-space pan-responder set-active-panel]]]
[messages-view {:chat current-chat
:bottom-space (max @bottom-space @panel-space)
:pan-responder pan-responder
:space-keeper space-keeper}]]]
(when show-input?
[accessory/view {:y position-y
:pan-state pan-state