领取通知

This commit is contained in:
roxy 2026-05-09 16:12:15 +08:00
parent 14de02c822
commit 4aae854b78
6 changed files with 113 additions and 11 deletions

View File

@ -70,6 +70,9 @@ class SCRoomMsgType {
///
static const String roomRedPacket = "ROOM_RED_PACKET";
///
static const String roomRedPacketClaim = "ROOM_RED_PACKET_CLAIM";
///
static const String inviteRoom = "INVITE_ROOM";

View File

@ -3022,6 +3022,36 @@ class RealTimeCommunicationManager extends ChangeNotifier {
);
}
void sendRoomRedPacketClaimMessage({
required String packetId,
required num amount,
required String packetSenderName,
}) {
final groupId = currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "";
if (groupId.isEmpty) {
return;
}
final normalizedPacketId = packetId.trim();
final normalizedSenderName = packetSenderName.trim();
unawaited(
rtmProvider?.dispatchMessage(
Msg(
groupId: groupId,
msg: normalizedSenderName,
type: SCRoomMsgType.roomRedPacketClaim,
role: currenRoom?.entrants?.roles ?? "",
number: amount,
giftBatchId:
normalizedPacketId.isEmpty
? null
: 'room-red-packet-claim-$normalizedPacketId',
user: AccountStorage().getCurrentUser()?.userProfile,
),
) ??
Future<void>.value(),
);
}
void _refreshRoomRedPacketListAfterEntry() {
final roomId = currenRoom?.roomProfile?.roomProfile?.id?.trim() ?? "";
if (roomId.isEmpty) {

View File

@ -753,6 +753,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
case SCRoomMsgType.roomGameClose:
case SCRoomMsgType.roomGameCreate:
case SCRoomMsgType.luckGiftAnimOther:
case SCRoomMsgType.roomRedPacketClaim:
_sendRoomMessage(msg);
break;
default:
@ -1133,6 +1134,8 @@ class RealTimeMessagingManager extends ChangeNotifier {
case SCRoomMsgType.text:
case SCRoomMsgType.image:
return true;
case SCRoomMsgType.roomRedPacketClaim:
return true;
case SCRoomMsgType.emoticons:
return (msg.number ?? -1) < 0;
default:
@ -1191,6 +1194,13 @@ class RealTimeMessagingManager extends ChangeNotifier {
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
}
msgChatListener?.call(msg);
} else if (msg.type == SCRoomMsgType.roomRedPacketClaim) {
roomChatMsgList.insert(0, msg);
if (roomChatMsgList.length > 250) {
print('大于200条消息');
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
}
msgChatListener?.call(msg);
} else if (msg.type == SCRoomMsgType.gift ||
msg.type == SCRoomMsgType.luckGiftAnimOther) {
roomGiftMsgList.insert(0, msg);

View File

@ -790,17 +790,13 @@ class _RoomRedPacketOpenCardState extends State<_RoomRedPacketOpenCard> {
widget.data.senderName.trim().isNotEmpty
? widget.data.senderName.trim()
: localizations.redEnvelope;
final message = localizations.roomRedPacketReceivedMessage(
_formatNumber(amount.round()),
senderName,
);
final packetId = widget.data.packetId.trim();
Provider.of<RtcProvider>(context, listen: false).sendRoomTextMessage(
message,
dedupKey:
packetId.isEmpty
? null
: 'room-red-packet-claim-$packetId-${DateTime.now().microsecondsSinceEpoch}',
Provider.of<RtcProvider>(
context,
listen: false,
).sendRoomRedPacketClaimMessage(
packetId: widget.data.packetId,
amount: amount,
packetSenderName: senderName,
);
}

View File

@ -128,6 +128,9 @@ class _MsgItemState extends State<MsgItem> {
if (widget.msg.type == SCRoomMsgType.roomRedPacket) {
return _buildRoomRedPacketMsg(context);
}
if (widget.msg.type == SCRoomMsgType.roomRedPacketClaim) {
return _buildRoomRedPacketClaimMsg(context);
}
if (widget.msg.user != null) {
return Container(
alignment: AlignmentDirectional.topStart,
@ -279,6 +282,65 @@ class _MsgItemState extends State<MsgItem> {
);
}
Widget _buildRoomRedPacketClaimMsg(BuildContext context) {
final localizations = SCAppLocalizations.of(context)!;
final packetSenderName =
(widget.msg.msg ?? '').trim().isNotEmpty
? (widget.msg.msg ?? '').trim()
: localizations.redEnvelope;
final message = localizations.roomRedPacketReceivedMessage(
_formatAwardAmount(widget.msg.number),
packetSenderName,
);
return Container(
alignment: AlignmentDirectional.topStart,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: width(5.w),
vertical: width(4),
),
margin: EdgeInsets.symmetric(
horizontal: width(10),
).copyWith(bottom: 6.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.msg.user != null) ...[
_buildUserInfoLine(context),
SizedBox(height: 6.w),
],
Container(
constraints: BoxConstraints(
maxWidth: ScreenUtil().screenWidth * 0.7,
),
decoration: BoxDecoration(
color: Colors.black38,
borderRadius: BorderRadius.only(
topRight: Radius.circular(15.w),
bottomLeft: Radius.circular(15.w),
bottomRight: Radius.circular(15.w),
),
),
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.w),
margin: EdgeInsetsDirectional.only(
start: 54.w,
).copyWith(bottom: 8.w),
child: Text(
message,
style: TextStyle(
fontSize: sp(13),
color: Color(_msgColor(widget.msg.type ?? "")),
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.start,
),
),
],
),
),
);
}
Widget _buildVipTextMessageBubble(
PropsResources? resource, {
required double maxBubbleWidth,

View File

@ -559,6 +559,7 @@
- 已按最新反馈修正领取记录头像和跨房进房:领取记录空头像不再回退成红包图标,统一走项目默认头像;红包飘窗 `GO` 跨房点击直接进目标房间,不再弹进入房间二次确认。
- 已修正延时红包多入口数据不一致:公屏红包消息会同步写入待领缓存,右侧入口和领取弹层遇到同一 `packetId` 会合并接口列表、缓存和聊天 payload 的倒计时字段,避免飘屏 `GO`/右侧入口丢失倒计时;领取成功后右侧入口会优先按本地已领状态隐藏,避免接口刷新滞后导致残留。
- 已补齐红包发送后的 IM 广播:发送成功后除本机兜底展示外,会把 `{type: ROOM_RED_PACKET, data: payload}` 发送到当前房间 IM 群和当前语区 IM 群;同房用户通过房间群看到公屏/飘屏,房外或其它房同语区用户通过语区群看到飘屏,并继续依赖 `packetId` 去重避免重复展示。
- 已修正红包领取成功公屏消息的多语言问题:领取后不再发送已翻译好的普通文本,改为 `ROOM_RED_PACKET_CLAIM` 结构化房间 IM只传领取金额、红包发送人名和 `packetId`,公屏渲染时按当前客户端语言生成文案,避免英文用户看到阿语消息。
## 已知问题
- 已接入语音房表情包素材第一版:桌面 `表情素材` 中的 `fluent_emoji``monkey` gif 已纳入项目资源,底部聊天入口改为图稿里的短白色胶囊并移除内部输入图标,右侧新增独立表情按钮;同一个房间输入弹层现在可从表情按钮直接打开表情包面板,原 unicode emoji 面板已替换为本地 gif 表情。发送逻辑同步按最新规则分流:用户在麦上发表情时只在自己麦位播放,不进入聊天列表;用户未上麦发表情时进入房间聊天框展示,不触发麦位动画。