Files
frontend/src/screens/message/components/ChatScreen/bubbleStyles.ts

270 lines
6.6 KiB
TypeScript
Raw Normal View History

/**
*
* Element X
*/
import { StyleSheet, ViewStyle, TextStyle } from 'react-native';
import { colors, spacing } from '../../../../theme';
// 气泡圆角大小(参考 Element X: 12pt
export const BUBBLE_RADIUS = 16;
// 气泡颜色方案(参考 Element X 的语义化颜色)
export const bubbleColors = {
// 自己发送的消息
outgoing: {
background: '#E8E8E8', // Element X 风格:灰色系
text: '#1A1A1A',
},
// 收到的消息
incoming: {
background: '#FFFFFF',
text: '#1A1A1A',
},
// 被回复的消息高亮
replyHighlight: {
background: 'rgba(255, 107, 53, 0.08)',
borderLeft: '#FF6B35',
},
};
// 消息在组中的位置类型
export type MessageGroupPosition = 'single' | 'first' | 'middle' | 'last';
/**
*
* Element X
*/
export const getBubbleBorderRadius = (
isMe: boolean,
position: MessageGroupPosition
): ViewStyle => {
const radius = BUBBLE_RADIUS;
if (isMe) {
// 自己发送的消息
switch (position) {
case 'single':
return {
borderTopLeftRadius: radius,
borderTopRightRadius: radius,
borderBottomLeftRadius: radius,
borderBottomRightRadius: 4, // 尖角在右下
};
case 'first':
return {
borderTopLeftRadius: radius,
borderTopRightRadius: radius,
borderBottomLeftRadius: radius,
borderBottomRightRadius: 4,
};
case 'middle':
return {
borderTopLeftRadius: radius,
borderTopRightRadius: 4,
borderBottomLeftRadius: radius,
borderBottomRightRadius: 4,
};
case 'last':
return {
borderTopLeftRadius: radius,
borderTopRightRadius: 4,
borderBottomLeftRadius: radius,
borderBottomRightRadius: radius,
};
}
} else {
// 收到的消息
switch (position) {
case 'single':
return {
borderTopLeftRadius: 4, // 尖角在左上
borderTopRightRadius: radius,
borderBottomLeftRadius: radius,
borderBottomRightRadius: radius,
};
case 'first':
return {
borderTopLeftRadius: 4,
borderTopRightRadius: radius,
borderBottomLeftRadius: 4,
borderBottomRightRadius: radius,
};
case 'middle':
return {
borderTopLeftRadius: 4,
borderTopRightRadius: radius,
borderBottomLeftRadius: 4,
borderBottomRightRadius: radius,
};
case 'last':
return {
borderTopLeftRadius: radius,
borderTopRightRadius: radius,
borderBottomLeftRadius: radius,
borderBottomRightRadius: radius,
};
}
}
};
/**
*
*/
export const getMessageGroupPosition = (
index: number,
messages: Array<{ sender_id: string }>,
currentUserId: string
): MessageGroupPosition => {
const currentMessage = messages[index];
if (!currentMessage) return 'single';
const prevMessage = index > 0 ? messages[index - 1] : null;
const nextMessage = index < messages.length - 1 ? messages[index + 1] : null;
const isSameSenderAsPrev = prevMessage && prevMessage.sender_id === currentMessage.sender_id;
const isSameSenderAsNext = nextMessage && nextMessage.sender_id === currentMessage.sender_id;
if (!isSameSenderAsPrev && !isSameSenderAsNext) {
return 'single';
} else if (!isSameSenderAsPrev && isSameSenderAsNext) {
return 'first';
} else if (isSameSenderAsPrev && isSameSenderAsNext) {
return 'middle';
} else {
return 'last';
}
};
/**
*
*/
export const shouldShowSenderInfo = (
index: number,
messages: Array<{ sender_id: string }>,
): boolean => {
if (index === 0) return true;
const currentMessage = messages[index];
const prevMessage = messages[index - 1];
return prevMessage.sender_id !== currentMessage.sender_id;
};
/**
*
*/
export const getBubbleBaseStyle = (isMe: boolean): ViewStyle => ({
paddingHorizontal: spacing.md,
paddingVertical: spacing.sm + 4,
minWidth: 60,
maxWidth: '75%',
backgroundColor: isMe ? bubbleColors.outgoing.background : bubbleColors.incoming.background,
// Element X 风格的微妙阴影
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.06,
shadowRadius: 2,
elevation: 2,
});
/**
*
*/
export const getBubbleTextStyle = (isMe: boolean): TextStyle => ({
color: isMe ? bubbleColors.outgoing.text : bubbleColors.incoming.text,
fontSize: 16,
lineHeight: 23,
letterSpacing: 0.2,
fontWeight: '400',
});
/**
*
*/
export const bubbleStyles = StyleSheet.create({
// 基础气泡
bubble: {
paddingHorizontal: spacing.md,
paddingVertical: spacing.sm + 4,
minWidth: 60,
},
// 自己发送的消息
outgoing: {
backgroundColor: bubbleColors.outgoing.background,
},
// 收到的消息
incoming: {
backgroundColor: bubbleColors.incoming.background,
},
// 文本样式
text: {
fontSize: 16,
lineHeight: 23,
letterSpacing: 0.2,
fontWeight: '400',
},
// 阴影样式Element X 风格)
shadow: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.06,
shadowRadius: 2,
elevation: 2,
},
// 长按反馈阴影
longPressShadow: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 3 },
shadowOpacity: 0.12,
shadowRadius: 8,
elevation: 6,
},
// 被回复消息的高亮边框
replyHighlight: {
borderLeftWidth: 3,
borderLeftColor: colors.primary.main,
backgroundColor: bubbleColors.replyHighlight.background,
},
// 已撤回消息
recalled: {
backgroundColor: '#F5F7FA',
borderWidth: 1,
borderColor: '#E8E8E8',
borderStyle: 'dashed',
borderRadius: 12,
},
// 系统通知
systemNotice: {
alignItems: 'center',
marginVertical: spacing.sm,
},
systemNoticeText: {
fontSize: 12,
color: '#8E8E93',
backgroundColor: 'rgba(142, 142, 147, 0.12)',
paddingHorizontal: spacing.md,
paddingVertical: spacing.xs,
borderRadius: 12,
overflow: 'hidden',
},
});
export default {
BUBBLE_RADIUS,
bubbleColors,
getBubbleBorderRadius,
getMessageGroupPosition,
shouldShowSenderInfo,
getBubbleBaseStyle,
getBubbleTextStyle,
bubbleStyles,
};