Hibok
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

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