New TopBar animation (#17582)
This commit is contained in:
parent
8d3558f1c3
commit
132e53844c
|
@ -47,6 +47,7 @@
|
||||||
"react-native-image-crop-picker": "git+https://github.com/status-im/react-native-image-crop-picker.git#refs/tags/v0.36.2-status.0",
|
"react-native-image-crop-picker": "git+https://github.com/status-im/react-native-image-crop-picker.git#refs/tags/v0.36.2-status.0",
|
||||||
"react-native-image-resizer": "^1.2.3",
|
"react-native-image-resizer": "^1.2.3",
|
||||||
"react-native-image-viewing": "git+https://github.com/status-im/react-native-image-viewing.git#refs/tags/v0.2.1.status",
|
"react-native-image-viewing": "git+https://github.com/status-im/react-native-image-viewing.git#refs/tags/v0.2.1.status",
|
||||||
|
"react-native-intersection-observer": "^0.2.0",
|
||||||
"react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#refs/tags/v.3.0.0-5-status",
|
"react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#refs/tags/v.3.0.0-5-status",
|
||||||
"react-native-languages": "^3.0.2",
|
"react-native-languages": "^3.0.2",
|
||||||
"react-native-linear-gradient": "^2.8.0",
|
"react-native-linear-gradient": "^2.8.0",
|
||||||
|
|
|
@ -300,6 +300,11 @@
|
||||||
{:clamp nil
|
{:clamp nil
|
||||||
:withPause (fn [])})
|
:withPause (fn [])})
|
||||||
|
|
||||||
|
(def react-native-intersection-observer
|
||||||
|
#js
|
||||||
|
{:InView #js {}
|
||||||
|
:IOFlatList #js {}})
|
||||||
|
|
||||||
(def react-native-languages
|
(def react-native-languages
|
||||||
(clj->js {:default {:language "en"
|
(clj->js {:default {:language "en"
|
||||||
:addEventListener (fn [])
|
:addEventListener (fn [])
|
||||||
|
@ -426,6 +431,7 @@
|
||||||
"react-native-transparent-video" react-native-transparent-video
|
"react-native-transparent-video" react-native-transparent-video
|
||||||
"react-native-orientation-locker" react-native-orientation-locker
|
"react-native-orientation-locker" react-native-orientation-locker
|
||||||
"react-native-gifted-charts" react-native-gifted-charts
|
"react-native-gifted-charts" react-native-gifted-charts
|
||||||
|
"react-native-intersection-observer" react-native-intersection-observer
|
||||||
"../resources/data/emojis/en.json" (js/JSON.parse (slurp
|
"../resources/data/emojis/en.json" (js/JSON.parse (slurp
|
||||||
"./resources/data/emojis/en.json"))
|
"./resources/data/emojis/en.json"))
|
||||||
"../src/js/worklets/core.js" worklet-factory
|
"../src/js/worklets/core.js" worklet-factory
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
(ns react-native.react-native-intersection-observer
|
||||||
|
(:require
|
||||||
|
["react-native-intersection-observer" :refer [InView IOFlatList]]
|
||||||
|
[react-native.flat-list :refer [base-list-props]]
|
||||||
|
[reagent.core :as reagent]))
|
||||||
|
|
||||||
|
(def view (reagent/adapt-react-class InView))
|
||||||
|
(def flat-list-comp (reagent/adapt-react-class IOFlatList))
|
||||||
|
|
||||||
|
(defn flat-list
|
||||||
|
[props]
|
||||||
|
[flat-list-comp (base-list-props props)])
|
|
@ -80,7 +80,10 @@
|
||||||
[opacity]
|
[opacity]
|
||||||
[reanimated/view {:style (reanimated/apply-animations-to-style {:opacity opacity} {})}
|
[reanimated/view {:style (reanimated/apply-animations-to-style {:opacity opacity} {})}
|
||||||
[quo/composer-button
|
[quo/composer-button
|
||||||
{:on-press #(js/alert "to be implemented")
|
{:on-press (fn []
|
||||||
|
(rf/dispatch [:chat.ui/set-input-focused false])
|
||||||
|
(rn/dismiss-keyboard!)
|
||||||
|
(js/alert "to be implemented"))
|
||||||
:icon :i/audio}]])
|
:icon :i/audio}]])
|
||||||
|
|
||||||
(defn audio-button
|
(defn audio-button
|
||||||
|
@ -213,13 +216,19 @@
|
||||||
[]
|
[]
|
||||||
[quo/composer-button
|
[quo/composer-button
|
||||||
{:icon :i/reaction
|
{:icon :i/reaction
|
||||||
:on-press #(js/alert "to be implemented")
|
:on-press (fn []
|
||||||
|
(rf/dispatch [:chat.ui/set-input-focused false])
|
||||||
|
(rn/dismiss-keyboard!)
|
||||||
|
(js/alert "to be implemented"))
|
||||||
:container-style {:margin-right 12}}])
|
:container-style {:margin-right 12}}])
|
||||||
|
|
||||||
(defn format-button
|
(defn format-button
|
||||||
[]
|
[]
|
||||||
[quo/composer-button
|
[quo/composer-button
|
||||||
{:on-press #(js/alert "to be implemented")
|
{:on-press (fn []
|
||||||
|
(rf/dispatch [:chat.ui/set-input-focused false])
|
||||||
|
(rn/dismiss-keyboard!)
|
||||||
|
(js/alert "to be implemented"))
|
||||||
:icon :i/format}])
|
:icon :i/format}])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
|
|
|
@ -172,7 +172,9 @@
|
||||||
(chat.state/reset-visible-item)
|
(chat.state/reset-visible-item)
|
||||||
(rf/merge cofx
|
(rf/merge cofx
|
||||||
(merge
|
(merge
|
||||||
{:db (dissoc db :current-chat-id)
|
{:db (-> db
|
||||||
|
(dissoc :current-chat-id)
|
||||||
|
(assoc-in [:chat/inputs chat-id :focused?] false))
|
||||||
:async-storage-set {:chat-id nil
|
:async-storage-set {:chat-id nil
|
||||||
:key-uid nil}}
|
:key-uid nil}}
|
||||||
(let [community-id (get-in db [:chats chat-id :community-id])]
|
(let [community-id (get-in db [:chats chat-id :community-id])]
|
||||||
|
|
|
@ -152,7 +152,9 @@
|
||||||
:outgoing-status outgoing-status})
|
:outgoing-status outgoing-status})
|
||||||
:on-press (fn []
|
:on-press (fn []
|
||||||
(if (and platform/ios? keyboard-shown?)
|
(if (and platform/ios? keyboard-shown?)
|
||||||
(rn/dismiss-keyboard!)
|
(do
|
||||||
|
(rf/dispatch [:chat.ui/set-input-focused false])
|
||||||
|
(rn/dismiss-keyboard!))
|
||||||
(when (and outgoing
|
(when (and outgoing
|
||||||
(not= outgoing-status :sending)
|
(not= outgoing-status :sending)
|
||||||
(not @show-delivery-state?))
|
(not @show-delivery-state?))
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.hooks :as hooks]
|
[react-native.hooks :as hooks]
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
|
[react-native.react-native-intersection-observer :as rnio]
|
||||||
[react-native.reanimated :as reanimated]
|
[react-native.reanimated :as reanimated]
|
||||||
[status-im.ui.screens.chat.group :as chat.group]
|
[status-im.ui.screens.chat.group :as chat.group]
|
||||||
[status-im.ui.screens.chat.message.gap :as message.gap]
|
[status-im.ui.screens.chat.message.gap :as message.gap]
|
||||||
|
@ -24,9 +25,12 @@
|
||||||
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
|
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
|
||||||
(defonce ^:const loading-indicator-extra-spacing 250)
|
(defonce ^:const loading-indicator-extra-spacing 250)
|
||||||
(defonce ^:const loading-indicator-page-loading-height 100)
|
(defonce ^:const loading-indicator-page-loading-height 100)
|
||||||
(defonce ^:const scroll-animation-input-range [50 125])
|
(defonce ^:const scroll-animation-input-range [0 50])
|
||||||
(defonce ^:const min-message-height 32)
|
(defonce ^:const min-message-height 32)
|
||||||
|
(defonce ^:const topbar-visible-scroll-y-value 85)
|
||||||
|
(defonce ^:const topbar-invisible-scroll-y-value 135)
|
||||||
|
(defonce ^:const minimum-scroll-y-topbar-overlaying-avatar 400)
|
||||||
|
(def root-margin-for-big-name-visibility-detector {:bottom -35})
|
||||||
(defonce messages-list-ref (atom nil))
|
(defonce messages-list-ref (atom nil))
|
||||||
|
|
||||||
(defn list-key-fn [{:keys [message-id value]}] (or message-id value))
|
(defn list-key-fn [{:keys [message-id value]}] (or message-id value))
|
||||||
|
@ -64,15 +68,15 @@
|
||||||
(= :message (:type first-not-visible)))
|
(= :message (:type first-not-visible)))
|
||||||
first-not-visible))))))
|
first-not-visible))))))
|
||||||
|
|
||||||
|
|
||||||
(defn list-on-end-reached
|
(defn list-on-end-reached
|
||||||
[scroll-y]
|
[scroll-y on-end-reached?]
|
||||||
;; FIXME: that's a bit of a hack but we need to update `scroll-y` once the new messages
|
;; FIXME: that's a bit of a hack but we need to update `scroll-y` once the new messages
|
||||||
;; are fetched in order for the header to work properly
|
;; are fetched in order for the header to work properly
|
||||||
(let [on-loaded (fn [n]
|
(let [on-loaded (fn [n]
|
||||||
(reanimated/set-shared-value scroll-y
|
(reanimated/set-shared-value scroll-y
|
||||||
(+ (reanimated/get-shared-value scroll-y)
|
(+ (reanimated/get-shared-value scroll-y)
|
||||||
(* n 200))))]
|
(* n 200))))]
|
||||||
|
(reset! on-end-reached? true)
|
||||||
(if @state/scrolling
|
(if @state/scrolling
|
||||||
(rf/dispatch [:chat.ui/load-more-messages-for-current-chat on-loaded])
|
(rf/dispatch [:chat.ui/load-more-messages-for-current-chat on-loaded])
|
||||||
(background-timer/set-timeout #(rf/dispatch [:chat.ui/load-more-messages-for-current-chat
|
(background-timer/set-timeout #(rf/dispatch [:chat.ui/load-more-messages-for-current-chat
|
||||||
|
@ -194,7 +198,7 @@
|
||||||
|
|
||||||
(defn f-list-footer
|
(defn f-list-footer
|
||||||
[{:keys [chat scroll-y cover-bg-color on-layout theme messages-view-height
|
[{:keys [chat scroll-y cover-bg-color on-layout theme messages-view-height
|
||||||
messages-view-header-height]}]
|
messages-view-header-height big-name-visible?]}]
|
||||||
(let [{:keys [chat-id chat-name emoji chat-type
|
(let [{:keys [chat-id chat-name emoji chat-type
|
||||||
group-chat]} chat
|
group-chat]} chat
|
||||||
all-loaded? (rf/sub [:chats/all-loaded? chat-id])
|
all-loaded? (rf/sub [:chats/all-loaded? chat-id])
|
||||||
|
@ -227,8 +231,10 @@
|
||||||
:display-name display-name
|
:display-name display-name
|
||||||
:online? online?
|
:online? online?
|
||||||
:profile-picture photo-path}])]
|
:profile-picture photo-path}])]
|
||||||
[rn/view
|
[rnio/view
|
||||||
{:style {:flex-direction :row
|
{:on-change (fn [view-visible?]
|
||||||
|
(reset! big-name-visible? view-visible?))
|
||||||
|
:style {:flex-direction :row
|
||||||
:margin-top (if group-chat 54 12)}}
|
:margin-top (if group-chat 54 12)}}
|
||||||
[quo/text
|
[quo/text
|
||||||
{:weight :semi-bold
|
{:weight :semi-bold
|
||||||
|
@ -275,14 +281,31 @@
|
||||||
[message/message message-data context keyboard-shown?])]))
|
[message/message message-data context keyboard-shown?])]))
|
||||||
|
|
||||||
(defn scroll-handler
|
(defn scroll-handler
|
||||||
[event scroll-y]
|
[event scroll-y animate-topbar-opacity? on-end-reached? animate-topbar-name?]
|
||||||
(let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height")
|
(let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height")
|
||||||
(oops/oget event "nativeEvent.layoutMeasurement.height"))
|
(oops/oget event "nativeEvent.layoutMeasurement.height"))
|
||||||
current-y (oops/oget event "nativeEvent.contentOffset.y")]
|
current-y (oops/oget event "nativeEvent.contentOffset.y")
|
||||||
(reanimated/set-shared-value scroll-y (- content-size-y current-y))))
|
scroll-distance (- content-size-y current-y)]
|
||||||
|
(when (and @on-end-reached? (pos? scroll-distance))
|
||||||
|
(reset! on-end-reached? false))
|
||||||
|
(if (< topbar-visible-scroll-y-value scroll-distance)
|
||||||
|
(reset! animate-topbar-opacity? true)
|
||||||
|
(reset! animate-topbar-opacity? false))
|
||||||
|
(if (< topbar-invisible-scroll-y-value scroll-distance)
|
||||||
|
(reset! animate-topbar-name? true)
|
||||||
|
(reset! animate-topbar-name? false))
|
||||||
|
(reanimated/set-shared-value scroll-y scroll-distance)))
|
||||||
|
|
||||||
(defn f-messages-list-content
|
(defn f-messages-list-content
|
||||||
[{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms]}]
|
[{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms
|
||||||
|
big-name-visible? animate-topbar-opacity? composer-active?
|
||||||
|
on-end-reached? animate-topbar-name?]}]
|
||||||
|
(rn/use-effect (fn []
|
||||||
|
(if (and (not @on-end-reached?)
|
||||||
|
(< topbar-visible-scroll-y-value (reanimated/get-shared-value scroll-y)))
|
||||||
|
(reset! animate-topbar-opacity? true)
|
||||||
|
(reset! animate-topbar-opacity? false)))
|
||||||
|
[composer-active? @on-end-reached? @animate-topbar-opacity?])
|
||||||
(let [theme (quo.theme/use-theme-value)
|
(let [theme (quo.theme/use-theme-value)
|
||||||
{window-height :height} (rn/get-window)
|
{window-height :height} (rn/get-window)
|
||||||
{:keys [keyboard-height]} (hooks/use-keyboard)
|
{:keys [keyboard-height]} (hooks/use-keyboard)
|
||||||
|
@ -294,8 +317,9 @@
|
||||||
messages-view-height
|
messages-view-height
|
||||||
messages-view-header-height]} inner-state-atoms]
|
messages-view-header-height]} inner-state-atoms]
|
||||||
[rn/view {:style {:flex 1}}
|
[rn/view {:style {:flex 1}}
|
||||||
[rn/flat-list
|
[rnio/flat-list
|
||||||
{:key-fn list-key-fn
|
{:root-margin root-margin-for-big-name-visibility-detector
|
||||||
|
:key-fn list-key-fn
|
||||||
:ref list-ref
|
:ref list-ref
|
||||||
:bounces false
|
:bounces false
|
||||||
:header [:<>
|
:header [:<>
|
||||||
|
@ -311,7 +335,8 @@
|
||||||
%
|
%
|
||||||
messages-view-header-height)
|
messages-view-header-height)
|
||||||
:messages-view-header-height messages-view-header-height
|
:messages-view-header-height messages-view-header-height
|
||||||
:messages-view-height messages-view-height}]
|
:messages-view-height messages-view-height
|
||||||
|
:big-name-visible? big-name-visible?}]
|
||||||
:data messages
|
:data messages
|
||||||
:render-data {:theme theme
|
:render-data {:theme theme
|
||||||
:context context
|
:context context
|
||||||
|
@ -320,10 +345,23 @@
|
||||||
:render-fn render-fn
|
:render-fn render-fn
|
||||||
:on-viewable-items-changed on-viewable-items-changed
|
:on-viewable-items-changed on-viewable-items-changed
|
||||||
:on-content-size-change (fn [_ y]
|
:on-content-size-change (fn [_ y]
|
||||||
;; NOTE(alwx): here we set the initial value of `scroll-y`
|
(if (or
|
||||||
;; which is needed because by default the chat is
|
(< minimum-scroll-y-topbar-overlaying-avatar
|
||||||
;; scrolled to the bottom and no initial `on-scroll`
|
(reanimated/get-shared-value scroll-y))
|
||||||
;; event is getting triggered
|
(< topbar-visible-scroll-y-value
|
||||||
|
(reanimated/get-shared-value scroll-y)))
|
||||||
|
(reset! animate-topbar-opacity? true)
|
||||||
|
(reset! animate-topbar-opacity? false))
|
||||||
|
(when-not (or
|
||||||
|
(not @big-name-visible?)
|
||||||
|
(= :initial-render @big-name-visible?)
|
||||||
|
(pos? (reanimated/get-shared-value
|
||||||
|
scroll-y)))
|
||||||
|
(reset! on-end-reached? false))
|
||||||
|
;; NOTE(alwx): here we set the initial value of
|
||||||
|
;; `scroll-y` which is needed because by default the
|
||||||
|
;; chat is scrolled to the bottom and no initial
|
||||||
|
;; `on-scroll` event is getting triggered
|
||||||
(let [scroll-y-shared (reanimated/get-shared-value
|
(let [scroll-y-shared (reanimated/get-shared-value
|
||||||
scroll-y)
|
scroll-y)
|
||||||
content-height-shared (reanimated/get-shared-value
|
content-height-shared (reanimated/get-shared-value
|
||||||
|
@ -337,19 +375,25 @@
|
||||||
(- (when keyboard-shown?
|
(- (when keyboard-shown?
|
||||||
keyboard-height))))
|
keyboard-height))))
|
||||||
(reanimated/set-shared-value content-height y))))
|
(reanimated/set-shared-value content-height y))))
|
||||||
:on-end-reached #(list-on-end-reached scroll-y)
|
:on-end-reached #(list-on-end-reached scroll-y on-end-reached?)
|
||||||
:on-scroll-to-index-failed identity
|
:on-scroll-to-index-failed identity
|
||||||
:scroll-indicator-insets {:top (if (:able-to-send-message? context)
|
:scroll-indicator-insets {:top (if (:able-to-send-message? context)
|
||||||
(- composer.constants/composer-default-height 16)
|
(- composer.constants/composer-default-height 16)
|
||||||
0)}
|
0)}
|
||||||
:keyboard-dismiss-mode :interactive
|
:keyboard-dismiss-mode :interactive
|
||||||
:keyboard-should-persist-taps :always
|
:keyboard-should-persist-taps :always
|
||||||
:on-scroll-begin-drag rn/dismiss-keyboard!
|
:on-scroll-begin-drag #(do
|
||||||
|
(rf/dispatch [:chat.ui/set-input-focused false])
|
||||||
|
(rn/dismiss-keyboard!))
|
||||||
:on-momentum-scroll-begin state/start-scrolling
|
:on-momentum-scroll-begin state/start-scrolling
|
||||||
:on-momentum-scroll-end state/stop-scrolling
|
:on-momentum-scroll-end state/stop-scrolling
|
||||||
:scroll-event-throttle 16
|
:scroll-event-throttle 16
|
||||||
:on-scroll (fn [event]
|
:on-scroll (fn [event]
|
||||||
(scroll-handler event scroll-y)
|
(scroll-handler event
|
||||||
|
scroll-y
|
||||||
|
animate-topbar-opacity?
|
||||||
|
on-end-reached?
|
||||||
|
animate-topbar-name?)
|
||||||
(on-scroll event show-floating-scroll-down-button?))
|
(on-scroll event show-floating-scroll-down-button?))
|
||||||
:style (add-inverted-y-android
|
:style (add-inverted-y-android
|
||||||
{:background-color (if all-loaded?
|
{:background-color (if all-loaded?
|
||||||
|
|
|
@ -10,38 +10,93 @@
|
||||||
[react-native.reanimated :as reanimated]
|
[react-native.reanimated :as reanimated]
|
||||||
[status-im2.common.home.actions.view :as actions]
|
[status-im2.common.home.actions.view :as actions]
|
||||||
[status-im2.config :as config]
|
[status-im2.config :as config]
|
||||||
|
[status-im2.contexts.chat.messages.list.view :refer [topbar-invisible-scroll-y-value]]
|
||||||
[status-im2.contexts.chat.messages.navigation.style :as style]
|
[status-im2.contexts.chat.messages.navigation.style :as style]
|
||||||
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
|
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(defonce ^:const title-opacity-interpolation-start 50)
|
||||||
|
;; This has two possibilities, One when sending messages and one when opening chat.
|
||||||
|
(defonce ^:const minimum-scroll-y-topbar-overlaying-avatar 80)
|
||||||
|
(defonce ^:const minimum-scroll-y-topbar-overlaying-avatar-2 350)
|
||||||
|
(defonce ^:const minimum-scroll-y-topbar-overlaying-avatar-composer-active 85)
|
||||||
|
|
||||||
(defn f-view
|
(defn f-view
|
||||||
[{:keys [theme scroll-y chat chat-screen-loaded? all-loaded? display-name online? photo-path
|
[{:keys [theme scroll-y chat chat-screen-loaded? all-loaded? display-name online? photo-path
|
||||||
back-icon]}]
|
back-icon animate-topbar-name? composer-active? big-name-visible? animate-topbar-opacity?
|
||||||
|
on-end-reached?]}]
|
||||||
(let [{:keys [group-chat chat-id]} chat
|
(let [{:keys [group-chat chat-id]} chat
|
||||||
opacity-animation (reanimated/interpolate scroll-y
|
opacity-animation (reanimated/use-shared-value 0)
|
||||||
[style/navigation-bar-height
|
banner-opacity-animation (reanimated/interpolate
|
||||||
(+ style/navigation-bar-height 30)]
|
scroll-y
|
||||||
[0 1]
|
|
||||||
{:extrapolateLeft "clamp"
|
|
||||||
:extrapolateRight "extend"})
|
|
||||||
banner-opacity-animation (reanimated/interpolate scroll-y
|
|
||||||
[(+ style/navigation-bar-height 150)
|
[(+ style/navigation-bar-height 150)
|
||||||
(+ style/navigation-bar-height 200)]
|
(+ style/navigation-bar-height 200)]
|
||||||
[0 1]
|
[0 1]
|
||||||
{:extrapolateLeft "clamp"
|
|
||||||
:extrapolateRight "extend"})
|
|
||||||
translate-animation (reanimated/interpolate scroll-y
|
|
||||||
[(+ style/navigation-bar-height 25)
|
|
||||||
(+ style/navigation-bar-height 100)]
|
|
||||||
[50 0]
|
|
||||||
{:extrapolateLeft "clamp"
|
{:extrapolateLeft "clamp"
|
||||||
:extrapolateRight "clamp"})
|
:extrapolateRight "clamp"})
|
||||||
title-opacity-animation (reanimated/interpolate scroll-y
|
translate-animation (reanimated/use-shared-value
|
||||||
[0 50]
|
title-opacity-interpolation-start)
|
||||||
[0 1]
|
title-opacity-animation (reanimated/use-shared-value 0)
|
||||||
{:extrapolateLeft "clamp"
|
messages (rf/sub [:chats/raw-chat-messages-stream
|
||||||
:extrapolateRight "clamp"})]
|
(:chat-id chat)])
|
||||||
|
more-than-two-messages? (<= 2 (count messages))
|
||||||
|
more-than-four-messages? (<= 4 (count messages))
|
||||||
|
more-than-eight-messages? (<= 8 (count messages))
|
||||||
|
scroll-y-sending-eight-messages-threshold 469]
|
||||||
|
(rn/use-effect
|
||||||
|
(fn []
|
||||||
|
(if
|
||||||
|
(or
|
||||||
|
(and (not composer-active?)
|
||||||
|
more-than-eight-messages?
|
||||||
|
(= :initial-render @big-name-visible?))
|
||||||
|
(and
|
||||||
|
(< minimum-scroll-y-topbar-overlaying-avatar (reanimated/get-shared-value scroll-y))
|
||||||
|
(not @on-end-reached?))
|
||||||
|
(and (if platform/ios? more-than-two-messages? more-than-four-messages?)
|
||||||
|
composer-active?)
|
||||||
|
(and
|
||||||
|
(not @on-end-reached?)
|
||||||
|
@animate-topbar-opacity?)
|
||||||
|
|
||||||
|
(or
|
||||||
|
(< minimum-scroll-y-topbar-overlaying-avatar-2 (reanimated/get-shared-value scroll-y))
|
||||||
|
(and (pos? (count messages))
|
||||||
|
composer-active?
|
||||||
|
(< minimum-scroll-y-topbar-overlaying-avatar-composer-active
|
||||||
|
(reanimated/get-shared-value scroll-y)))))
|
||||||
|
(reanimated/animate opacity-animation 1)
|
||||||
|
(reanimated/animate opacity-animation 0))
|
||||||
|
(if (when-not (and
|
||||||
|
@on-end-reached?
|
||||||
|
(not composer-active?)
|
||||||
|
(true? @big-name-visible?))
|
||||||
|
(or
|
||||||
|
(and
|
||||||
|
(and composer-active?
|
||||||
|
(not @big-name-visible?))
|
||||||
|
(< topbar-invisible-scroll-y-value (reanimated/get-shared-value scroll-y)))
|
||||||
|
(<= scroll-y-sending-eight-messages-threshold (reanimated/get-shared-value scroll-y))
|
||||||
|
(and (not composer-active?)
|
||||||
|
more-than-eight-messages?
|
||||||
|
(= :initial-render @big-name-visible?))
|
||||||
|
;; Keyboard height increasing is different between iOS and Android, That's why we have two
|
||||||
|
;; values.
|
||||||
|
(and (if platform/ios? more-than-two-messages? more-than-four-messages?)
|
||||||
|
(< title-opacity-interpolation-start (reanimated/get-shared-value scroll-y))
|
||||||
|
composer-active?)
|
||||||
|
(and (if platform/ios? more-than-two-messages? more-than-four-messages?)
|
||||||
|
composer-active?)
|
||||||
|
@animate-topbar-name?))
|
||||||
|
(do
|
||||||
|
(reanimated/animate title-opacity-animation 1)
|
||||||
|
(reanimated/animate translate-animation 0))
|
||||||
|
(do
|
||||||
|
(reanimated/animate title-opacity-animation 0)
|
||||||
|
(reanimated/animate translate-animation title-opacity-interpolation-start))))
|
||||||
|
[@animate-topbar-name? @big-name-visible? @animate-topbar-opacity? composer-active?
|
||||||
|
@on-end-reached?])
|
||||||
[rn/view {:style (style/navigation-view chat-screen-loaded?)}
|
[rn/view {:style (style/navigation-view chat-screen-loaded?)}
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (style/animated-background-view all-loaded? opacity-animation nil)}]
|
{:style (style/animated-background-view all-loaded? opacity-animation nil)}]
|
||||||
|
|
|
@ -14,11 +14,13 @@
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn f-chat
|
(defn f-chat
|
||||||
[{:keys [extra-keyboard-height show-floating-scroll-down-button?] :as inner-state-atoms}]
|
[{:keys [show-floating-scroll-down-button? animate-topbar-name?
|
||||||
|
big-name-visible? animate-topbar-opacity? on-end-reached?]
|
||||||
|
:as inner-state-atoms}]
|
||||||
(let [insets (safe-area/get-insets)
|
(let [insets (safe-area/get-insets)
|
||||||
scroll-y (reanimated/use-shared-value 0)
|
scroll-y (reanimated/use-shared-value 0)
|
||||||
content-height (reanimated/use-shared-value 0)
|
content-height (reanimated/use-shared-value 0)
|
||||||
{:keys [keyboard-height keyboard-shown]} (hooks/use-keyboard)
|
{:keys [keyboard-shown]} (hooks/use-keyboard)
|
||||||
{:keys [chat-id
|
{:keys [chat-id
|
||||||
contact-request-state
|
contact-request-state
|
||||||
group-chat
|
group-chat
|
||||||
|
@ -42,23 +44,10 @@
|
||||||
photo-path (rf/sub [:chats/photo-path chat-id])
|
photo-path (rf/sub [:chats/photo-path chat-id])
|
||||||
back-icon (if (= chat-type constants/one-to-one-chat-type)
|
back-icon (if (= chat-type constants/one-to-one-chat-type)
|
||||||
:i/close
|
:i/close
|
||||||
:i/arrow-left)]
|
:i/arrow-left)
|
||||||
(rn/use-effect
|
{:keys [focused?]} (rf/sub [:chats/current-chat-input])]
|
||||||
(fn []
|
;; Note - Don't pass `behavior :height` to keyboard avoiding view,. It breaks composer -
|
||||||
;; If keyboard is shown then adjust `scroll-y`
|
;; https://github.com/status-im/status-mobile/issues/16595
|
||||||
(when (and keyboard-shown (> keyboard-height 0))
|
|
||||||
(reanimated/set-shared-value scroll-y
|
|
||||||
(+ (reanimated/get-shared-value scroll-y)
|
|
||||||
keyboard-height))
|
|
||||||
(reset! extra-keyboard-height keyboard-height))
|
|
||||||
;; If keyboard is not shown then subtract the keyboard height from `scroll-y` value
|
|
||||||
(when-not keyboard-shown
|
|
||||||
(reanimated/set-shared-value scroll-y
|
|
||||||
(- (reanimated/get-shared-value scroll-y)
|
|
||||||
@extra-keyboard-height))))
|
|
||||||
[keyboard-shown keyboard-height])
|
|
||||||
;; Note - Don't pass `behavior :height` to keyboard avoiding view,
|
|
||||||
;; It breaks composer - https://github.com/status-im/status-mobile/issues/16595
|
|
||||||
[rn/keyboard-avoiding-view
|
[rn/keyboard-avoiding-view
|
||||||
{:style (style/keyboard-avoiding-container insets)
|
{:style (style/keyboard-avoiding-container insets)
|
||||||
:keyboard-vertical-offset (- (:bottom insets))}
|
:keyboard-vertical-offset (- (:bottom insets))}
|
||||||
|
@ -70,17 +59,27 @@
|
||||||
:content-height content-height
|
:content-height content-height
|
||||||
:cover-bg-color :turquoise
|
:cover-bg-color :turquoise
|
||||||
:keyboard-shown? keyboard-shown
|
:keyboard-shown? keyboard-shown
|
||||||
:inner-state-atoms inner-state-atoms}]
|
:inner-state-atoms inner-state-atoms
|
||||||
|
:animate-topbar-name? animate-topbar-name?
|
||||||
|
:big-name-visible? big-name-visible?
|
||||||
|
:animate-topbar-opacity? animate-topbar-opacity?
|
||||||
|
:composer-active? focused?
|
||||||
|
:on-end-reached? on-end-reached?}]
|
||||||
|
|
||||||
[messages.navigation/navigation-view
|
[messages.navigation/navigation-view
|
||||||
{:scroll-y scroll-y
|
{:scroll-y scroll-y
|
||||||
|
:animate-topbar-name? animate-topbar-name?
|
||||||
:back-icon back-icon
|
:back-icon back-icon
|
||||||
:chat chat
|
:chat chat
|
||||||
:chat-screen-loaded? chat-screen-loaded?
|
:chat-screen-loaded? chat-screen-loaded?
|
||||||
:all-loaded? all-loaded?
|
:all-loaded? all-loaded?
|
||||||
:display-name display-name
|
:display-name display-name
|
||||||
:online? online?
|
:online? online?
|
||||||
:photo-path photo-path}]
|
:photo-path photo-path
|
||||||
|
:big-name-visible? big-name-visible?
|
||||||
|
:animate-topbar-opacity? animate-topbar-opacity?
|
||||||
|
:composer-active? focused?
|
||||||
|
:on-end-reached? on-end-reached?}]
|
||||||
|
|
||||||
(when (seq chat)
|
(when (seq chat)
|
||||||
(if able-to-send-message?
|
(if able-to-send-message?
|
||||||
|
@ -96,5 +95,9 @@
|
||||||
{:extra-keyboard-height (reagent/atom 0)
|
{:extra-keyboard-height (reagent/atom 0)
|
||||||
:show-floating-scroll-down-button? (reagent/atom false)
|
:show-floating-scroll-down-button? (reagent/atom false)
|
||||||
:messages-view-height (reagent/atom 0)
|
:messages-view-height (reagent/atom 0)
|
||||||
:messages-view-header-height (reagent/atom 0)}]
|
:messages-view-header-height (reagent/atom 0)
|
||||||
|
:animate-topbar-name? (reagent/atom false)
|
||||||
|
:big-name-visible? (reagent/atom :initial-render)
|
||||||
|
:animate-topbar-opacity? (reagent/atom false)
|
||||||
|
:on-end-reached? (reagent/atom false)}]
|
||||||
[:f> f-chat inner-state-atoms]))
|
[:f> f-chat inner-state-atoms]))
|
||||||
|
|
|
@ -7008,7 +7008,7 @@ lodash.union@^4.6.0:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
|
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
|
||||||
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
|
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
|
||||||
|
|
||||||
lodash@4.17.x, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
|
lodash@4.17.x, lodash@^4.0.0, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
@ -8875,6 +8875,13 @@ react-native-image-resizer@^1.2.3:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "git+https://github.com/status-im/react-native-image-viewing.git#94af89356f2e4e08f462370c77e4778d7626ce2f"
|
resolved "git+https://github.com/status-im/react-native-image-viewing.git#94af89356f2e4e08f462370c77e4778d7626ce2f"
|
||||||
|
|
||||||
|
react-native-intersection-observer@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-intersection-observer/-/react-native-intersection-observer-0.2.0.tgz#15a07cf2adbab6cd9821986168d5484405674ad9"
|
||||||
|
integrity sha512-h48i7AjYl1BLkfTupiJqv7dLUdLmxBIf4AxlrzvUvy5PLr3bnEFGTAMjaeUUcQklkdKSHRqIXP8wz1ex49my4g==
|
||||||
|
dependencies:
|
||||||
|
lodash "^4.0.0"
|
||||||
|
|
||||||
"react-native-keychain@git+https://github.com/status-im/react-native-keychain.git#refs/tags/v.3.0.0-5-status":
|
"react-native-keychain@git+https://github.com/status-im/react-native-keychain.git#refs/tags/v.3.0.0-5-status":
|
||||||
version "3.0.0-rc.3"
|
version "3.0.0-rc.3"
|
||||||
resolved "git+https://github.com/status-im/react-native-keychain.git#9b0d9b283116947cf125e12b6d1d17203604f0d9"
|
resolved "git+https://github.com/status-im/react-native-keychain.git#9b0d9b283116947cf125e12b6d1d17203604f0d9"
|
||||||
|
|
Loading…
Reference in New Issue