fix(dm): Android scroll-to-bottom via scrollToOffset(999999)
scrollToEnd() unterschätzt Content-Höhe auf Android und stoppt
konsistent eine Message zu früh (verifiziert per adb-Screenshot).
scrollToOffset({offset:999999}) wird auf den echten Max-Wert geclampt
und landet immer am absoluten Ende der Liste.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
89391a807b
commit
bd8d5a3072
@ -79,6 +79,16 @@ export default function DmScreen() {
|
||||
const { userId } = useLocalSearchParams<{ userId: string }>();
|
||||
|
||||
const flatListRef = useRef<FlatListType<ChatMsg>>(null);
|
||||
|
||||
// scrollToEnd() auf Android unterschätzt Content-Höhe und stoppt 1 Item
|
||||
// zu früh. scrollToOffset(999999) wird auf den echten Max-Wert geclampt.
|
||||
const scrollToBottom = useCallback((animated = false) => {
|
||||
if (Platform.OS === 'android') {
|
||||
flatListRef.current?.scrollToOffset({ offset: 999999, animated });
|
||||
} else {
|
||||
flatListRef.current?.scrollToEnd({ animated });
|
||||
}
|
||||
}, []);
|
||||
const [messages, setMessages] = useState<ChatMsg[]>([]);
|
||||
const [partner, setPartner] = useState<DmHistoryResponse['partner'] | null>(null);
|
||||
const partnerRef = useRef<DmHistoryResponse['partner'] | null>(null);
|
||||
@ -110,12 +120,12 @@ export default function DmScreen() {
|
||||
const show = Keyboard.addListener(showEvent, (e) => {
|
||||
setKeyboardHeight(e.endCoordinates.height);
|
||||
setKeyboardVisible(true);
|
||||
requestAnimationFrame(() => flatListRef.current?.scrollToEnd({ animated: false }));
|
||||
requestAnimationFrame(() => scrollToBottom(false));
|
||||
});
|
||||
const hide = Keyboard.addListener(hideEvent, () => {
|
||||
setKeyboardHeight(0);
|
||||
setKeyboardVisible(false);
|
||||
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: false }), 50);
|
||||
setTimeout(() => scrollToBottom(false), 50);
|
||||
});
|
||||
return () => { show.remove(); hide.remove(); };
|
||||
}, []);
|
||||
@ -170,9 +180,9 @@ export default function DmScreen() {
|
||||
setMessages(msgs);
|
||||
// Dreistufiges Scroll-to-bottom: rAF + 100ms + 300ms deckt
|
||||
// Fälle ab wo Bilder nachgeladen werden und Content-Höhe wächst.
|
||||
requestAnimationFrame(() => flatListRef.current?.scrollToEnd({ animated: false }));
|
||||
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: false }), 100);
|
||||
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: false }), 300);
|
||||
requestAnimationFrame(() => scrollToBottom(false));
|
||||
setTimeout(() => scrollToBottom(false), 100);
|
||||
setTimeout(() => scrollToBottom(false), 300);
|
||||
return data;
|
||||
} catch (err: any) {
|
||||
console.error('[dm] history fetch failed:', err?.message ?? err);
|
||||
@ -187,7 +197,7 @@ export default function DmScreen() {
|
||||
// Neue Nachricht (incoming Realtime oder outgoing send) → immer scrollen
|
||||
useEffect(() => {
|
||||
if (messages.length === 0) return;
|
||||
requestAnimationFrame(() => flatListRef.current?.scrollToEnd({ animated: true }));
|
||||
requestAnimationFrame(() => scrollToBottom(true));
|
||||
}, [messages.length]);
|
||||
|
||||
// Realtime: neue DMs vom Partner
|
||||
@ -545,8 +555,8 @@ export default function DmScreen() {
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="handled"
|
||||
onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: false })}
|
||||
onLayout={() => flatListRef.current?.scrollToEnd({ animated: false })}
|
||||
onContentSizeChange={() => scrollToBottom(false)}
|
||||
onLayout={() => scrollToBottom(false)}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user