mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(chat): maintain scroll position when keyboard appears
When the keyboard appeared, the chat content would get pushed up and the user would lose sight of what they were viewing. This happened because the outer container had keyboard-aware padding, but the ScrollView's content padding was static. Now the ScrollView's contentContainerStyle receives animated padding that matches the keyboard height, ensuring the content maintains its relative position and the user keeps seeing the same messages when the keyboard appears. Changes: - Pass keyboardHeight SharedValue to AgentStreamView - Add animated contentPaddingStyle that adjusts for keyboard - Apply dynamic padding to ScrollView contentContainerStyle - Content now smoothly adjusts as keyboard animates in/out 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,7 @@ export default function AgentScreen() {
|
||||
onPermissionResponse={(requestId, optionId) =>
|
||||
respondToPermission(requestId, id!, agent.sessionId || "", [optionId])
|
||||
}
|
||||
keyboardHeight={keyboardHeight}
|
||||
/>
|
||||
)}
|
||||
</ReanimatedAnimated.View>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { View, Text, ScrollView, Pressable } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||
import { BottomSheetModal } from "@gorhom/bottom-sheet";
|
||||
import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
|
||||
import Animated, { FadeIn, FadeOut, useAnimatedStyle, SharedValue } from "react-native-reanimated";
|
||||
import { ChevronDown } from "lucide-react-native";
|
||||
import {
|
||||
AssistantMessage,
|
||||
@@ -25,6 +25,7 @@ export interface AgentStreamViewProps {
|
||||
streamItems: StreamItem[];
|
||||
pendingPermissions: Map<string, PendingPermission>;
|
||||
onPermissionResponse: (requestId: string, optionId: string) => void;
|
||||
keyboardHeight: SharedValue<number>;
|
||||
}
|
||||
|
||||
export function AgentStreamView({
|
||||
@@ -33,6 +34,7 @@ export function AgentStreamView({
|
||||
streamItems,
|
||||
pendingPermissions,
|
||||
onPermissionResponse,
|
||||
keyboardHeight,
|
||||
}: AgentStreamViewProps) {
|
||||
const scrollViewRef = useRef<ScrollView>(null);
|
||||
const bottomSheetRef = useRef<BottomSheetModal | null>(null);
|
||||
@@ -42,6 +44,17 @@ export function AgentStreamView({
|
||||
const [isNearBottom, setIsNearBottom] = useState(true);
|
||||
const hasScrolledInitially = useRef(false);
|
||||
|
||||
// Animated content padding that responds to keyboard
|
||||
const contentPaddingStyle = useAnimatedStyle(() => {
|
||||
"worklet";
|
||||
const absoluteHeight = Math.abs(keyboardHeight.value);
|
||||
const keyboardPadding = Math.max(0, absoluteHeight - insets.bottom);
|
||||
const basePadding = Math.max(insets.bottom, 32);
|
||||
return {
|
||||
paddingBottom: basePadding + keyboardPadding,
|
||||
};
|
||||
}, [insets.bottom]);
|
||||
|
||||
// Scroll to bottom immediately on initial load, then animate for new messages
|
||||
useEffect(() => {
|
||||
if (isNearBottom) {
|
||||
@@ -82,10 +95,12 @@ export function AgentStreamView({
|
||||
<ScrollView
|
||||
ref={scrollViewRef}
|
||||
style={stylesheet.scrollView}
|
||||
contentContainerStyle={{
|
||||
paddingTop: 24,
|
||||
paddingBottom: Math.max(insets.bottom, 32),
|
||||
}}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
paddingTop: 24,
|
||||
},
|
||||
contentPaddingStyle,
|
||||
]}
|
||||
onScroll={handleScroll}
|
||||
scrollEventThrottle={16}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user