|
8 | 8 | [react-native.core :as rn]
|
9 | 9 | [react-native.hooks :as hooks]
|
10 | 10 | [react-native.platform :as platform]
|
| 11 | + [react-native.react-native-intersection-observer :as rnio] |
11 | 12 | [react-native.reanimated :as reanimated]
|
12 | 13 | [status-im.ui.screens.chat.group :as chat.group]
|
13 | 14 | [status-im.ui.screens.chat.message.gap :as message.gap]
|
|
24 | 25 | (defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
|
25 | 26 | (defonce ^:const loading-indicator-extra-spacing 250)
|
26 | 27 | (defonce ^:const loading-indicator-page-loading-height 100)
|
27 |
| -(defonce ^:const scroll-animation-input-range [50 125]) |
| 28 | +(defonce ^:const scroll-animation-input-range [0 50]) |
28 | 29 | (defonce ^:const min-message-height 32)
|
29 |
| - |
| 30 | +(defonce ^:const topbar-visible-scroll-y-value 85) |
| 31 | +(defonce ^:const topbar-invisible-scroll-y-value 135) |
| 32 | +(defonce ^:const minimum-scroll-y-topbar-overlaying-avatar 400) |
| 33 | +(def root-margin-for-big-name-visibility-detector {:bottom -35}) |
30 | 34 | (defonce messages-list-ref (atom nil))
|
31 | 35 |
|
32 | 36 | (defn list-key-fn [{:keys [message-id value]}] (or message-id value))
|
|
64 | 68 | (= :message (:type first-not-visible)))
|
65 | 69 | first-not-visible))))))
|
66 | 70 |
|
67 |
| - |
68 | 71 | (defn list-on-end-reached
|
69 |
| - [scroll-y] |
| 72 | + [scroll-y on-end-reached?] |
70 | 73 | ;; FIXME: that's a bit of a hack but we need to update `scroll-y` once the new messages
|
71 | 74 | ;; are fetched in order for the header to work properly
|
72 | 75 | (let [on-loaded (fn [n]
|
73 | 76 | (reanimated/set-shared-value scroll-y
|
74 | 77 | (+ (reanimated/get-shared-value scroll-y)
|
75 | 78 | (* n 200))))]
|
| 79 | + (reset! on-end-reached? true) |
76 | 80 | (if @state/scrolling
|
77 | 81 | (rf/dispatch [:chat.ui/load-more-messages-for-current-chat on-loaded])
|
78 | 82 | (background-timer/set-timeout #(rf/dispatch [:chat.ui/load-more-messages-for-current-chat
|
|
194 | 198 |
|
195 | 199 | (defn f-list-footer
|
196 | 200 | [{:keys [chat scroll-y cover-bg-color on-layout theme messages-view-height
|
197 |
| - messages-view-header-height]}] |
| 201 | + messages-view-header-height big-name-visible?]}] |
198 | 202 | (let [{:keys [chat-id chat-name emoji chat-type
|
199 | 203 | group-chat]} chat
|
200 | 204 | all-loaded? (rf/sub [:chats/all-loaded? chat-id])
|
|
227 | 231 | :display-name display-name
|
228 | 232 | :online? online?
|
229 | 233 | :profile-picture photo-path}])]
|
230 |
| - [rn/view |
231 |
| - {:style {:flex-direction :row |
232 |
| - :margin-top (if group-chat 54 12)}} |
| 234 | + [rnio/view |
| 235 | + {:on-change (fn [view-visible?] |
| 236 | + (reset! big-name-visible? view-visible?)) |
| 237 | + :style {:flex-direction :row |
| 238 | + :margin-top (if group-chat 54 12)}} |
233 | 239 | [quo/text
|
234 | 240 | {:weight :semi-bold
|
235 | 241 | :size :heading-1
|
|
275 | 281 | [message/message message-data context keyboard-shown?])]))
|
276 | 282 |
|
277 | 283 | (defn scroll-handler
|
278 |
| - [event scroll-y] |
279 |
| - (let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height") |
280 |
| - (oops/oget event "nativeEvent.layoutMeasurement.height")) |
281 |
| - current-y (oops/oget event "nativeEvent.contentOffset.y")] |
282 |
| - (reanimated/set-shared-value scroll-y (- content-size-y current-y)))) |
| 284 | + [event scroll-y animate-topbar-opacity? on-end-reached? animate-topbar-name?] |
| 285 | + (let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height") |
| 286 | + (oops/oget event "nativeEvent.layoutMeasurement.height")) |
| 287 | + current-y (oops/oget event "nativeEvent.contentOffset.y") |
| 288 | + scroll-distance (- content-size-y current-y)] |
| 289 | + (when (and @on-end-reached? (pos? scroll-distance)) |
| 290 | + (reset! on-end-reached? false)) |
| 291 | + (if (< topbar-visible-scroll-y-value scroll-distance) |
| 292 | + (reset! animate-topbar-opacity? true) |
| 293 | + (reset! animate-topbar-opacity? false)) |
| 294 | + (if (< topbar-invisible-scroll-y-value scroll-distance) |
| 295 | + (reset! animate-topbar-name? true) |
| 296 | + (reset! animate-topbar-name? false)) |
| 297 | + (reanimated/set-shared-value scroll-y scroll-distance))) |
283 | 298 |
|
284 | 299 | (defn f-messages-list-content
|
285 |
| - [{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms]}] |
| 300 | + [{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms |
| 301 | + big-name-visible? animate-topbar-opacity? composer-active? |
| 302 | + on-end-reached? animate-topbar-name?]}] |
| 303 | + (rn/use-effect (fn [] |
| 304 | + (if (and (not @on-end-reached?) |
| 305 | + (< topbar-visible-scroll-y-value (reanimated/get-shared-value scroll-y))) |
| 306 | + (reset! animate-topbar-opacity? true) |
| 307 | + (reset! animate-topbar-opacity? false))) |
| 308 | + [composer-active? @on-end-reached? @animate-topbar-opacity?]) |
286 | 309 | (let [theme (quo.theme/use-theme-value)
|
287 | 310 | {window-height :height} (rn/get-window)
|
288 | 311 | {:keys [keyboard-height]} (hooks/use-keyboard)
|
|
294 | 317 | messages-view-height
|
295 | 318 | messages-view-header-height]} inner-state-atoms]
|
296 | 319 | [rn/view {:style {:flex 1}}
|
297 |
| - [rn/flat-list |
298 |
| - {:key-fn list-key-fn |
| 320 | + [rnio/flat-list |
| 321 | + {:root-margin root-margin-for-big-name-visibility-detector |
| 322 | + :key-fn list-key-fn |
299 | 323 | :ref list-ref
|
300 | 324 | :bounces false
|
301 | 325 | :header [:<>
|
|
311 | 335 | %
|
312 | 336 | messages-view-header-height)
|
313 | 337 | :messages-view-header-height messages-view-header-height
|
314 |
| - :messages-view-height messages-view-height}] |
| 338 | + :messages-view-height messages-view-height |
| 339 | + :big-name-visible? big-name-visible?}] |
315 | 340 | :data messages
|
316 | 341 | :render-data {:theme theme
|
317 | 342 | :context context
|
|
320 | 345 | :render-fn render-fn
|
321 | 346 | :on-viewable-items-changed on-viewable-items-changed
|
322 | 347 | :on-content-size-change (fn [_ y]
|
323 |
| - ;; NOTE(alwx): here we set the initial value of `scroll-y` |
324 |
| - ;; which is needed because by default the chat is |
325 |
| - ;; scrolled to the bottom and no initial `on-scroll` |
326 |
| - ;; event is getting triggered |
| 348 | + (if (or |
| 349 | + (< minimum-scroll-y-topbar-overlaying-avatar |
| 350 | + (reanimated/get-shared-value scroll-y)) |
| 351 | + (< topbar-visible-scroll-y-value |
| 352 | + (reanimated/get-shared-value scroll-y))) |
| 353 | + (reset! animate-topbar-opacity? true) |
| 354 | + (reset! animate-topbar-opacity? false)) |
| 355 | + (when-not (or |
| 356 | + (not @big-name-visible?) |
| 357 | + (= :initial-render @big-name-visible?) |
| 358 | + (pos? (reanimated/get-shared-value |
| 359 | + scroll-y))) |
| 360 | + (reset! on-end-reached? false)) |
| 361 | + ;; NOTE(alwx): here we set the initial value of |
| 362 | + ;; `scroll-y` which is needed because by default the |
| 363 | + ;; chat is scrolled to the bottom and no initial |
| 364 | + ;; `on-scroll` event is getting triggered |
327 | 365 | (let [scroll-y-shared (reanimated/get-shared-value
|
328 | 366 | scroll-y)
|
329 | 367 | content-height-shared (reanimated/get-shared-value
|
|
337 | 375 | (- (when keyboard-shown?
|
338 | 376 | keyboard-height))))
|
339 | 377 | (reanimated/set-shared-value content-height y))))
|
340 |
| - :on-end-reached #(list-on-end-reached scroll-y) |
| 378 | + :on-end-reached #(list-on-end-reached scroll-y on-end-reached?) |
341 | 379 | :on-scroll-to-index-failed identity
|
342 | 380 | :scroll-indicator-insets {:top (if (:able-to-send-message? context)
|
343 | 381 | (- composer.constants/composer-default-height 16)
|
344 | 382 | 0)}
|
345 | 383 | :keyboard-dismiss-mode :interactive
|
346 | 384 | :keyboard-should-persist-taps :always
|
347 |
| - :on-scroll-begin-drag rn/dismiss-keyboard! |
| 385 | + :on-scroll-begin-drag #(do |
| 386 | + (rf/dispatch [:chat.ui/set-input-focused false]) |
| 387 | + (rn/dismiss-keyboard!)) |
348 | 388 | :on-momentum-scroll-begin state/start-scrolling
|
349 | 389 | :on-momentum-scroll-end state/stop-scrolling
|
350 | 390 | :scroll-event-throttle 16
|
351 | 391 | :on-scroll (fn [event]
|
352 |
| - (scroll-handler event scroll-y) |
| 392 | + (scroll-handler event |
| 393 | + scroll-y |
| 394 | + animate-topbar-opacity? |
| 395 | + on-end-reached? |
| 396 | + animate-topbar-name?) |
353 | 397 | (on-scroll event show-floating-scroll-down-button?))
|
354 | 398 | :style (add-inverted-y-android
|
355 | 399 | {:background-color (if all-loaded?
|
|
0 commit comments