refactor(PostCard, PostCard.legacy): remove legacy PostCard component and update exports
- Deleted the legacy PostCard component to streamline the codebase and improve maintainability. - Updated exports in PostCard and index files to remove references to the legacy component. - Adjusted PostCardProps to eliminate legacy properties, ensuring only the new API is supported. - Enhanced the PostCard component to focus on modern implementation and features.
This commit is contained in:
235
src/screens/profile/UserProfileScreen.tsx
Normal file
235
src/screens/profile/UserProfileScreen.tsx
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* 统一的用户主页组件
|
||||
* 胡萝卜BBS - 支持两种模式:self(当前用户)和 other(其他用户)
|
||||
* 采用现代卡片式设计,优化视觉层次和交互体验
|
||||
* 支持桌面端双栏布局
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
View,
|
||||
RefreshControl,
|
||||
ScrollView,
|
||||
} from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
import { colors } from '../../theme';
|
||||
import { Post } from '../../types';
|
||||
import { PostCard, TabBar, UserProfileHeader } from '../../components/business';
|
||||
import { Loading, EmptyState, ResponsiveContainer } from '../../components/common';
|
||||
import { useResponsive } from '../../hooks';
|
||||
import { ProfileStackParamList } from '../../navigation/types';
|
||||
import { useUserProfile, ProfileMode, TABS, TAB_ICONS, sharedStyles } from './useUserProfile';
|
||||
|
||||
interface UserProfileScreenProps {
|
||||
mode: ProfileMode;
|
||||
userId?: string; // 仅 other 模式需要
|
||||
profileNavigation?: NativeStackNavigationProp<ProfileStackParamList>; // 仅 self 模式需要
|
||||
}
|
||||
|
||||
export const UserProfileScreen: React.FC<UserProfileScreenProps> = ({ mode, userId, profileNavigation }) => {
|
||||
const { isDesktop, isTablet } = useResponsive();
|
||||
|
||||
const {
|
||||
user,
|
||||
posts,
|
||||
favorites,
|
||||
loading,
|
||||
refreshing,
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
scrollBottomInset,
|
||||
onRefresh,
|
||||
handleFollow,
|
||||
handlePostAction,
|
||||
handleFollowingPress,
|
||||
handleFollowersPress,
|
||||
handleMessage,
|
||||
handleMore,
|
||||
handleSettings,
|
||||
handleEditProfile,
|
||||
isCurrentUser,
|
||||
currentUser,
|
||||
} = useUserProfile({ mode, userId, isDesktop, isTablet, profileNavigation });
|
||||
|
||||
// 渲染帖子列表
|
||||
const renderPostList = useCallback((postList: Post[], emptyTitle: string, emptyDesc: string) => {
|
||||
if (postList.length === 0) {
|
||||
return (
|
||||
<EmptyState
|
||||
title={emptyTitle}
|
||||
description={emptyDesc}
|
||||
icon={activeTab === 0 ? 'file-document-edit-outline' : 'bookmark-heart-outline'}
|
||||
variant="modern"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={sharedStyles.postsContainer}>
|
||||
{postList.map((post, index) => {
|
||||
const isPostAuthor = currentUser?.id === post.author?.id;
|
||||
return (
|
||||
<View key={post.id} style={[
|
||||
sharedStyles.postWrapper,
|
||||
index === postList.length - 1 && sharedStyles.lastPost,
|
||||
]}>
|
||||
<PostCard
|
||||
post={post}
|
||||
onAction={(action) => handlePostAction(post, action)}
|
||||
isPostAuthor={isPostAuthor}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
}, [currentUser?.id, handlePostAction, activeTab]);
|
||||
|
||||
// 渲染内容
|
||||
const renderContent = useCallback(() => {
|
||||
if (loading) return <Loading />;
|
||||
|
||||
if (activeTab === 0) {
|
||||
return renderPostList(
|
||||
posts,
|
||||
mode === 'self' ? '还没有帖子' : '这个用户还没有发布任何帖子',
|
||||
mode === 'self' ? '分享你的想法,发布第一条帖子吧' : ''
|
||||
);
|
||||
}
|
||||
|
||||
if (activeTab === 1) {
|
||||
return renderPostList(
|
||||
favorites,
|
||||
mode === 'self' ? '还没有收藏' : '这个用户还没有收藏任何帖子',
|
||||
mode === 'self' ? '发现喜欢的内容,点击收藏按钮保存' : ''
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [loading, activeTab, posts, favorites, mode, renderPostList]);
|
||||
|
||||
// 渲染用户信息头部
|
||||
const renderUserHeader = useMemo(() => {
|
||||
if (!user) return null;
|
||||
|
||||
return (
|
||||
<UserProfileHeader
|
||||
user={user}
|
||||
isCurrentUser={isCurrentUser}
|
||||
onFollow={handleFollow}
|
||||
onSettings={handleSettings}
|
||||
onEditProfile={handleEditProfile}
|
||||
onMessage={handleMessage}
|
||||
onMore={handleMore}
|
||||
onFollowingPress={handleFollowingPress}
|
||||
onFollowersPress={handleFollowersPress}
|
||||
/>
|
||||
);
|
||||
}, [user, isCurrentUser, handleFollow, handleSettings, handleEditProfile, handleMessage, handleMore, handleFollowingPress, handleFollowersPress]);
|
||||
|
||||
// 渲染 TabBar 和内容
|
||||
const renderTabBarAndContent = useMemo(() => (
|
||||
<>
|
||||
<View style={sharedStyles.tabBarContainer}>
|
||||
<TabBar
|
||||
tabs={TABS}
|
||||
activeIndex={activeTab}
|
||||
onTabChange={setActiveTab}
|
||||
variant="modern"
|
||||
icons={TAB_ICONS}
|
||||
/>
|
||||
</View>
|
||||
<View style={sharedStyles.contentContainer}>
|
||||
{renderContent()}
|
||||
</View>
|
||||
</>
|
||||
), [activeTab, renderContent]);
|
||||
|
||||
// 未登录/用户不存在状态
|
||||
if (mode === 'self' && !currentUser) {
|
||||
return (
|
||||
<SafeAreaView style={sharedStyles.container} edges={['top', 'bottom']}>
|
||||
<EmptyState
|
||||
title="未登录"
|
||||
description="请先登录"
|
||||
icon="account-off-outline"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
if (mode === 'other' && !user && !loading) {
|
||||
return (
|
||||
<SafeAreaView style={sharedStyles.container} edges={['bottom']}>
|
||||
<EmptyState
|
||||
title="用户不存在"
|
||||
description="该用户可能已被删除"
|
||||
icon="account-off-outline"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
// 桌面端使用双栏布局
|
||||
if (isDesktop || isTablet) {
|
||||
return (
|
||||
<SafeAreaView style={sharedStyles.container} edges={mode === 'self' ? ['top', 'bottom'] : ['bottom']}>
|
||||
<ResponsiveContainer maxWidth={1400}>
|
||||
<View style={sharedStyles.desktopContainer}>
|
||||
{/* 左侧:用户信息 */}
|
||||
<View style={sharedStyles.desktopSidebar}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={{ paddingBottom: scrollBottomInset }}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={onRefresh}
|
||||
colors={[colors.primary.main]}
|
||||
tintColor={colors.primary.main}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{renderUserHeader}
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
{/* 右侧:帖子列表 */}
|
||||
<View style={sharedStyles.desktopContent}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={[sharedStyles.desktopScrollContent, { paddingBottom: scrollBottomInset }]}
|
||||
>
|
||||
{renderTabBarAndContent}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
</ResponsiveContainer>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
// 移动端使用单栏布局
|
||||
return (
|
||||
<SafeAreaView style={sharedStyles.container} edges={mode === 'self' ? ['top', 'bottom'] : ['bottom']}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={onRefresh}
|
||||
colors={[colors.primary.main]}
|
||||
tintColor={colors.primary.main}
|
||||
/>
|
||||
}
|
||||
contentContainerStyle={[sharedStyles.scrollContent, { paddingBottom: scrollBottomInset }]}
|
||||
>
|
||||
{renderUserHeader}
|
||||
{renderTabBarAndContent}
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserProfileScreen;
|
||||
Reference in New Issue
Block a user