memowake-front/app/(tabs)/memo-list.tsx
2025-07-22 15:24:23 +08:00

337 lines
9.7 KiB
TypeScript

import ChatSvg from "@/assets/icons/svg/chat.svg";
import UploaderProgress from "@/components/file-upload/upload-progress/uploader-progress";
import AskNavbar from "@/components/layout/ask";
import { useUploadManager } from "@/hooks/useUploadManager";
import { fetchApi } from "@/lib/server-api-util";
import { useAppSelector } from "@/store";
import { Chat } from "@/types/ask";
import { router, useFocusEffect } from "expo-router";
import React from 'react';
import { FlatList, Platform, RefreshControl, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const MemoList = () => {
const insets = useSafeAreaInsets();
const uploadSessionStartTime = useAppSelector((state) => state.appState.uploadSessionStartTime);
// 历史消息
const [historyList, setHistoryList] = React.useState<Chat[]>([]);
// 刷新状态
const [refreshing, setRefreshing] = React.useState(false);
// 获取历史消息
const getHistoryList = async () => {
try {
setRefreshing(true);
const res = await fetchApi<Chat[]>(`/chats`);
setHistoryList(res);
} catch (error) {
console.error('Failed to fetch history:', error);
} finally {
setRefreshing(false);
}
}
// 获取对话历史消息
const getChatHistory = async (id: string) => {
// 跳转到聊天页面,并携带参数
router.push({
pathname: '/ask',
params: {
sessionId: id,
}
});
}
const handleMemoPress = (item: Chat) => {
getChatHistory(item.session_id)
}
useFocusEffect(
React.useCallback(() => {
getHistoryList()
}, [])
);
const { progressInfo, uploadSessionStartTime: uploadSessionStartTimeFromHook } = useUploadManager();
const renderHeader = () => (
<>
{/* {process.env.NODE_ENV === 'development' && <TouchableOpacity
className='mt-2 bg-red-500 items-center h-10 justify-center'
onPress={() => router.push('/debug')}
>
<Text className="text-white">
进入db调试页面
</Text>
</TouchableOpacity>} */}
{/* 顶部标题和上传按钮 */}
<View style={styles.header}>
<Text style={styles.title}>Memo List</Text>
</View>
{/* 上传进度展示区域 */}
{uploadSessionStartTime && progressInfo.total > 0 && (
<View className="h-10 mt-6 mb-2 mx-4">
<UploaderProgress
imageUrl={progressInfo.image}
uploadedCount={progressInfo.completed}
totalCount={progressInfo.total}
/>
</View>
)}
</>
);
return (
<View style={[styles.container, { paddingTop: insets.top }]}>
{/* <View className="w-full h-full">
<AutoUploadScreen />
</View> */}
{/* 历史对话 */}
<FlatList
ListHeaderComponent={renderHeader}
data={historyList}
keyExtractor={(item) => item.session_id}
// 下拉刷新
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={getHistoryList}
colors={['#FFB645']} // Android
tintColor="#FFB645" // iOS
/>
}
ItemSeparatorComponent={() => (
<View style={styles.separator} />
)}
renderItem={({ item }) => (
<TouchableOpacity
style={styles.memoItem}
onPress={() => handleMemoPress(item)}
>
<View className="w-[3rem] h-[3rem] z-1">
<ChatSvg
width="100%"
height="100%"
preserveAspectRatio="xMidYMid meet"
/>
</View>
<View style={styles.memoContent}>
<Text
style={styles.memoTitle}
numberOfLines={1}
ellipsizeMode="tail"
>
{item.title || 'memo list 历史消息'}
</Text>
<Text
style={styles.memoTitle}
numberOfLines={1}
ellipsizeMode="tail"
>
{item.latest_message?.content?.text || 'memo list 历史消息'}
</Text>
</View>
</TouchableOpacity>
)}
/>
{/* 底部导航栏 */}
<AskNavbar />
</View>
);
};
const styles = StyleSheet.create({
separator: {
height: 1,
backgroundColor: '#f0f0f0',
marginLeft: 60, // 与头像对齐
},
container: {
flex: 1,
backgroundColor: 'white',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
padding: 16,
},
title: {
fontSize: 24,
fontWeight: 'bold',
color: '#4C320C',
},
uploadButton: {
padding: 8,
},
searchContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#FFF',
borderRadius: 20,
marginHorizontal: 16,
paddingHorizontal: 16,
height: 48,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 2,
},
searchIcon: {
marginRight: 8,
},
memoItem: {
flexDirection: 'row',
borderRadius: 0, // 移除圆角
padding: 16,
marginBottom: 0, // 移除底部边距
alignItems: 'center',
gap: 16,
backgroundColor: 'white',
},
avatar: {
width: 60,
height: 60,
borderRadius: 30,
marginRight: 16,
},
memoContent: {
flex: 1,
marginLeft: 12,
gap: 6,
justifyContent: 'center',
minWidth: 0, // 这行很重要,确保文本容器可以收缩到比内容更小
},
memoTitle: {
fontSize: 16,
fontWeight: '500',
color: '#333',
flex: 1, // 或者 flexShrink: 1
marginLeft: 12,
},
memoSubtitle: {
fontSize: 14,
color: '#666',
},
tabBar: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
backgroundColor: '#FFF',
borderTopWidth: 1,
borderTopColor: '#EEE',
paddingVertical: 12,
},
tabBarSvg: {
color: 'red',
},
tabItem: {
flex: 1,
alignItems: 'center',
},
tabCenter: {
width: 60,
height: 60,
alignItems: 'center',
justifyContent: 'center',
},
centerTabIcon: {
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#FF9500',
justifyContent: 'center',
alignItems: 'center',
marginTop: -30,
},
centerTabImage: {
width: 40,
height: 40,
borderRadius: 20,
},
// 在 tabBarContainer 样式中添加
tabBarContainer: {
position: 'relative',
paddingBottom: 0,
overflow: 'visible',
marginTop: 10, // 添加一些上边距
},
tabBarContent: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
height: 60,
position: 'relative',
backgroundColor: 'rgba(255, 255, 255, 0.7)', // 半透明白色背景
borderRadius: 30, // 圆角
marginHorizontal: 16, // 左右边距
// 添加边框效果
borderWidth: 1,
borderColor: 'rgba(255, 255, 255, 0.8)',
// 添加阴影
...Platform.select({
ios: {
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 4,
},
android: {
elevation: 8,
},
}),
},
// 移除之前的 tabBarBackground 样式
// 修改 centerTabShadow 样式
centerTabShadow: {
position: 'absolute',
bottom: 15,
width: 60,
height: 60,
borderRadius: 30,
backgroundColor: 'white',
...Platform.select({
ios: {
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 6,
},
android: {
elevation: 10,
},
}),
},
centerTabContainer: {
flex: 1,
alignItems: 'center',
position: 'relative',
height: '100%',
},
centerTabButton: {
width: '100%',
height: '100%',
borderRadius: 30,
backgroundColor: '#FF9500',
justifyContent: 'center',
alignItems: 'center',
},
notificationDot: {
position: 'absolute',
top: -2,
right: -4,
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: '#FF3B30',
},
});
export default MemoList;