Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0df76e2af6 | |||
| f80fe1df93 |
@@ -79,8 +79,8 @@ android {
|
|||||||
applicationId "com.ariacockpit"
|
applicationId "com.ariacockpit"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 305
|
versionCode 306
|
||||||
versionName "0.0.3.5"
|
versionName "0.0.3.6"
|
||||||
// Fallback fuer Libraries mit Product Flavors
|
// Fallback fuer Libraries mit Product Flavors
|
||||||
missingDimensionStrategy 'react-native-camera', 'general'
|
missingDimensionStrategy 'react-native-camera', 'general'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aria-cockpit",
|
"name": "aria-cockpit",
|
||||||
"version": "0.0.3.5",
|
"version": "0.0.3.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"android": "react-native run-android",
|
"android": "react-native run-android",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Datei- und Kamera-Upload.
|
* Datei- und Kamera-Upload.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
Text,
|
Text,
|
||||||
@@ -369,42 +369,8 @@ const ChatScreen: React.FC = () => {
|
|||||||
return () => { if (saveTimer.current) clearTimeout(saveTimer.current); };
|
return () => { if (saveTimer.current) clearTimeout(saveTimer.current); };
|
||||||
}, [messages]);
|
}, [messages]);
|
||||||
|
|
||||||
// Auto-Scroll: immer zur letzten Nachricht springen
|
// Inverted FlatList: neueste Nachrichten unten, kein manuelles Scrollen noetig
|
||||||
const shouldAutoScroll = useRef(true);
|
const invertedMessages = useMemo(() => [...messages].reverse(), [messages]);
|
||||||
const lastMessageCount = useRef(0);
|
|
||||||
|
|
||||||
// Bei neuen Nachrichten oder App-Start: nach unten springen
|
|
||||||
useEffect(() => {
|
|
||||||
if (messages.length > 0 && shouldAutoScroll.current) {
|
|
||||||
const isInitial = lastMessageCount.current === 0;
|
|
||||||
const scrollToBottom = () => {
|
|
||||||
try {
|
|
||||||
flatListRef.current?.scrollToIndex({
|
|
||||||
index: messages.length - 1,
|
|
||||||
animated: !isInitial,
|
|
||||||
viewPosition: 1, // 1 = Item am unteren Rand
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
// Fallback wenn Index nicht berechnet werden kann
|
|
||||||
flatListRef.current?.scrollToEnd({ animated: !isInitial });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const delays = isInitial ? [200, 500, 1000] : [150];
|
|
||||||
for (const delay of delays) {
|
|
||||||
setTimeout(scrollToBottom, delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastMessageCount.current = messages.length;
|
|
||||||
}, [messages]);
|
|
||||||
|
|
||||||
const handleScrollBeginDrag = useCallback(() => {
|
|
||||||
shouldAutoScroll.current = false;
|
|
||||||
}, []);
|
|
||||||
const handleScrollEndDrag = useCallback((e: any) => {
|
|
||||||
const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
|
|
||||||
const isAtBottom = contentOffset.y + layoutMeasurement.height >= contentSize.height - 50;
|
|
||||||
shouldAutoScroll.current = isAtBottom;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// GPS-Position holen (optional)
|
// GPS-Position holen (optional)
|
||||||
const getCurrentLocation = useCallback((): Promise<{ lat: number; lon: number } | null> => {
|
const getCurrentLocation = useCallback((): Promise<{ lat: number; lon: number } | null> => {
|
||||||
@@ -693,18 +659,12 @@ const ChatScreen: React.FC = () => {
|
|||||||
{/* Nachrichtenliste */}
|
{/* Nachrichtenliste */}
|
||||||
<FlatList
|
<FlatList
|
||||||
ref={flatListRef}
|
ref={flatListRef}
|
||||||
data={searchQuery ? messages.filter(m => m.text.toLowerCase().includes(searchQuery.toLowerCase())) : messages}
|
inverted
|
||||||
|
data={searchQuery ? messages.filter(m => m.text.toLowerCase().includes(searchQuery.toLowerCase())).reverse() : invertedMessages}
|
||||||
keyExtractor={item => item.id}
|
keyExtractor={item => item.id}
|
||||||
renderItem={renderMessage}
|
renderItem={renderMessage}
|
||||||
contentContainerStyle={styles.messageList}
|
contentContainerStyle={styles.messageList}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
onScrollBeginDrag={handleScrollBeginDrag}
|
|
||||||
onScrollEndDrag={handleScrollEndDrag}
|
|
||||||
onScrollToIndexFailed={(info) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
flatListRef.current?.scrollToEnd({ animated: false });
|
|
||||||
}, 200);
|
|
||||||
}}
|
|
||||||
ListEmptyComponent={
|
ListEmptyComponent={
|
||||||
<View style={styles.emptyContainer}>
|
<View style={styles.emptyContainer}>
|
||||||
<Text style={styles.emptyIcon}>{'\uD83E\uDD16'}</Text>
|
<Text style={styles.emptyIcon}>{'\uD83E\uDD16'}</Text>
|
||||||
|
|||||||
Reference in New Issue
Block a user