Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

798 regels
25 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:chat/data/translate_hk_data_mgr.dart';
  4. import 'package:chat/home/audio_chat_view.dart';
  5. import 'package:chat/utils/screen.dart';
  6. import 'package:chat/utils/upload_util.dart';
  7. import 'package:fixnum/fixnum.dart';
  8. import 'package:cached_network_image/cached_network_image.dart';
  9. import 'package:chat/chat/translate_state.dart';
  10. import 'package:chat/data/UserData.dart';
  11. import 'package:chat/data/chat_data_mgr.dart';
  12. import 'package:chat/data/constants.dart';
  13. import 'package:chat/generated/i18n.dart';
  14. import 'package:chat/home/add_friend.dart';
  15. import 'package:chat/models/ChatMsg.dart';
  16. import 'package:chat/models/UserInfo.dart';
  17. import 'package:chat/models/keyboard_provider.dart';
  18. import 'package:chat/models/ref_name_provider.dart';
  19. import 'package:chat/models/voucher_change.dart';
  20. import 'package:chat/proto/all.pbserver.dart';
  21. import 'package:chat/utils/CustomUI.dart';
  22. import 'package:chat/utils/HttpUtil.dart';
  23. import 'package:chat/utils/MessageMgr.dart';
  24. import 'package:chat/utils/TokenMgr.dart';
  25. import 'package:chat/utils/analyze_utils.dart';
  26. import 'package:chat/utils/app_navigator.dart';
  27. import 'package:chat/utils/blacklist_mgr.dart';
  28. import 'package:chat/utils/count_down_button.dart';
  29. import 'package:chat/utils/friend_list_mgr.dart';
  30. import 'package:chat/utils/msgHandler.dart';
  31. import 'package:chat/utils/net_state_widget.dart';
  32. import 'package:chat/utils/sound_util.dart';
  33. import 'package:chat/utils/sp_utils.dart';
  34. import 'package:chat/utils/sql_util.dart';
  35. import 'package:dio/dio.dart';
  36. import 'package:extended_text/extended_text.dart';
  37. import 'package:flutter/cupertino.dart';
  38. import 'package:flutter/material.dart';
  39. import 'package:flutter/services.dart';
  40. import 'package:oktoast/oktoast.dart';
  41. import 'package:provider/provider.dart';
  42. import 'package:scroll_to_index/scroll_to_index.dart';
  43. //import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
  44. import '../r.dart';
  45. import 'ChatPageItem.dart';
  46. import 'input_bar.dart';
  47. import 'package:chat/utils/PopUpMenu.dart' as myPop;
  48. import 'package:chat/models/money_change.dart';
  49. class ChatPage extends StatefulWidget {
  50. final int friendId;
  51. final int enterType; // 0默认 1图片
  52. final dynamic enterContent;
  53. final bool isTranslateButler;
  54. ChatPage(
  55. {Key key,
  56. this.friendId,
  57. this.enterType = 0,
  58. this.enterContent,
  59. this.isTranslateButler = false})
  60. : super(key: key);
  61. _ChatPageState createState() => _ChatPageState();
  62. }
  63. class _ChatPageState extends State<ChatPage> {
  64. MessageMgr msgMgr = MessageMgr();
  65. UserInfo friendInfo;
  66. List<MsgModel> msgList;
  67. KeyboardIndexProvider _keyboardIndexProvider = KeyboardIndexProvider();
  68. TextEditingController nickNameController = new TextEditingController();
  69. //统计聊天时长
  70. int startTime;
  71. bool isTranslateButler;
  72. bool isTranslateButlerFinish=false;///翻译管家是否已经结束
  73. int jumpTime;
  74. AutoScrollController controller;
  75. @override
  76. void dispose() {
  77. var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
  78. AnalyzeUtils.commitChatDuration(startTime, endTime);
  79. MessageMgr().off('Send CoinBag', _sendCoin);
  80. msgMgr.off('New Chat Message', receiveMsg);
  81. msgMgr.off('Keyboard Hide', dealWithKeyboardHide);
  82. msgMgr.off('Delete Select Message', _deleteItem);
  83. msgMgr.off(MessageMgr.TRANSLATE_HK_END_CHAT, translateHKChatEnd);
  84. msgMgr.off('Jump to Msg', jumpToMsg);
  85. MsgHandler.curActiveSession = 0;
  86. SoundUtils().stop();
  87. nickNameController.dispose();
  88. super.dispose();
  89. }
  90. jumpToMsg(time) async {
  91. hideKeyBoard();
  92. int jumIndex = 0;
  93. jumpTime = time;
  94. for (int i = 0; i < msgList.length; i++) {
  95. if (time == msgList[i].time) {
  96. jumIndex = i;
  97. break;
  98. }
  99. }
  100. if (jumIndex < 0) {
  101. jumIndex = 0;
  102. }
  103. if (jumIndex > msgList.length - 1) {
  104. jumIndex = msgList.length - 1;
  105. }
  106. await controller.scrollToIndex(jumIndex,
  107. preferPosition: AutoScrollPosition.middle);
  108. controller.highlight(jumIndex,
  109. highlightDuration: new Duration(milliseconds: 100));
  110. }
  111. @override
  112. void initState() {
  113. super.initState();
  114. print('init chatpage');
  115. getDefaultSetting();
  116. getUserInfo();
  117. controller = AutoScrollController(
  118. viewportBoundaryGetter: () =>
  119. Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
  120. axis: Axis.vertical);
  121. isTranslateButler = widget.isTranslateButler;
  122. ///todo 这里再判断是否还在服务时间
  123. startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
  124. msgList = ChatDataMgr().getRecord();
  125. msgMgr.on('New Chat Message', receiveMsg);
  126. msgMgr.on('Keyboard Hide', dealWithKeyboardHide);
  127. msgMgr.on('Send CoinBag', _sendCoin);
  128. msgMgr.on('Delete Select Message', _deleteItem);
  129. msgMgr.on(MessageMgr.TRANSLATE_HK_END_CHAT, translateHKChatEnd);
  130. msgMgr.on('Jump to Msg', jumpToMsg);
  131. }
  132. translateHKChatEnd(args){
  133. setState(() {
  134. isTranslateButlerFinish=true;
  135. });
  136. }
  137. void _sendFile(File file) async {
  138. // File file = await FilePicker.getFile();
  139. int fileSize = file.lengthSync();
  140. print('选择的文件 ${file.path} 大小 $fileSize');
  141. if (fileSize > 33 * 1024 * 1024) {
  142. showToast(I18n.of(context).max_file.replaceFirst('/s1', 33.toString()));
  143. return;
  144. }
  145. var fileName = file.path.split('/').last;
  146. print('fileName $fileName');
  147. var ext = '';
  148. var extList = fileName.split('.');
  149. if (extList.length > 1) {
  150. ext = extList.last;
  151. }
  152. print('ext $ext');
  153. var fileMsg = FileChat.create();
  154. fileMsg.type = ext;
  155. fileMsg.size = fileSize;
  156. fileMsg.name = fileName;
  157. var msg = MsgHandler.createSendMsg(
  158. ChatType.FileChatType, fileMsg.writeToBuffer(),
  159. friendId: widget.friendId,
  160. localFile: file.path,
  161. channelType: ChatChannelType.Session);
  162. sendMsg(msg);
  163. }
  164. _sendCoin(args) async {
  165. var res = await _checkCoinBeforeSend(args['amount']);
  166. if (res != null) {
  167. args['redNo'] = res['redNo'];
  168. args['friendId'] = widget.friendId;
  169. var msg = MsgHandler.createCoinBagMsg(args);
  170. sendMsg(msg);
  171. }
  172. }
  173. //校验
  174. _checkCoinBeforeSend(int amount) async {
  175. Map data = {
  176. "userId": UserData().basicInfo.userId,
  177. "rUserId": friendInfo.userId,
  178. "price": amount,
  179. };
  180. data['sign'] = TokenMgr().getSign(data);
  181. Response res = await HttpUtil().post('red/packet/send', data: data);
  182. if (res == null) {
  183. return null;
  184. }
  185. Map resData = res.data;
  186. if (resData['code'] == 0) {
  187. print(resData['data']);
  188. return resData['data'];
  189. }
  190. return null;
  191. }
  192. void getDefaultSetting() async {
  193. bool soundPlayMode =
  194. (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false;
  195. _keyboardIndexProvider.init(soundPlayMode);
  196. }
  197. dealWithKeyboardHide(args) {
  198. if (_keyboardIndexProvider.curKeyboardIndex == 0) {
  199. hideKeyBoard();
  200. }
  201. }
  202. getUserInfo() async {
  203. //先从本地获取用户信息
  204. friendInfo = await HttpUtil().getFriendInfo(widget.friendId, true);
  205. //如果是新的聊天,向服务器发送创建会话消息
  206. if (msgList.length == 0) {
  207. MsgHandler.getActiveSesstion(
  208. [friendInfo.userId, UserData().basicInfo.userId]);
  209. }
  210. if (mounted) {
  211. setState(() {});
  212. }
  213. WidgetsBinding.instance.addPostFrameCallback((_) {
  214. if (widget.enterType == 1) {
  215. print('接收到的:${widget.enterContent}');
  216. _sendFile(File(widget.enterContent));
  217. } else if (widget.enterType == 2 || widget.enterType == 3) {
  218. //转发消息
  219. MsgModel originMsg = widget.enterContent;
  220. MsgModel msg = MsgHandler.createSendMsg(
  221. ChatType.valueOf(originMsg.msgType), originMsg.msgContent);
  222. msg.extraInfo = originMsg.extraInfo;
  223. if (originMsg.extraFile == null ||
  224. originMsg.extraFile.contains('http')) {
  225. msg.extraFile = originMsg.extraFile;
  226. } else {
  227. msg.extraFile = UploadUtil().getFullUrl(
  228. originMsg.extraFile, originMsg.sessionId, originMsg.channelType);
  229. }
  230. msg.localFile = originMsg.localFile;
  231. msg.friendId = widget.friendId;
  232. if (msg.localFile != null) {
  233. msg.state = MsgState.Uploaded;
  234. }
  235. sendMsg(msg);
  236. }
  237. });
  238. }
  239. @override
  240. Widget build(BuildContext context) {
  241. print('build chatpage');
  242. if (friendInfo == null) {
  243. return Scaffold(
  244. backgroundColor: const Color(0xFFE2E9F1),
  245. body: SafeArea(
  246. child: Center(
  247. child: CircularProgressIndicator(),
  248. ),
  249. ),
  250. );
  251. }
  252. List<Widget> actions = [];
  253. int voucher = Provider.of<VoucherChangeProvider>(context).voucher;
  254. actions.add(Row(
  255. children: <Widget>[
  256. CustomUI.buildImageLabel("assets/images/voucher.png", voucher,
  257. imgOpc: 0.5, imgHeight: 13),
  258. CustomUI.buildImageLabel(
  259. R.assetsImagesCoin, Provider.of<MoneyChangeProvider>(context).money,
  260. isLeft: false)
  261. ],
  262. ));
  263. actions.add(TranslateSateWidget(friendId: friendInfo.userId));
  264. actions.add(Container(
  265. margin: EdgeInsets.only(top: 1),
  266. child: myPop.PopupMenuButton(
  267. icon: Icon(
  268. Icons.more_horiz,
  269. size: 24,
  270. ),
  271. offset: Offset(0, 100),
  272. onSelected: (int index) {
  273. if (index == 2) {
  274. AppNavigator.pushInformUserPage(
  275. context, friendInfo.sex == 1, friendInfo.userId);
  276. } else if (index == 1) {
  277. Navigator.of(context).push(
  278. new MaterialPageRoute(
  279. builder: (context) {
  280. return AddFriendPage(
  281. userId: friendInfo.userId,
  282. pageType: SendMessagePageType.Remark,
  283. originalName: Provider.of<RefNameProvider>(context)
  284. .getRefName(
  285. friendInfo.userId, friendInfo.nickName));
  286. },
  287. ),
  288. );
  289. }
  290. },
  291. itemBuilder: (BuildContext context) {
  292. return <myPop.PopupMenuItem<int>>[
  293. myPop.PopupMenuItem(
  294. child: Container(
  295. alignment: Alignment.center,
  296. color: Colors.white,
  297. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
  298. child: Text(I18n.of(context).anonymous_report,
  299. textScaleFactor: 1.0,
  300. maxLines: 1,
  301. style: TextStyle(
  302. color: Color(AppColors.AppBarColor), fontSize: 12)),
  303. ),
  304. value: 2,
  305. ),
  306. myPop.PopupMenuItem(
  307. child: Container(
  308. decoration: BoxDecoration(
  309. border: Border(
  310. top: BorderSide(width: 1, color: Colors.grey[300])),
  311. color: Colors.white,
  312. ),
  313. alignment: Alignment.center,
  314. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
  315. child: Text(I18n.of(context).Remark,
  316. textScaleFactor: 1.0,
  317. maxLines: 1,
  318. style: TextStyle(
  319. color: Color(AppColors.AppBarColor), fontSize: 12)),
  320. ),
  321. value: 1,
  322. ),
  323. ];
  324. })));
  325. return WillPopScope(
  326. child: Stack(
  327. children: <Widget>[
  328. MultiProvider(
  329. providers: [
  330. ChangeNotifierProvider(create: (_) => _keyboardIndexProvider),
  331. Provider<bool>.value(value: false),
  332. Provider<int>.value(value: widget.friendId),
  333. ],
  334. child: GestureDetector(
  335. onTap: hideKeyBoard,
  336. child: ExtendedTextSelectionPointerHandler(
  337. ///选择文字,消除弹窗
  338. builder: (states) {
  339. return Listener(
  340. child: Scaffold(
  341. resizeToAvoidBottomInset: false,
  342. backgroundColor: const Color(0xFFE2E9F1),
  343. appBar: AppBar(
  344. title: Text(
  345. '${Provider.of<RefNameProvider>(context).getRefName(friendInfo.userId, friendInfo.nickName)}',
  346. textScaleFactor: 1.0,
  347. style: TextStyle(
  348. color: Constants.BlackTextColor,
  349. fontSize: 16.47),
  350. ),
  351. leading: CustomUI.buildCustomLeading(context,onTap:(){
  352. goBackCheck();
  353. }),
  354. titleSpacing: -10,
  355. centerTitle: false,
  356. elevation: 1,
  357. actions: actions),
  358. body: SafeArea(
  359. child: Column(
  360. children: <Widget>[
  361. NetStateWidget(),
  362. (isTranslateButler&!isTranslateButlerFinish)
  363. ? _buildTranslationButler()
  364. : Container(),
  365. Expanded(child: _buildMessageList()),
  366. InputBar(sendMsg: sendMsg,isTranslateHK: isTranslateButler,),
  367. ],
  368. ))),
  369. behavior: HitTestBehavior.translucent,
  370. onPointerDown: (value) {
  371. for (var state in states) {
  372. if (!state.containsPosition(value.position)) {
  373. //clear other selection
  374. state.clearSelection();
  375. }
  376. }
  377. },
  378. onPointerMove: (value) {
  379. //clear other selection
  380. for (var state in states) {
  381. if (!state.containsPosition(value.position)) {
  382. //clear other selection
  383. state.clearSelection();
  384. }
  385. }
  386. },
  387. );
  388. },
  389. ))),
  390. isTranslateButler ? getAudioChatView() : Container(),
  391. isTranslateButler ? zoomAudioButton() : Container()
  392. ],
  393. ),
  394. onWillPop: () {
  395. goBackCheck();
  396. return Future.value(true);
  397. });
  398. }
  399. goBackCheck(){
  400. if(isTranslateButler && !isTranslateButlerFinish){
  401. if(UserData().isTranslateUser){
  402. showToast('翻译服务未结束不能主动结束');
  403. }else{
  404. CustomUI.buildTowConfirm(
  405. context,
  406. '是否提前结束翻译管家服务?',
  407. I18n.of(context).confirm,
  408. (){
  409. setState(() {
  410. isTranslateButlerFinish=true;
  411. });
  412. MsgHandler.sendEndTransHKOrderReq();
  413. Navigator.of(context).pop();
  414. },
  415. '取消',
  416. (){ Navigator.of(context).pop();});
  417. }
  418. }else{
  419. Navigator.of(context).pop();
  420. }
  421. }
  422. Widget getAudioChatView() {
  423. if (friendInfo == null || isTranslateButlerFinish) {
  424. return Container();
  425. }
  426. return isActive == null
  427. ? Container()
  428. : Offstage(
  429. offstage: !isShowAudio,
  430. child: AudioChatPage(
  431. userInfo: friendInfo,
  432. isTranslateButler: true,
  433. isReplay: !TranslateHKMgr().isUser,
  434. translateButlerCloseCallBack: audioChatPageCallBack,
  435. ),
  436. );
  437. }
  438. audioChatPageCallBack(int args) {
  439. switch (args) {
  440. case 1:
  441. setState(() {
  442. isShowAudio = !isShowAudio;
  443. isShowZoomButton = true;
  444. });
  445. break;
  446. case 2:
  447. setState(() {
  448. isActive = false;
  449. });
  450. break;
  451. }
  452. }
  453. bool isShowAudio = false;
  454. ///控住连麦窗口是否显示
  455. bool isActive = true;
  456. ///控制连麦是否关闭
  457. bool isShowZoomButton = true;
  458. GlobalKey mykey = GlobalKey();
  459. double dx = 0 , dy = 0;
  460. double zoomButtonSize = 60;
  461. void dragEvent(DragUpdateDetails details) {
  462. final RenderObject box = context.findRenderObject();
  463. // 获得自定义Widget的大小,用来计算Widget的中心锚点
  464. dx = details.globalPosition.dx - mykey.currentContext.size.width / 2;
  465. dy = details.globalPosition.dy - mykey.currentContext.size.height / 2;
  466. // print('dx $dx dy $dy screen width:${Screen.width}');
  467. if (dx > Screen.width - zoomButtonSize) {
  468. dx = Screen.width - zoomButtonSize;
  469. } else if (dx < 0) {
  470. dx = 0;
  471. }
  472. if (dy > Screen.height - zoomButtonSize) {
  473. dy = Screen.height - zoomButtonSize;
  474. } else if (dy < 0) {
  475. dy = 0;
  476. }
  477. setState(() {});
  478. }
  479. Widget zoomAudioButton() {
  480. if (friendInfo == null || !isShowZoomButton) {
  481. return Container();
  482. }
  483. Widget button = Container(
  484. key: mykey,
  485. width: 57,
  486. height: 74,
  487. child: Card(child: Align(child: Icon(
  488. IconData(0xe67d, fontFamily: Constants.IconFontFamily),
  489. color: Color(0xFF008AFF),
  490. size: 35.0,
  491. ),alignment: Alignment.center,),),
  492. );
  493. return GestureDetector(
  494. onHorizontalDragUpdate: dragEvent,
  495. onVerticalDragUpdate: dragEvent,
  496. onTap: (){
  497. setState(() {
  498. isShowAudio = !isShowAudio;
  499. isShowZoomButton = !isShowZoomButton;
  500. });
  501. },
  502. child: Container(
  503. child: Transform.translate(
  504. offset: Offset(dx, dy),
  505. child: Align(
  506. alignment: Alignment.topLeft,
  507. child: button,
  508. ),
  509. ),
  510. ),
  511. );
  512. }
  513. Widget _buildTranslationButler() {
  514. bool hasHeadImg = true;
  515. if (friendInfo.headimgurl == null || friendInfo.headimgurl.length == 0) {
  516. hasHeadImg = false;
  517. }
  518. /// 5H币/1分钟
  519. String coinTIme = I18n.of(context).translation_butler_coin_time;
  520. coinTIme = coinTIme.replaceAll('/s1', '5');
  521. coinTIme = coinTIme.replaceAll('/s2', '1');
  522. return Container(
  523. padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
  524. color: Colors.white,
  525. child: Row(
  526. children: <Widget>[
  527. ClipRRect(
  528. borderRadius: BorderRadius.circular(8),
  529. child: hasHeadImg
  530. ? CachedNetworkImage(
  531. imageUrl: friendInfo.headimgurl,
  532. placeholder: (context, url) => Image.asset(
  533. Constants.DefaultHeadImgUrl,
  534. width: 54,
  535. height: 54,
  536. ),
  537. width: 54,
  538. height: 54,
  539. )
  540. : SizedBox(
  541. width: 54,
  542. height: 54,
  543. child: Image.asset(R.assetsImagesDefaultNorAvatar))),
  544. Padding(
  545. padding: EdgeInsets.only(left: 10),
  546. child: Container(
  547. child: Column(
  548. crossAxisAlignment: CrossAxisAlignment.start,
  549. children: <Widget>[
  550. Text(
  551. I18n.of(context).translation_butler,
  552. textScaleFactor: 1.0,
  553. overflow: TextOverflow.ellipsis,
  554. maxLines: 1,
  555. style: TextStyle(
  556. color: AppColors.NewAppbarTextColor, fontSize: 15),
  557. ),
  558. SizedBox(
  559. height: 5,
  560. ),
  561. Text(
  562. coinTIme,
  563. textScaleFactor: 1.0,
  564. maxLines: 1,
  565. style: TextStyle(color: Color(0xFF797979), fontSize: 13),
  566. )
  567. ],
  568. ),
  569. constraints: BoxConstraints(maxWidth: 135),
  570. ),
  571. ),
  572. TranslateHKMgr().isUser?Expanded(
  573. child: Container(
  574. constraints: BoxConstraints(maxWidth: 130),
  575. width: double.maxFinite,
  576. child: CountDownButton(
  577. I18n.of(context).translation_butler_end_service,
  578. () {
  579. // Navigator.of(context).pop();
  580. },
  581. countDownTime: 60*5,
  582. align: Alignment.centerRight,
  583. onPress: () {
  584. MsgHandler.sendEndTransHKOrderReq();
  585. // Navigator.of(context).pop();
  586. },
  587. ),
  588. // alignment: Alignment(1,0),
  589. )):Container(),
  590. ],
  591. ),
  592. );
  593. }
  594. Widget _buildMessageList() {
  595. return Container(
  596. alignment: Alignment.topCenter,
  597. child: msgList.length == 0
  598. ? Padding(
  599. padding: EdgeInsets.all(8),
  600. child: Text(
  601. I18n.of(context).chat_tips,
  602. textAlign: TextAlign.center,
  603. textScaleFactor: 1.0,
  604. style: TextStyle(color: Colors.grey, fontSize: 12),
  605. ))
  606. : NotificationListener(
  607. child: Scrollbar(
  608. child: ListView.builder(
  609. controller: controller,
  610. physics: new ClampingScrollPhysics(),
  611. itemCount: msgList.length,
  612. itemBuilder: _buildItem,
  613. padding: EdgeInsets.symmetric(vertical: 8),
  614. reverse: true,
  615. shrinkWrap: true,
  616. )),
  617. onNotification: (notification) {
  618. if (notification is ScrollNotification) {}
  619. return true;
  620. },
  621. ),
  622. );
  623. }
  624. hideKeyBoard() {
  625. _keyboardIndexProvider.changeSelectIndex(-1);
  626. }
  627. readOnly() {
  628. _keyboardIndexProvider.changeReadOnlyKey(true);
  629. }
  630. sendMsg(MsgModel msg) async {
  631. // if(widget.isTranslateButler){ ///翻译管家聊天通道
  632. // msg.channelType = ChatChannelType.TransHK.value;
  633. // }
  634. print('对方是否拉黑你 ${friendInfo.isBlackened}');
  635. if (BlacklistMgr.isBlack(friendInfo.userId)) {
  636. return;
  637. }
  638. print('chat page session id:${msg.sessionId}');
  639. if (!friendInfo.isCanStrangerNews &&
  640. !FriendListMgr().isMyFriend(friendInfo.userId)) {
  641. showToast(I18n.of(context).stranger_close_tips);
  642. return;
  643. }
  644. MsgHandler.insertMsgToDB(msg);
  645. MsgHandler.sendChatMsg(msg);
  646. if (mounted) {
  647. setState(() {});
  648. await controller.scrollToIndex(0,
  649. preferPosition: AutoScrollPosition.begin);
  650. }
  651. }
  652. MsgModel msg;
  653. int count = 0;
  654. testBig(MsgModel msg) async {
  655. for (int k = 0; k < 100; k++) {
  656. msg.msgContent = utf8.encode('测试$count');
  657. Int64 time = Int64((DateTime.now()).millisecondsSinceEpoch);
  658. msg.time = time.toInt();
  659. MsgHandler.insertMsgToDB(msg);
  660. MsgHandler.sendChatMsg(msg);
  661. await Future.delayed(Duration(milliseconds: 500), () {});
  662. count++;
  663. }
  664. count = 0;
  665. print('发送完毕');
  666. showToast('发送完毕');
  667. }
  668. void receiveMsg(args) {
  669. if (mounted) {
  670. setState(() {});
  671. }
  672. }
  673. _deleteItem(msg) {
  674. MessageMgr().emit('Cancel Request', msg);
  675. print('#### 开始删除--');
  676. msgList.remove(msg);
  677. setState(() {});
  678. SqlUtil().deleteSigleRecordWith(msg.sessionId, msg.time);
  679. }
  680. Widget _wrapScrollTag({int index, Widget child}) => AutoScrollTag(
  681. key: ValueKey(index),
  682. controller: controller,
  683. index: index,
  684. child: child,
  685. highlightColor: Colors.white.withOpacity(1),
  686. );
  687. Widget _buildItem(BuildContext context, int index) {
  688. var lastMsgTime;
  689. if (index < msgList.length - 1) {
  690. lastMsgTime = msgList[index + 1].time;
  691. }
  692. MsgModel msg = msgList[index];
  693. return _wrapScrollTag(
  694. index: index,
  695. child: ChatPageItem(
  696. key: Key(msg.time.toString()),
  697. msg: msg,
  698. hideKeyboard: readOnly,
  699. friendInfo: friendInfo,
  700. lastMsgTime: lastMsgTime));
  701. }
  702. }