refactor: standardize pagination response structure and enhance cursor handling
- Update various services and hooks to replace 'items' with 'list' for consistency in pagination responses. - Modify PostRepository, commentService, groupService, messageService, and postService to align with the new response structure. - Enhance cursor pagination logic in hooks and components to ensure proper handling of pagination states. - Refactor HomeScreen, PostDetailScreen, SearchScreen, and other components to utilize the updated pagination structure.
This commit is contained in:
@@ -88,6 +88,10 @@ export const HomeScreen: React.FC = () => {
|
||||
// 用于跟踪当前页面显示的帖子 ID,以便从 store 同步状态
|
||||
const postIdsRef = useRef<Set<string>>(new Set());
|
||||
const lastSwipeAtRef = useRef(0);
|
||||
|
||||
// 网格模式滚动位置检测
|
||||
const gridScrollYRef = useRef(0);
|
||||
const isLoadingMoreRef = useRef(false);
|
||||
|
||||
// 构建一个以 postId 为 key 的 map,用于快速查找
|
||||
const postsMap = useMemo(() => {
|
||||
@@ -131,14 +135,30 @@ export const HomeScreen: React.FC = () => {
|
||||
|
||||
// 加载更多方法
|
||||
const loadMore = useCallback(async () => {
|
||||
if (hasMore && !isLoading) {
|
||||
if (hasMore && !isLoading && !isLoadingMoreRef.current) {
|
||||
isLoadingMoreRef.current = true;
|
||||
try {
|
||||
await processPostUseCase.loadMorePosts(listKey);
|
||||
} catch (err) {
|
||||
console.error('加载更多失败:', err);
|
||||
} finally {
|
||||
isLoadingMoreRef.current = false;
|
||||
}
|
||||
}
|
||||
}, [listKey, hasMore, isLoading]);
|
||||
|
||||
// 网格模式滚动处理 - 检测是否滚动到底部
|
||||
const handleGridScroll = useCallback((event: any) => {
|
||||
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent;
|
||||
const scrollY = contentOffset.y;
|
||||
const visibleHeight = layoutMeasurement.height;
|
||||
const contentHeight = contentSize.height;
|
||||
|
||||
// 当滚动到距离底部 200px 时触发加载更多
|
||||
if (scrollY + visibleHeight >= contentHeight - 200) {
|
||||
loadMore();
|
||||
}
|
||||
}, [loadMore]);
|
||||
|
||||
// 刷新方法 - 先获取正确类型的帖子,再刷新
|
||||
const refresh = useCallback(async () => {
|
||||
@@ -485,6 +505,7 @@ export const HomeScreen: React.FC = () => {
|
||||
]}
|
||||
showsVerticalScrollIndicator={false}
|
||||
scrollEventThrottle={100}
|
||||
onScroll={handleGridScroll}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={isRefreshing}
|
||||
@@ -495,6 +516,12 @@ export const HomeScreen: React.FC = () => {
|
||||
}
|
||||
>
|
||||
{distributePostsToColumns.map((column, index) => renderWaterfallColumn(column, index))}
|
||||
{/* 加载更多指示器 */}
|
||||
{isLoading && displayPosts.length > 0 && (
|
||||
<View style={styles.loadingMore}>
|
||||
<Loading size="sm" />
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
@@ -767,4 +794,9 @@ const styles = StyleSheet.create({
|
||||
height: 72,
|
||||
borderRadius: 36,
|
||||
},
|
||||
loadingMore: {
|
||||
paddingVertical: 20,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -72,7 +72,7 @@ export const PostDetailScreen: React.FC = () => {
|
||||
|
||||
// 使用游标分页 Hook 管理评论列表
|
||||
const {
|
||||
items: paginatedComments,
|
||||
list: paginatedComments,
|
||||
isLoading: isCommentsLoading,
|
||||
isRefreshing: isCommentsRefreshing,
|
||||
hasMore: hasMoreComments,
|
||||
@@ -206,13 +206,13 @@ export const PostDetailScreen: React.FC = () => {
|
||||
|
||||
// 如果是从评论按钮跳转过来的,加载完成后滚动到评论区
|
||||
useEffect(() => {
|
||||
if (shouldScrollToComments && !loading && comments.length > 0) {
|
||||
if (shouldScrollToComments && !loading && (comments?.length ?? 0) > 0) {
|
||||
// 延迟确保列表已完成渲染和布局
|
||||
setTimeout(() => {
|
||||
flatListRef.current?.scrollToIndex({ index: 0, animated: true, viewPosition: 0 });
|
||||
}, 500);
|
||||
}
|
||||
}, [shouldScrollToComments, loading, comments.length]);
|
||||
}, [shouldScrollToComments, loading, comments?.length]);
|
||||
|
||||
// 动态设置导航头部
|
||||
useEffect(() => {
|
||||
@@ -1413,7 +1413,7 @@ export const PostDetailScreen: React.FC = () => {
|
||||
加载更多评论
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
) : comments.length > 0 ? (
|
||||
) : (comments?.length ?? 0) > 0 ? (
|
||||
<Text variant="caption" color={colors.text.hint} style={styles.noMoreComments}>
|
||||
没有更多评论了
|
||||
</Text>
|
||||
@@ -1546,7 +1546,7 @@ export const PostDetailScreen: React.FC = () => {
|
||||
加载更多评论
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
) : comments.length > 0 ? (
|
||||
) : (comments?.length ?? 0) > 0 ? (
|
||||
<Text variant="caption" color={colors.text.hint} style={styles.noMoreComments}>
|
||||
没有更多评论了
|
||||
</Text>
|
||||
|
||||
@@ -83,7 +83,7 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack, navigation:
|
||||
|
||||
// 使用游标分页进行帖子搜索
|
||||
const {
|
||||
items: searchResults,
|
||||
list: searchResults,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
hasMore,
|
||||
@@ -93,7 +93,7 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack, navigation:
|
||||
} = useCursorPagination<Post, { query: string }>(
|
||||
async ({ cursor, pageSize, extraParams }) => {
|
||||
if (!extraParams?.query) {
|
||||
return { items: [], next_cursor: null, prev_cursor: null, has_more: false };
|
||||
return { list: [], next_cursor: null, prev_cursor: null, has_more: false };
|
||||
}
|
||||
const response = await postService.searchPostsCursor(extraParams.query, {
|
||||
cursor,
|
||||
|
||||
@@ -72,7 +72,7 @@ const GroupMembersScreen: React.FC = () => {
|
||||
|
||||
// 使用游标分页 Hook 管理成员列表
|
||||
const {
|
||||
items: members,
|
||||
list: members,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
hasMore,
|
||||
|
||||
@@ -36,7 +36,7 @@ const JoinGroupScreen: React.FC = () => {
|
||||
|
||||
// 使用游标分页 Hook 管理群组列表
|
||||
const {
|
||||
items: groups,
|
||||
list: groups,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
hasMore,
|
||||
|
||||
@@ -164,7 +164,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
|
||||
// 【游标分页】使用 useCursorPagination hook 获取会话列表
|
||||
const {
|
||||
items: conversations,
|
||||
list: conversationList,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
hasMore,
|
||||
@@ -453,7 +453,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
if (activeSearchTab === 'chat') {
|
||||
const results: SearchResultItem[] = [];
|
||||
|
||||
for (const conv of conversations) {
|
||||
for (const conv of conversationList) {
|
||||
await messageManager.fetchMessages(String(conv.id));
|
||||
const messages = messageManager.getMessages(String(conv.id));
|
||||
const matchedMessages = messages.filter(msg => {
|
||||
@@ -484,7 +484,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
} finally {
|
||||
setIsSearching(false);
|
||||
}
|
||||
}, [conversations, activeSearchTab]);
|
||||
}, [conversationList, activeSearchTab]);
|
||||
|
||||
// 搜索文本变化时触发搜索
|
||||
useEffect(() => {
|
||||
@@ -533,7 +533,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
// 合并列表数据
|
||||
const listData: ConversationResponse[] = [
|
||||
createSystemMessageItem(),
|
||||
...conversations,
|
||||
...conversationList,
|
||||
];
|
||||
|
||||
// 总未读数
|
||||
@@ -923,7 +923,7 @@ export const MessageListScreen: React.FC = () => {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
{isLoading && conversations.length === 0 ? (
|
||||
{isLoading && conversationList.length === 0 ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={colors.primary.main} />
|
||||
</View>
|
||||
|
||||
@@ -88,7 +88,7 @@ export const NotificationsScreen: React.FC<{ onBack?: () => void }> = ({ onBack
|
||||
);
|
||||
|
||||
const {
|
||||
items: messages,
|
||||
list: messages,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
hasMore,
|
||||
|
||||
Reference in New Issue
Block a user