2105 lines
80 KiB
Dart
2105 lines
80 KiB
Dart
import 'dart:convert';
|
||
import 'dart:io';
|
||
import 'package:extended_image/extended_image.dart'
|
||
show ExtendedImage, ExtendedRawImage, ExtendedImageState, LoadState;
|
||
import 'package:extended_text/extended_text.dart';
|
||
import 'package:extended_text_field/extended_text_field.dart';
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||
import 'package:yumi/app_localizations.dart';
|
||
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
|
||
import 'package:yumi/ui_kit/components/text/sc_text.dart';
|
||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||
import 'package:yumi/app/constants/sc_emoji_datas.dart';
|
||
import 'package:yumi/shared/tools/sc_date_utils.dart';
|
||
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||
import 'package:yumi/shared/tools/sc_message_utils.dart';
|
||
import 'package:yumi/shared/data_sources/sources/repositories/sc_user_repository_impl.dart';
|
||
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
|
||
import 'package:yumi/services/audio/rtm_manager.dart';
|
||
import 'package:marquee/marquee.dart';
|
||
import 'package:provider/provider.dart';
|
||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||
import 'package:tencent_cloud_chat_sdk/enum/V2TimAdvancedMsgListener.dart';
|
||
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
|
||
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_custom_elem.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_elem.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_image_elem.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_extension.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_online_url.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_text_elem.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_video_elem.dart';
|
||
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
|
||
|
||
import 'package:yumi/config/pickImage.dart';
|
||
import 'package:yumi/ui_kit/components/dialog/dialog_base.dart';
|
||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
|
||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||
import 'package:yumi/app/config/business_logic_strategy.dart';
|
||
import 'package:yumi/app/constants/sc_screen.dart';
|
||
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
|
||
import 'package:yumi/shared/tools/sc_keybord_util.dart';
|
||
import 'package:yumi/shared/tools/sc_message_notifier.dart';
|
||
import 'package:yumi/shared/tools/sc_path_utils.dart';
|
||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||
import 'package:yumi/shared/business_logic/usecases/custom_tab_selector.dart';
|
||
import 'package:yumi/services/auth/user_profile_manager.dart';
|
||
import 'package:yumi/modules/index/main_route.dart';
|
||
|
||
import '../../shared/business_logic/models/res/sc_user_red_packet_send_res.dart';
|
||
|
||
class SCMessageChatPage extends StatefulWidget {
|
||
final V2TimConversation? conversation;
|
||
final bool shrinkWrap;
|
||
|
||
//是否是房间内聊天界面。
|
||
final bool inRoom;
|
||
|
||
const SCMessageChatPage({
|
||
Key? key,
|
||
this.conversation,
|
||
this.shrinkWrap = false,
|
||
this.inRoom = false,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
_SCMessageChatPageState createState() => _SCMessageChatPageState();
|
||
}
|
||
|
||
class _SCMessageChatPageState extends State<SCMessageChatPage> {
|
||
BusinessLogicStrategy get _strategy => SCGlobalConfig.businessLogicStrategy;
|
||
|
||
final TextEditingController _textController = TextEditingController();
|
||
final ScrollController _scrollController = ScrollController();
|
||
final RefreshController _refreshController = RefreshController();
|
||
|
||
// FlutterSoundPlayer? flutterSound;
|
||
RtmProvider? rtmProvider;
|
||
V2TimConversation? currentConversation;
|
||
List<V2TimMessage> currentConversationMessageList = [];
|
||
final FocusNode _focusNode = FocusNode();
|
||
|
||
///是否显示工具栏
|
||
bool showTools = false;
|
||
bool showEmoji = false;
|
||
|
||
bool showDoNotClickUnfamiliarTips = true;
|
||
|
||
///互相关注才能互相发送消息
|
||
bool canSendMsg = false;
|
||
SocialChatUserProfile? friend;
|
||
|
||
///是否显示发送按钮
|
||
bool showSend = false;
|
||
|
||
List<String> coinsTitles = ["100", "1000", "10000", "50000"];
|
||
String selecteCoins = "100";
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
SCMessageNotifier.canPlay = false;
|
||
SCMessageUtils.redPacketFutureCache.clear();
|
||
|
||
// flutterSound = FlutterSoundPlayer();
|
||
|
||
rtmProvider = Provider.of<RtmProvider>(context, listen: false);
|
||
currentConversation = widget.conversation;
|
||
rtmProvider?.onMessageRecvC2CReadListener = _onMessageRecvC2CRead;
|
||
rtmProvider?.onRevokeMessageListener = _onRevokeMessage;
|
||
rtmProvider?.onNewMessageCurrentConversationListener = _onNewMessage;
|
||
loadMsg();
|
||
|
||
if (friend == null) {
|
||
loadFriend();
|
||
}
|
||
|
||
_focusNode.addListener(() {
|
||
if (_focusNode.hasFocus) {
|
||
setState(() {
|
||
showTools = false;
|
||
showEmoji = false;
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
rtmProvider?.onMessageRecvC2CReadListener = null;
|
||
rtmProvider?.onRevokeMessageListener = null;
|
||
rtmProvider?.onNewMessageCurrentConversationListener = null;
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Consumer<RtmProvider>(
|
||
builder: (_, provider, __) {
|
||
return WillPopScope(
|
||
onWillPop: () {
|
||
if (showEmoji || showTools) {
|
||
setState(() {
|
||
showEmoji = false;
|
||
showTools = false;
|
||
});
|
||
return Future.value(false);
|
||
}
|
||
SCNavigatorUtils.goBack(context);
|
||
return Future.value(true);
|
||
},
|
||
child: Stack(
|
||
children: [
|
||
if (!widget.inRoom)
|
||
// 渐变背景
|
||
Positioned(
|
||
left: 0,
|
||
right: 0,
|
||
top: 0,
|
||
child: Column(
|
||
children: [
|
||
SizedBox(
|
||
width: ScreenUtil().screenWidth,
|
||
height: ScreenUtil().screenHeight,
|
||
child: Image.asset(
|
||
_strategy.getSCMessageChatPageRoomSettingBackground(),
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
Scaffold(
|
||
//backgroundColor: widget.inRoom ? Colors.transparent: Color(0xfff8f8f8),
|
||
backgroundColor: Colors.transparent,
|
||
// appBar: _appBar(),
|
||
appBar: null,
|
||
body: SafeArea(
|
||
top: widget.shrinkWrap ? false : true,
|
||
bottom: false,
|
||
child: Column(
|
||
children: <Widget>[
|
||
Row(
|
||
children: [
|
||
!widget.inRoom
|
||
? GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
Navigator.pop(context);
|
||
},
|
||
child: Container(
|
||
padding: EdgeInsets.symmetric(
|
||
horizontal: 10.w,
|
||
vertical: 10.w,
|
||
),
|
||
child: Icon(
|
||
SCGlobalConfig.lang == "ar"
|
||
? Icons.keyboard_arrow_right
|
||
: Icons.keyboard_arrow_left,
|
||
size: 28.w,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
)
|
||
: Container(),
|
||
SizedBox(width: 5.w),
|
||
Expanded(
|
||
child: Container(
|
||
alignment: AlignmentDirectional.center,
|
||
child: socialchatNickNameText(
|
||
friend?.userNickname ?? "",
|
||
fontSize: 14.sp,
|
||
fontWeight: FontWeight.w500,
|
||
textColor: Colors.white,
|
||
type: "",
|
||
needScroll:
|
||
(friend?.userNickname?.characters.length ??
|
||
0) >
|
||
22,
|
||
),
|
||
),
|
||
),
|
||
GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
SCNavigatorUtils.push(
|
||
context,
|
||
replace: true,
|
||
"${SCMainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == friend?.id}&tageId=${friend?.id}",
|
||
);
|
||
},
|
||
child: Container(
|
||
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
||
child: Icon(
|
||
Icons.more_vert,
|
||
size: 22.w,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
Expanded(child: _msgList()),
|
||
Container(
|
||
decoration: BoxDecoration(
|
||
//color: Colors.white,
|
||
//border: Border(top: BorderSide(color: Color(0xfff1f1f1)))
|
||
),
|
||
child: SafeArea(
|
||
top: false,
|
||
child: Column(
|
||
children: <Widget>[
|
||
if (!SCGlobalConfig.isSystemConversationId(
|
||
currentConversation?.conversationID,
|
||
))
|
||
_input(),
|
||
_tools(provider),
|
||
_emoji(),
|
||
// _fahongbao(),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
void loadFriend() {
|
||
if (SCGlobalConfig.isSystemConversationId(currentConversation?.conversationID) ||
|
||
SCGlobalConfig.isSystemUserId(currentConversation?.userID)) {
|
||
return;
|
||
}
|
||
SCLoadingManager.show();
|
||
Future.wait([
|
||
SCAccountRepository().loadUserInfo("${currentConversation?.userID}"),
|
||
SCAccountRepository().friendRelationCheck(
|
||
"${currentConversation?.userID}",
|
||
),
|
||
])
|
||
.then((result) {
|
||
SCLoadingManager.hide();
|
||
friend = result[0] as SocialChatUserProfile;
|
||
canSendMsg = result[1] as bool;
|
||
setState(() {});
|
||
})
|
||
.catchError((e) {
|
||
SCLoadingManager.hide();
|
||
});
|
||
}
|
||
|
||
///消息列表
|
||
Widget _msgList() {
|
||
print('xiaoxiliebiao:${currentConversationMessageList.length}');
|
||
return SmartRefresher(
|
||
enablePullDown: false,
|
||
enablePullUp: true,
|
||
onLoading: () async {
|
||
print('onLoading');
|
||
if (currentConversationMessageList.isNotEmpty) {
|
||
// 拉取单聊历史消息
|
||
// 首次拉取,lastMsgID 设置为 null
|
||
// 再次拉取时,lastMsgID 可以使用返回的消息列表中的最后一条消息的id
|
||
V2TimValueCallback<List<V2TimMessage>> v2timValueCallback =
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.getC2CHistoryMessageList(
|
||
userID: currentConversation!.userID ?? "",
|
||
count: 30,
|
||
lastMsgID: currentConversationMessageList.last.msgID,
|
||
);
|
||
List<V2TimMessage> messages =
|
||
v2timValueCallback.data as List<V2TimMessage>;
|
||
print('加载前:${currentConversationMessageList.length}');
|
||
currentConversationMessageList.addAll(messages);
|
||
print('加载后:${currentConversationMessageList.length}');
|
||
if (messages.length == 30) {
|
||
_refreshController.loadComplete();
|
||
} else {
|
||
_refreshController.loadNoData();
|
||
}
|
||
} else {
|
||
_refreshController.loadNoData();
|
||
}
|
||
setState(() {});
|
||
},
|
||
footer: CustomFooter(
|
||
height: 1,
|
||
builder: (context, mode) {
|
||
return SizedBox(
|
||
height: 1,
|
||
width: 1,
|
||
child: SizedBox(height: 1, width: 1),
|
||
);
|
||
},
|
||
),
|
||
controller: _refreshController,
|
||
child: CustomScrollView(
|
||
shrinkWrap: true,
|
||
controller: _scrollController,
|
||
reverse: true,
|
||
physics: const ClampingScrollPhysics(),
|
||
// 禁用回弹效果
|
||
slivers: [
|
||
SliverList(
|
||
delegate: SliverChildBuilderDelegate(
|
||
(c, i) => _MessageItem(
|
||
message: currentConversationMessageList[i],
|
||
preMessage:
|
||
i < currentConversationMessageList.length - 1
|
||
? currentConversationMessageList[i + 1]
|
||
: null,
|
||
isSystem:
|
||
currentConversationMessageList[i].sender == "administrator",
|
||
friend: friend,
|
||
currentConversationMessageList: currentConversationMessageList,
|
||
updateCall: () {
|
||
setState(() {});
|
||
},
|
||
),
|
||
childCount: currentConversationMessageList.length,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<void> loadMsg() async {
|
||
// 1. 在初始化时,添加高级消息监听器
|
||
TencentImSDKPlugin.v2TIMManager.getMessageManager().addAdvancedMsgListener(
|
||
listener: V2TimAdvancedMsgListener(
|
||
// 监听消息扩展更新
|
||
onRecvMessageExtensionsChanged: (msgID, extensions) {
|
||
for (var ext in extensions) {
|
||
if (ext.extensionKey == "packetID") {
|
||
String packetID = ext.extensionValue;
|
||
SCMessageUtils.redPacketFutureCache[packetID] =
|
||
SCAccountRepository().userRedPacketDetail(packetID);
|
||
setState(() {});
|
||
break;
|
||
}
|
||
}
|
||
},
|
||
),
|
||
);
|
||
V2TimValueCallback<List<V2TimMessage>> v2timValueCallback =
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.getC2CHistoryMessageList(
|
||
userID: currentConversation!.userID!,
|
||
count: 100,
|
||
lastMsgID: null,
|
||
);
|
||
List<V2TimMessage> messages = v2timValueCallback.data!;
|
||
// List<V2TimMessage> messages = await FTIM.getMessageManager().getMessages(conversation: currentConversation);
|
||
print("messages : ${messages?.length ?? 0}");
|
||
currentConversationMessageList ??= [];
|
||
currentConversationMessageList?.clear();
|
||
|
||
for (var msg in messages) {
|
||
if (!msg.isSelf! && msg.isPeerRead!) {
|
||
TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.sendMessageReadReceipts(messageIDList: [msg.msgID!]);
|
||
}
|
||
}
|
||
currentConversationMessageList.insertAll(0, messages ?? []);
|
||
setState(() {});
|
||
}
|
||
|
||
///输入栏
|
||
Widget _input() {
|
||
return Consumer<SocialChatUserProfileManager>(
|
||
builder:
|
||
(_, provider, __) => Container(
|
||
color: Colors.transparent,
|
||
height: 56.w,
|
||
child: Row(
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: <Widget>[
|
||
SizedBox(width: 15.w),
|
||
Expanded(
|
||
child: Container(
|
||
height: 34.w,
|
||
decoration: BoxDecoration(
|
||
borderRadius: BorderRadius.circular(52.w),
|
||
color: Color(0xff18F2B1).withOpacity(0.1),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
child: ExtendedTextField(
|
||
controller: _textController,
|
||
focusNode: _focusNode,
|
||
onChanged: (s) {
|
||
setState(() {
|
||
showSend = _textController.text.isNotEmpty;
|
||
});
|
||
},
|
||
onSubmitted: (s) {
|
||
if (s.isNotEmpty) {
|
||
sendMsg(s);
|
||
showSend = false;
|
||
setState(() {});
|
||
_scrollController.jumpTo(0.0);
|
||
_textController.clear();
|
||
}
|
||
},
|
||
decoration: InputDecoration(
|
||
hintText:
|
||
SCAppLocalizations.of(
|
||
context,
|
||
)!.clickHereToStartChatting,
|
||
hintStyle: TextStyle(
|
||
color: Color(0xff999999),
|
||
fontSize: 14.sp,
|
||
),
|
||
contentPadding: const EdgeInsets.symmetric(
|
||
horizontal: 15,
|
||
),
|
||
counterText: '',
|
||
isDense: true,
|
||
filled: false,
|
||
focusColor: Colors.transparent,
|
||
hoverColor: Colors.transparent,
|
||
border: InputBorder.none,
|
||
enabledBorder: InputBorder.none,
|
||
focusedBorder: InputBorder.none,
|
||
disabledBorder: InputBorder.none,
|
||
errorBorder: InputBorder.none,
|
||
focusedErrorBorder: InputBorder.none,
|
||
),
|
||
style: TextStyle(
|
||
fontSize: ScreenUtil().setSp(14),
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
),
|
||
//原来的emoji按钮
|
||
//SizedBox(width: 10.w,),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
SizedBox(width: 10.w),
|
||
!showEmoji
|
||
? GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
SCKeybordUtil.hide(context);
|
||
setState(() {
|
||
if (showTools) {
|
||
showTools = false;
|
||
}
|
||
showEmoji = !showEmoji;
|
||
});
|
||
},
|
||
child: Image.asset(
|
||
_strategy.getSCMessageChatPageEmojiIcon(),
|
||
width: 24.w,
|
||
color: Colors.white,
|
||
fit: BoxFit.fill,
|
||
),
|
||
)
|
||
: Container(),
|
||
showEmoji
|
||
? GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
SCKeybordUtil.hide(context);
|
||
setState(() {
|
||
if (showTools) {
|
||
showTools = false;
|
||
}
|
||
showEmoji = !showEmoji;
|
||
});
|
||
},
|
||
child: Image.asset(
|
||
_strategy.getSCMessageChatPageChatKeyboardIcon(),
|
||
width: 24.w,
|
||
color: Colors.white,
|
||
fit: BoxFit.fill,
|
||
),
|
||
)
|
||
: Container(),
|
||
if (!showSend) SizedBox(width: 12.w),
|
||
if (showSend) SizedBox(width: 5.w),
|
||
Visibility(
|
||
visible: !showSend,
|
||
child: GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
SCKeybordUtil.hide(context);
|
||
setState(() {
|
||
if (showEmoji) {
|
||
showEmoji = false;
|
||
}
|
||
showTools = !showTools;
|
||
});
|
||
},
|
||
child: Image.asset(
|
||
_strategy.getSCMessageChatPageAddIcon(),
|
||
width: 24.w,
|
||
color: Colors.white,
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
),
|
||
Visibility(
|
||
visible: showSend,
|
||
child: GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () async {
|
||
_scrollController.jumpTo(0.0);
|
||
if (_textController.text.isNotEmpty) {
|
||
SCKeybordUtil.hide(context);
|
||
sendMsg(_textController.text);
|
||
showSend = false;
|
||
setState(() {});
|
||
_textController.clear();
|
||
}
|
||
},
|
||
child: Image.asset(
|
||
_strategy.getSCMessageChatPageSendMessageIcon(),
|
||
height: 22.w,
|
||
color: Colors.white,
|
||
width: 32.w,
|
||
),
|
||
),
|
||
),
|
||
SizedBox(width: 15.w),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
///发消息
|
||
sendMsg(String msg) async {
|
||
if (!canSendMsg) {
|
||
SCTts.show(SCAppLocalizations.of(context)!.canSendMsgTips);
|
||
return;
|
||
}
|
||
Provider.of<RtmProvider>(
|
||
context,
|
||
listen: false,
|
||
).sendC2CTextMsg(msg, currentConversation!);
|
||
}
|
||
|
||
///发消息
|
||
sendCustomMsg(String msg, String extension) async {
|
||
if (!canSendMsg) {
|
||
SCTts.show(SCAppLocalizations.of(context)!.canSendMsgTips);
|
||
return;
|
||
}
|
||
Provider.of<RtmProvider>(
|
||
context,
|
||
listen: false,
|
||
).sendC2CCustomMsg(msg, currentConversation!, extension);
|
||
}
|
||
|
||
///工具栏
|
||
Widget _tools(RtmProvider provider) {
|
||
return Visibility(
|
||
visible: showTools,
|
||
child: Container(
|
||
color: Colors.white,
|
||
padding: EdgeInsets.only(bottom: 18.w, top: 5.w),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.start,
|
||
mainAxisSize: MainAxisSize.max,
|
||
children: <Widget>[
|
||
SizedBox(width: 20.w),
|
||
Expanded(
|
||
child: _toolsItem(
|
||
_strategy.getSCMessageChatPageCameraIcon(),
|
||
SCAppLocalizations.of(context)!.camera,
|
||
() async {
|
||
if (!canSendMsg) {
|
||
SCTts.show(SCAppLocalizations.of(context)!.canSendMsgTips);
|
||
return;
|
||
}
|
||
var pick = await ImagePick.pickFromCamera(context);
|
||
if (pick != null) {
|
||
provider.sendImageMsg(
|
||
file: pick,
|
||
conversation: currentConversation!,
|
||
);
|
||
}
|
||
},
|
||
),
|
||
),
|
||
Expanded(
|
||
child: _toolsItem(
|
||
_strategy.getSCMessageChatPagePictureIcon(),
|
||
SCAppLocalizations.of(context)!.album,
|
||
() async {
|
||
if (!canSendMsg) {
|
||
SCTts.show(SCAppLocalizations.of(context)!.canSendMsgTips);
|
||
return;
|
||
}
|
||
final List<File>? result =
|
||
await ImagePick.pickPicAndVideoFromGallery(context);
|
||
|
||
if (result == null) return; // 用户取消选择
|
||
if (result.isNotEmpty) {
|
||
provider.sendImageMsg(
|
||
selectedList: result,
|
||
conversation: currentConversation!,
|
||
);
|
||
}
|
||
},
|
||
),
|
||
),
|
||
Expanded(flex: 1, child: SizedBox()),
|
||
Expanded(flex: 1, child: SizedBox()),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
_emoji() {
|
||
return Visibility(
|
||
visible: showEmoji,
|
||
child: Container(
|
||
color: Colors.white,
|
||
height: 150.w,
|
||
child: GridView.builder(
|
||
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||
crossAxisCount: 8,
|
||
crossAxisSpacing: 8.w,
|
||
mainAxisSpacing: 8.w,
|
||
),
|
||
itemBuilder: (c, index) {
|
||
return GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
var text = SCEmojiDatas.smileys[index];
|
||
final TextEditingValue value = _textController.value;
|
||
_textController.value = value.copyWith(
|
||
text: value.text + text,
|
||
selection: TextSelection.fromPosition(
|
||
TextPosition(offset: text.length),
|
||
),
|
||
);
|
||
showSend = true;
|
||
setState(() {});
|
||
},
|
||
child: Padding(
|
||
padding: EdgeInsets.all(4.0.w),
|
||
child: ExtendedText(
|
||
SCEmojiDatas.smileys[index],
|
||
// specialTextSpanBuilder: MySpecialTextSpanBuilder(),
|
||
style: TextStyle(fontSize: sp(15)),
|
||
),
|
||
),
|
||
);
|
||
},
|
||
itemCount: SCEmojiDatas.smileys.length,
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
///工具项
|
||
_toolsItem(String image, String title, Function() onclick) {
|
||
return GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: onclick,
|
||
child: Column(
|
||
children: [
|
||
Image.asset(image, width: 50.w, fit: BoxFit.fitWidth),
|
||
SizedBox(height: 9.w),
|
||
Text(title, style: TextStyle(fontSize: 11.sp, color: Colors.black)),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
_onRevokeMessage(String msgId) {
|
||
int index = 0;
|
||
for (var msg in currentConversationMessageList) {
|
||
if (msgId == msg.msgID) {
|
||
break;
|
||
}
|
||
index = index + 1;
|
||
}
|
||
currentConversationMessageList.removeAt(index);
|
||
setState(() {});
|
||
}
|
||
|
||
_onMessageRecvC2CRead(List<String> messageIDList) {
|
||
for (var msg in currentConversationMessageList) {
|
||
for (var id in messageIDList) {
|
||
if (id == msg.msgID) {
|
||
msg.isPeerRead = true;
|
||
}
|
||
}
|
||
}
|
||
setState(() {});
|
||
}
|
||
|
||
_onNewMessage(V2TimMessage? message, {String? msgId}) async {
|
||
if (message == null) {
|
||
return;
|
||
}
|
||
if (message.userID != currentConversation?.userID) return;
|
||
|
||
int? index;
|
||
for (var element in currentConversationMessageList) {
|
||
if (msgId != null) {
|
||
if (msgId == element.msgID) {
|
||
element.status = MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL;
|
||
setState(() {});
|
||
continue;
|
||
}
|
||
} else {
|
||
if (element.msgID == message.msgID) {
|
||
index = currentConversationMessageList.indexOf(element);
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
if (msgId != null) {
|
||
return;
|
||
}
|
||
if (index != null) {
|
||
currentConversationMessageList.removeAt(index!);
|
||
currentConversationMessageList.insert(index!, message);
|
||
} else {
|
||
currentConversationMessageList.insert(0, message);
|
||
}
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.markC2CMessageAsRead(userID: currentConversation!.userID!);
|
||
//发送已读回执
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.sendMessageReadReceipts(messageIDList: [message.msgID!]);
|
||
setState(() {});
|
||
// await FTIM.getContactManager().setReadMessage(currentConversation);
|
||
}
|
||
}
|
||
|
||
class _MessageItem extends StatelessWidget {
|
||
final V2TimMessage message;
|
||
final V2TimMessage? preMessage;
|
||
|
||
BusinessLogicStrategy get _strategy => SCGlobalConfig.businessLogicStrategy;
|
||
|
||
// final FTIMUserProfile userProfile;
|
||
final SocialChatUserProfile? friend;
|
||
bool isSystem = false;
|
||
List<V2TimMessage> currentConversationMessageList = [];
|
||
Function updateCall;
|
||
|
||
///上一条
|
||
late BuildContext context;
|
||
|
||
_MessageItem({
|
||
required this.message,
|
||
this.preMessage,
|
||
// this.userProfile,
|
||
this.isSystem = false,
|
||
required this.currentConversationMessageList,
|
||
this.friend,
|
||
required this.updateCall,
|
||
});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
this.context = context;
|
||
SocialChatUserProfile? me = AccountStorage().getCurrentUser()?.userProfile;
|
||
bool showTime = true;
|
||
int timestamp = (message.timestamp ?? 0) * 1000;
|
||
int preTimestamp = (preMessage?.timestamp ?? 0) * 1000;
|
||
if (preMessage != null) {
|
||
///5分钟以内 不显示
|
||
// print('timestamp:$timestamp===preTimestamp:${preTimestamp}');
|
||
if (DateTime.fromMillisecondsSinceEpoch(timestamp)
|
||
.difference(DateTime.fromMillisecondsSinceEpoch(preTimestamp))
|
||
.inMilliseconds <
|
||
1000 * 60 * 5) {
|
||
showTime = false;
|
||
}
|
||
}
|
||
String time = SCMDateUtils.formatMessageTime(
|
||
context,
|
||
DateTime.fromMillisecondsSinceEpoch(timestamp ?? 0),
|
||
);
|
||
if (message.status == MessageStatus.V2TIM_MSG_STATUS_LOCAL_REVOKED) {
|
||
return Container(
|
||
alignment: AlignmentDirectional.center,
|
||
padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 5.w),
|
||
child: text(
|
||
SCAppLocalizations.of(context)!.messageHasBeenRecalled,
|
||
fontSize: 12.sp,
|
||
textColor: Colors.white54,
|
||
fontWeight: FontWeight.w400,
|
||
),
|
||
);
|
||
}
|
||
return Container(
|
||
margin: EdgeInsets.symmetric(horizontal: 15.w, vertical: 8.w),
|
||
child: Column(
|
||
crossAxisAlignment:
|
||
!message.isSelf!
|
||
? CrossAxisAlignment.start
|
||
: CrossAxisAlignment.end,
|
||
// textDirection: message.isSelf ? TextDirection.rtl : TextDirection.ltr,
|
||
children: <Widget>[
|
||
Visibility(
|
||
visible: showTime,
|
||
child: Container(
|
||
margin: EdgeInsets.only(bottom: 12.w),
|
||
child: Row(
|
||
children: <Widget>[
|
||
Spacer(),
|
||
Container(
|
||
alignment: Alignment.center,
|
||
padding: EdgeInsets.symmetric(
|
||
horizontal: width(15),
|
||
vertical: 8.w,
|
||
),
|
||
decoration: BoxDecoration(
|
||
//color: Color(0xFFEAEFF7),
|
||
borderRadius: BorderRadius.all(
|
||
Radius.circular(height(13)),
|
||
),
|
||
),
|
||
child: Text(
|
||
time,
|
||
style: TextStyle(
|
||
fontSize: sp(12),
|
||
color: Colors.white54,
|
||
fontWeight: FontWeight.w400,
|
||
decoration: TextDecoration.none,
|
||
height: 1,
|
||
),
|
||
),
|
||
),
|
||
Spacer(),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
Row(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
mainAxisSize: MainAxisSize.min,
|
||
textDirection:
|
||
message.isSelf! ? TextDirection.rtl : TextDirection.ltr,
|
||
children: <Widget>[
|
||
GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
if (isSystem) {
|
||
return;
|
||
}
|
||
SCNavigatorUtils.push(
|
||
context,
|
||
replace:
|
||
AccountStorage().getCurrentUser()?.userProfile?.id !=
|
||
message.sender,
|
||
"${SCMainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == message.sender}&tageId=${message.sender}",
|
||
);
|
||
},
|
||
child:
|
||
message.sender == "administrator" ||
|
||
message.sender == "customer"
|
||
? ExtendedImage.asset(
|
||
_strategy.getSCMessageChatPageSystemHeadImage(),
|
||
width: 45.w,
|
||
shape: BoxShape.circle,
|
||
fit: BoxFit.cover,
|
||
)
|
||
: netImage(
|
||
url:
|
||
message.isSelf!
|
||
? (me?.userAvatar ?? "")
|
||
: (friend?.userAvatar ?? ""),
|
||
shape: BoxShape.circle,
|
||
width: width(45),
|
||
),
|
||
),
|
||
// 他人消息的阴影间隔是10dp
|
||
Container(width: 8.w),
|
||
Row(
|
||
textDirection:
|
||
message.isSelf! ? TextDirection.rtl : TextDirection.ltr,
|
||
children: <Widget>[
|
||
Container(
|
||
alignment:
|
||
message.isSelf!
|
||
? AlignmentDirectional.topEnd
|
||
: AlignmentDirectional.topStart,
|
||
margin: EdgeInsets.only(top: 4.w),
|
||
child: _msg(),
|
||
),
|
||
SizedBox(width: 6.w),
|
||
Visibility(
|
||
visible:
|
||
message.status ==
|
||
MessageStatus.V2TIM_MSG_STATUS_SENDING,
|
||
child: CupertinoActivityIndicator(),
|
||
),
|
||
|
||
Visibility(
|
||
visible:
|
||
message.status ==
|
||
MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL,
|
||
child: Icon(Icons.error, color: Colors.red),
|
||
),
|
||
],
|
||
),
|
||
Spacer(),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
_msg() {
|
||
V2TIMElem? elem = message.textElem;
|
||
if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT) {
|
||
V2TimTextElem textElem = elem as V2TimTextElem;
|
||
String content = textElem.text ?? "";
|
||
} else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
|
||
V2TimImageElem imageElem = message.imageElem as V2TimImageElem;
|
||
var image;
|
||
if (imageElem.path!.length > 2 &&
|
||
File("${imageElem.path}").existsSync()) {
|
||
image = Image.file(File(imageElem.path!), fit: BoxFit.cover);
|
||
} else {
|
||
image = ExtendedImage.network(
|
||
'${imageElem.imageList![1]?.url}',
|
||
fit: BoxFit.cover,
|
||
width: double.infinity,
|
||
cache: true,
|
||
shape: BoxShape.rectangle,
|
||
borderRadius: BorderRadius.all(Radius.circular(width(6))),
|
||
loadStateChanged: (ExtendedImageState state) {
|
||
if (state.extendedImageLoadState == LoadState.completed) {
|
||
return ExtendedRawImage(
|
||
image: state.extendedImageInfo?.image,
|
||
fit: BoxFit.cover,
|
||
);
|
||
} else {
|
||
return Image.asset(
|
||
_strategy.getSCMessageChatPageLoadingIcon(),
|
||
fit: BoxFit.cover,
|
||
);
|
||
}
|
||
},
|
||
);
|
||
}
|
||
return Builder(
|
||
builder: (ct) {
|
||
return GestureDetector(
|
||
onTap: () {
|
||
List<String> ims = [];
|
||
int initialIndex = 0;
|
||
int index = 0;
|
||
for (var imageMsg in currentConversationMessageList) {
|
||
if (imageMsg.elemType ==
|
||
MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
|
||
String path = imageMsg.imageElem?.imageList![1]?.url ?? "";
|
||
if (path.isNotEmpty) {
|
||
ims.add(imageMsg.imageElem?.imageList![1]?.url ?? "");
|
||
if (imageMsg.msgID == message.msgID) {
|
||
initialIndex = index;
|
||
}
|
||
index = index + 1;
|
||
}
|
||
}
|
||
}
|
||
String encodedUrls = Uri.encodeComponent(jsonEncode(ims));
|
||
SCNavigatorUtils.push(
|
||
context,
|
||
"${SCMainRoute.imagePreview}?imageUrls=$encodedUrls&initialIndex=$initialIndex",
|
||
);
|
||
},
|
||
onLongPress: () {
|
||
_showMsgItemMenu(ct, "");
|
||
},
|
||
child: Container(
|
||
constraints: BoxConstraints(maxWidth: 200.w),
|
||
child: ClipRRect(
|
||
borderRadius: BorderRadius.circular(6.w),
|
||
child: image,
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
} else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_VIDEO) {
|
||
V2TimVideoElem videoElem = message.videoElem as V2TimVideoElem;
|
||
if (videoElem.snapshotPath != null &&
|
||
videoElem.snapshotPath!.isNotEmpty) {
|
||
return Builder(
|
||
builder: (ct) {
|
||
return GestureDetector(
|
||
child: Container(
|
||
constraints: BoxConstraints(maxWidth: 200.w),
|
||
child: ClipRRect(
|
||
borderRadius: BorderRadius.circular(6.w),
|
||
child: Stack(
|
||
alignment: Alignment.center,
|
||
children: [
|
||
Image.file(
|
||
File(videoElem.snapshotPath!),
|
||
fit: BoxFit.cover,
|
||
),
|
||
Icon(Icons.play_circle, color: Colors.white, size: 55.w),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
onTap: () {
|
||
String encodedVideoUrl = Uri.encodeComponent(
|
||
videoElem.videoPath ?? "",
|
||
);
|
||
SCNavigatorUtils.push(
|
||
context,
|
||
"${SCMainRoute.videoPlayer}?videoUrl=$encodedVideoUrl",
|
||
);
|
||
},
|
||
onLongPress: () {
|
||
_showMsgItemMenu(ct, "");
|
||
},
|
||
);
|
||
},
|
||
);
|
||
} else {
|
||
return FutureBuilder<V2TimValueCallback<V2TimMessageOnlineUrl>>(
|
||
// 假设 getMessageOnlineUrlForMessage 是对 TencentImSDKPlugin.v2TIMManager.getMessageManager().getMessageOnlineUrl 的封装,返回 Future<String>
|
||
future: SCMessageUtils().getMessageOnlineUrl(
|
||
msgID: message.msgID ?? "",
|
||
),
|
||
builder: (context, snapshot) {
|
||
// 根据异步任务状态构建UI
|
||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||
// 数据加载中,显示占位符
|
||
return Container();
|
||
} else if (snapshot.hasError) {
|
||
// 数据加载失败,显示错误UI
|
||
return Container();
|
||
} else if (snapshot.hasData) {
|
||
// 数据加载成功,更新消息的mediaUrl并构建正常消息UI
|
||
message.videoElem = snapshot.data?.data?.videoElem!;
|
||
return Builder(
|
||
builder: (ct) {
|
||
return GestureDetector(
|
||
child: Container(
|
||
constraints: BoxConstraints(maxWidth: 200.w),
|
||
child: ClipRRect(
|
||
borderRadius: BorderRadius.circular(6.w),
|
||
child: Stack(
|
||
alignment: Alignment.center,
|
||
children: [
|
||
SCPathUtils.getPathType(
|
||
message.videoElem?.snapshotPath ?? "",
|
||
) ==
|
||
PathType.file
|
||
? Image.file(
|
||
File(message.videoElem?.snapshotPath ?? ""),
|
||
fit: BoxFit.cover,
|
||
)
|
||
: netImage(
|
||
url: message.videoElem?.snapshotUrl ?? "",
|
||
),
|
||
Icon(
|
||
Icons.play_circle,
|
||
color: Colors.white,
|
||
size: 55.w,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
onTap: () {
|
||
String encodedVideoUrl = Uri.encodeComponent(
|
||
message.videoElem?.videoUrl ?? "",
|
||
);
|
||
SCNavigatorUtils.push(
|
||
context,
|
||
"${SCMainRoute.videoPlayer}?videoUrl=$encodedVideoUrl",
|
||
);
|
||
},
|
||
onLongPress: () {
|
||
_showMsgItemMenu(ct, "");
|
||
},
|
||
);
|
||
},
|
||
);
|
||
} else {
|
||
// 其他情况
|
||
return Container();
|
||
}
|
||
},
|
||
);
|
||
}
|
||
}
|
||
|
||
return _text();
|
||
}
|
||
|
||
///文本消息
|
||
_text() {
|
||
String content = "";
|
||
if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT) {
|
||
V2TimTextElem textElem = message.textElem!;
|
||
content = textElem.text ?? "";
|
||
if (isSystem) {}
|
||
} else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
|
||
content = SCAppLocalizations.of(context)!.image;
|
||
} else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_VIDEO) {
|
||
content = SCAppLocalizations.of(context)!.video;
|
||
} else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND) {
|
||
content = SCAppLocalizations.of(context)!.sound;
|
||
} else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
|
||
V2TimCustomElem customElem = message.customElem!;
|
||
content = customElem.data ?? "";
|
||
}
|
||
|
||
return Builder(
|
||
builder: (ct) {
|
||
return GestureDetector(
|
||
child: Container(
|
||
decoration: BoxDecoration(
|
||
color: Color(0xff18F2B1).withOpacity(0.1),
|
||
borderRadius: BorderRadius.only(
|
||
topLeft:
|
||
message.isSelf! ? Radius.circular(8) : Radius.circular(0),
|
||
topRight: Radius.circular(8.w),
|
||
bottomLeft: Radius.circular(8.w),
|
||
bottomRight:
|
||
message.isSelf! ? Radius.circular(0) : Radius.circular(8),
|
||
),
|
||
),
|
||
padding: EdgeInsets.all(8.0.w),
|
||
child: Container(
|
||
constraints: BoxConstraints(maxWidth: width(220)),
|
||
child: ExtendedText(
|
||
content,
|
||
// specialTextSpanBuilder: MySpecialTextSpanBuilder(),
|
||
style: TextStyle(
|
||
fontSize: sp(14),
|
||
color: message.isSelf! ? Colors.white : Colors.white,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
onLongPress: () {
|
||
_showMsgItemMenu(ct, content);
|
||
},
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
void _showMsgItemMenu(BuildContext ct, String content) {
|
||
SmartDialog.showAttach(
|
||
tag: "showMsgItemMenu",
|
||
targetContext: ct,
|
||
alignment: Alignment.topCenter,
|
||
maskColor: Colors.transparent,
|
||
animationType: SmartAnimationType.fade,
|
||
scalePointBuilder: (selfSize) => Offset(selfSize.width, 10),
|
||
builder: (_) {
|
||
return Container(
|
||
margin: EdgeInsets.only(bottom: 10.w),
|
||
decoration: BoxDecoration(
|
||
color: Color(0xffdcdddf),
|
||
borderRadius: BorderRadius.circular(10),
|
||
),
|
||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.w),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
SmartDialog.dismiss(tag: "showMsgItemMenu");
|
||
_delete();
|
||
},
|
||
child: Container(
|
||
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
_strategy.getSCMessageChatPageMessageMenuDeleteIcon(),
|
||
width: 20.w,
|
||
),
|
||
SizedBox(height: 3.w),
|
||
text(
|
||
SCAppLocalizations.of(context)!.delete,
|
||
fontSize: 12.sp,
|
||
textColor: Color(0xff777777),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
content.isNotEmpty
|
||
? GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
SmartDialog.dismiss(tag: "showMsgItemMenu");
|
||
Clipboard.setData(ClipboardData(text: content));
|
||
SCTts.show(
|
||
SCAppLocalizations.of(context)!.copiedToClipboard,
|
||
);
|
||
},
|
||
child: Container(
|
||
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
_strategy.getSCMessageChatPageMessageMenuCopyIcon(),
|
||
width: 20.w,
|
||
),
|
||
SizedBox(height: 3.w),
|
||
text(
|
||
SCAppLocalizations.of(context)!.copy,
|
||
fontSize: 12.sp,
|
||
textColor: Color(0xff777777),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
)
|
||
: Container(),
|
||
(message.isSelf ?? false)
|
||
? GestureDetector(
|
||
onTap: () {
|
||
SmartDialog.dismiss(tag: "showMsgItemMenu");
|
||
_revokeMessage();
|
||
},
|
||
behavior: HitTestBehavior.opaque,
|
||
child: Container(
|
||
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
_strategy
|
||
.getSCMessageChatPageMessageMenuRecallIcon(),
|
||
width: 20.w,
|
||
),
|
||
SizedBox(height: 3.w),
|
||
text(
|
||
SCAppLocalizations.of(context)!.recall,
|
||
fontSize: 12.sp,
|
||
textColor: Color(0xff777777),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
)
|
||
: Container(),
|
||
],
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
///撤回消息
|
||
void _revokeMessage() async {
|
||
SmartDialog.show(
|
||
tag: "showConfirmDialog",
|
||
alignment: Alignment.center,
|
||
debounce: true,
|
||
animationType: SmartAnimationType.fade,
|
||
builder: (_) {
|
||
return MsgDialog(
|
||
title: SCAppLocalizations.of(context)!.tips,
|
||
msg: SCAppLocalizations.of(context)!.recallThisMessage,
|
||
btnText: SCAppLocalizations.of(context)!.confirm,
|
||
onEnsure: () async {
|
||
// 撤回指定msgID的消息
|
||
V2TimCallback revokeMessage = await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.revokeMessage(msgID: message.msgID ?? "");
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.deleteMessages(msgIDs: [message.msgID ?? ""]);
|
||
if (revokeMessage.code == 0) {
|
||
// 撤回成功
|
||
int index = 0;
|
||
for (var value in currentConversationMessageList) {
|
||
if (value.msgID == message.msgID) {
|
||
break;
|
||
}
|
||
index = index + 1;
|
||
}
|
||
currentConversationMessageList.removeAt(index);
|
||
updateCall();
|
||
} else {
|
||
// 撤回失败,可通过 revokeMessage.desc 获取错误描述
|
||
SCTts.show("fail:${revokeMessage.desc}");
|
||
}
|
||
},
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
///删除消息
|
||
void _delete() {
|
||
SmartDialog.show(
|
||
tag: "showDeleteDialog",
|
||
alignment: Alignment.bottomCenter,
|
||
debounce: true,
|
||
animationType: SmartAnimationType.fade,
|
||
builder: (_) {
|
||
return SafeArea(
|
||
child: Container(
|
||
height: 168.w,
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.only(
|
||
topLeft: Radius.circular(8.0),
|
||
topRight: Radius.circular(8.0),
|
||
),
|
||
),
|
||
child: Column(
|
||
children: [
|
||
SizedBox(height: 10.w),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(context)!.tips,
|
||
fontSize: 16.sp,
|
||
textColor: Colors.black,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
],
|
||
),
|
||
SizedBox(height: 5.w),
|
||
Divider(height: height(1), color: SocialChatTheme.dividerColor),
|
||
GestureDetector(
|
||
child: Container(
|
||
padding: EdgeInsets.symmetric(vertical: 10.w),
|
||
color: Colors.transparent,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(context)!.deleteFromMyDevice,
|
||
fontSize: 14.sp,
|
||
textColor: Colors.black,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
onTap: () async {
|
||
V2TimCallback deleteMessageFromLocalStorage =
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.deleteMessageFromLocalStorage(
|
||
msgID: message.msgID ?? "",
|
||
);
|
||
if (deleteMessageFromLocalStorage.code == 0) {
|
||
//删除成功
|
||
int index = 0;
|
||
for (var value in currentConversationMessageList) {
|
||
if (value.msgID == message.msgID) {
|
||
break;
|
||
}
|
||
index = index + 1;
|
||
}
|
||
currentConversationMessageList.removeAt(index);
|
||
updateCall();
|
||
SmartDialog.dismiss(tag: "showDeleteDialog");
|
||
}
|
||
},
|
||
),
|
||
Divider(height: height(1), color: SocialChatTheme.dividerColor),
|
||
GestureDetector(
|
||
onTap: () async {
|
||
V2TimCallback deleteMessageFromLocalStorage =
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.deleteMessages(msgIDs: [message.msgID ?? ""]);
|
||
if (deleteMessageFromLocalStorage.code == 0) {
|
||
//删除成功
|
||
int index = 0;
|
||
for (var value in currentConversationMessageList) {
|
||
if (value.msgID == message.msgID) {
|
||
break;
|
||
}
|
||
index = index + 1;
|
||
}
|
||
currentConversationMessageList.removeAt(index);
|
||
updateCall();
|
||
SmartDialog.dismiss(tag: "showDeleteDialog");
|
||
}
|
||
},
|
||
child: Container(
|
||
padding: EdgeInsets.symmetric(vertical: 10.w),
|
||
color: Colors.transparent,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(context)!.deleteOnAllDevices,
|
||
fontSize: 14.sp,
|
||
textColor: Colors.black,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
Divider(height: height(1), color: SocialChatTheme.dividerColor),
|
||
GestureDetector(
|
||
onTap: () async {
|
||
SmartDialog.dismiss(tag: "showDeleteDialog");
|
||
},
|
||
child: Container(
|
||
padding: EdgeInsets.symmetric(vertical: 10.w),
|
||
color: Colors.transparent,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(context)!.cancel,
|
||
fontSize: 14.sp,
|
||
textColor: Colors.black,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
Future<void> updateRedPacketStatus(String messageID, String packetID) async {
|
||
// 构建扩展信息,例如标记为已领取,并包含领取者ID
|
||
Map<String, String> extensionMap = {"packetID": packetID};
|
||
|
||
List<V2TimMessageExtension> extensions =
|
||
extensionMap.entries
|
||
.map(
|
||
(e) => V2TimMessageExtension(
|
||
extensionKey: e.key,
|
||
extensionValue: e.value,
|
||
),
|
||
)
|
||
.toList();
|
||
|
||
await TencentImSDKPlugin.v2TIMManager
|
||
.getMessageManager()
|
||
.setMessageExtensions(
|
||
msgID: messageID, // 原始红包消息的ID
|
||
extensions: extensions,
|
||
);
|
||
}
|
||
|
||
void _showOpenDialog(SCUserRedPacketSendRes resData) {
|
||
SmartDialog.show(
|
||
tag: "showOpenDialog",
|
||
alignment: Alignment.center,
|
||
debounce: true,
|
||
animationType: SmartAnimationType.fade,
|
||
builder: (_) {
|
||
return Container(
|
||
height: 400.w,
|
||
alignment: Alignment.topCenter,
|
||
decoration: BoxDecoration(
|
||
image: DecorationImage(
|
||
image: AssetImage(
|
||
_strategy.getSCMessageChatPageRedEnvelopeOpenBackground(),
|
||
),
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
child: Column(
|
||
children: [
|
||
SizedBox(height: 100.w),
|
||
SCDebounceWidget(
|
||
child: Container(
|
||
alignment: Alignment.center,
|
||
width: 60.w,
|
||
height: 60.w,
|
||
color: Colors.transparent,
|
||
child: text(
|
||
SCAppLocalizations.of(context)!.open,
|
||
textColor: Colors.white,
|
||
fontSize: 16.sp,
|
||
fontWeight: FontWeight.w900,
|
||
),
|
||
),
|
||
onTap: () {
|
||
SmartDialog.dismiss(tag: "showOpenDialog");
|
||
SCLoadingManager.show();
|
||
SCAccountRepository()
|
||
.userRedPacketGrab(resData.packetId ?? "")
|
||
.then((res) {
|
||
var future = SCAccountRepository().userRedPacketDetail(
|
||
resData.packetId ?? "",
|
||
);
|
||
updateRedPacketStatus(
|
||
message.msgID ?? "",
|
||
resData.packetId ?? "",
|
||
);
|
||
SCMessageUtils.redPacketFutureCache[resData.packetId ??
|
||
""] =
|
||
future;
|
||
future
|
||
.then((res2) {
|
||
SCLoadingManager.hide();
|
||
updateCall();
|
||
_showOpenedDialog(res2);
|
||
})
|
||
.catchError((e) {
|
||
SCLoadingManager.hide();
|
||
});
|
||
})
|
||
.catchError((e) {
|
||
SCLoadingManager.hide();
|
||
});
|
||
},
|
||
),
|
||
SizedBox(height: 35.w),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(context)!.openRedPackDialogTip,
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white,
|
||
fontSize: 14.sp,
|
||
),
|
||
SizedBox(width: 3.w),
|
||
Container(
|
||
margin: EdgeInsets.only(bottom: 1.w),
|
||
height: 18.w,
|
||
constraints: BoxConstraints(maxWidth: 65.w),
|
||
child:
|
||
(resData.senderInfo?.nickName?.length ?? 0) > 6
|
||
? Marquee(
|
||
text: resData.senderInfo?.nickName ?? "",
|
||
style: TextStyle(
|
||
fontSize: 14.sp,
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.w600,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
scrollAxis: Axis.horizontal,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
blankSpace: 20.0,
|
||
velocity: 40.0,
|
||
pauseAfterRound: Duration(seconds: 1),
|
||
accelerationDuration: Duration(seconds: 1),
|
||
accelerationCurve: Curves.easeOut,
|
||
decelerationDuration: Duration(milliseconds: 550),
|
||
decelerationCurve: Curves.easeOut,
|
||
)
|
||
: Text(
|
||
resData.senderInfo?.nickName ?? "",
|
||
maxLines: 1,
|
||
overflow: TextOverflow.ellipsis,
|
||
style: TextStyle(
|
||
fontSize: 14.sp,
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.w600,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
),
|
||
),
|
||
SizedBox(width: 3.w),
|
||
Container(
|
||
child: text(
|
||
SCAppLocalizations.of(context)!.sent,
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white,
|
||
fontSize: 14.sp,
|
||
),
|
||
height: 18.w,
|
||
),
|
||
],
|
||
),
|
||
SizedBox(height: 15.w),
|
||
Row(
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(context)!.wishingYouHappinessEveryDay,
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white70,
|
||
fontSize: 13.sp,
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
void _showOpenedDialog(SCUserRedPacketSendRes resData) {
|
||
SmartDialog.show(
|
||
tag: "showOpenedDialog",
|
||
alignment: Alignment.center,
|
||
debounce: true,
|
||
animationType: SmartAnimationType.fade,
|
||
builder: (_) {
|
||
return Container(
|
||
margin: EdgeInsets.symmetric(horizontal: 20.w),
|
||
decoration: BoxDecoration(
|
||
image: DecorationImage(
|
||
image: AssetImage(
|
||
_strategy.getSCMessageChatPageRedEnvelopeOpenedBackground(),
|
||
),
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
SizedBox(height: 70.w),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.end,
|
||
children: [
|
||
GestureDetector(
|
||
child: Icon(Icons.close, size: 18.w, color: Colors.white),
|
||
onTap: () {
|
||
SmartDialog.dismiss(tag: "showOpenedDialog");
|
||
},
|
||
),
|
||
SizedBox(width: 10.w),
|
||
],
|
||
),
|
||
SizedBox(height: 25.w),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.start,
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: [
|
||
SizedBox(width: 20.w),
|
||
netImage(
|
||
url: resData.senderInfo?.avatar ?? "",
|
||
shape: BoxShape.circle,
|
||
width: 45.w,
|
||
height: 45.w,
|
||
),
|
||
SizedBox(width: 10.w),
|
||
Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Container(
|
||
height: 18.w,
|
||
constraints: BoxConstraints(maxWidth: 85.w),
|
||
child:
|
||
(resData.senderInfo?.nickName?.length ?? 0) > 8
|
||
? Marquee(
|
||
text: resData.senderInfo?.nickName ?? "",
|
||
style: TextStyle(
|
||
fontSize: 14.sp,
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.w600,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
scrollAxis: Axis.horizontal,
|
||
crossAxisAlignment:
|
||
CrossAxisAlignment.start,
|
||
blankSpace: 20.0,
|
||
velocity: 40.0,
|
||
pauseAfterRound: Duration(seconds: 1),
|
||
accelerationDuration: Duration(
|
||
seconds: 1,
|
||
),
|
||
accelerationCurve: Curves.easeOut,
|
||
decelerationDuration: Duration(
|
||
milliseconds: 500,
|
||
),
|
||
decelerationCurve: Curves.easeOut,
|
||
)
|
||
: Text(
|
||
resData.senderInfo?.nickName ?? "",
|
||
maxLines: 1,
|
||
overflow: TextOverflow.ellipsis,
|
||
style: TextStyle(
|
||
fontSize: 14.sp,
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.w600,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
),
|
||
),
|
||
SizedBox(width: 5.w),
|
||
Container(
|
||
child: text(
|
||
SCAppLocalizations.of(context)!.sentARedEnvelope,
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white,
|
||
fontSize: 14.sp,
|
||
),
|
||
height: 18.w,
|
||
),
|
||
],
|
||
),
|
||
SizedBox(height: 5.w),
|
||
Row(
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(
|
||
context,
|
||
)!.wishingYouHappinessEveryDay,
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white70,
|
||
fontSize: 13.sp,
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
SizedBox(height: 10.w),
|
||
AccountStorage().getCurrentUser()?.userProfile?.id ==
|
||
"${resData.receiverInfo?.userId}"
|
||
? Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Image.asset(
|
||
_strategy.getSCMessageChatPageGoldCoinIcon(),
|
||
height: 35.w,
|
||
),
|
||
text(
|
||
"${resData.totalAmount ?? 0}",
|
||
fontWeight: FontWeight.w900,
|
||
textColor: Color(0xffFFF836),
|
||
fontSize: 22.sp,
|
||
),
|
||
],
|
||
)
|
||
: Container(),
|
||
Divider(
|
||
color: Color(0xffF3F3F3),
|
||
endIndent: 15.w,
|
||
indent: 15.w,
|
||
thickness: 0.4,
|
||
),
|
||
SizedBox(height: 5.w),
|
||
Row(
|
||
children: [
|
||
SizedBox(width: 15.w),
|
||
text(
|
||
SCAppLocalizations.of(
|
||
context,
|
||
)!.redEnvelopeAmount("${resData.totalAmount}"),
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white70,
|
||
fontSize: 13.sp,
|
||
),
|
||
Spacer(),
|
||
resData.status == 2
|
||
? Row(
|
||
children: [
|
||
Image.asset(
|
||
_strategy.getSCMessageChatPageGoldCoinIcon(),
|
||
height: 15.w,
|
||
),
|
||
text(
|
||
"${resData.totalAmount ?? 0}",
|
||
fontWeight: FontWeight.w400,
|
||
textColor: Color(0xffFFF836),
|
||
fontSize: 14.sp,
|
||
),
|
||
],
|
||
)
|
||
: Container(),
|
||
SizedBox(width: 15.w),
|
||
],
|
||
),
|
||
SizedBox(height: 8.w),
|
||
resData.status == 2
|
||
? Row(
|
||
mainAxisAlignment: MainAxisAlignment.start,
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: [
|
||
SizedBox(width: 20.w),
|
||
netImage(
|
||
url: resData.receiverInfo?.avatar ?? "",
|
||
shape: BoxShape.circle,
|
||
width: 45.w,
|
||
height: 45.w,
|
||
),
|
||
SizedBox(width: 10.w),
|
||
Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Container(
|
||
height: 18.w,
|
||
constraints: BoxConstraints(maxWidth: 120.w),
|
||
child:
|
||
(resData.receiverInfo?.nickName?.length ??
|
||
0) >
|
||
12
|
||
? Marquee(
|
||
text:
|
||
resData.receiverInfo?.nickName ??
|
||
"",
|
||
style: TextStyle(
|
||
fontSize: 14.sp,
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.w600,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
scrollAxis: Axis.horizontal,
|
||
crossAxisAlignment:
|
||
CrossAxisAlignment.start,
|
||
blankSpace: 20.0,
|
||
velocity: 40.0,
|
||
pauseAfterRound: Duration(seconds: 1),
|
||
accelerationDuration: Duration(
|
||
seconds: 1,
|
||
),
|
||
accelerationCurve: Curves.easeOut,
|
||
decelerationDuration: Duration(
|
||
milliseconds: 500,
|
||
),
|
||
decelerationCurve: Curves.easeOut,
|
||
)
|
||
: Text(
|
||
resData.receiverInfo?.nickName ?? "",
|
||
maxLines: 1,
|
||
overflow: TextOverflow.ellipsis,
|
||
style: TextStyle(
|
||
fontSize: 14.sp,
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.w600,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
),
|
||
),
|
||
SizedBox(width: 5.w),
|
||
],
|
||
),
|
||
SizedBox(height: 5.w),
|
||
Row(
|
||
children: [
|
||
text(
|
||
SCMDateUtils.formatDateTime3(
|
||
DateTime.fromMillisecondsSinceEpoch(
|
||
resData.grabbedAt ?? 0,
|
||
),
|
||
),
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white70,
|
||
fontSize: 13.sp,
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
],
|
||
)
|
||
: (resData.status == 1
|
||
? Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
text(
|
||
SCAppLocalizations.of(
|
||
context,
|
||
)!.redEnvelopeNotYetClaimed,
|
||
fontWeight: FontWeight.w600,
|
||
textColor: Colors.white,
|
||
fontSize: 15.sp,
|
||
),
|
||
],
|
||
)
|
||
: Container()),
|
||
SizedBox(height: 18.w),
|
||
],
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
_buildPackTips(SCUserRedPacketSendRes? resData) {
|
||
//状态:1-待领取 2-已领取 3-已过期
|
||
if (resData?.status == 2) {
|
||
if ("${resData?.receiverInfo?.userId}" ==
|
||
AccountStorage().getCurrentUser()?.userProfile?.id) {
|
||
return Container(
|
||
width: ScreenUtil().screenWidth * 0.6,
|
||
child: Text.rich(
|
||
TextSpan(
|
||
children: [
|
||
TextSpan(
|
||
text: SCAppLocalizations.of(
|
||
context,
|
||
)!.youAccepted(resData?.senderInfo?.nickName ?? ""),
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Colors.black26,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
TextSpan(
|
||
text: SCAppLocalizations.of(context)!.redEnvelope,
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Color(0xffFF7759),
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
TextSpan(
|
||
text: ".",
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Color(0xffFF7759),
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
} else if ("${resData?.senderInfo?.userId}" ==
|
||
AccountStorage().getCurrentUser()?.userProfile?.id) {
|
||
return Container(
|
||
width: ScreenUtil().screenWidth * 0.6,
|
||
child: Text.rich(
|
||
TextSpan(
|
||
children: [
|
||
TextSpan(
|
||
text: SCAppLocalizations.of(
|
||
context,
|
||
)!.acceptedYour(resData?.receiverInfo?.nickName ?? ""),
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Colors.black26,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
TextSpan(
|
||
text: SCAppLocalizations.of(context)!.redEnvelope,
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Color(0xffFF7759),
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
TextSpan(
|
||
text: ".",
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Color(0xffFF7759),
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
return Container();
|
||
}
|
||
}
|
||
|
||
// class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
|
||
// /// whether show background for @somebody
|
||
// MySpecialTextSpanBuilder();
|
||
//
|
||
// @override
|
||
// TextSpan build(String data, {TextStyle? textStyle, onTap}) {
|
||
// var textSpan = super.build(data, textStyle: textStyle, onTap: onTap);
|
||
// return textSpan;
|
||
// }
|
||
//
|
||
// @override
|
||
// SpecialText? createSpecialText(
|
||
// String flag, {
|
||
// TextStyle? textStyle,
|
||
// SpecialTextGestureTapCallback? onTap,
|
||
// required int index,
|
||
// }) {
|
||
// if (flag == null || flag == "") return null;
|
||
//
|
||
// ///index is end index of start flag, so text start index should be index-(flag.length-1)
|
||
// if (textStyle != null) {
|
||
// if (isStart(flag, EmojiText.flag)) {
|
||
// return EmojiText(textStyle, start: index - (EmojiText.flag.length - 1));
|
||
// }
|
||
// }
|
||
// return null;
|
||
// }
|
||
// }
|
||
|
||
// class EmojiText extends SpecialText {
|
||
// EmojiText(TextStyle textStyle, {required this.start})
|
||
// : super(EmojiText.flag, ']', textStyle);
|
||
// static const String flag = '[';
|
||
// final int start;
|
||
//
|
||
// @override
|
||
// InlineSpan finishText() {
|
||
// String key = toString();
|
||
// key = key.replaceAll("[", "");
|
||
// key = key.replaceAll("]", "");
|
||
// int index;
|
||
// try {
|
||
// index = int.parse(key);
|
||
// } catch (e) {
|
||
// return TextSpan(text: toString(), style: textStyle);
|
||
// }
|
||
//
|
||
// ///https://github.com/flutter/flutter/issues/42086
|
||
// /// widget span is not working on web
|
||
// if (index <= 113) {
|
||
// //fontsize id define image height
|
||
// //size = 30.0/26.0 * fontSize
|
||
// double size = 16.w;
|
||
//
|
||
// ///fontSize 26 and text height =30.0
|
||
// //final double fontSize = 26.0;
|
||
// return ImageSpan(
|
||
// AssetImage("sc_images/msg/emoji/$key.png"),
|
||
// actualText: key,
|
||
// imageWidth: textStyle!.fontSize!,
|
||
// imageHeight: textStyle!.fontSize!,
|
||
// start: start,
|
||
// fit: BoxFit.fill,
|
||
// margin: const EdgeInsets.only(left: 2.0, top: 2.0, right: 2.0),
|
||
// );
|
||
// }
|
||
//
|
||
// return TextSpan(text: toString(), style: textStyle);
|
||
// }
|
||
// }
|