diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 0eafb9d..5833252 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"agora_rtc_engine","dependencies":[]},{"name":"amap_location","dependencies":[]},{"name":"android_intent","dependencies":[]},{"name":"app_installer","dependencies":[]},{"name":"apple_sign_in","dependencies":[]},{"name":"audioplayer","dependencies":[]},{"name":"auto_orientation","dependencies":[]},{"name":"city_pickers","dependencies":[]},{"name":"connectivity","dependencies":[]},{"name":"easy_contact_picker","dependencies":[]},{"name":"file_picker","dependencies":[]},{"name":"flutter_app_badger","dependencies":[]},{"name":"flutter_audio_recorder","dependencies":[]},{"name":"flutter_bugly","dependencies":[]},{"name":"flutter_facebook_login","dependencies":[]},{"name":"flutter_ijkplayer","dependencies":[]},{"name":"flutter_inapp_purchase","dependencies":[]},{"name":"flutter_local_notifications","dependencies":[]},{"name":"flutter_native_image","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_qr_reader","dependencies":["image_picker"]},{"name":"flutter_webview_plugin","dependencies":[]},{"name":"fluwx_no_pay","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"google_maps_flutter","dependencies":[]},{"name":"image_cropper","dependencies":[]},{"name":"image_gallery_saver","dependencies":[]},{"name":"image_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"jpush_flutter","dependencies":[]},{"name":"keyboard_utils","dependencies":[]},{"name":"location","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"multi_image_picker","dependencies":[]},{"name":"open_file","dependencies":[]},{"name":"package_info","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"photo_manager","dependencies":[]},{"name":"receive_sharing_intent","dependencies":[]},{"name":"share","dependencies":[]},{"name":"share_extend","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"url_launcher","dependencies":[]},{"name":"video_player","dependencies":[]},{"name":"video_thumbnail","dependencies":[]},{"name":"wifi_info_plugin","dependencies":[]}]} \ No newline at end of file +{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"agora_rtc_engine","dependencies":[]},{"name":"amap_location","dependencies":[]},{"name":"android_intent","dependencies":[]},{"name":"app_installer","dependencies":[]},{"name":"apple_sign_in","dependencies":[]},{"name":"audioplayer","dependencies":[]},{"name":"auto_orientation","dependencies":[]},{"name":"city_pickers","dependencies":[]},{"name":"connectivity","dependencies":[]},{"name":"device_info","dependencies":[]},{"name":"easy_contact_picker","dependencies":[]},{"name":"file_picker","dependencies":[]},{"name":"flutter_app_badger","dependencies":[]},{"name":"flutter_audio_recorder","dependencies":[]},{"name":"flutter_bugly","dependencies":[]},{"name":"flutter_facebook_login","dependencies":[]},{"name":"flutter_ijkplayer","dependencies":[]},{"name":"flutter_inapp_purchase","dependencies":[]},{"name":"flutter_local_notifications","dependencies":[]},{"name":"flutter_native_image","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_qr_reader","dependencies":["image_picker"]},{"name":"flutter_webview_plugin","dependencies":[]},{"name":"fluwx_no_pay","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"google_maps_flutter","dependencies":[]},{"name":"image_cropper","dependencies":[]},{"name":"image_gallery_saver","dependencies":[]},{"name":"image_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"jpush_flutter","dependencies":[]},{"name":"keyboard_utils","dependencies":[]},{"name":"location","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"multi_image_picker","dependencies":[]},{"name":"open_file","dependencies":[]},{"name":"package_info","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"photo_manager","dependencies":[]},{"name":"receive_sharing_intent","dependencies":[]},{"name":"share","dependencies":[]},{"name":"share_extend","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"url_launcher","dependencies":[]},{"name":"video_player","dependencies":[]},{"name":"video_thumbnail","dependencies":[]},{"name":"wifi_info_plugin","dependencies":[]}]} \ No newline at end of file diff --git a/lib/chat/ChatPage.dart b/lib/chat/ChatPage.dart index 041edc2..9c271d7 100644 --- a/lib/chat/ChatPage.dart +++ b/lib/chat/ChatPage.dart @@ -4,6 +4,7 @@ import 'package:chat/data/translate_hk_data_mgr.dart'; import 'package:chat/home/audio_chat_view.dart'; import 'package:chat/utils/screen.dart'; import 'package:chat/utils/upload_util.dart'; +import 'package:chat/utils/white_opacity_anim.dart'; import 'package:fixnum/fixnum.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:chat/chat/translate_state.dart'; @@ -63,7 +64,10 @@ class ChatPage extends StatefulWidget { } class _ChatPageState extends State { - ScrollController _scrollCtrl = ScrollController(); + final ItemScrollController itemScrollController = ItemScrollController(); + final ItemPositionsListener itemPositionListener = + ItemPositionsListener.create(); + //ScrollController _scrollCtrl = ScrollController(); MessageMgr msgMgr = MessageMgr(); @@ -82,6 +86,8 @@ class _ChatPageState extends State { bool isTranslateButlerFinish=false;///翻译管家是否已经结束 + int jumpTime; + @override void dispose() { var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; @@ -92,14 +98,36 @@ class _ChatPageState extends State { msgMgr.off('Keyboard Hide', dealWithKeyboardHide); msgMgr.off('Delete Select Message', _deleteItem); msgMgr.off(MessageMgr.TRANSLATE_HK_END_CHAT, translateHKChatEnd); + msgMgr.off('Jump to Msg', jumpToMsg); + MsgHandler.curActiveSession = 0; SoundUtils().stop(); nickNameController.dispose(); - _scrollCtrl.dispose(); - super.dispose(); } + jumpToMsg(time) { + //var screenItemNums = itemPositionListener.itemPositions.value.length; + int jumIndex = 0; + jumpTime = time; + for (int i = 0; i < msgList.length; i++) { + if (time == msgList[i].time) { + jumIndex = i - 1; // - screenItemNums + 2; + break; + } + } + if (jumIndex < 0) { + jumIndex = 0; + } + if (jumIndex > msgList.length - 1) { + jumIndex = msgList.length - 1; + } + setState(() { + itemScrollController.scrollTo( + index: jumIndex, duration: new Duration(microseconds: 1)); + }); + } + @override void initState() { super.initState(); @@ -119,12 +147,14 @@ class _ChatPageState extends State { msgMgr.on('Send CoinBag', _sendCoin); msgMgr.on('Delete Select Message', _deleteItem); msgMgr.on(MessageMgr.TRANSLATE_HK_END_CHAT, translateHKChatEnd); + msgMgr.on('Jump to Msg', jumpToMsg); } translateHKChatEnd(args){ setState(() { isTranslateButlerFinish=true; }); + } void _sendFile(File file) async { @@ -507,8 +537,7 @@ class _ChatPageState extends State { Widget zoomAudioButton() { - - if (friendInfo == null || !isShowZoomButton || isTranslateButlerFinish) { + if (friendInfo == null || !isShowZoomButton) { return Container(); } @@ -645,13 +674,15 @@ class _ChatPageState extends State { )) : NotificationListener( child: Scrollbar( - child: ListView.builder( - reverse: true, - shrinkWrap: true, + child: ScrollablePositionedList.builder( + physics: new ClampingScrollPhysics(), itemCount: msgList.length, - controller: _scrollCtrl, - padding: EdgeInsets.all(8.0), itemBuilder: _buildItem, + itemScrollController: itemScrollController, + itemPositionsListener: itemPositionListener, + //padding: EdgeInsets.all(8.0), + reverse: true, + hitCallback: hideKeyBoard, )), onNotification: (notification) { if (notification is ScrollNotification) { @@ -690,12 +721,8 @@ class _ChatPageState extends State { MsgHandler.sendChatMsg(msg); if (mounted) { setState(() {}); - if (_scrollCtrl.hasClients) { - _scrollCtrl.animateTo(0, - duration: new Duration(milliseconds: 500), curve: Curves.ease); - } + itemScrollController.jumpTo(index: 0); } -// testBig(msg); } MsgModel msg; @@ -719,10 +746,6 @@ class _ChatPageState extends State { void receiveMsg(args) { if (mounted) { setState(() {}); - if (_scrollCtrl.hasClients) { - _scrollCtrl.animateTo(0, - duration: new Duration(milliseconds: 500), curve: Curves.ease); - } } } @@ -741,11 +764,26 @@ class _ChatPageState extends State { } MsgModel msg = msgList[index]; - return ChatPageItem( + if (msg.time == jumpTime) { + return WhiteOpacityAnim( key: Key(msg.time.toString()), - msg: msg, - hideKeyboard: readOnly, - friendInfo: friendInfo, - lastMsgTime: lastMsgTime); + child: ChatPageItem( + key: Key(msg.time.toString()), + msg: msg, + hideKeyboard: readOnly, + friendInfo: friendInfo, + lastMsgTime: lastMsgTime), + animFinishCallback: () { + jumpTime = null; + }, + ); + } else { + return ChatPageItem( + key: Key(msg.time.toString()), + msg: msg, + hideKeyboard: readOnly, + friendInfo: friendInfo, + lastMsgTime: lastMsgTime); + } } } diff --git a/lib/chat/ChatPageItem.dart b/lib/chat/ChatPageItem.dart index 6c46646..83e6688 100644 --- a/lib/chat/ChatPageItem.dart +++ b/lib/chat/ChatPageItem.dart @@ -90,6 +90,8 @@ class _ChatPageItemState extends State CancelToken _cancelToken = CancelToken(); bool isLongPressed = false; + + double maxWidth = Screen.width - 140; @override void initState() { super.initState(); @@ -146,10 +148,10 @@ class _ChatPageItemState extends State } } - getTodayTime(msgDate) { + getTodayTime(msgDate, {var sendTime}) { String showTimeStr; - var sendTime = widget.msg.time; + sendTime = sendTime ?? widget.msg.time; var today = DateTime.now(); //今天 if (msgDate.year == today.year && @@ -188,7 +190,7 @@ class _ChatPageItemState extends State return Container( width: Screen.width, - margin: const EdgeInsets.symmetric(vertical: 10.0), + margin: const EdgeInsets.symmetric(vertical: 18.0,horizontal: 8), child: Column( children: [ showTime == null @@ -258,6 +260,7 @@ class _ChatPageItemState extends State } else { ///todo 翻译管家系统通知消息 + print('这里应该要有翻译管家'); if (type == ChatType.GroupChatNoticeType.value && widget.msg.channelType ==ChatChannelType.Session.value) { TransHKChatNotice res = TransHKChatNotice.fromBuffer(widget.msg.msgContent); @@ -312,55 +315,100 @@ class _ChatPageItemState extends State } _textMsg(List msgContent) { + List showMsg = []; + var width = 0.0; var msg = utf8.decode(msgContent); - bool isUrl =false; - if(textList[curTextType].contains('http') ){ - isUrl =true; + if (msg.contains('[ ')) { + msg = msg.replaceAll('[ ', '['); + } + if (msg.contains(' ]')) { + msg = msg.replaceAll(' ]', ']'); + } + bool isUrl = false; + if (textList[curTextType].contains('http')) { + isUrl = true; + } + + if (widget.msg.refMsgContent != null && + widget.msg.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(widget.msg.refMsgContent); + var refName = Provider.of(context) + .getRefName(friendInfo.userId, friendInfo.nickName); + var msgDate = + DateTime.fromMillisecondsSinceEpoch(quoteMsg.sendTime.toInt()); + var showTimeStr = getTodayTime(msgDate, sendTime: quoteMsg.sendTime.toInt()); + + var timetWidth = CustomUI.getRealTextWidht(showTimeStr, 13); + var nameWidhth = CustomUI.getRealTextWidht(refName, 13); + width = timetWidth + (nameWidhth > 70 ? 70 : nameWidhth) + 36; + var tempIndex = quoteMsg.content.indexOf(':'); + var quoteContent = tempIndex == -1 + ? quoteMsg.content + : quoteMsg.content.substring(quoteMsg.content.indexOf(':') + 2); + var contentWidht = _getTextWidth(quoteContent, fontSize: 13); + width = min(max(width, contentWidht), maxWidth); + showMsg.add(InkWell( + onTap: () { + MessageMgr().emit('Jump to Msg', quoteMsg.sendTime.toInt()); + }, + child: Container( + padding: EdgeInsets.all(8), + margin: EdgeInsets.only(bottom: 5), + decoration: BoxDecoration( + color: Color(0xFFC4E0F5), + borderRadius: BorderRadius.circular(5.5)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Container( + constraints: BoxConstraints(maxWidth: 70), + child: Text( + refName, + style: TextStyle(fontSize: 13), + overflow: TextOverflow.ellipsis, + )), + SizedBox(width: 20), + Text( + showTimeStr, + style: TextStyle(fontSize: 13), + ) + ]), + SizedBox(height: 7.5), + Text( + quoteContent, + style: TextStyle(fontSize: 13), + ) + ], + ), + ))); } - Widget text = Container( + var contentWidth = _getTextWidth(textList[curTextType]); + if (contentWidth > width && contentWidth <= maxWidth) { + width = contentWidth; + } + + showMsg.add(Container( + constraints: BoxConstraints(maxWidth: maxWidth, minHeight: 22), + alignment: Alignment.centerLeft, + child: extendedText( + textList[curTextType], + color: isUrl ? Colors.blue : Constants.BlackTextColor, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + ))); + + return Container( constraints: BoxConstraints(maxWidth: Screen.width - 120), - child: extendedText( - msg, - hideKeyboard: widget.hideKeyboard, - fontSize: FontSize, - color: isUrl?Colors.blue:Colors.black, - ), + width: width + 20, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), decoration: BoxDecoration( color: isLongPressed ? Colors.grey[300] : SendMsgBg, border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), ); - - if (widget.msg.refMsgContent != null && - widget.msg.refMsgContent.length > 0) { - QuoteMsg quoteMsg = QuoteMsg.fromBuffer(widget.msg.refMsgContent); - - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - text, - SizedBox(height: 2), - Container( - constraints: BoxConstraints(maxWidth: Screen.width - 120), - padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), - child: Text( - quoteMsg.content, - maxLines: 1, - textScaleFactor: 1.0, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 12), - ), - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(5)), - ) - ], - ); - } else { - return text; - } } _soundMsg() { @@ -503,7 +551,9 @@ class _ChatPageItemState extends State _imgMsg(List imgData) { var imgSize = _getImgSize(); - ImageProvider provider = MemoryImage(widget.msg.localFile==null?Uint8List.fromList(imgData):File(widget.msg.localFile).readAsBytesSync()); + ImageProvider provider = MemoryImage(widget.msg.localFile == null + ? Uint8List.fromList(imgData) + : File(widget.msg.localFile).readAsBytesSync()); return GestureDetector( child: ClipRRect( @@ -663,43 +713,42 @@ class _ChatPageItemState extends State ///转发 - if (widget.msg.msgType == ChatType.TextChatType.value|| - widget.msg.msgType == ChatType.ImageChatType.value|| - widget.msg.msgType == ChatType.ShortVideoChatType.value|| - widget.msg.msgType == ChatType.PlaceChatType.value|| - widget.msg.msgType == ChatType.EmoticonType.value|| - widget.msg.msgType == ChatType.FileChatType.value - ){ - actions.add( I18n.of(context).forward); + if (widget.msg.msgType == ChatType.TextChatType.value || + widget.msg.msgType == ChatType.ImageChatType.value || + widget.msg.msgType == ChatType.ShortVideoChatType.value || + widget.msg.msgType == ChatType.PlaceChatType.value || + widget.msg.msgType == ChatType.EmoticonType.value || + widget.msg.msgType == ChatType.FileChatType.value) { + actions.add(I18n.of(context).forward); actionsFunc.add(() { print('转发消息'); - if(widget.msg.msgType == ChatType.FileChatType.value && widget.msg.localFile==null){ + if (widget.msg.msgType == ChatType.FileChatType.value && + widget.msg.localFile == null) { showToast('请先下载文件'); - return ; + return; } AppNavigator.pushForwardPage(context, widget.msg); }); } - - - - if (widget.msg.msgType == ChatType.FileChatType.value &&widget.msg.localFile!=null) { - - - + if (widget.msg.msgType == ChatType.FileChatType.value && + widget.msg.localFile != null) { //分享文件 actions.add(I18n.of(context).copy_download_url); - actionsFunc.add(() async{ + actionsFunc.add(() async { UploadUtil().copyFileUrl(widget.msg, context); String path = widget.msg.localFile; - String type='file'; - if(path.contains('mp4') ||path.contains('mp3')){ + String type = 'file'; + if (path.contains('mp4') || path.contains('mp3')) { type = 'video'; - }else if(path.contains('png')||path.contains('jpg')||path.contains('jpeg')||path.contains('JPG')||path.contains('PNG')){ + } else if (path.contains('png') || + path.contains('jpg') || + path.contains('jpeg') || + path.contains('JPG') || + path.contains('PNG')) { type = 'image'; } @@ -735,18 +784,17 @@ class _ChatPageItemState extends State }); } // String date2 = DateTime.fromMillisecondsSinceEpoch(widget.msg.time).toString(); - bool isUrl =false; - if(widget.msg.msgType==ChatType.TextChatType.value ){ - if( textList[curTextType].contains('http')){ - isUrl =true; + bool isUrl = false; + if (widget.msg.msgType == ChatType.TextChatType.value) { + if (textList[curTextType].contains('http')) { + isUrl = true; } - } - return WPopupMenu( + return WPopupMenu( child: item, actions: actions, - onTap: ()async{ - if(isUrl){ + onTap: () async { + if (isUrl) { if (await canLaunch(textList[curTextType])) { launch(textList[curTextType]); } @@ -783,9 +831,9 @@ class _ChatPageItemState extends State return extendedText(text, hideKeyboard: widget.hideKeyboard); } - double _getTextWidth(String text) { + double _getTextWidth(String text, {double fontSize: FontSize}) { var tp = TextPainter( - text: TextSpan(style: TextStyle(fontSize: FontSize), text: text), + text: TextSpan(style: TextStyle(fontSize: fontSize), text: text), textAlign: TextAlign.left, textDirection: TextDirection.ltr, textScaleFactor: 1, @@ -812,11 +860,70 @@ class _ChatPageItemState extends State _receiveText(MsgModel msg) { List showMsg = []; + double width = 0.0; if (textList.length > 0) { + bool isUrl = false; + if (textList[curTextType].contains('http')) { + isUrl = true; + } + + if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); + + var refName = Provider.of(context) + .getGroupRefName(msg.sessionId, quoteMsg.sendUserId); + + var msgDate = + DateTime.fromMillisecondsSinceEpoch(quoteMsg.sendTime.toInt()); + var showTimeStr = getTodayTime(msgDate, sendTime: quoteMsg.sendTime.toInt()); - bool isUrl =false; - if(textList[curTextType].contains('http') ){ - isUrl =true; + var timetWidth = CustomUI.getRealTextWidht(showTimeStr, 13); + var nameWidhth = CustomUI.getRealTextWidht(refName, 13); + width = timetWidth + (nameWidhth > 70 ? 70 : nameWidhth) + 36; + var quoteContent = + quoteMsg.content.substring(quoteMsg.content.indexOf(':') + 2); + var contentWidht = _getTextWidth(quoteContent, fontSize: 13); + width = min(max(width, contentWidht), maxWidth); + showMsg.add(InkWell( + onTap: () { + MessageMgr().emit('Jump to Msg', quoteMsg.sendTime.toInt()); + }, + child: Container( + padding: EdgeInsets.all(8), + margin: EdgeInsets.only(bottom: 5), + decoration: BoxDecoration( + color: Color(0xFFC4E0F5), + borderRadius: BorderRadius.circular(5.5)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Container( + constraints: BoxConstraints(maxWidth: 70), + child: Text( + refName, + style: TextStyle(fontSize: 13), + overflow: TextOverflow.ellipsis, + )), + SizedBox(width: 20), + Text( + showTimeStr, + style: TextStyle(fontSize: 13), + ) + ]), + SizedBox(height: 7.5), + Text( + quoteContent, + style: TextStyle(fontSize: 13), + ) + ], + ), + ))); + } + + var contentWidth = _getTextWidth(textList[curTextType]); + if (contentWidth > width && contentWidth <= maxWidth) { + width = contentWidth; } showMsg.add(InkWell( @@ -833,8 +940,7 @@ class _ChatPageItemState extends State } }, child: Container( - constraints: - BoxConstraints(maxWidth: Screen.width - 140, minHeight: 22), + constraints: BoxConstraints(maxWidth: maxWidth, minHeight: 22), alignment: Alignment.centerLeft, child: extendedText( textList[curTextType], @@ -844,9 +950,7 @@ class _ChatPageItemState extends State )))); } - var width = _getTextWidth(textList[curTextType]); - - var minWidth = width; + var minWidth = width + 20; if (msg.transTag != 0) { minWidth = 200; showMsg.add(Padding( @@ -870,7 +974,7 @@ class _ChatPageItemState extends State color: isLongPressed ? Colors.grey[300] : Colors.white, borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), ), - msg.transTag != 1 + msg.transTag != 1 && msg.transTag != 0 ? Positioned( right: 5, top: 5, @@ -884,34 +988,7 @@ class _ChatPageItemState extends State : Container() ]); - if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { - QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); - - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - text, - SizedBox(height: 2), - Container( - constraints: BoxConstraints(maxWidth: Screen.width - 120), - padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), - child: Text( - quoteMsg.content, - maxLines: 1, - textScaleFactor: 1.0, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 12), - ), - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(5)), - ) - ], - ); - } else { - return text; - } + return text; } _translateItemWidget(int code, String title, Function onTap) { @@ -949,14 +1026,17 @@ class _ChatPageItemState extends State if (transTag == 1) { //机器翻译中 - userTranslateWidget = _translateItemWidget(0xe670, I18n.of(context).man_retranslate, null); + userTranslateWidget = + _translateItemWidget(0xe670, I18n.of(context).man_retranslate, null); machineTranslateWidget = _translateItemWidget(0xe671, I18n.of(context).robotTranslate, null); } else if (transTag == 2) { //人工翻译中 - userTranslateWidget = _translateItemWidget(0xe670, I18n.of(context).ManTranslate, null); - machineTranslateWidget = _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { + userTranslateWidget = + _translateItemWidget(0xe670, I18n.of(context).ManTranslate, null); + machineTranslateWidget = + _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { setState(() { curTextType += 1; curTextType %= textList.length; @@ -1008,7 +1088,8 @@ class _ChatPageItemState extends State }); } }); - machineTranslateWidget = _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { + machineTranslateWidget = + _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { setState(() { curTextType += 1; curTextType %= textList.length; @@ -1063,7 +1144,8 @@ class _ChatPageItemState extends State )) ], ))); - machineTranslateWidget = _translateItemWidget(0xe675, I18n.of(context).see_original, () { + machineTranslateWidget = + _translateItemWidget(0xe675, I18n.of(context).see_original, () { setState(() { curTextType = textList.length - 1; }); @@ -1085,15 +1167,16 @@ class _ChatPageItemState extends State } _receiveImg(BuildContext context, List imgData, {String downloadData}) { - - ImageProvider provider = MemoryImage(widget.msg.localFile==null?Uint8List.fromList(imgData):File(widget.msg.localFile).readAsBytesSync()); + ImageProvider provider = MemoryImage(widget.msg.localFile == null + ? Uint8List.fromList(imgData) + : File(widget.msg.localFile).readAsBytesSync()); var imgSize = _getImgSize(); return DownloadItem( isAutoDown: false, msg: widget.msg, - onFinishTap: (){ + onFinishTap: () { widget.hideKeyboard(); showFullImg(context, widget.msg); }, diff --git a/lib/chat/company_server_view.dart b/lib/chat/company_server_view.dart index f1bf89a..8de0f58 100644 --- a/lib/chat/company_server_view.dart +++ b/lib/chat/company_server_view.dart @@ -7,8 +7,6 @@ import 'package:chat/data/constants.dart'; import 'package:chat/generated/i18n.dart'; import 'package:chat/models/ChatMsg.dart'; import 'package:chat/models/UserInfo.dart'; -import 'package:chat/photo/entity/options.dart'; -import 'package:chat/photo/photo.dart'; import 'package:chat/proto/chat.pb.dart'; import 'package:chat/r.dart'; import 'package:chat/utils/CustomUI.dart'; @@ -23,7 +21,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:multi_image_picker/multi_image_picker.dart'; import 'package:oktoast/oktoast.dart'; -import 'package:photo_manager/photo_manager.dart'; import 'package:chat/utils/MessageMgr.dart'; class CompanyServerPage extends StatefulWidget { diff --git a/lib/chat/group_chat_item.dart b/lib/chat/group_chat_item.dart index d629302..99252c0 100644 --- a/lib/chat/group_chat_item.dart +++ b/lib/chat/group_chat_item.dart @@ -36,7 +36,6 @@ import 'package:chat/utils/video_anim.dart'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; import 'package:oktoast/oktoast.dart'; import 'package:chat/utils/HttpUtil.dart'; @@ -92,6 +91,8 @@ class _GroupChatPageItemState extends State bool isLongPressed = false; + double maxWidth = Screen.width - 140; + @override void initState() { super.initState(); @@ -145,10 +146,10 @@ class _GroupChatPageItemState extends State } } - getTodayTime(msgDate) { + getTodayTime(msgDate, {var sendTime}) { String showTimeStr; - var sendTime = widget.msg.time; + sendTime = sendTime ?? widget.msg.time; var today = DateTime.now(); //今天 if (msgDate.year == today.year && @@ -187,6 +188,7 @@ class _GroupChatPageItemState extends State return Container( width: Screen.width, + color: Colors.white.withOpacity(0), margin: const EdgeInsets.symmetric(vertical: 10.0), child: Column( children: [ @@ -277,6 +279,8 @@ class _GroupChatPageItemState extends State } _textMsg(MsgModel msgModel) { + List showMsg = []; + var width = 0.0; var msg = utf8.decode(msgModel.msgContent); if (msg.contains('[ ')) { msg = msg.replaceAll('[ ', '['); @@ -284,53 +288,94 @@ class _GroupChatPageItemState extends State if (msg.contains(' ]')) { msg = msg.replaceAll(' ]', ']'); } - bool isUrl =false; - if(textList[curTextType].contains('http') ){ - isUrl =true; + bool isUrl = false; + if (textList[curTextType].contains('http')) { + isUrl = true; + } + + if (msgModel.refMsgContent != null && msgModel.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msgModel.refMsgContent); + + var refName = Provider.of(context) + .getGroupRefName(msgModel.sessionId, quoteMsg.sendUserId); + + var msgDate = + DateTime.fromMillisecondsSinceEpoch(quoteMsg.sendTime.toInt()); + var showTimeStr = + getTodayTime(msgDate, sendTime: quoteMsg.sendTime.toInt()); + + var timetWidth = CustomUI.getRealTextWidht(showTimeStr, 13); + var nameWidhth = CustomUI.getRealTextWidht(refName, 13); + width = timetWidth + (nameWidhth > 70 ? 70 : nameWidhth) + 36; + var tempIndex = quoteMsg.content.indexOf(':'); + var quoteContent = tempIndex == -1 + ? quoteMsg.content + : quoteMsg.content.substring(quoteMsg.content.indexOf(':') + 2); + var contentWidht = _getTextWidth(quoteContent, fontSize: 13); + width = min(max(width, contentWidht), maxWidth); + + showMsg.add(InkWell( + onTap: () { + MessageMgr().emit('Jump to Msg', quoteMsg.sendTime.toInt()); + }, + child: Container( + padding: EdgeInsets.all(8), + margin: EdgeInsets.only(bottom: 5), + decoration: BoxDecoration( + color: Color(0xFFC4E0F5), + borderRadius: BorderRadius.circular(5.5)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Container( + constraints: BoxConstraints(maxWidth: 70), + child: Text( + refName, + style: TextStyle(fontSize: 13), + overflow: TextOverflow.ellipsis, + )), + SizedBox(width: 20), + Text( + showTimeStr, + style: TextStyle(fontSize: 13), + ) + ]), + SizedBox(height: 7.5), + Text( + quoteContent, + style: TextStyle(fontSize: 13), + ) + ], + ), + ))); + } + var contentWidth = _getTextWidth(textList[curTextType]); + if (contentWidth > width && contentWidth <= maxWidth) { + width = contentWidth; } - Widget text = Container( + + showMsg.add(Container( + constraints: BoxConstraints(maxWidth: maxWidth, minHeight: 22), + alignment: Alignment.centerLeft, + child: extendedText( + textList[curTextType], + color: isUrl ? Colors.blue : Constants.BlackTextColor, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + ))); + + return Container( constraints: BoxConstraints(maxWidth: Screen.width - 120), - child: extendedText( - msg, - hideKeyboard: widget.hideKeyboard, - fontSize: FontSize, - color: isUrl?Colors.blue:SendMsgText, - ), + width: width + 20, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), decoration: BoxDecoration( color: isLongPressed ? Colors.grey[300] : SendMsgBg, border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), ); - - if (msgModel.refMsgContent != null && msgModel.refMsgContent.length > 0) { - QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msgModel.refMsgContent); - - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - text, - SizedBox(height: 2), - Container( - constraints: BoxConstraints(maxWidth: Screen.width - 120), - padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), - child: Text( - quoteMsg.content, - maxLines: 1, - textScaleFactor: 1.0, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 12), - ), - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(5)), - ) - ], - ); - } else { - return text; - } } _soundMsg() { @@ -472,7 +517,9 @@ class _GroupChatPageItemState extends State _imgMsg(List imgData) { var imgSize = _getImgSize(); - ImageProvider provider = MemoryImage(widget.msg.localFile==null?Uint8List.fromList(imgData):File(widget.msg.localFile).readAsBytesSync()); + ImageProvider provider = MemoryImage(widget.msg.localFile == null + ? Uint8List.fromList(imgData) + : File(widget.msg.localFile).readAsBytesSync()); return GestureDetector( child: ClipRRect( @@ -484,7 +531,7 @@ class _GroupChatPageItemState extends State width: imgSize.width, child: Image( fit: BoxFit.contain, - image:provider, + image: provider, ), )), borderRadius: BorderRadius.circular(5), @@ -586,46 +633,46 @@ class _GroupChatPageItemState extends State MessageMgr().emit('Delete Select Message', widget.msg); }); - ///转发 - if (widget.msg.msgType == ChatType.TextChatType.value|| - widget.msg.msgType == ChatType.ImageChatType.value|| - widget.msg.msgType == ChatType.ShortVideoChatType.value|| - widget.msg.msgType == ChatType.PlaceChatType.value|| - widget.msg.msgType == ChatType.EmoticonType.value|| - widget.msg.msgType == ChatType.FileChatType.value - ){ - actions.add( I18n.of(context).forward); + if (widget.msg.msgType == ChatType.TextChatType.value || + widget.msg.msgType == ChatType.ImageChatType.value || + widget.msg.msgType == ChatType.ShortVideoChatType.value || + widget.msg.msgType == ChatType.PlaceChatType.value || + widget.msg.msgType == ChatType.EmoticonType.value || + widget.msg.msgType == ChatType.FileChatType.value) { + actions.add(I18n.of(context).forward); actionsFunc.add(() { print('转发消息'); - if(widget.msg.msgType == ChatType.FileChatType.value && widget.msg.localFile==null){ + if (widget.msg.msgType == ChatType.FileChatType.value && + widget.msg.localFile == null) { showToast('请先下载文件'); - return ; + return; } AppNavigator.pushForwardPage(context, widget.msg); }); } - - if (widget.msg.msgType == ChatType.FileChatType.value &&widget.msg.localFile!=null) { + if (widget.msg.msgType == ChatType.FileChatType.value && + widget.msg.localFile != null) { //分享文件 - actions.add( I18n.of(context).copy_download_url); - actionsFunc.add(() async{ + actions.add(I18n.of(context).copy_download_url); + actionsFunc.add(() async { //如果是文件增加复制下载地址 - String path = widget.msg.localFile; - UploadUtil().copyFileUrl(widget.msg, context); - String type='file'; - if(path.contains('mp4') ||path.contains('mp3')){ - type = 'video'; - }else if(path.contains('png')||path.contains('jpg')||path.contains('jpeg')||path.contains('JPG')||path.contains('PNG')){ - type = 'image'; - } - - ShareExtend.share(FileCacheMgr.replacePath(path), type); - + String path = widget.msg.localFile; + UploadUtil().copyFileUrl(widget.msg, context); + String type = 'file'; + if (path.contains('mp4') || path.contains('mp3')) { + type = 'video'; + } else if (path.contains('png') || + path.contains('jpg') || + path.contains('jpeg') || + path.contains('JPG') || + path.contains('PNG')) { + type = 'image'; + } + ShareExtend.share(FileCacheMgr.replacePath(path), type); }); - } if (widget.msg.msgType == ChatType.TextChatType.value) { @@ -639,8 +686,6 @@ class _GroupChatPageItemState extends State }); } - - if (widget.msg.msgType == ChatType.ShortVoiceChatType.value) { var soundPlayMode = Provider.of(context).soundPlayMode; @@ -656,23 +701,22 @@ class _GroupChatPageItemState extends State } // String date2 = DateTime.fromMillisecondsSinceEpoch(widget.msg.time).toString(); - bool isUrl =false; - if(widget.msg.msgType==ChatType.TextChatType.value ){ - if( textList[curTextType].contains('http')){ - isUrl =true; + bool isUrl = false; + if (widget.msg.msgType == ChatType.TextChatType.value) { + if (textList[curTextType].contains('http')) { + isUrl = true; } - } return WPopupMenu( child: item, actions: actions, - onTap: ()async{ - if(isUrl){ - if (await canLaunch(textList[curTextType])) { - launch(textList[curTextType]); + onTap: () async { + if (isUrl) { + if (await canLaunch(textList[curTextType])) { + launch(textList[curTextType]); + } } - } }, onLongPressStart: () { isLongPressed = true; @@ -739,16 +783,16 @@ class _GroupChatPageItemState extends State selectionEnabled: false, hideKeyboard: widget.hideKeyboard)); } - double _getTextWidth(String text) { + double _getTextWidth(String text, {double fontSize = FontSize}) { var tp = TextPainter( text: TextSpan( - style: TextStyle(fontSize: FontSize), text: textList[curTextType]), + style: TextStyle(fontSize: fontSize), text: textList[curTextType]), textAlign: TextAlign.left, textDirection: TextDirection.ltr, textScaleFactor: 1, ); - tp.layout(maxWidth: Screen.width - 140); + tp.layout(maxWidth: maxWidth); if (text.contains('[')) { if (text.length < 5 && text.startsWith('[') && text.endsWith(']')) { ///单表情 @@ -763,7 +807,7 @@ class _GroupChatPageItemState extends State if (length > 6) scale = 7; double width = tp.width + length * scale; - return width > (Screen.width - 140) ? Screen.width - 140 : width; + return width > (maxWidth) ? maxWidth : width; } } return tp.width; @@ -785,10 +829,71 @@ class _GroupChatPageItemState extends State _receiveText(MsgModel msg) { List showMsg = []; + double width = 0.0; if (textList.length > 0) { - bool isUrl =false; - if(textList[curTextType].contains('http') ){ - isUrl =true; + bool isUrl = false; + if (textList[curTextType].contains('http')) { + isUrl = true; + } + + if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); + + var refName = Provider.of(context) + .getGroupRefName(msg.sessionId, quoteMsg.sendUserId); + + var msgDate = + DateTime.fromMillisecondsSinceEpoch(quoteMsg.sendTime.toInt()); + var showTimeStr = + getTodayTime(msgDate, sendTime: quoteMsg.sendTime.toInt()); + + var timetWidth = CustomUI.getRealTextWidht(showTimeStr, 13); + var nameWidhth = CustomUI.getRealTextWidht(refName, 13); + width = timetWidth + (nameWidhth > 70 ? 70 : nameWidhth) + 36; + var quoteContent = + quoteMsg.content.substring(quoteMsg.content.indexOf(':') + 2); + var contentWidht = _getTextWidth(quoteContent, fontSize: 13); + width = min(max(width, contentWidht), maxWidth); + showMsg.add(InkWell( + onTap: () { + MessageMgr().emit('Jump to Msg', quoteMsg.sendTime.toInt()); + }, + child: Container( + padding: EdgeInsets.all(8), + margin: EdgeInsets.only(bottom: 5), + decoration: BoxDecoration( + color: Color(0xFFC4E0F5), + borderRadius: BorderRadius.circular(5.5)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Container( + constraints: BoxConstraints(maxWidth: 70), + child: Text( + refName, + style: TextStyle(fontSize: 13), + overflow: TextOverflow.ellipsis, + )), + SizedBox(width: 20), + Text( + showTimeStr, + style: TextStyle(fontSize: 13), + ) + ]), + SizedBox(height: 7.5), + Text( + quoteContent, + style: TextStyle(fontSize: 13), + ) + ], + ), + ))); + } + + var contentWidth = _getTextWidth(textList[curTextType]); + if (contentWidth > width && contentWidth <= maxWidth) { + width = contentWidth; } showMsg.add(InkWell( @@ -805,8 +910,7 @@ class _GroupChatPageItemState extends State } }, child: Container( - constraints: - BoxConstraints(maxWidth: Screen.width - 140, minHeight: 22), + constraints: BoxConstraints(maxWidth: maxWidth, minHeight: 22), alignment: Alignment.centerLeft, child: extendedText( textList[curTextType], @@ -816,8 +920,6 @@ class _GroupChatPageItemState extends State )))); } - var width = _getTextWidth(textList[curTextType]); - var minWidth = width + 20; if (msg.transTag != 0) { minWidth = 200; @@ -841,7 +943,7 @@ class _GroupChatPageItemState extends State color: isLongPressed ? Colors.grey[300] : Colors.white, borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), ), - msg.transTag != 1 && msg.transTag !=0 + msg.transTag != 1 && msg.transTag != 0 ? Positioned( right: 5, top: 5, @@ -855,34 +957,7 @@ class _GroupChatPageItemState extends State : Container() ]); - if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { - QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); - - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - text, - SizedBox(height: 2), - Container( - constraints: BoxConstraints(maxWidth: Screen.width - 120), - padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), - child: Text( - quoteMsg.content, - maxLines: 1, - textScaleFactor: 1.0, - overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 12), - ), - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(5)), - ) - ], - ); - } else { - return text; - } + return text; } //用户评价人工翻译,差评 @@ -1083,14 +1158,16 @@ class _GroupChatPageItemState extends State _receiveImg(BuildContext context, List imgData, {String downloadData}) { // ImageProvider provider = MemoryImage(Uint8List.fromList(imgData)); - ImageProvider provider = MemoryImage(widget.msg.localFile==null?Uint8List.fromList(imgData):File(widget.msg.localFile).readAsBytesSync()); + ImageProvider provider = MemoryImage(widget.msg.localFile == null + ? Uint8List.fromList(imgData) + : File(widget.msg.localFile).readAsBytesSync()); var imgSize = _getImgSize(); return DownloadItem( isAutoDown: false, msg: widget.msg, - onFinishTap: (){ + onFinishTap: () { widget.hideKeyboard(); showFullImg(context, widget.msg); }, @@ -1106,7 +1183,6 @@ class _GroupChatPageItemState extends State ), ), ); - } _receiveVideo(BuildContext context, List imgData, @@ -1116,7 +1192,6 @@ class _GroupChatPageItemState extends State return InkWell( onTap: () { if (widget.msg.localFile != null) { - showVideoPage(context, widget.msg.localFile); } }, diff --git a/lib/chat/group_chat_view.dart b/lib/chat/group_chat_view.dart index 491faa9..5cceb18 100644 --- a/lib/chat/group_chat_view.dart +++ b/lib/chat/group_chat_view.dart @@ -24,6 +24,7 @@ import 'package:chat/utils/sound_util.dart'; import 'package:chat/utils/sp_utils.dart'; import 'package:chat/utils/sql_util.dart'; import 'package:chat/utils/upload_util.dart'; +import 'package:chat/utils/white_opacity_anim.dart'; import 'package:extended_text/extended_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -75,6 +76,8 @@ class _GroupChatPageState extends State { String alterUserName = ''; + int jumpTime; + @override void dispose() { var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; @@ -84,6 +87,7 @@ class _GroupChatPageState extends State { msgMgr.off('Keyboard Hide', dealWithKeyboardHide); msgMgr.off('Update Group Info', updateGroupInfo); msgMgr.off('Delete Select Message', _deleteItem); + msgMgr.off('Jump to Msg', jumpToMsg); MsgHandler.curActiveSession = 0; SoundUtils().stop(); @@ -126,6 +130,7 @@ class _GroupChatPageState extends State { msgMgr.on('Keyboard Hide', dealWithKeyboardHide); msgMgr.on('Update Group Info', updateGroupInfo); msgMgr.on('Delete Select Message', _deleteItem); + msgMgr.on('Jump to Msg', jumpToMsg); WidgetsBinding.instance.addPostFrameCallback((_) { if (widget.enterType == 1) { @@ -157,6 +162,26 @@ class _GroupChatPageState extends State { }); } + jumpToMsg(time) { + //var screenItemNums = itemPositionListener.itemPositions.value.length; + jumpTime = time; + int jumIndex = 0; + for (int i = 0; i < msgList.length; i++) { + if (time == msgList[i].time) { + jumIndex = i - 1; // - screenItemNums + 2; + break; + } + } + if (jumIndex < 0) { + jumIndex = 0; + } + if (jumIndex > msgList.length - 1) { + jumIndex = msgList.length - 1; + } + itemScrollController.scrollTo( + index: jumIndex, duration: new Duration(microseconds: 1)); + } + void _sendFile(File file) async { // File file = await FilePicker.getFile(); int fileSize = file.lengthSync(); @@ -253,7 +278,7 @@ class _GroupChatPageState extends State { Map refMap = Provider.of(context).refMap; - bool isHaveUnreadNews = unreadTime !=null; + bool isHaveUnreadNews = unreadTime != null; bool isAlterYou = alterTime != null; return MultiProvider( @@ -301,31 +326,9 @@ class _GroupChatPageState extends State { right: 0, child: InkWell( onTap: () { - var screenItemNums = - itemPositionListener - .itemPositions.value.length; - int jumIndex = 0; - if (isAlterYou) { - for (int i = 0; - i < msgList.length; - i++) { - if (alterTime == msgList[i].time) { - jumIndex = i - screenItemNums + 2; - break; - } - } - } else { - for (int i = 0; - i < msgList.length; - i++) { - if (unreadTime == msgList[i].time) { - jumIndex = i - screenItemNums + 2; - break; - } - } - } - itemScrollController.jumpTo( - index: jumIndex); + jumpToMsg(isAlterYou + ? alterTime + : unreadTime); unreadTime = null; setState(() {}); }, @@ -349,7 +352,7 @@ class _GroupChatPageState extends State { child: Row( children: [ Icon( - Icons.file_upload, + Icons.arrow_upward, color: Color(0xFF3875E9), size: 20, ), @@ -495,7 +498,7 @@ class _GroupChatPageState extends State { itemPositionsListener: itemPositionListener, padding: EdgeInsets.all(8.0), reverse: true, -// hitCallback: hideKeyBoard, + hitCallback: hideKeyBoard, )), ); } @@ -518,9 +521,10 @@ class _GroupChatPageState extends State { MsgHandler.insertMsgToDB(msg); MsgHandler.sendChatMsg(msg); if (mounted) { - setState(() {}); + setState(() { + itemScrollController.jumpTo(index: 0); + }); } - itemScrollController.jumpTo(index: 0); } MsgModel msg; @@ -566,18 +570,29 @@ class _GroupChatPageState extends State { } MsgModel msg = msgList[index]; + var result; if (msg.from == 0) { - return GroupChatPageItem( + result = GroupChatPageItem( key: Key(msg.time.toString()), msg: msg, lastMsgTime: lastMsgTime); } else { - return GroupChatPageItem( + result = GroupChatPageItem( key: Key(msg.time.toString()), msg: msg, memberModel: widget.groupInfoModel.getMember(msg.from), hideKeyboard: readOnly, lastMsgTime: lastMsgTime); } + if (msg.time == jumpTime) { + result = WhiteOpacityAnim( + key: Key(msg.time.toString()), + child: result, + animFinishCallback: () { + jumpTime = null; + }, + ); + } + return result; } quiteGroup() { diff --git a/lib/chat/input_bar.dart b/lib/chat/input_bar.dart index e720750..ba9e1a7 100644 --- a/lib/chat/input_bar.dart +++ b/lib/chat/input_bar.dart @@ -153,7 +153,7 @@ class InputBarState extends State // SystemChannels.textInput.invokeMethod('TextInput.show'); } - _getRefShortText() { + _getRefShortText(){ if (refMsg == null) { return null; } @@ -209,11 +209,19 @@ class InputBarState extends State break; default: } - - GroupInfoModel groupInfoModel = Provider.of(context); - var member = groupInfoModel.getMember(refMsg.from); - - return '${member.refName}: $desc'; + if (refMsg.channelType == ChatChannelType.Group.value) { + GroupInfoModel groupInfoModel = Provider.of(context); + var member = groupInfoModel.getMember(refMsg.from); + return '${member.refName}: $desc'; + //} + //else if (refMsg.channelType == ChatChannelType.Session.value) { + // UserInfo info = await HttpUtil().getFriendInfo(refMsg.from); + // var refName = Provider.of(context) + // .getRefName(info.userId, info.nickName); + // return '$refName: $desc'; + } else { + return desc; + } } bool isReceiver = false; @@ -229,8 +237,7 @@ class InputBarState extends State Widget centerWidget; Widget input = Container( - child: - TextField( + child: TextField( // textSelectionControls: ExtendedMaterialTextSelectionControls(), keyboardAppearance: Brightness.light, onChanged: (String messageText) { @@ -700,14 +707,16 @@ class InputBarState extends State for (var i = 0; i < resultList.length; i++) { Asset photoEntity = resultList[i]; ByteData byteData = await photoEntity.getByteData(); - File file = await FileCacheMgr().writeFile('temp-photo-${DateTime.now().millisecondsSinceEpoch}-${photoEntity.name}', byteData.buffer.asInt8List(0)); + File file = await FileCacheMgr().writeFile( + 'temp-photo-${DateTime.now().millisecondsSinceEpoch}-${photoEntity.name}', + byteData.buffer.asInt8List(0)); _sendPhotoFile(file); } } } on Exception catch (e) { - print(e.toString()); + print(e.toString()); } @@ -765,7 +774,7 @@ class InputBarState extends State if (imgSize > ImgSizeLimit) { print('图片大于 $ImgSizeLimit,压缩'); //发送压缩图 WidgetUtil.getCompressImg(path,quality: 80,percentage: 80); - sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path ); + sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path); isNeedUpload = true; } else { sendImg = imgFile.readAsBytesSync(); diff --git a/lib/chat/translate_state.dart b/lib/chat/translate_state.dart index 29a6018..64dacaa 100644 --- a/lib/chat/translate_state.dart +++ b/lib/chat/translate_state.dart @@ -3,7 +3,6 @@ import 'package:chat/data/constants.dart'; import 'package:chat/generated/i18n.dart'; import 'package:chat/utils/HttpUtil.dart'; import 'package:chat/utils/MessageMgr.dart'; -import 'package:chat/utils/msgHandler.dart'; import 'package:chat/utils/screen.dart'; import 'package:flutter/material.dart'; import 'package:oktoast/oktoast.dart'; diff --git a/lib/data/UserData.dart b/lib/data/UserData.dart index 6a87e23..fdd1ead 100644 --- a/lib/data/UserData.dart +++ b/lib/data/UserData.dart @@ -65,6 +65,8 @@ class UserData { int homemainIndex = 0; String currentCity = ''; + String deviceLanguageCode; + Map toJson() { Map json = new Map(); json['language'] = language; diff --git a/lib/data/translate_hk_data_mgr.dart b/lib/data/translate_hk_data_mgr.dart index 2356b42..5744bad 100644 --- a/lib/data/translate_hk_data_mgr.dart +++ b/lib/data/translate_hk_data_mgr.dart @@ -1,14 +1,4 @@ -import 'dart:convert'; - -import 'package:chat/data/UserData.dart'; -import 'package:chat/data/chat_data_mgr.dart'; -import 'package:chat/models/group_info_model.dart'; -import 'package:chat/proto/chat.pbserver.dart'; -import 'package:chat/utils/MessageMgr.dart'; -import 'package:chat/utils/group_member_model.dart'; -import 'package:chat/utils/sql_util.dart'; -import 'package:chat/utils/upload_util.dart'; -import 'package:crclib/crclib.dart'; + class TranslateOrder{ diff --git a/lib/home/AddProgram.dart b/lib/home/AddProgram.dart index b153722..1ec8966 100644 --- a/lib/home/AddProgram.dart +++ b/lib/home/AddProgram.dart @@ -12,8 +12,6 @@ import 'package:chat/home/SelectPage.dart'; import 'package:chat/home/VerificationCenter.dart'; import 'package:chat/home/VipPage.dart'; import 'package:chat/models/money_change.dart'; -import 'package:chat/photo/entity/options.dart'; -import 'package:chat/photo/photo.dart'; import 'package:chat/utils/ChargeMoney.dart'; import 'package:chat/utils/CustomUI.dart'; import 'package:chat/utils/HttpUtil.dart'; @@ -31,7 +29,6 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:multi_image_picker/multi_image_picker.dart'; import 'package:oktoast/oktoast.dart'; -import 'package:photo_manager/photo_manager.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/ShadowButton.dart'; diff --git a/lib/home/InformUser.dart b/lib/home/InformUser.dart index 6f8c9d5..8dbc889 100644 --- a/lib/home/InformUser.dart +++ b/lib/home/InformUser.dart @@ -6,8 +6,6 @@ import 'package:chat/data/UserData.dart'; import 'package:chat/data/WebData.dart'; import 'package:chat/data/constants.dart'; import 'package:chat/generated/i18n.dart'; -import 'package:chat/photo/entity/options.dart'; -import 'package:chat/photo/photo.dart'; import 'package:chat/utils/CustomUI.dart'; import 'package:chat/utils/HttpUtil.dart'; import 'package:chat/utils/PicSwiper.dart'; @@ -18,7 +16,6 @@ import 'package:flutter/material.dart'; import 'package:multi_image_picker/multi_image_picker.dart'; import 'package:oktoast/oktoast.dart'; -import 'package:photo_manager/photo_manager.dart'; import '../data/UserData.dart'; import '../utils/TokenMgr.dart'; diff --git a/lib/home/ProfilePage.dart b/lib/home/ProfilePage.dart index 8c0e770..3d96bfa 100644 --- a/lib/home/ProfilePage.dart +++ b/lib/home/ProfilePage.dart @@ -6,8 +6,6 @@ import 'package:chat/home/rich_title.dart'; import 'package:chat/models/money_change.dart'; import 'package:chat/models/ref_name_provider.dart'; import 'package:chat/models/voucher_change.dart'; -import 'package:chat/photo/entity/options.dart'; -import 'package:chat/photo/photo.dart'; import 'package:chat/utils/ChargeMoney.dart'; import 'package:chat/utils/app_navigator.dart'; import 'package:chat/utils/blacklist_mgr.dart'; @@ -42,7 +40,6 @@ import 'package:image_picker/image_picker.dart'; import 'package:multi_image_picker/multi_image_picker.dart'; import 'package:oktoast/oktoast.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:photo_manager/photo_manager.dart'; import 'package:provider/provider.dart'; import 'package:share/share.dart'; import '../utils/FullWithButton.dart'; diff --git a/lib/home/homeMain.dart b/lib/home/homeMain.dart index 2cd3764..f4cb2bc 100644 --- a/lib/home/homeMain.dart +++ b/lib/home/homeMain.dart @@ -10,7 +10,6 @@ import 'package:chat/home/realtimehelper/real_time_helper_page.dart'; import 'package:chat/home/unread_dot_widget.dart'; import 'package:chat/models/UserInfo.dart'; import 'package:chat/models/ref_name_provider.dart'; -import 'package:chat/proto/transhousekeeper.pb.dart'; import 'package:chat/utils/CustomUI.dart'; import 'package:chat/utils/HttpUtil.dart'; import 'package:chat/utils/MessageMgr.dart'; @@ -35,7 +34,6 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:chat/utils/my_bottom_navigation_bar.dart' as myBottm; import 'friend_page.dart'; -import 'group_chat_page.dart'; class NavigationIconView { final BottomNavigationBarItem item; @@ -175,7 +173,7 @@ class _HomeMainState extends State { postContact(null); postLoaction(); locationSchedule(); - + HttpUtil().saveMobileInfo(); WidgetsBinding.instance.addPostFrameCallback((_) { VersionUtils.versionUpdate(context); ReceiveShareFile.start(); diff --git a/lib/home/realtimehelper/translation_butler_page.dart b/lib/home/realtimehelper/translation_butler_page.dart index 534a8a8..76936ca 100644 --- a/lib/home/realtimehelper/translation_butler_page.dart +++ b/lib/home/realtimehelper/translation_butler_page.dart @@ -1,36 +1,22 @@ import 'dart:async'; -import 'package:cached_network_image/cached_network_image.dart'; -import 'package:chat/chat/ChatPage.dart'; import 'package:chat/data/UserData.dart'; -import 'package:chat/data/chat_data_mgr.dart'; -import 'package:chat/data/group_data_mgr.dart'; import 'package:chat/data/translate_hk_data_mgr.dart'; -import 'package:chat/home/add_friend.dart'; -import 'package:chat/home/group_announcement.dart'; -import 'package:chat/home/group_manage_page.dart'; import 'package:chat/models/group_info_model.dart'; import 'package:chat/models/money_change.dart'; -import 'package:chat/models/ref_name_provider.dart'; -import 'package:chat/utils/LoadingDialog.dart'; import 'package:chat/utils/MessageMgr.dart'; -import 'package:chat/utils/group_member_model.dart'; import 'package:chat/utils/msgHandler.dart'; import 'package:chat/utils/screen.dart'; import 'package:chat/utils/sp_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:oktoast/oktoast.dart'; import 'package:provider/provider.dart'; import '../../data/constants.dart'; import '../../generated/i18n.dart'; import '../../r.dart'; import '../../utils/CustomUI.dart'; -import '../../utils/FullWithButton.dart'; -import '../../utils/app_navigator.dart'; -import '../create_group_view.dart'; import 'package:chat/utils/PopUpMenu.dart' as myPop; class TranslationButlerPage extends StatefulWidget { diff --git a/lib/home/realtimehelper/translation_evaluation_dialog.dart b/lib/home/realtimehelper/translation_evaluation_dialog.dart index fcdda6e..582c8da 100644 --- a/lib/home/realtimehelper/translation_evaluation_dialog.dart +++ b/lib/home/realtimehelper/translation_evaluation_dialog.dart @@ -31,13 +31,11 @@ class TravelEvaluationPageState extends State { @override void initState() { - // TODO: implement initState super.initState(); } @override void didChangeDependencies() { - // TODO: implement didChangeDependencies super.didChangeDependencies(); posList = [ EvaluationBean(6, I18n.of(context).translation_pos_1), @@ -81,7 +79,6 @@ class TravelEvaluationPageState extends State { @override Widget build(BuildContext context) { - // TODO: implement build List evaluationWidget = getItem(isGood ? posList : negList); diff --git a/lib/main.dart b/lib/main.dart index 5b9ff40..98f3866 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -405,6 +405,7 @@ class _MyAppState extends State with WidgetsBindingObserver { final String lang = deviceLocale != null ? deviceLocale.toString() : ""; print('#### fl: $lang'); + UserData().deviceLanguageCode = deviceLocale.toString(); //设置设备语言 if (language.containsKey(deviceLocale.toString())) UserData().deviceLanguage = diff --git a/lib/utils/CustomUI.dart b/lib/utils/CustomUI.dart index 7924b89..496400c 100644 --- a/lib/utils/CustomUI.dart +++ b/lib/utils/CustomUI.dart @@ -1280,4 +1280,15 @@ class CustomUI { child: TravelEvaluationPage(), )); } + + static double getRealTextWidht(String text, double fontSize) { + TextPainter _textPainter = TextPainter( + maxLines: 2, + text: TextSpan( + text: text, + style: TextStyle(fontSize: fontSize, color: Colors.black)), + textDirection: TextDirection.ltr) + ..layout(); + return _textPainter.width; + } } diff --git a/lib/utils/HttpUtil.dart b/lib/utils/HttpUtil.dart index 1a322ab..043ba06 100644 --- a/lib/utils/HttpUtil.dart +++ b/lib/utils/HttpUtil.dart @@ -24,6 +24,7 @@ import 'package:chat/utils/local_notification_util.dart'; import 'package:chat/utils/sp_utils.dart'; import 'package:chat/utils/sql_util.dart'; import 'package:chat/utils/user_info_table.dart'; +import 'package:device_info/device_info.dart'; import 'dart:core'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; @@ -35,7 +36,6 @@ import 'dart:io'; import '../data/UserData.dart'; import '../utils/TokenMgr.dart'; import 'package:http_parser/http_parser.dart'; -import 'package:chat/utils/friend_list_mgr.dart'; class HttpUtil { static HttpUtil _instance; @@ -836,10 +836,9 @@ class HttpUtil { UserData().stationOpenSwitch = config['station'] == 1; UserData().myProgramOpenSwitch = config['myProgram'] == 1; UserData().nearbyOpenSwitch = config['nearby'] == 1; - UserData().isTranslateUser = config['isTranslateUser'] == 1; // print('### config: start'); - print('### config: isTranslateUser:${config['isTranslateUser']}'); +// print('### config: iapPay:${config['iapPay']}'); } } } @@ -1419,6 +1418,35 @@ class HttpUtil { } } + + + //保存设备名称和编码 + saveMobileInfo() async { +String mobileType = ''; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + mobileType = androidInfo.model; + print('Running on ${androidInfo.model}'); // e.g. "Moto G (4)" + } else if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + mobileType = iosInfo.utsname.machine; + } + + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['model'] = mobileType; + data['coding'] = UserData().deviceLanguageCode; + + Response res = + await HttpUtil().post('user/save/modelAndCoding', data: data); + + Map resData = res.data; + print(resData); + } + ///实时帮-翻译管家评价 evaluationTransalteHK(String orderNo,String value,bool isGood,Function callback) async { Map data = { diff --git a/lib/utils/count_down_button.dart b/lib/utils/count_down_button.dart index ad9690d..33b8c58 100644 --- a/lib/utils/count_down_button.dart +++ b/lib/utils/count_down_button.dart @@ -14,7 +14,7 @@ class CountDownButton extends StatefulWidget{ @override State createState() { - // TODO: implement createState + return CountDownButtonState(); } @@ -44,7 +44,6 @@ class CountDownButtonState extends State { } @override void initState() { - // TODO: implement initState super.initState(); secondsPassed = widget.countDownTime; timer = Timer.periodic(Duration(seconds: 1), (Timer t){ @@ -54,14 +53,12 @@ class CountDownButtonState extends State { @override void dispose() { - // TODO: implement dispose super.dispose(); timer?.cancel(); } @override Widget build(BuildContext context) { - // TODO: implement build // ~/ 取整操作 int seconds = secondsPassed % 60; int minutes = secondsPassed ~/ 60; diff --git a/lib/utils/file_cache_mgr.dart b/lib/utils/file_cache_mgr.dart index cad71a7..7b98866 100644 --- a/lib/utils/file_cache_mgr.dart +++ b/lib/utils/file_cache_mgr.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'dart:typed_data'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; diff --git a/lib/utils/image_util.dart b/lib/utils/image_util.dart index df91a60..b9a76c3 100644 --- a/lib/utils/image_util.dart +++ b/lib/utils/image_util.dart @@ -5,7 +5,6 @@ import 'dart:ui'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:chat/data/group_data_mgr.dart'; import 'package:chat/models/group_info_model.dart'; -import 'package:chat/utils/screen.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; diff --git a/lib/utils/msgHandler.dart b/lib/utils/msgHandler.dart index 6cd11ba..50bc660 100644 --- a/lib/utils/msgHandler.dart +++ b/lib/utils/msgHandler.dart @@ -9,7 +9,6 @@ import 'package:chat/data/group_data_mgr.dart'; import 'package:chat/data/translate_hk_data_mgr.dart'; import 'package:chat/generated/i18n.dart'; import 'package:chat/home/IndexPage.dart'; -import 'package:chat/home/realtimehelper/translation_butler_page.dart'; import 'package:chat/models/ChatMsg.dart'; import 'package:chat/models/group_info_model.dart'; import 'package:chat/proto/all.pbserver.dart'; @@ -26,7 +25,6 @@ import 'package:flutter/material.dart'; import 'package:oktoast/oktoast.dart'; import 'package:fixnum/fixnum.dart'; -import 'LoadingDialog.dart'; import 'MessageMgr.dart'; const MaxMsgContentSize = 1024 * 1024 * 3; @@ -414,7 +412,7 @@ class MsgHandler { channelType: ChatChannelType.Group.value); } } - else if(isTranslateHK){ //TODO ddddd + else if(isTranslateHK){ var myId = UserData().basicInfo.userId; print('chat.contentBuff:${chat.contentBuff.length}'); TransHKChatNotice notice = TransHKChatNotice.fromBuffer(chat.contentBuff); diff --git a/lib/utils/screen_shot.dart b/lib/utils/screen_shot.dart index ee13c20..8fa51cf 100644 --- a/lib/utils/screen_shot.dart +++ b/lib/utils/screen_shot.dart @@ -1,7 +1,6 @@ import 'dart:typed_data'; import 'dart:io'; import 'package:chat/map/location_result.dart'; -import 'package:chat/utils/screen.dart'; import 'package:flutter/services.dart'; import 'package:flutter_native_image/flutter_native_image.dart'; //import 'package:flutter_image_compress/flutter_image_compress.dart'; diff --git a/lib/utils/white_opacity_anim.dart b/lib/utils/white_opacity_anim.dart new file mode 100644 index 0000000..be338b1 --- /dev/null +++ b/lib/utils/white_opacity_anim.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +class WhiteOpacityAnim extends StatefulWidget { + final Widget child; + final animFinishCallback; + WhiteOpacityAnim( + {Key key, @required this.child, @required this.animFinishCallback}); + @override + _WhiteOpacityAnimState createState() => _WhiteOpacityAnimState(); +} + +class _WhiteOpacityAnimState extends State + with SingleTickerProviderStateMixin { + Animation _animation; + AnimationController _controller; + + @override + void initState() { + super.initState(); + // 启动动画controller + _controller = new AnimationController( + duration: Duration(milliseconds: 1000), vsync: this); + _controller.addStatusListener((AnimationStatus status) { + setState(() {}); + if (status == AnimationStatus.completed) { + widget.animFinishCallback(); + } + }); + + _animation = new Tween(begin: 1, end: 0).animate(_controller) + ..addListener(() { + setState(() {}); + }); + + _controller.forward(); + } + + @override + void dispose() { + _controller.stop(); + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + child: widget.child, + color: Colors.white.withOpacity(_animation.value), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 1ef9686..40911db 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -259,6 +259,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.2.9" + device_info: + dependency: "direct main" + description: + name: device_info + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.2+1" dio: dependency: "direct main" description: @@ -919,9 +926,11 @@ packages: scrollable_positioned_list: dependency: "direct main" description: - name: scrollable_positioned_list - url: "https://pub.flutter-io.cn" - source: hosted + path: "." + ref: HEAD + resolved-ref: "6ac696b0550694de0eac3f4c30956e21a6dad748" + url: "https://github.com/KerwinZheng/scrollable_positioned_list.git" + source: git version: "0.1.2" share: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index 60ffcca..9dc07ae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -177,7 +177,10 @@ dependencies: share_extend: ^1.1.1 #多图片选择 multi_image_picker: ^4.6.4 - scrollable_positioned_list: ^0.1.2 + scrollable_positioned_list: + git: https://github.com/KerwinZheng/scrollable_positioned_list.git + #设备信息 + device_info: ^0.4.2+1 dev_dependencies: flutter_test: