refactor(ui): modernize components with flat design and UX refinements
Some checks failed
Frontend CI / build-and-push-web (push) Failing after 42s
Frontend CI / build-android-apk (push) Failing after 7m16s
Frontend CI / ota-android (push) Successful in 10m29s

- 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:
lafay
2026-04-27 01:02:39 +08:00
parent e519346261
commit 0e2945b86b
15 changed files with 535 additions and 384 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -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',