feat: 兼容

This commit is contained in:
jinyaqiu 2025-07-17 19:29:06 +08:00
parent 39b768f2cc
commit 436b44a107
4 changed files with 59 additions and 51 deletions

View File

@ -1,3 +1,4 @@
import IP from '@/assets/icons/svg/ip.svg';
import * as MediaLibrary from 'expo-media-library';
import { useRouter } from 'expo-router';
import * as SecureStore from 'expo-secure-store';
@ -96,7 +97,7 @@ export default function HomeScreen() {
isLoggedIn ? <MemoList /> :
<View className="flex-1 bg-bgPrimary px-[1rem] h-screen overflow-auto py-[2rem] " style={{ paddingTop: insets.top + 48 }}>
{/* 标题区域 */}
<View className="items-center mb-10 w-full px-5">
<View className="mb-10 w-full px-5">
<Text className="text-white text-3xl font-bold mb-3 text-left">
{t('auth.welcomeAwaken.awaken', { ns: 'login' })}
{"\n"}
@ -110,9 +111,9 @@ export default function HomeScreen() {
</View>
{/* Memo 形象区域 */}
{/* <View className="items-center">
<View className="items-center">
<IP />
</View> */}
</View>
{/* 介绍文本 */}
<Text className="text-white text-base text-center mb-[1rem] leading-6 opacity-90 px-10 -mt-[4rem]">

View File

@ -0,0 +1,45 @@
import { useVideoPlayer, VideoView } from 'expo-video';
import {
Pressable,
StyleProp,
ViewStyle
} from 'react-native';
const VideoPlayer = ({
videoUrl,
style,
onPress
}: {
videoUrl: string;
style?: StyleProp<ViewStyle>;
onPress?: () => void;
}) => {
const player = useVideoPlayer(videoUrl, (player) => {
player.loop = true;
player.play();
});
return (
<Pressable
style={[{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}, style]}
onPress={onPress}
>
<VideoView
style={{
width: '100%',
height: '100%',
backgroundColor: '#000', // 添加背景色
}}
player={player}
allowsFullscreen
allowsPictureInPicture
/>
</Pressable>
);
};
export default VideoPlayer

View File

@ -5,24 +5,22 @@ import ReturnArrow from "@/assets/icons/svg/returnArrow.svg";
import YesSvg from "@/assets/icons/svg/yes.svg";
import { Message, Video } from "@/types/ask";
import { MaterialItem } from "@/types/personal-info";
import { useVideoPlayer, VideoView } from 'expo-video';
import { TFunction } from "i18next";
import React from 'react';
import { useTranslation } from "react-i18next";
import {
FlatList,
Image,
Modal,
Pressable,
StyleProp,
StyleSheet,
Text,
TouchableOpacity,
View,
ViewStyle
View
} from 'react-native';
import { ThemedText } from "../ThemedText";
import TypewriterText from "./typewriterText";
import { mergeArrays } from "./utils";
import VideoPlayer from "./VideoPlayer";
interface RenderMessageProps {
insets: { top: number };
@ -34,51 +32,14 @@ interface RenderMessageProps {
modalDetailsVisible: boolean;
setSelectedImages: React.Dispatch<React.SetStateAction<string[]>>;
selectedImages: string[];
t: TFunction;
}
const renderMessage = ({ insets, item, sessionId, setModalVisible, modalVisible, setModalDetailsVisible, modalDetailsVisible, setSelectedImages, selectedImages }: RenderMessageProps) => {
const MessageItem = ({ t, insets, item, sessionId, setModalVisible, modalVisible, setModalDetailsVisible, modalDetailsVisible, setSelectedImages, selectedImages }: RenderMessageProps) => {
const isUser = item.role === 'User';
const isVideo = (data: Video | MaterialItem): data is Video => {
return 'video' in data;
};
const { t } = useTranslation();
// 创建一个新的 VideoPlayer 组件
const VideoPlayer = ({
videoUrl,
style,
onPress
}: {
videoUrl: string;
style?: StyleProp<ViewStyle>;
onPress?: () => void;
}) => {
const player = useVideoPlayer(videoUrl, (player) => {
player.loop = true;
player.play();
});
return (
<Pressable
style={[{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}, style]}
onPress={onPress}
>
<VideoView
style={{
width: '100%',
height: '100%',
backgroundColor: '#000', // 添加背景色
}}
player={player}
allowsFullscreen
allowsPictureInPicture
/>
</Pressable>
);
};
return (
<View className={`flex-row items-start gap-2 w-full ${isUser ? 'justify-end' : 'justify-start'}`}>
@ -304,7 +265,7 @@ const renderMessage = ({ insets, item, sessionId, setModalVisible, modalVisible,
);
};
export default renderMessage;
export default MessageItem;
const styles = StyleSheet.create({
imageGridContainer: {

View File

@ -1,12 +1,13 @@
import { Message, Video } from '@/types/ask';
import { MaterialItem } from '@/types/personal-info';
import React, { Dispatch, memo, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
FlatList,
SafeAreaView
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import renderMessage from "./aiChat";
import MessageItem from './aiChat';
interface ChatProps {
userMessages: Message[];
@ -19,7 +20,7 @@ function ChatComponent({ userMessages, sessionId, setSelectedImages, selectedIma
const flatListRef = useRef<FlatList>(null);
const insets = useSafeAreaInsets();
const [modalVisible, setModalVisible] = React.useState({ visible: false, data: {} as Video | MaterialItem });
const { t } = useTranslation();
// 使用 useCallback 缓存 keyExtractor 函数
const keyExtractor = useCallback((item: Message) => `${item.role}-${item.timestamp}`, []);
@ -51,7 +52,7 @@ function ChatComponent({ userMessages, sessionId, setSelectedImages, selectedIma
updateCellsBatchingPeriod={50}
initialNumToRender={10}
windowSize={11}
renderItem={({ item }) => renderMessage({ setSelectedImages, selectedImages, insets, item, sessionId, modalVisible, setModalVisible, setModalDetailsVisible, modalDetailsVisible })}
renderItem={({ item }) => MessageItem({ t, setSelectedImages, selectedImages, insets, item, sessionId, modalVisible, setModalVisible, setModalDetailsVisible, modalDetailsVisible })}
/>
</SafeAreaView>
);