refactor(LocalDataSource, PostRepository, ChatScreen): enhance database handling and message loading
Some checks failed
Frontend CI / build-and-push-web (push) Successful in 2m41s
Frontend CI / ota-android (push) Successful in 12m45s
Frontend CI / build-android-apk (push) Has been cancelled

- Introduced a promise-based initialization mechanism in LocalDataSource to prevent concurrent initialization issues.
- Updated PostRepository to utilize an enqueueWrite method for database operations, ensuring thread-safe writes.
- Refactored ChatScreen to improve message loading logic, including preloading history and managing scroll behavior more effectively.
- Enhanced message rendering logic to maintain correct indices in inverted lists and optimize user experience during scrolling.
This commit is contained in:
lafay
2026-03-23 23:06:19 +08:00
parent 7305254e11
commit c98f1917f7
9 changed files with 396 additions and 185 deletions

View File

@@ -7,11 +7,12 @@ import {
View,
Modal,
TouchableOpacity,
TouchableWithoutFeedback,
Pressable,
Animated,
Alert,
Clipboard,
Dimensions,
Platform,
} from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { chatScreenStyles as styles } from './styles';
@@ -35,34 +36,41 @@ export const LongPressMenu: React.FC<LongPressMenuProps> = ({
}) => {
const scaleAnimation = useRef(new Animated.Value(0)).current;
const opacityAnimation = useRef(new Animated.Value(0)).current;
const blurActiveElementOnWeb = () => {
if (Platform.OS !== 'web') return;
const active = (globalThis as any)?.document?.activeElement as { blur?: () => void } | undefined;
active?.blur?.();
};
// 显示动画 - 缩放弹出
useEffect(() => {
if (visible) {
blurActiveElementOnWeb();
Animated.parallel([
Animated.spring(scaleAnimation, {
toValue: 1,
useNativeDriver: true,
useNativeDriver: Platform.OS !== 'web',
friction: 8,
tension: 100,
}),
Animated.timing(opacityAnimation, {
toValue: 1,
duration: 150,
useNativeDriver: true,
useNativeDriver: Platform.OS !== 'web',
}),
]).start();
} else {
blurActiveElementOnWeb();
Animated.parallel([
Animated.timing(scaleAnimation, {
toValue: 0,
duration: 150,
useNativeDriver: true,
useNativeDriver: Platform.OS !== 'web',
}),
Animated.timing(opacityAnimation, {
toValue: 0,
duration: 150,
useNativeDriver: true,
useNativeDriver: Platform.OS !== 'web',
}),
]).start();
}
@@ -242,11 +250,18 @@ export const LongPressMenu: React.FC<LongPressMenuProps> = ({
visible={visible}
transparent
animationType="none"
onShow={blurActiveElementOnWeb}
onRequestClose={onClose}
>
<TouchableWithoutFeedback onPress={onClose}>
<View style={styles.qqMenuOverlay}>
<TouchableWithoutFeedback>
<Pressable
onPress={() => {
blurActiveElementOnWeb();
onClose();
}}
style={styles.qqMenuOverlay}
>
<View>
<Pressable onPress={() => {}}>
<Animated.View
style={[
styles.qqMenuContainer,
@@ -286,9 +301,9 @@ export const LongPressMenu: React.FC<LongPressMenuProps> = ({
))}
</View>
</Animated.View>
</TouchableWithoutFeedback>
</Pressable>
</View>
</TouchableWithoutFeedback>
</Pressable>
</Modal>
);
};