-
Notifications
You must be signed in to change notification settings - Fork 3.9k
fix: unable to see the fourth split row while put cursor on it #80858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d48622f
11d07a0
0d65eb5
12f918d
784242a
7a4d8e7
53c370a
5e369c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ import type {FlashListRef, ListRenderItem, ListRenderItemInfo} from '@shopify/fl | |
| import {deepEqual} from 'fast-equals'; | ||
| import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; | ||
| import type {TextInputKeyPressEvent} from 'react-native'; | ||
| import {View} from 'react-native'; | ||
| import {Keyboard, View} from 'react-native'; | ||
| import OptionsListSkeletonView from '@components/OptionsListSkeletonView'; | ||
| import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; | ||
| import useActiveElementRole from '@hooks/useActiveElementRole'; | ||
|
|
@@ -105,6 +105,7 @@ function BaseSelectionList<TItem extends ListItem>({ | |
| const hasKeyBeenPressed = useRef(false); | ||
| const listRef = useRef<FlashListRef<TItem> | null>(null); | ||
| const itemFocusTimeoutRef = useRef<NodeJS.Timeout | null>(null); | ||
| const keyboardListenerRef = useRef<ReturnType<typeof Keyboard.addListener> | null>(null); | ||
|
|
||
| const initialFocusedIndex = useMemo(() => data.findIndex((i) => i.keyForList === initiallyFocusedItemKey), [data, initiallyFocusedItemKey]); | ||
| const [itemsToHighlight, setItemsToHighlight] = useState<Set<string> | null>(null); | ||
|
|
@@ -375,25 +376,68 @@ function BaseSelectionList<TItem extends ListItem>({ | |
|
|
||
| const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null); | ||
|
|
||
| useEffect(() => { | ||
| return () => { | ||
| if (keyboardListenerRef.current) { | ||
| keyboardListenerRef.current.remove(); | ||
| keyboardListenerRef.current = null; | ||
| } | ||
| if (scrollTimeoutRef.current) { | ||
| clearTimeout(scrollTimeoutRef.current); | ||
| scrollTimeoutRef.current = null; | ||
| } | ||
| }; | ||
| }, []); | ||
|
|
||
| // The function scrolls to the focused input to prevent keyboard occlusion. | ||
| // It ensures the entire list item is visible, not just the input field. | ||
| // Added specifically for SplitExpensePage | ||
| const scrollToFocusedInput = useCallback((item: TItem) => { | ||
| if (!listRef.current) { | ||
| return; | ||
| } | ||
| const scrollToFocusedInput = useCallback( | ||
| (item: TItem) => { | ||
| if (!listRef.current) { | ||
| return; | ||
| } | ||
|
|
||
| // Clear any existing timer before starting a new one | ||
| if (scrollTimeoutRef.current) { | ||
| clearTimeout(scrollTimeoutRef.current); | ||
| } | ||
| // Clear any existing timer and listener before starting new ones | ||
| if (scrollTimeoutRef.current) { | ||
| clearTimeout(scrollTimeoutRef.current); | ||
| } | ||
| if (keyboardListenerRef.current) { | ||
| keyboardListenerRef.current.remove(); | ||
| } | ||
|
|
||
| // Delay scrolling by 300ms to allow the keyboard to open. | ||
| // This ensures FlashList calculates the correct window size. | ||
| setTimeout(() => { | ||
| listRef.current?.scrollToItem({item, viewPosition: 1, animated: true, viewOffset: 4}); | ||
| }, CONST.ANIMATED_TRANSITION); | ||
| }, []); | ||
| const performScroll = () => { | ||
| const index = data.findIndex((dataItem) => dataItem.keyForList === item.keyForList); | ||
| if (index === -1) { | ||
| return; | ||
| } | ||
| // Use scrollToIndex with viewPosition 0.5 to center the item in the visible area | ||
| // This ensures the item is visible above the keyboard | ||
| listRef.current?.scrollToIndex({index, animated: true, viewPosition: 0.5}); | ||
| }; | ||
|
|
||
| // Wait for keyboard to fully appear, then scroll | ||
| keyboardListenerRef.current = Keyboard.addListener('keyboardDidShow', () => { | ||
| keyboardListenerRef.current?.remove(); | ||
| keyboardListenerRef.current = null; | ||
| // Clear fallback timeout since keyboard event fired | ||
| if (scrollTimeoutRef.current) { | ||
| clearTimeout(scrollTimeoutRef.current); | ||
| scrollTimeoutRef.current = null; | ||
| } | ||
| // Add small delay after keyboard is shown for layout to settle | ||
| scrollTimeoutRef.current = setTimeout(performScroll, CONST.ANIMATION_IN_TIMING); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @daledah does it mean even
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, exactly. Even after |
||
| }); | ||
|
|
||
| // Fallback timeout in case keyboard event doesn't fire (e.g., keyboard already open) | ||
| scrollTimeoutRef.current = setTimeout(() => { | ||
| keyboardListenerRef.current?.remove(); | ||
| keyboardListenerRef.current = null; | ||
| performScroll(); | ||
| }, CONST.ANIMATED_TRANSITION); | ||
| }, | ||
| [data], | ||
| ); | ||
|
|
||
| const scrollAndHighlightItem = useCallback( | ||
| (items: string[]) => { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.