2025-12-18 14:52:20 +08:00
|
|
|
|
package com.example.livestreaming;
|
|
|
|
|
|
|
2025-12-29 18:02:28 +08:00
|
|
|
|
import com.example.livestreaming.net.MessageReaction;
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
import java.util.List;
|
2025-12-23 15:37:37 +08:00
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
2025-12-18 14:52:20 +08:00
|
|
|
|
public class ChatMessage {
|
2025-12-23 15:37:37 +08:00
|
|
|
|
public enum MessageStatus {
|
|
|
|
|
|
SENDING, // 发送中
|
|
|
|
|
|
SENT, // 已发送
|
|
|
|
|
|
READ // 已读
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 17:43:14 +08:00
|
|
|
|
public enum MessageType {
|
|
|
|
|
|
TEXT, // 文本消息
|
|
|
|
|
|
IMAGE, // 图片消息
|
2026-01-08 16:44:12 +08:00
|
|
|
|
VOICE, // 语音消息
|
|
|
|
|
|
BURN_IMAGE
|
2025-12-24 17:43:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-23 15:37:37 +08:00
|
|
|
|
private String messageId;
|
2025-12-18 14:52:20 +08:00
|
|
|
|
private String username;
|
2025-12-24 17:43:14 +08:00
|
|
|
|
private String message; // 文本消息内容
|
2025-12-18 14:52:20 +08:00
|
|
|
|
private long timestamp;
|
|
|
|
|
|
private boolean isSystemMessage;
|
2025-12-24 17:43:14 +08:00
|
|
|
|
private boolean isGiftMessage; // 是否是礼物消息
|
2025-12-30 10:10:35 +08:00
|
|
|
|
private boolean isOutgoing; // 是否是自己发送的消息
|
2025-12-23 15:37:37 +08:00
|
|
|
|
private MessageStatus status;
|
|
|
|
|
|
private String avatarUrl; // 发送者头像 URL,后续从后端获取
|
2025-12-24 17:43:14 +08:00
|
|
|
|
|
|
|
|
|
|
// 新增字段:消息类型和媒体相关
|
|
|
|
|
|
private MessageType messageType; // 消息类型
|
|
|
|
|
|
private String mediaUrl; // 图片/语音的 URL(从后端获取)
|
|
|
|
|
|
private String localMediaPath; // 本地图片/语音路径(发送前使用)
|
|
|
|
|
|
private int voiceDuration; // 语音时长(秒)
|
|
|
|
|
|
private int imageWidth; // 图片宽度
|
|
|
|
|
|
private int imageHeight; // 图片高度
|
2026-01-08 16:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
private Integer burnSeconds;
|
|
|
|
|
|
private Long viewedAt;
|
|
|
|
|
|
private Long burnAt;
|
|
|
|
|
|
private Boolean burned;
|
|
|
|
|
|
|
2025-12-29 18:02:28 +08:00
|
|
|
|
// 表情回应相关字段
|
|
|
|
|
|
private List<MessageReaction> reactions; // 表情回应列表
|
2025-12-24 17:43:14 +08:00
|
|
|
|
|
|
|
|
|
|
// 文本消息构造函数
|
2025-12-18 14:52:20 +08:00
|
|
|
|
public ChatMessage(String username, String message) {
|
2025-12-23 15:37:37 +08:00
|
|
|
|
this.messageId = UUID.randomUUID().toString();
|
2025-12-18 14:52:20 +08:00
|
|
|
|
this.username = username;
|
|
|
|
|
|
this.message = message;
|
|
|
|
|
|
this.timestamp = System.currentTimeMillis();
|
|
|
|
|
|
this.isSystemMessage = false;
|
2025-12-24 17:43:14 +08:00
|
|
|
|
this.isGiftMessage = false;
|
|
|
|
|
|
this.messageType = MessageType.TEXT;
|
2025-12-23 15:37:37 +08:00
|
|
|
|
// 如果是自己发送的消息,初始状态为发送中
|
2025-12-30 10:10:35 +08:00
|
|
|
|
this.isOutgoing = "我".equals(username);
|
|
|
|
|
|
this.status = this.isOutgoing ? MessageStatus.SENDING : MessageStatus.SENT;
|
2025-12-18 14:52:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 17:43:14 +08:00
|
|
|
|
// 系统消息构造函数
|
2025-12-18 14:52:20 +08:00
|
|
|
|
public ChatMessage(String message, boolean isSystemMessage) {
|
2025-12-23 15:37:37 +08:00
|
|
|
|
this.messageId = UUID.randomUUID().toString();
|
2025-12-18 14:52:20 +08:00
|
|
|
|
this.message = message;
|
|
|
|
|
|
this.timestamp = System.currentTimeMillis();
|
|
|
|
|
|
this.isSystemMessage = isSystemMessage;
|
2025-12-24 17:43:14 +08:00
|
|
|
|
this.isGiftMessage = false;
|
2025-12-18 14:52:20 +08:00
|
|
|
|
this.username = isSystemMessage ? "系统" : "匿名用户";
|
2025-12-23 15:37:37 +08:00
|
|
|
|
this.status = MessageStatus.SENT; // 系统消息默认已发送
|
2025-12-24 17:43:14 +08:00
|
|
|
|
this.messageType = MessageType.TEXT;
|
2025-12-23 15:37:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 17:43:14 +08:00
|
|
|
|
// 礼物消息构造函数
|
|
|
|
|
|
public ChatMessage(String username, String message, boolean isGiftMessage) {
|
|
|
|
|
|
this.messageId = UUID.randomUUID().toString();
|
|
|
|
|
|
this.username = username;
|
|
|
|
|
|
this.message = message;
|
|
|
|
|
|
this.timestamp = System.currentTimeMillis();
|
|
|
|
|
|
this.isSystemMessage = false;
|
|
|
|
|
|
this.isGiftMessage = isGiftMessage;
|
|
|
|
|
|
this.messageType = MessageType.TEXT;
|
|
|
|
|
|
this.status = MessageStatus.SENT;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 完整构造函数(从后端数据构造)
|
|
|
|
|
|
public ChatMessage(String messageId, String username, String message, long timestamp,
|
|
|
|
|
|
boolean isSystemMessage, MessageStatus status) {
|
2025-12-23 15:37:37 +08:00
|
|
|
|
this.messageId = messageId;
|
|
|
|
|
|
this.username = username;
|
|
|
|
|
|
this.message = message;
|
|
|
|
|
|
this.timestamp = timestamp;
|
|
|
|
|
|
this.isSystemMessage = isSystemMessage;
|
|
|
|
|
|
this.status = status;
|
2025-12-24 17:43:14 +08:00
|
|
|
|
this.messageType = MessageType.TEXT;
|
2025-12-30 10:10:35 +08:00
|
|
|
|
this.isOutgoing = "我".equals(username);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 完整构造函数(从后端数据构造,带 isOutgoing 参数)
|
|
|
|
|
|
public ChatMessage(String messageId, String username, String message, long timestamp,
|
|
|
|
|
|
boolean isSystemMessage, MessageStatus status, boolean isOutgoing) {
|
|
|
|
|
|
this.messageId = messageId;
|
|
|
|
|
|
this.username = username;
|
|
|
|
|
|
this.message = message;
|
|
|
|
|
|
this.timestamp = timestamp;
|
|
|
|
|
|
this.isSystemMessage = isSystemMessage;
|
|
|
|
|
|
this.status = status;
|
|
|
|
|
|
this.messageType = MessageType.TEXT;
|
|
|
|
|
|
this.isOutgoing = isOutgoing;
|
2025-12-23 15:37:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 17:43:14 +08:00
|
|
|
|
// 图片消息构造函数
|
|
|
|
|
|
public static ChatMessage createImageMessage(String username, String localPath) {
|
|
|
|
|
|
ChatMessage msg = new ChatMessage(username, "");
|
|
|
|
|
|
msg.messageType = MessageType.IMAGE;
|
|
|
|
|
|
msg.localMediaPath = localPath;
|
|
|
|
|
|
msg.status = "我".equals(username) ? MessageStatus.SENDING : MessageStatus.SENT;
|
|
|
|
|
|
return msg;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 语音消息构造函数
|
|
|
|
|
|
public static ChatMessage createVoiceMessage(String username, String localPath, int duration) {
|
|
|
|
|
|
ChatMessage msg = new ChatMessage(username, "");
|
|
|
|
|
|
msg.messageType = MessageType.VOICE;
|
|
|
|
|
|
msg.localMediaPath = localPath;
|
|
|
|
|
|
msg.voiceDuration = duration;
|
|
|
|
|
|
msg.status = "我".equals(username) ? MessageStatus.SENDING : MessageStatus.SENT;
|
|
|
|
|
|
return msg;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-08 16:44:12 +08:00
|
|
|
|
public static ChatMessage createBurnImageMessage(String username, String localPath, Integer burnSeconds) {
|
|
|
|
|
|
ChatMessage msg = new ChatMessage(username, "");
|
|
|
|
|
|
msg.messageType = MessageType.BURN_IMAGE;
|
|
|
|
|
|
msg.localMediaPath = localPath;
|
|
|
|
|
|
msg.burnSeconds = burnSeconds;
|
|
|
|
|
|
msg.burned = false;
|
|
|
|
|
|
msg.status = "我".equals(username) ? MessageStatus.SENDING : MessageStatus.SENT;
|
|
|
|
|
|
return msg;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 17:43:14 +08:00
|
|
|
|
// Getters and Setters
|
2025-12-23 15:37:37 +08:00
|
|
|
|
public String getMessageId() {
|
|
|
|
|
|
return messageId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setMessageId(String messageId) {
|
|
|
|
|
|
this.messageId = messageId;
|
2025-12-18 14:52:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public String getUsername() {
|
|
|
|
|
|
return username;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public String getMessage() {
|
|
|
|
|
|
return message;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public long getTimestamp() {
|
|
|
|
|
|
return timestamp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public boolean isSystemMessage() {
|
|
|
|
|
|
return isSystemMessage;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-24 17:43:14 +08:00
|
|
|
|
public boolean isGiftMessage() {
|
|
|
|
|
|
return isGiftMessage;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setGiftMessage(boolean giftMessage) {
|
|
|
|
|
|
isGiftMessage = giftMessage;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-30 10:10:35 +08:00
|
|
|
|
public boolean isOutgoing() {
|
|
|
|
|
|
return isOutgoing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setOutgoing(boolean outgoing) {
|
|
|
|
|
|
isOutgoing = outgoing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-23 15:37:37 +08:00
|
|
|
|
public MessageStatus getStatus() {
|
|
|
|
|
|
return status;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setStatus(MessageStatus status) {
|
|
|
|
|
|
this.status = status;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-18 14:52:20 +08:00
|
|
|
|
public void setUsername(String username) {
|
|
|
|
|
|
this.username = username;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setMessage(String message) {
|
|
|
|
|
|
this.message = message;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setTimestamp(long timestamp) {
|
|
|
|
|
|
this.timestamp = timestamp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setSystemMessage(boolean systemMessage) {
|
|
|
|
|
|
isSystemMessage = systemMessage;
|
|
|
|
|
|
}
|
2025-12-23 15:37:37 +08:00
|
|
|
|
|
|
|
|
|
|
public String getAvatarUrl() {
|
|
|
|
|
|
return avatarUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setAvatarUrl(String avatarUrl) {
|
|
|
|
|
|
this.avatarUrl = avatarUrl;
|
|
|
|
|
|
}
|
2025-12-24 17:43:14 +08:00
|
|
|
|
|
|
|
|
|
|
public MessageType getMessageType() {
|
|
|
|
|
|
return messageType;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setMessageType(MessageType messageType) {
|
|
|
|
|
|
this.messageType = messageType;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public String getMediaUrl() {
|
|
|
|
|
|
return mediaUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setMediaUrl(String mediaUrl) {
|
|
|
|
|
|
this.mediaUrl = mediaUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public String getLocalMediaPath() {
|
|
|
|
|
|
return localMediaPath;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setLocalMediaPath(String localMediaPath) {
|
|
|
|
|
|
this.localMediaPath = localMediaPath;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int getVoiceDuration() {
|
|
|
|
|
|
return voiceDuration;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setVoiceDuration(int voiceDuration) {
|
|
|
|
|
|
this.voiceDuration = voiceDuration;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int getImageWidth() {
|
|
|
|
|
|
return imageWidth;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setImageWidth(int imageWidth) {
|
|
|
|
|
|
this.imageWidth = imageWidth;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int getImageHeight() {
|
|
|
|
|
|
return imageHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setImageHeight(int imageHeight) {
|
|
|
|
|
|
this.imageHeight = imageHeight;
|
|
|
|
|
|
}
|
2025-12-29 18:02:28 +08:00
|
|
|
|
|
2026-01-08 16:44:12 +08:00
|
|
|
|
public Integer getBurnSeconds() {
|
|
|
|
|
|
return burnSeconds;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setBurnSeconds(Integer burnSeconds) {
|
|
|
|
|
|
this.burnSeconds = burnSeconds;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Long getViewedAt() {
|
|
|
|
|
|
return viewedAt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setViewedAt(Long viewedAt) {
|
|
|
|
|
|
this.viewedAt = viewedAt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Long getBurnAt() {
|
|
|
|
|
|
return burnAt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setBurnAt(Long burnAt) {
|
|
|
|
|
|
this.burnAt = burnAt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Boolean getBurned() {
|
|
|
|
|
|
return burned;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setBurned(Boolean burned) {
|
|
|
|
|
|
this.burned = burned;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-29 18:02:28 +08:00
|
|
|
|
public List<MessageReaction> getReactions() {
|
|
|
|
|
|
return reactions;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setReactions(List<MessageReaction> reactions) {
|
|
|
|
|
|
this.reactions = reactions;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void addReaction(MessageReaction reaction) {
|
|
|
|
|
|
if (this.reactions == null) {
|
|
|
|
|
|
this.reactions = new ArrayList<>();
|
|
|
|
|
|
}
|
|
|
|
|
|
this.reactions.add(reaction);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void removeReaction(String emoji) {
|
|
|
|
|
|
if (this.reactions != null) {
|
|
|
|
|
|
this.reactions.removeIf(r -> r.getEmoji().equals(emoji));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-18 14:52:20 +08:00
|
|
|
|
}
|