From 132e53844c7dd7637b5946ea4da1b69203b3faa0 Mon Sep 17 00:00:00 2001 From: Ibrahem Khalil Date: Fri, 3 Nov 2023 14:20:10 +0200 Subject: [PATCH] New TopBar animation (#17582) --- package.json | 1 + src/mocks/js_dependencies.cljs | 6 + .../react_native_intersection_observer.cljs | 12 ++ .../contexts/chat/composer/actions/view.cljs | 15 ++- src/status_im2/contexts/chat/events.cljs | 4 +- .../contexts/chat/messages/content/view.cljs | 4 +- .../contexts/chat/messages/list/view.cljs | 92 +++++++++++---- .../chat/messages/navigation/view.cljs | 105 +++++++++++++---- .../contexts/chat/messages/view.cljs | 111 +++++++++--------- yarn.lock | 9 +- 10 files changed, 250 insertions(+), 109 deletions(-) create mode 100644 src/react_native/react_native_intersection_observer.cljs diff --git a/package.json b/package.json index 070c1cd844..d5b791f217 100644 --- a/package.json +++ b/package.json @@ -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-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-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-languages": "^3.0.2", "react-native-linear-gradient": "^2.8.0", diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index f062203d4c..e4e809e981 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -300,6 +300,11 @@ {:clamp nil :withPause (fn [])}) +(def react-native-intersection-observer + #js + {:InView #js {} + :IOFlatList #js {}}) + (def react-native-languages (clj->js {:default {:language "en" :addEventListener (fn []) @@ -426,6 +431,7 @@ "react-native-transparent-video" react-native-transparent-video "react-native-orientation-locker" react-native-orientation-locker "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")) "../src/js/worklets/core.js" worklet-factory diff --git a/src/react_native/react_native_intersection_observer.cljs b/src/react_native/react_native_intersection_observer.cljs new file mode 100644 index 0000000000..d44aa621ce --- /dev/null +++ b/src/react_native/react_native_intersection_observer.cljs @@ -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)]) diff --git a/src/status_im2/contexts/chat/composer/actions/view.cljs b/src/status_im2/contexts/chat/composer/actions/view.cljs index a196001368..927116dbac 100644 --- a/src/status_im2/contexts/chat/composer/actions/view.cljs +++ b/src/status_im2/contexts/chat/composer/actions/view.cljs @@ -80,7 +80,10 @@ [opacity] [reanimated/view {:style (reanimated/apply-animations-to-style {:opacity opacity} {})} [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}]]) (defn audio-button @@ -213,13 +216,19 @@ [] [quo/composer-button {: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}}]) (defn format-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}]) (defn view diff --git a/src/status_im2/contexts/chat/events.cljs b/src/status_im2/contexts/chat/events.cljs index c54fb68971..9819f370a6 100644 --- a/src/status_im2/contexts/chat/events.cljs +++ b/src/status_im2/contexts/chat/events.cljs @@ -172,7 +172,9 @@ (chat.state/reset-visible-item) (rf/merge cofx (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 :key-uid nil}} (let [community-id (get-in db [:chats chat-id :community-id])] diff --git a/src/status_im2/contexts/chat/messages/content/view.cljs b/src/status_im2/contexts/chat/messages/content/view.cljs index 0cc98c0b8c..91315f994e 100644 --- a/src/status_im2/contexts/chat/messages/content/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/view.cljs @@ -152,7 +152,9 @@ :outgoing-status outgoing-status}) :on-press (fn [] (if (and platform/ios? keyboard-shown?) - (rn/dismiss-keyboard!) + (do + (rf/dispatch [:chat.ui/set-input-focused false]) + (rn/dismiss-keyboard!)) (when (and outgoing (not= outgoing-status :sending) (not @show-delivery-state?)) diff --git a/src/status_im2/contexts/chat/messages/list/view.cljs b/src/status_im2/contexts/chat/messages/list/view.cljs index 0b3b813215..5311f563db 100644 --- a/src/status_im2/contexts/chat/messages/list/view.cljs +++ b/src/status_im2/contexts/chat/messages/list/view.cljs @@ -8,6 +8,7 @@ [react-native.core :as rn] [react-native.hooks :as hooks] [react-native.platform :as platform] + [react-native.react-native-intersection-observer :as rnio] [react-native.reanimated :as reanimated] [status-im.ui.screens.chat.group :as chat.group] [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 loading-indicator-extra-spacing 250) (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 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)) (defn list-key-fn [{:keys [message-id value]}] (or message-id value)) @@ -64,15 +68,15 @@ (= :message (:type first-not-visible))) first-not-visible)))))) - (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 ;; are fetched in order for the header to work properly (let [on-loaded (fn [n] (reanimated/set-shared-value scroll-y (+ (reanimated/get-shared-value scroll-y) (* n 200))))] + (reset! on-end-reached? true) (if @state/scrolling (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 @@ -194,7 +198,7 @@ (defn f-list-footer [{: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 group-chat]} chat all-loaded? (rf/sub [:chats/all-loaded? chat-id]) @@ -227,9 +231,11 @@ :display-name display-name :online? online? :profile-picture photo-path}])] - [rn/view - {:style {:flex-direction :row - :margin-top (if group-chat 54 12)}} + [rnio/view + {:on-change (fn [view-visible?] + (reset! big-name-visible? view-visible?)) + :style {:flex-direction :row + :margin-top (if group-chat 54 12)}} [quo/text {:weight :semi-bold :size :heading-1 @@ -275,14 +281,31 @@ [message/message message-data context keyboard-shown?])])) (defn scroll-handler - [event scroll-y] - (let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height") - (oops/oget event "nativeEvent.layoutMeasurement.height")) - current-y (oops/oget event "nativeEvent.contentOffset.y")] - (reanimated/set-shared-value scroll-y (- content-size-y current-y)))) + [event scroll-y animate-topbar-opacity? on-end-reached? animate-topbar-name?] + (let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height") + (oops/oget event "nativeEvent.layoutMeasurement.height")) + current-y (oops/oget event "nativeEvent.contentOffset.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 - [{: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) {window-height :height} (rn/get-window) {:keys [keyboard-height]} (hooks/use-keyboard) @@ -294,8 +317,9 @@ messages-view-height messages-view-header-height]} inner-state-atoms] [rn/view {:style {:flex 1}} - [rn/flat-list - {:key-fn list-key-fn + [rnio/flat-list + {:root-margin root-margin-for-big-name-visibility-detector + :key-fn list-key-fn :ref list-ref :bounces false :header [:<> @@ -311,7 +335,8 @@ % 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 :render-data {:theme theme :context context @@ -320,10 +345,23 @@ :render-fn render-fn :on-viewable-items-changed on-viewable-items-changed :on-content-size-change (fn [_ y] - ;; 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 + (if (or + (< minimum-scroll-y-topbar-overlaying-avatar + (reanimated/get-shared-value scroll-y)) + (< 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 scroll-y) content-height-shared (reanimated/get-shared-value @@ -337,19 +375,25 @@ (- (when keyboard-shown? keyboard-height)))) (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 :scroll-indicator-insets {:top (if (:able-to-send-message? context) (- composer.constants/composer-default-height 16) 0)} :keyboard-dismiss-mode :interactive :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-end state/stop-scrolling :scroll-event-throttle 16 :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?)) :style (add-inverted-y-android {:background-color (if all-loaded? diff --git a/src/status_im2/contexts/chat/messages/navigation/view.cljs b/src/status_im2/contexts/chat/messages/navigation/view.cljs index b36ef8a61e..e1354d0026 100644 --- a/src/status_im2/contexts/chat/messages/navigation/view.cljs +++ b/src/status_im2/contexts/chat/messages/navigation/view.cljs @@ -10,38 +10,93 @@ [react-native.reanimated :as reanimated] [status-im2.common.home.actions.view :as actions] [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.pin.banner.view :as pin.banner] [utils.i18n :as i18n] [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 [{:keys [theme scroll-y chat chat-screen-loaded? all-loaded? display-name online? photo-path - back-icon]}] - (let [{:keys [group-chat chat-id]} chat - opacity-animation (reanimated/interpolate scroll-y - [style/navigation-bar-height - (+ style/navigation-bar-height 30)] - [0 1] - {:extrapolateLeft "clamp" - :extrapolateRight "extend"}) - banner-opacity-animation (reanimated/interpolate scroll-y - [(+ style/navigation-bar-height 150) - (+ style/navigation-bar-height 200)] - [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" - :extrapolateRight "clamp"}) - title-opacity-animation (reanimated/interpolate scroll-y - [0 50] - [0 1] - {:extrapolateLeft "clamp" - :extrapolateRight "clamp"})] + back-icon animate-topbar-name? composer-active? big-name-visible? animate-topbar-opacity? + on-end-reached?]}] + (let [{:keys [group-chat chat-id]} chat + opacity-animation (reanimated/use-shared-value 0) + banner-opacity-animation (reanimated/interpolate + scroll-y + [(+ style/navigation-bar-height 150) + (+ style/navigation-bar-height 200)] + [0 1] + {:extrapolateLeft "clamp" + :extrapolateRight "clamp"}) + translate-animation (reanimated/use-shared-value + title-opacity-interpolation-start) + title-opacity-animation (reanimated/use-shared-value 0) + messages (rf/sub [:chats/raw-chat-messages-stream + (: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?)} [reanimated/view {:style (style/animated-background-view all-loaded? opacity-animation nil)}] diff --git a/src/status_im2/contexts/chat/messages/view.cljs b/src/status_im2/contexts/chat/messages/view.cljs index cefec73c60..b6c29ea0df 100644 --- a/src/status_im2/contexts/chat/messages/view.cljs +++ b/src/status_im2/contexts/chat/messages/view.cljs @@ -14,11 +14,13 @@ [utils.re-frame :as rf])) (defn f-chat - [{:keys [extra-keyboard-height show-floating-scroll-down-button?] :as inner-state-atoms}] - (let [insets (safe-area/get-insets) - scroll-y (reanimated/use-shared-value 0) - content-height (reanimated/use-shared-value 0) - {:keys [keyboard-height keyboard-shown]} (hooks/use-keyboard) + [{: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) + scroll-y (reanimated/use-shared-value 0) + content-height (reanimated/use-shared-value 0) + {:keys [keyboard-shown]} (hooks/use-keyboard) {:keys [chat-id contact-request-state group-chat @@ -26,61 +28,58 @@ chat-type chat-name emoji] - :as chat} (rf/sub [:chats/current-chat-chat-view]) - chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?]) - all-loaded? (when chat-screen-loaded? - (rf/sub [:chats/all-loaded? (:chat-id chat)])) - display-name (cond - (= chat-type constants/one-to-one-chat-type) - (first (rf/sub - [:contacts/contact-two-names-by-identity - chat-id])) - (= chat-type constants/community-chat-type) - (str (when emoji (str emoji " ")) "# " chat-name) - :else (str emoji chat-name)) - online? (rf/sub [:visibility-status-updates/online? chat-id]) - photo-path (rf/sub [:chats/photo-path chat-id]) - back-icon (if (= chat-type constants/one-to-one-chat-type) - :i/close - :i/arrow-left)] - (rn/use-effect - (fn [] - ;; If keyboard is shown then adjust `scroll-y` - (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 + :as chat} (rf/sub [:chats/current-chat-chat-view]) + chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?]) + all-loaded? (when chat-screen-loaded? + (rf/sub [:chats/all-loaded? (:chat-id chat)])) + display-name (cond + (= chat-type constants/one-to-one-chat-type) + (first (rf/sub + [:contacts/contact-two-names-by-identity + chat-id])) + (= chat-type constants/community-chat-type) + (str (when emoji (str emoji " ")) "# " chat-name) + :else (str emoji chat-name)) + online? (rf/sub [:visibility-status-updates/online? chat-id]) + photo-path (rf/sub [:chats/photo-path chat-id]) + back-icon (if (= chat-type constants/one-to-one-chat-type) + :i/close + :i/arrow-left) + {:keys [focused?]} (rf/sub [:chats/current-chat-input])] + ;; 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 {:style (style/keyboard-avoiding-container insets) :keyboard-vertical-offset (- (:bottom insets))} [list.view/message-list-content-view - {:chat chat - :insets insets - :scroll-y scroll-y - :content-height content-height - :cover-bg-color :turquoise - :keyboard-shown? keyboard-shown - :inner-state-atoms inner-state-atoms}] + {:chat chat + :insets insets + :scroll-y scroll-y + :content-height content-height + :cover-bg-color :turquoise + :keyboard-shown? keyboard-shown + :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 - {:scroll-y scroll-y - :back-icon back-icon - :chat chat - :chat-screen-loaded? chat-screen-loaded? - :all-loaded? all-loaded? - :display-name display-name - :online? online? - :photo-path photo-path}] + {:scroll-y scroll-y + :animate-topbar-name? animate-topbar-name? + :back-icon back-icon + :chat chat + :chat-screen-loaded? chat-screen-loaded? + :all-loaded? all-loaded? + :display-name display-name + :online? online? + :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) (if able-to-send-message? @@ -96,5 +95,9 @@ {:extra-keyboard-height (reagent/atom 0) :show-floating-scroll-down-button? (reagent/atom false) :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])) diff --git a/yarn.lock b/yarn.lock index 499183a425..e6eba98c56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7008,7 +7008,7 @@ lodash.union@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" 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" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8875,6 +8875,13 @@ react-native-image-resizer@^1.2.3: version "0.2.1" 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": version "3.0.0-rc.3" resolved "git+https://github.com/status-im/react-native-keychain.git#9b0d9b283116947cf125e12b6d1d17203604f0d9"