Keep keyboard offsets tied to visibility

Derive app keyboard offsets from one provider-owned shared value so chat content, composer surfaces, and floating panels share the same policy.

Treat progress-zero keyboard samples as closed, even if Android reports a stale nonzero height.
This commit is contained in:
Mohamed Boudra
2026-06-18 12:03:44 +07:00
parent e4da3693e9
commit 4e899c644a
7 changed files with 138 additions and 73 deletions
@@ -337,14 +337,14 @@ export function TerminalPane({
}, [clearKeyboardRefitTimeouts]);
useAnimatedReaction(
() => keyboardShift.value > 0,
() => isMobile && keyboardShift.value > 0,
(next, prev) => {
if (next === prev) {
return;
}
runOnJS(pulseKeyboardRefits)();
},
[pulseKeyboardRefits],
[isMobile, pulseKeyboardRefits],
);
useEffect(() => {
@@ -1,19 +1,14 @@
import { useEffect, useMemo, useState, type ReactElement, type RefObject } from "react";
import { Keyboard, View, useWindowDimensions } from "react-native";
import { Portal } from "@gorhom/portal";
import Animated, {
useAnimatedStyle,
useDerivedValue,
useSharedValue,
} from "react-native-reanimated";
import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Animated, { useAnimatedStyle, useSharedValue } from "react-native-reanimated";
import { StyleSheet } from "react-native-unistyles";
import { Autocomplete, type AutocompleteOption } from "@/components/ui/autocomplete";
import {
measureFloatingPanelPortalHost,
useFloatingPanelPortalHostName,
} from "@/components/ui/floating-panel-portal";
import { useKeyboardShift } from "@/hooks/use-keyboard-shift-style";
import { SPACING } from "@/styles/theme";
import { inlineUnistylesStyle } from "@/styles/unistyles-inline-style";
@@ -68,18 +63,8 @@ export function AutocompletePopover({
// React Compiler memoizes effect captures by reading SharedValue.value during render.
const [relativeAnchorRect, setRelativeAnchorRect] = useState<RelativeAnchorRect | null>(null);
const windowDimensions = useWindowDimensions();
const insets = useSafeAreaInsets();
const portalHostName = useFloatingPanelPortalHostName();
const { height: rawKeyboardHeight } = useReanimatedKeyboardAnimation();
const bottomInsetSV = useSharedValue(insets.bottom);
useEffect(() => {
bottomInsetSV.value = insets.bottom;
}, [bottomInsetSV, insets.bottom]);
const shift = useDerivedValue(() =>
Math.max(0, Math.abs(rawKeyboardHeight.value) - bottomInsetSV.value),
);
const { shift } = useKeyboardShift();
const openShift = useSharedValue(0);
useEffect(() => {