From eccfd675508e0bbabe638fe700282536a5b4d1a1 Mon Sep 17 00:00:00 2001 From: lafay <2021211506@stu.hit.edu.cn> Date: Sat, 25 Apr 2026 15:28:13 +0800 Subject: [PATCH] fix(android): handle hardware back button and navigation with active panels/keyboard Improve back navigation UX by checking for open panels or keyboard before leaving the chat screen. When back is triggered, dismiss keyboard or close panel first instead of immediately navigating away. Apply this logic to both the navigation gesture listener and Android hardware back button for consistent behavior. --- src/screens/message/ChatScreen.tsx | 39 +++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/screens/message/ChatScreen.tsx b/src/screens/message/ChatScreen.tsx index 20402a4..105335e 100644 --- a/src/screens/message/ChatScreen.tsx +++ b/src/screens/message/ChatScreen.tsx @@ -26,6 +26,7 @@ import { KeyboardAvoidingView, Platform, TouchableOpacity, + BackHandler, } from 'react-native'; import { FlashList, ListRenderItem } from '@shopify/flash-list'; import { MaterialCommunityIcons } from '@expo/vector-icons'; @@ -268,14 +269,44 @@ export const ChatScreen: React.FC = (props) => { }); }, [displayMessages, flatListRef, setBrowsingHistory]); - // 监听返回事件,刷新会话列表 + // 监听返回事件:面板/键盘打开时先关闭它们,否则刷新会话列表后返回 useEffect(() => { - const unsubscribe = navigation.addListener('beforeRemove', () => { - // 刷新会话列表,确保已读状态正确显示 + const unsubscribe = navigation.addListener('beforeRemove', (e) => { + const hasPanelOpen = activePanel !== 'none'; + const hasKeyboardOpen = keyboardHeight > 0; + if (hasPanelOpen || hasKeyboardOpen) { + e.preventDefault(); + if (hasKeyboardOpen) { + handleDismiss(); + } else { + closePanel(); + } + return; + } + // 真正返回时刷新会话列表 messageManager.refreshConversations(true, 'chat-before-remove'); }); return unsubscribe; - }, [navigation]); + }, [navigation, activePanel, keyboardHeight, closePanel, handleDismiss]); + + // Android 物理返回键:面板/键盘打开时先关闭它们 + useEffect(() => { + const backHandler = BackHandler.addEventListener('hardwareBackPress', () => { + const hasPanelOpen = activePanel !== 'none'; + const hasKeyboardOpen = keyboardHeight > 0; + if (hasPanelOpen || hasKeyboardOpen) { + if (hasKeyboardOpen) { + handleDismiss(); + } else { + closePanel(); + } + return true; // 阻止默认返回行为 + } + return false; + }); + + return () => backHandler.remove(); + }, [activePanel, keyboardHeight, closePanel, handleDismiss]); // 渲染消息气泡 const messageIndexMap = useMemo(() => {