Hibok
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

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