Mirror — see github.com/blacksky-algorithms/blacksky.community
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix message input overlapping messages on mobile web

On mobile web, the DM conversation sets minimal shell mode to hide
the bottom tab bar. However, footerHeight (set by the bar's onLayout)
persisted at ~50px even after the bar was hidden. The animated
translateY on the message input pulled it up by footerHeight, but
the corresponding marginBottom on the List (a regular View, not
Animated.View) may not have updated, causing the input to overlap
the last visible messages.

Introduce effectiveFooterHeight via useDerivedValue that interpolates
footerHeight down to 0 as footerMode transitions to 1 (hidden). This
ensures both the list margin and input translation stay in sync and
resolve to 0 when the bar is hidden.

+22 -7
+22 -7
src/screens/Messages/components/MessagesList.tsx
··· 2 2 import {type LayoutChangeEvent, View} from 'react-native' 3 3 import {useKeyboardHandler} from 'react-native-keyboard-controller' 4 4 import Animated, { 5 + interpolate, 5 6 runOnJS, 6 7 scrollTo, 7 8 useAnimatedRef, 8 9 useAnimatedStyle, 10 + useDerivedValue, 9 11 useSharedValue, 10 12 } from 'react-native-reanimated' 11 13 import {type ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes' ··· 36 38 } from '#/state/messages/convo/types' 37 39 import {useGetPost} from '#/state/queries/post' 38 40 import {useAgent} from '#/state/session' 41 + import {useMinimalShellMode} from '#/state/shell/minimal-mode' 39 42 import {useShellLayout} from '#/state/shell/shell-layout' 40 43 import { 41 44 EmojiPicker, ··· 50 53 import {NewMessagesPill} from '#/components/dms/NewMessagesPill' 51 54 import {Loader} from '#/components/Loader' 52 55 import {Text} from '#/components/Typography' 53 - import {IS_NATIVE} from '#/env' 54 - import {IS_WEB} from '#/env' 56 + import {IS_NATIVE, IS_WEB} from '#/env' 55 57 import {ChatStatusInfo} from './ChatStatusInfo' 56 58 import {MessageInputEmbed, useMessageEmbed} from './MessageInputEmbed' 57 59 ··· 255 257 256 258 // -- Keyboard animation handling 257 259 const {footerHeight} = useShellLayout() 260 + const {footerMode} = useMinimalShellMode() 261 + 262 + // When the bottom bar is hidden (minimal shell mode on mobile web), don't 263 + // reserve space for it. Without this, the input translateY pulls it into 264 + // the list area while the list marginBottom may not compensate on web. 265 + const effectiveFooterHeight = useDerivedValue(() => { 266 + return interpolate(footerMode.get(), [0, 1], [footerHeight.get(), 0]) 267 + }) 258 268 259 269 const keyboardHeight = useSharedValue(0) 260 270 const keyboardIsOpening = useSharedValue(false) ··· 279 289 onMove: e => { 280 290 'worklet' 281 291 keyboardHeight.set(e.height) 282 - if (e.height > footerHeight.get()) { 292 + if (e.height > effectiveFooterHeight.get()) { 283 293 scrollTo(flatListRef, 0, 1e7, false) 284 294 } 285 295 }, 286 296 onEnd: e => { 287 297 'worklet' 288 298 keyboardHeight.set(e.height) 289 - if (e.height > footerHeight.get()) { 299 + if (e.height > effectiveFooterHeight.get()) { 290 300 scrollTo(flatListRef, 0, 1e7, false) 291 301 } 292 302 keyboardIsOpening.set(false) 293 303 }, 294 304 }, 295 - [footerHeight], 305 + [effectiveFooterHeight], 296 306 ) 297 307 298 308 const animatedListStyle = useAnimatedStyle(() => ({ 299 - marginBottom: Math.max(keyboardHeight.get(), footerHeight.get()), 309 + marginBottom: Math.max(keyboardHeight.get(), effectiveFooterHeight.get()), 300 310 })) 301 311 302 312 const animatedStickyViewStyle = useAnimatedStyle(() => ({ 303 313 transform: [ 304 - {translateY: -Math.max(keyboardHeight.get(), footerHeight.get())}, 314 + { 315 + translateY: -Math.max( 316 + keyboardHeight.get(), 317 + effectiveFooterHeight.get(), 318 + ), 319 + }, 305 320 ], 306 321 })) 307 322