From a04a944f46c4e2bf9c62d25501746e69c22db47a Mon Sep 17 00:00:00 2001 From: vineyardbovines Date: Tue, 5 May 2026 10:20:42 -0400 Subject: [PATCH] better smooth scrolling --- src/features/gifPicker/GifPickerDialog.tsx | 11 ++++++++--- src/features/gifPicker/components/GifPickerGrid.tsx | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/features/gifPicker/GifPickerDialog.tsx b/src/features/gifPicker/GifPickerDialog.tsx index bdcf3ca86f..677b953f55 100644 --- a/src/features/gifPicker/GifPickerDialog.tsx +++ b/src/features/gifPicker/GifPickerDialog.tsx @@ -1,4 +1,4 @@ -import {useImperativeHandle, useRef, useState} from 'react' +import {useEffect, useImperativeHandle, useRef, useState} from 'react' import {type TextInput} from 'react-native' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' @@ -114,6 +114,13 @@ function GifPickerBody({ void fetchNextPage() } + // Scroll to top when the effective query/category changes, NOT on every + // keystroke. Calling scrollToOffset on the FlatList while its sticky header + // holds the focused input blurs that input on web. + useEffect(() => { + listRef.current?.scrollToOffset({offset: 0, animated: false}) + }, [effectiveSearch, isRecentsActive]) + const onClearSearch = () => { textInputRef.current?.clear() setRawSearch('') @@ -130,12 +137,10 @@ function GifPickerBody({ const onChangeSearch = (text: string) => { setRawSearch(text) - listRef.current?.scrollToOffset({offset: 0, animated: false}) } const onSelectCategory = (category: GifCategory) => { setActiveCategory(category.id) - listRef.current?.scrollToOffset({offset: 0, animated: false}) } const handleSelectGif = (gif: Gif) => { diff --git a/src/features/gifPicker/components/GifPickerGrid.tsx b/src/features/gifPicker/components/GifPickerGrid.tsx index a2ac8ad0fa..a34aeacab0 100644 --- a/src/features/gifPicker/components/GifPickerGrid.tsx +++ b/src/features/gifPicker/components/GifPickerGrid.tsx @@ -1,5 +1,5 @@ import {forwardRef} from 'react' -import {useWindowDimensions, View} from 'react-native' +import {Platform, useWindowDimensions, View} from 'react-native' import {cleanError} from '#/lib/strings/errors' import {type ListMethods} from '#/view/com/util/List' @@ -75,8 +75,12 @@ export const GifPickerGrid = forwardRef( ListHeaderComponent={<>{header}} stickyHeaderIndices={[0]} onEndReached={onEndReached} - onEndReachedThreshold={4} - keyboardDismissMode="on-drag" + onEndReachedThreshold={1} + // On web, "on-drag" blurs the focused input on ANY scroll event, + // including programmatic scrolls (e.g., content shrinking when search + // results swap in). That breaks search-while-scrolled — the blur fires + // mid-typing and subsequent keystrokes go nowhere. + keyboardDismissMode={Platform.OS === 'web' ? 'none' : 'on-drag'} ListFooterComponent={ hasData ? (