Hibok
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

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