feat(pagination): implement cursor-based pagination across the app
Add useCursorPagination hook and update multiple screens and services to use cursor-based pagination for better performance and consistency. - Add useCursorPagination hook with deduplication and caching support - Add cursor pagination types to infrastructure layer - Refactor HomeScreen, PostDetailScreen, SearchScreen for posts/comments - Refactor GroupMembersScreen, JoinGroupScreen for groups/members - Refactor MessageListScreen, NotificationsScreen for messages - Update post, message, group, comment, notification services with cursor endpoints - Add CursorPaginationRequest/Response DTOs - Remove deprecated OPTIMIZATION_DESIGN.md documentation
This commit is contained in:
@@ -30,12 +30,13 @@ import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { colors, spacing, fontSizes, shadows, borderRadius } from '../../theme';
|
||||
import { ConversationResponse, UserDTO, MessageResponse, extractTextFromSegments, extractTextFromSegmentsAsync, MessageSegment } from '../../types/dto';
|
||||
import { authService } from '../../services';
|
||||
import { authService, messageService } from '../../services';
|
||||
import { useUserStore, useAuthStore } from '../../stores';
|
||||
// 【新架构】使用MessageManager hooks
|
||||
import { useMessageList, messageManager, useMessageListRefresh, useCreateConversation } from '../../stores';
|
||||
import { messageManager, useMessageListRefresh, useCreateConversation, useUnreadCount, useMarkAsRead } from '../../stores';
|
||||
import { Avatar, Text, EmptyState, ResponsiveContainer } from '../../components/common';
|
||||
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
|
||||
import { useCursorPagination } from '../../hooks/useCursorPagination';
|
||||
import { RootStackParamList, MessageStackParamList } from '../../navigation/types';
|
||||
import { getUserCache } from '../../services/database';
|
||||
// 导入 EmbeddedChat 组件用于桌面端双栏布局
|
||||
@@ -160,22 +161,43 @@ export const MessageListScreen: React.FC = () => {
|
||||
const { isDesktop, isTablet, width } = useResponsive();
|
||||
const isWideScreen = useBreakpointGTE('lg');
|
||||
|
||||
// 【新架构】使用MessageManager的hook获取数据
|
||||
// 【游标分页】使用 useCursorPagination hook 获取会话列表
|
||||
const {
|
||||
conversations,
|
||||
items: conversations,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
hasMore,
|
||||
loadMore,
|
||||
refresh,
|
||||
totalUnreadCount,
|
||||
systemUnreadCount,
|
||||
markAllAsRead,
|
||||
isMarking,
|
||||
} = useMessageList();
|
||||
error: paginationError,
|
||||
} = useCursorPagination(
|
||||
async ({ cursor, pageSize }) => {
|
||||
return await messageService.getConversationsCursor({
|
||||
cursor,
|
||||
page_size: pageSize,
|
||||
});
|
||||
},
|
||||
{ pageSize: 20 }
|
||||
);
|
||||
|
||||
// 使用 MessageManager 获取未读数和系统通知数
|
||||
const { totalUnreadCount, systemUnreadCount } = useUnreadCount();
|
||||
const { markAllAsRead, isMarking } = useMarkAsRead(null);
|
||||
|
||||
// 【新架构】使用MessageManager的hook创建会话
|
||||
const { createConversation } = useCreateConversation();
|
||||
|
||||
// 本地刷新状态(仅用于下拉刷新的UI显示)
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
|
||||
// 上拉加载更多
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isLoading || loadingMore || !hasMore) return;
|
||||
setLoadingMore(true);
|
||||
await loadMore();
|
||||
setLoadingMore(false);
|
||||
}, [isLoading, loadingMore, hasMore, loadMore]);
|
||||
|
||||
// 搜索相关状态
|
||||
const [isSearchMode, setIsSearchMode] = useState(false);
|
||||
@@ -885,7 +907,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
{isLoading ? (
|
||||
{isLoading && conversations.length === 0 ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={colors.primary.main} />
|
||||
</View>
|
||||
@@ -901,6 +923,8 @@ export const MessageListScreen: React.FC = () => {
|
||||
]}
|
||||
showsVerticalScrollIndicator={false}
|
||||
ListEmptyComponent={renderEmpty}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={0.5}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
@@ -909,6 +933,14 @@ export const MessageListScreen: React.FC = () => {
|
||||
tintColor={colors.primary.main}
|
||||
/>
|
||||
}
|
||||
ListFooterComponent={
|
||||
loadingMore ? (
|
||||
<View style={styles.loadingMoreContainer}>
|
||||
<ActivityIndicator size="small" color={colors.primary.main} />
|
||||
<Text style={styles.loadingMoreText}>加载中...</Text>
|
||||
</View>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@@ -1261,6 +1293,17 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
paddingVertical: spacing.xl * 2,
|
||||
},
|
||||
loadingMoreContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: spacing.md,
|
||||
},
|
||||
loadingMoreText: {
|
||||
marginLeft: spacing.sm,
|
||||
fontSize: 14,
|
||||
color: '#999',
|
||||
},
|
||||
searchModeContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: '#FAFAFA',
|
||||
|
||||
Reference in New Issue
Block a user