import 'package:cached_network_image/cached_network_image.dart'; import 'package:dating_touchme_app/controller/discover/svga_player_manager.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:im_flutter_sdk/im_flutter_sdk.dart'; import 'package:get/get.dart'; import '../../generated/assets.dart'; import '../../controller/global.dart'; import '../../controller/message/chat_controller.dart'; class GiftItem extends StatelessWidget { final EMMessage message; final bool isSentByMe; final bool showTime; final String formattedTime; final VoidCallback? onResend; const GiftItem({ required this.message, required this.isSentByMe, required this.showTime, required this.formattedTime, this.onResend, super.key, }); /// 从自定义消息的 params 中解析礼物信息 Map? _parseGiftInfo() { try { if (message.body.type == MessageType.CUSTOM) { final customBody = message.body as EMCustomMessageBody; if (customBody.event == 'gift' && customBody.params != null) { // 将 Map 转换为 Map final params = customBody.params!; return { 'giftProductId': params['giftProductId'] ?? '', 'giftProductTitle': params['giftProductTitle'] ?? '', 'giftMainPic': params['giftMainPic'] ?? '', 'svgaFile': params['svgaFile'] ?? '', 'giftPrice': params['giftPrice'] ?? '0', 'quantity': int.tryParse(params['quantity'] ?? '1') ?? 1, }; } } } catch (e) { print('解析礼物信息失败: $e'); } return null; } /// 获取礼物标题 String _getGiftTitle() { final giftInfo = _parseGiftInfo(); if (giftInfo != null) { return giftInfo['giftProductTitle']?.toString() ?? '礼物'; } return '礼物'; } String _getGiftSvga() { final giftInfo = _parseGiftInfo(); if (giftInfo != null) { return giftInfo['svgaFile']?.toString() ?? ''; } return ''; } /// 获取礼物图片 String _getGiftImage() { final giftInfo = _parseGiftInfo(); if (giftInfo != null) { return giftInfo['giftMainPic']?.toString() ?? ''; } return ''; } /// 获取礼物数量 int _getGiftQuantity() { final giftInfo = _parseGiftInfo(); if (giftInfo != null) { final quantity = giftInfo['quantity']; if (quantity is int) { return quantity; } else if (quantity is String) { return int.tryParse(quantity) ?? 1; } } return 1; } @override Widget build(BuildContext context) { final giftInfo = _parseGiftInfo(); if (giftInfo == null) { // 如果解析失败,不显示 return SizedBox.shrink(); } final giftTitle = _getGiftTitle(); final giftImage = _getGiftImage(); final quantity = _getGiftQuantity(); return Column( children: [ // 显示时间 if (showTime) _buildTimeLabel(), Container( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), child: Row( mainAxisAlignment: isSentByMe ? MainAxisAlignment.end : MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ if (!isSentByMe) _buildAvatar(), if (!isSentByMe) SizedBox(width: 8.w), // 发送消息时,状态在左侧 if (isSentByMe) Align( alignment: Alignment.center, child: Container( margin: EdgeInsets.only(top: 10.h), child: _buildMessageStatus(), ), ), if (isSentByMe) SizedBox(width: 10.w), // 礼物消息容器 Container( constraints: BoxConstraints(maxWidth: 200.w), margin: EdgeInsets.only(top: 10.h), padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: isSentByMe ? Color(0xff8E7BF6) : Colors.white, borderRadius: BorderRadius.only( topLeft: isSentByMe ? Radius.circular(12.w) : Radius.circular(0), topRight: isSentByMe ? Radius.circular(0) : Radius.circular(12.w), bottomLeft: Radius.circular(12.w), bottomRight: Radius.circular(12.w), ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ // 礼物图片 if (giftImage.isNotEmpty) Container( width: 40.w, height: 40.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.w), color: Colors.grey[200], ), child: ClipRRect( borderRadius: BorderRadius.circular(8.w), child: CachedNetworkImage( imageUrl: giftImage, fit: BoxFit.cover, placeholder: (context, url) => Container( color: Colors.grey[200], child: Center( child: SizedBox( width: 20.w, height: 20.w, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.grey[600], ), ), ), ), errorWidget: (context, url, error) => Container( color: Colors.grey[200], child: Icon( Icons.card_giftcard, size: 20.w, color: Colors.grey[400], ), ), ), ), ) else Container( width: 40.w, height: 40.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.w), color: Colors.grey[200], ), child: Icon( Icons.card_giftcard, size: 20.w, color: Colors.grey[400], ), ), SizedBox(width: 8.w), // 礼物信息 Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( giftTitle, style: TextStyle( fontSize: 14.sp, color: isSentByMe ? Colors.white : Colors.black87, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (quantity > 1) ...[ SizedBox(height: 2.h), Text( 'x$quantity', style: TextStyle( fontSize: 12.sp, color: isSentByMe ? Colors.white70 : Colors.grey[600], ), ), ], ], ), ), ], ), ).onTap((){ final svgaFile = _getGiftSvga(); Get.log(giftInfo.toString()); Get.log('${message.status}'); if ((message.status == MessageStatus.SUCCESS || message.status == MessageStatus.PROGRESS) && svgaFile.isNotEmpty) { final svgaManager = SvgaPlayerManager.instance; svgaManager.addToQueue( SvgaAnimationItem( svgaFile: svgaFile, giftProductId: giftInfo['giftProductId']?.toString() ?? '', ), ); } }), if (isSentByMe) SizedBox(width: 8.w), if (isSentByMe) _buildAvatar(), ], ), ), ], ); } // 构建时间标签 Widget _buildTimeLabel() { return Container( alignment: Alignment.center, padding: EdgeInsets.symmetric(horizontal: 16.w), child: Container( padding: EdgeInsets.symmetric(horizontal: 12.w), child: Text( formattedTime, style: TextStyle(fontSize: 12.sp, color: Colors.grey), ), ), ); } // 构建头像 Widget _buildAvatar() { String? avatarUrl; if (isSentByMe) { // 发送的消息:使用当前登录用户的头像 // 优先从消息 attributes 中获取 try { final attributes = message.attributes; if (attributes != null) { avatarUrl = attributes['sender_avatarUrl'] as String? ?? attributes['avatarUrl'] as String?; } } catch (e) { // 忽略错误 } // 如果消息中没有,使用当前登录用户的头像 if (avatarUrl == null || avatarUrl.isEmpty) { avatarUrl = GlobalData().userData?.profilePhoto; } } else { // 接收的消息:使用发送者的头像 try { final attributes = message.attributes; if (attributes != null) { avatarUrl = attributes['sender_avatarUrl'] as String? ?? attributes['avatarUrl'] as String?; } } catch (e) { // 忽略错误 } // 如果消息中没有,尝试从 ChatController 获取对方用户头像 if ((avatarUrl == null || avatarUrl.isEmpty)) { try { // 尝试从 Get 获取 ChatController final chatController = Get.find(); avatarUrl = chatController.userAvatarUrl; } catch (e) { // ChatController 可能不存在,忽略错误 } } } // 清理头像URL(移除反引号) if (avatarUrl != null && avatarUrl.isNotEmpty) { avatarUrl = avatarUrl.trim().replaceAll('`', ''); } return ClipOval( child: avatarUrl != null && avatarUrl.isNotEmpty ? CachedNetworkImage( imageUrl: avatarUrl, width: 40.w, height: 40.w, fit: BoxFit.cover, placeholder: (context, url) => Image.asset( Assets.imagesUserAvatar, width: 40.w, height: 40.w, fit: BoxFit.cover, ), errorWidget: (context, url, error) => Image.asset( Assets.imagesUserAvatar, width: 40.w, height: 40.w, fit: BoxFit.cover, ), ) : Image.asset( Assets.imagesUserAvatar, width: 40.w, height: 40.w, fit: BoxFit.cover, ), ); } // 构建消息状态(发送中、已发送、失败重发) Widget _buildMessageStatus() { if (!isSentByMe) { return SizedBox.shrink(); } final status = message.status; if (status == MessageStatus.FAIL) { // 发送失败,显示重发按钮 return GestureDetector( onTap: onResend, child: Container( width: 44.w, height: 26.h, decoration: BoxDecoration( color: Color.fromRGBO(248, 85, 66, 1), borderRadius: BorderRadius.circular(8.w), ), child: Center( child: Text( '重发', style: TextStyle( fontSize: 12.sp, color: Colors.white, ), ), ), ), ); } else if (status == MessageStatus.PROGRESS) { // 发送中,不显示loading return SizedBox.shrink(); } else { // 发送成功,不显示任何状态 return SizedBox.shrink(); } } }