refactor(ui): modernize components with flat design and UX refinements
- Redesign chat screen header with improved layout and panel styling - Update emoji panel tab bar from emoji to icon-based navigation - Simplify trade detail view with inline content attributes - Add masonry layout support to market view grid - Refactor privacy settings from card-based to list-based dropdown UI - Improve comment item actions layout and styling - Update trade creation flow with buy/sell specific text - Adjust padding, gaps, and font sizes across multiple components - Clean up unused code and imports
This commit is contained in:
@@ -79,56 +79,52 @@ export const ChatHeader: React.FC<ChatHeaderProps> = ({
|
||||
return (
|
||||
<View style={styles.headerContainer}>
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity style={styles.backButton} onPress={onBack} activeOpacity={0.7}>
|
||||
<MaterialCommunityIcons name="chevron-left" size={28} color={iconColor} />
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.headerLeft}>
|
||||
<TouchableOpacity style={styles.backButton} onPress={onBack} activeOpacity={0.7}>
|
||||
<MaterialCommunityIcons name="chevron-left" size={28} color={iconColor} />
|
||||
</TouchableOpacity>
|
||||
{isGroupChat ? (
|
||||
<Avatar
|
||||
source={groupInfo?.avatar || null}
|
||||
size={36}
|
||||
name={groupInfo?.name || '群'}
|
||||
style={styles.groupAvatar}
|
||||
/>
|
||||
) : (
|
||||
<Avatar
|
||||
source={otherUser?.avatar || null}
|
||||
size={36}
|
||||
name={otherUser?.nickname || ''}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={styles.headerCenter}>
|
||||
<TouchableOpacity
|
||||
style={styles.titleRow}
|
||||
onPress={onTitlePress}
|
||||
activeOpacity={0.75}
|
||||
>
|
||||
{isGroupChat ? (
|
||||
<>
|
||||
<View style={styles.titleLeading}>
|
||||
<Avatar
|
||||
source={groupInfo?.avatar || null}
|
||||
size={36}
|
||||
name={groupInfo?.name || '群'}
|
||||
style={styles.groupAvatar}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.titleContent}>
|
||||
<Text style={styles.headerName} numberOfLines={1}>{getDisplayTitle()}</Text>
|
||||
<View style={styles.subtitleRow}>
|
||||
<Text style={styles.memberCount}>{groupInfo?.member_count || 0}位成员</Text>
|
||||
{typingHint && (
|
||||
<Text style={styles.typingHint} numberOfLines={1}>{typingHint}</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Avatar
|
||||
source={otherUser?.avatar || null}
|
||||
size={36}
|
||||
name={otherUser?.nickname || ''}
|
||||
/>
|
||||
<View style={styles.titleContent}>
|
||||
<Text style={styles.headerName} numberOfLines={1}>{getDisplayTitle()}</Text>
|
||||
<View style={styles.titleContent}>
|
||||
<Text style={styles.headerName} numberOfLines={1}>{getDisplayTitle()}</Text>
|
||||
{isGroupChat ? (
|
||||
<View style={styles.subtitleRow}>
|
||||
<Text style={styles.memberCount}>{groupInfo?.member_count || 0}位成员</Text>
|
||||
{typingHint && (
|
||||
<View style={styles.subtitleRow}>
|
||||
<Text style={styles.typingHint} numberOfLines={1}>{typingHint}</Text>
|
||||
</View>
|
||||
<Text style={styles.typingHint} numberOfLines={1}>{typingHint}</Text>
|
||||
)}
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
) : (
|
||||
typingHint && (
|
||||
<View style={styles.subtitleRow}>
|
||||
<Text style={styles.typingHint} numberOfLines={1}>{typingHint}</Text>
|
||||
</View>
|
||||
)
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
|
||||
{/* 大屏幕 + 群聊时显示群信息按钮,否则显示三点菜单 */}
|
||||
{isWideScreen && isGroupChat && onGroupInfoPress ? (
|
||||
<TouchableOpacity
|
||||
|
||||
@@ -74,7 +74,9 @@ export const EmojiPanel: React.FC<EmojiPanelProps> = ({
|
||||
...baseStyles,
|
||||
emojiContainer: {
|
||||
flex: 1,
|
||||
padding: spacing.sm,
|
||||
paddingTop: spacing.sm,
|
||||
paddingHorizontal: spacing.sm,
|
||||
backgroundColor: baseStyles.panelContainer.backgroundColor,
|
||||
},
|
||||
emojiItem: {
|
||||
width: 40,
|
||||
@@ -281,21 +283,19 @@ export const EmojiPanel: React.FC<EmojiPanelProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
// 渲染管理按钮(表情面板第一位)- 现代扁平化设计
|
||||
// 渲染管理按钮(表情面板第一位)- 填满格子
|
||||
const renderManageButton = () => (
|
||||
<TouchableOpacity
|
||||
key="manage-button"
|
||||
style={[styles.stickerItem, stickerButtonStyles.manageButton]}
|
||||
style={[styles.stickerItem, { alignItems: 'center', justifyContent: 'center' }]}
|
||||
onPress={handleOpenManage}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<View style={stickerButtonStyles.iconContainer}>
|
||||
<MaterialCommunityIcons
|
||||
name="cog-outline"
|
||||
size={28}
|
||||
color={colors.chat.textSecondary}
|
||||
/>
|
||||
</View>
|
||||
<MaterialCommunityIcons
|
||||
name="cog-outline"
|
||||
size={32}
|
||||
color={colors.chat.textSecondary}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
@@ -561,24 +561,28 @@ export const EmojiPanel: React.FC<EmojiPanelProps> = ({
|
||||
{activeTab === 'emoji' ? renderEmojiPanel() : renderStickerPanel()}
|
||||
</View>
|
||||
|
||||
{/* 底部 Tab 栏 - 现代胶囊式设计 */}
|
||||
{/* 底部 Tab 栏 - QQ/微信风格横向导航 */}
|
||||
<View style={styles.panelTabBar}>
|
||||
<View style={styles.panelTabContainer}>
|
||||
<View style={styles.panelTabScroll}>
|
||||
<TouchableOpacity
|
||||
style={[styles.panelTab, activeTab === 'emoji' && styles.panelTabActive]}
|
||||
style={[styles.panelTabItem, activeTab === 'emoji' && styles.panelTabItemActive]}
|
||||
onPress={() => setActiveTab('emoji')}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<Text style={[styles.panelTabEmoji, activeTab === 'emoji' ? { opacity: 1 } : {}]}>😊</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.panelTab, activeTab === 'sticker' && styles.panelTabActive]}
|
||||
onPress={() => setActiveTab('sticker')}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<MaterialCommunityIcons
|
||||
name="emoticon-happy-outline"
|
||||
size={22}
|
||||
color={activeTab === 'emoji' ? colors.primary.main : colors.chat.textSecondary}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.panelTabItem, activeTab === 'sticker' && styles.panelTabItemActive]}
|
||||
onPress={() => setActiveTab('sticker')}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<MaterialCommunityIcons
|
||||
name="image-multiple-outline"
|
||||
size={22}
|
||||
color={activeTab === 'sticker' ? colors.primary.main : colors.chat.textSecondary}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -105,6 +105,12 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
backgroundColor: cardBgColor,
|
||||
height: 56,
|
||||
},
|
||||
headerLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: spacing.xs,
|
||||
zIndex: 2,
|
||||
},
|
||||
backButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
@@ -114,27 +120,21 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
padding: 0,
|
||||
},
|
||||
headerCenter: {
|
||||
flex: 1,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
alignItems: 'center',
|
||||
marginHorizontal: spacing.sm,
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 50,
|
||||
},
|
||||
titleRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: spacing.sm,
|
||||
paddingHorizontal: spacing.sm,
|
||||
paddingVertical: spacing.xs,
|
||||
borderRadius: 8,
|
||||
},
|
||||
titleLeading: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: panelBgColor,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
groupAvatar: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
@@ -429,17 +429,17 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
|
||||
// 输入框区域 - 与列表背景同色底栏,顶部细分隔
|
||||
inputWrapper: {
|
||||
backgroundColor: screenBgColor,
|
||||
backgroundColor: cardBgColor,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderTopColor: colors.chat.border,
|
||||
borderTopColor: colors.chat.borderHairline,
|
||||
},
|
||||
inputContainer: {
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderRadius: 0,
|
||||
marginHorizontal: 10,
|
||||
marginBottom: 10,
|
||||
marginTop: 2,
|
||||
marginBottom: 6,
|
||||
marginTop: 6,
|
||||
paddingHorizontal: spacing.sm,
|
||||
paddingVertical: spacing.sm,
|
||||
shadowColor: 'transparent',
|
||||
@@ -451,7 +451,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
inputInner: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: inputBgColor,
|
||||
backgroundColor: colors.chat.surfaceRaised,
|
||||
borderRadius: 20,
|
||||
paddingHorizontal: spacing.xs,
|
||||
paddingVertical: 4,
|
||||
@@ -464,7 +464,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
elevation: 0,
|
||||
},
|
||||
inputInnerMuted: {
|
||||
backgroundColor: colors.chat.borderHairline,
|
||||
backgroundColor: colors.chat.surfaceMuted,
|
||||
opacity: 0.7,
|
||||
},
|
||||
|
||||
@@ -585,14 +585,9 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
|
||||
// 面板
|
||||
panelWrapper: {
|
||||
backgroundColor: panelBgColor,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.chat.border,
|
||||
shadowColor: colors.chat.shadow,
|
||||
shadowOffset: { width: 0, height: -2 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 8,
|
||||
elevation: 8,
|
||||
backgroundColor: cardBgColor,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderTopColor: colors.chat.borderHairline,
|
||||
},
|
||||
// 表情面板包装器 - 底部 tab 栏是白色,安全区域也用白色填充
|
||||
emojiPanelWrapper: {
|
||||
@@ -600,7 +595,11 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
},
|
||||
panelContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: panelBgColor,
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
morePanelBackground: {
|
||||
flex: 1,
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
|
||||
// 表情面板
|
||||
@@ -611,6 +610,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
paddingTop: spacing.md,
|
||||
paddingBottom: spacing.xl,
|
||||
alignItems: 'flex-start',
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
emojiItem: {
|
||||
width: '12.5%',
|
||||
@@ -636,55 +636,41 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
flex: 1,
|
||||
},
|
||||
|
||||
// Tab 栏 - 现代胶囊式设计
|
||||
// Tab 栏 - 底部横向导航条(QQ/微信风格)
|
||||
panelTabBar: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: spacing.md,
|
||||
paddingVertical: spacing.sm + 2,
|
||||
paddingHorizontal: 0,
|
||||
paddingVertical: 0,
|
||||
backgroundColor: cardBgColor,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderTopColor: colors.chat.borderHairline,
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
panelTabContainer: {
|
||||
panelTabScroll: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: panelBgColor,
|
||||
borderRadius: 12,
|
||||
padding: 3,
|
||||
paddingHorizontal: spacing.sm,
|
||||
gap: spacing.sm,
|
||||
},
|
||||
panelTab: {
|
||||
width: 42,
|
||||
height: 36,
|
||||
panelTabItem: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 10,
|
||||
width: 48,
|
||||
height: 44,
|
||||
borderBottomWidth: 2.5,
|
||||
borderBottomColor: 'transparent',
|
||||
},
|
||||
panelTabActive: {
|
||||
backgroundColor: cardBgColor,
|
||||
shadowColor: colors.chat.shadow,
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.08,
|
||||
shadowRadius: 2,
|
||||
elevation: 1,
|
||||
},
|
||||
panelTabEmoji: {
|
||||
fontSize: 22,
|
||||
},
|
||||
panelTabDivider: {
|
||||
width: 1,
|
||||
height: 20,
|
||||
backgroundColor: colors.chat.border,
|
||||
marginHorizontal: spacing.sm,
|
||||
panelTabItemActive: {
|
||||
borderBottomColor: colors.primary.main,
|
||||
},
|
||||
panelCloseButton: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
width: 44,
|
||||
height: 44,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 10,
|
||||
backgroundColor: panelBgColor,
|
||||
marginRight: spacing.sm,
|
||||
},
|
||||
|
||||
// 自定义表情面板
|
||||
@@ -692,12 +678,14 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
stickerEmptyContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: spacing.xl,
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
stickerEmptyText: {
|
||||
fontSize: 16,
|
||||
@@ -715,6 +703,7 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
paddingHorizontal: spacing.md,
|
||||
paddingTop: spacing.md,
|
||||
paddingBottom: spacing.xl,
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
stickerItem: {
|
||||
width: (SCREEN_WIDTH - spacing.md * 2) / 4 - 8,
|
||||
@@ -734,9 +723,10 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
paddingHorizontal: spacing.lg + 4,
|
||||
paddingTop: spacing.lg,
|
||||
paddingTop: spacing.md,
|
||||
paddingBottom: spacing.xl,
|
||||
justifyContent: 'flex-start',
|
||||
backgroundColor: cardBgColor,
|
||||
},
|
||||
moreItem: {
|
||||
width: (SCREEN_WIDTH - spacing.lg * 2 - 8) / 4,
|
||||
@@ -779,12 +769,6 @@ export function createChatScreenStyles(colors: AppColors, dynamicStyles?: {
|
||||
fontWeight: '500',
|
||||
letterSpacing: 0.3,
|
||||
},
|
||||
// MorePanel 整体背景
|
||||
morePanelBackground: {
|
||||
flex: 1,
|
||||
backgroundColor: panelBgColor,
|
||||
},
|
||||
|
||||
// @成员选择浮层 - 绝对定位浮在输入框上方
|
||||
mentionPanelFloat: {
|
||||
position: 'absolute',
|
||||
|
||||
Reference in New Issue
Block a user