|
- import 'dart:convert';
- import 'dart:io';
- 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';
- import 'package:chat/data/UserData.dart';
- import 'package:chat/data/chat_data_mgr.dart';
- import 'package:chat/data/constants.dart';
- import 'package:chat/generated/i18n.dart';
- import 'package:chat/home/add_friend.dart';
- import 'package:chat/models/ChatMsg.dart';
- import 'package:chat/models/UserInfo.dart';
- import 'package:chat/models/keyboard_provider.dart';
- import 'package:chat/models/ref_name_provider.dart';
- import 'package:chat/models/voucher_change.dart';
- import 'package:chat/proto/all.pbserver.dart';
- import 'package:chat/utils/CustomUI.dart';
- import 'package:chat/utils/HttpUtil.dart';
- import 'package:chat/utils/MessageMgr.dart';
- import 'package:chat/utils/TokenMgr.dart';
- import 'package:chat/utils/analyze_utils.dart';
- import 'package:chat/utils/app_navigator.dart';
- import 'package:chat/utils/blacklist_mgr.dart';
- import 'package:chat/utils/count_down_button.dart';
- import 'package:chat/utils/friend_list_mgr.dart';
- import 'package:chat/utils/msgHandler.dart';
- import 'package:chat/utils/net_state_widget.dart';
- import 'package:chat/utils/sound_util.dart';
- import 'package:chat/utils/sp_utils.dart';
- import 'package:chat/utils/sql_util.dart';
- import 'package:dio/dio.dart';
- import 'package:extended_text/extended_text.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 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
- import '../r.dart';
- import 'ChatPageItem.dart';
- import 'input_bar.dart';
- import 'package:chat/utils/PopUpMenu.dart' as myPop;
- import 'package:chat/models/money_change.dart';
-
- class ChatPage extends StatefulWidget {
- final int friendId;
- final int enterType; // 0默认 1图片
- final dynamic enterContent;
- final bool isTranslateButler;
-
- ChatPage(
- {Key key,
- this.friendId,
- this.enterType = 0,
- this.enterContent,
- this.isTranslateButler = false})
- : super(key: key);
-
- _ChatPageState createState() => _ChatPageState();
- }
-
- class _ChatPageState extends State<ChatPage> {
- final ItemScrollController itemScrollController = ItemScrollController();
- final ItemPositionsListener itemPositionListener =
- ItemPositionsListener.create();
- //ScrollController _scrollCtrl = ScrollController();
-
- MessageMgr msgMgr = MessageMgr();
-
- UserInfo friendInfo;
-
- List<MsgModel> msgList;
-
- KeyboardIndexProvider _keyboardIndexProvider = KeyboardIndexProvider();
-
- TextEditingController nickNameController = new TextEditingController();
-
- //统计聊天时长
- int startTime;
-
- bool isTranslateButler;
-
- bool isTranslateButlerFinish=false;///翻译管家是否已经结束
-
- int jumpTime;
-
- @override
- void dispose() {
- var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
- AnalyzeUtils.commitChatDuration(startTime, endTime);
-
- MessageMgr().off('Send CoinBag', _sendCoin);
- msgMgr.off('New Chat Message', receiveMsg);
- 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();
- 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();
- print('init chatpage');
- getDefaultSetting();
- getUserInfo();
-
- isTranslateButler = widget.isTranslateButler;
- ///todo 这里再判断是否还在服务时间
-
- startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
-
- msgList = ChatDataMgr().getRecord();
-
- msgMgr.on('New Chat Message', receiveMsg);
- msgMgr.on('Keyboard Hide', dealWithKeyboardHide);
- 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 {
- // File file = await FilePicker.getFile();
- int fileSize = file.lengthSync();
- print('选择的文件 ${file.path} 大小 $fileSize');
-
- if (fileSize > 33 * 1024 * 1024) {
- showToast(I18n.of(context).max_file.replaceFirst('/s1', 33.toString()));
- return;
- }
-
- var fileName = file.path.split('/').last;
- print('fileName $fileName');
-
- var ext = '';
- var extList = fileName.split('.');
- if (extList.length > 1) {
- ext = extList.last;
- }
- print('ext $ext');
-
- var fileMsg = FileChat.create();
- fileMsg.type = ext;
- fileMsg.size = fileSize;
- fileMsg.name = fileName;
-
- var msg = MsgHandler.createSendMsg(
- ChatType.FileChatType, fileMsg.writeToBuffer(),
- friendId: widget.friendId,
- localFile: file.path,
- channelType: ChatChannelType.Session);
-
- sendMsg(msg);
- }
-
- _sendCoin(args) async {
- var res = await _checkCoinBeforeSend(args['amount']);
- if (res != null) {
- args['redNo'] = res['redNo'];
- args['friendId'] = widget.friendId;
- var msg = MsgHandler.createCoinBagMsg(args);
-
- sendMsg(msg);
- }
- }
-
- //校验
- _checkCoinBeforeSend(int amount) async {
- Map data = {
- "userId": UserData().basicInfo.userId,
- "rUserId": friendInfo.userId,
- "price": amount,
- };
- data['sign'] = TokenMgr().getSign(data);
-
- Response res = await HttpUtil().post('red/packet/send', data: data);
- if (res == null) {
- return null;
- }
- Map resData = res.data;
- if (resData['code'] == 0) {
- print(resData['data']);
- return resData['data'];
- }
-
- return null;
- }
-
- void getDefaultSetting() async {
- bool soundPlayMode =
- (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false;
-
- _keyboardIndexProvider.init(soundPlayMode);
- }
-
- dealWithKeyboardHide(args) {
- if (_keyboardIndexProvider.curKeyboardIndex == 0) {
- hideKeyBoard();
- }
- }
-
- getUserInfo() async {
- //先从本地获取用户信息
- friendInfo = await HttpUtil().getFriendInfo(widget.friendId, true);
-
- //如果是新的聊天,向服务器发送创建会话消息
- if (msgList.length == 0) {
- MsgHandler.getActiveSesstion(
- [friendInfo.userId, UserData().basicInfo.userId]);
- }
-
- if (mounted) {
- setState(() {});
- }
-
- WidgetsBinding.instance.addPostFrameCallback((_) {
- if (widget.enterType == 1) {
- print('接收到的:${widget.enterContent}');
-
- _sendFile(File(widget.enterContent));
- } else if (widget.enterType == 2) {
- //转发消息
-
- MsgModel originMsg = widget.enterContent;
- MsgModel msg = MsgHandler.createSendMsg(
- ChatType.valueOf(originMsg.msgType), originMsg.msgContent);
- msg.extraInfo = originMsg.extraInfo;
- if (originMsg.extraFile == null ||
- originMsg.extraFile.contains('http')) {
- msg.extraFile = originMsg.extraFile;
- } else {
- msg.extraFile = UploadUtil().getFullUrl(
- originMsg.extraFile, originMsg.sessionId, originMsg.channelType);
- }
-
- msg.localFile = originMsg.localFile;
- msg.friendId = widget.friendId;
- if (msg.localFile != null) {
- msg.state = MsgState.Uploaded;
- }
-
- sendMsg(msg);
- }
- });
- }
-
- @override
- Widget build(BuildContext context) {
- print('build chatpage');
-
- if (friendInfo == null) {
- return Scaffold(
- backgroundColor: const Color(0xFFE2E9F1),
- body: SafeArea(
- child: Center(
- child: CircularProgressIndicator(),
- ),
- ),
- );
- }
-
- List<Widget> actions = [];
-
- int voucher = Provider.of<VoucherChangeProvider>(context).voucher;
- actions.add(Row(
- children: <Widget>[
- CustomUI.buildImageLabel("assets/images/voucher.png", voucher,
- imgOpc: 0.5, imgHeight: 13),
- CustomUI.buildImageLabel(
- R.assetsImagesCoin, Provider.of<MoneyChangeProvider>(context).money,
- isLeft: false)
- ],
- ));
- actions.add(TranslateSateWidget(friendId: friendInfo.userId));
- actions.add(Container(
- margin: EdgeInsets.only(top: 1),
- child: myPop.PopupMenuButton(
- icon: Icon(
- Icons.more_horiz,
- size: 24,
- ),
- offset: Offset(0, 100),
- onSelected: (int index) {
- if (index == 2) {
- AppNavigator.pushInformUserPage(
- context, friendInfo.sex == 1, friendInfo.userId);
- } else if (index == 1) {
- Navigator.of(context).push(
- new MaterialPageRoute(
- builder: (context) {
- return AddFriendPage(
- userId: friendInfo.userId,
- pageType: SendMessagePageType.Remark,
- originalName: Provider.of<RefNameProvider>(context)
- .getRefName(
- friendInfo.userId, friendInfo.nickName));
- },
- ),
- );
- }
- },
- itemBuilder: (BuildContext context) {
- return <myPop.PopupMenuItem<int>>[
- myPop.PopupMenuItem(
- child: Container(
- alignment: Alignment.center,
- color: Colors.white,
- padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
- child: Text(I18n.of(context).anonymous_report,
- textScaleFactor: 1.0,
- maxLines: 1,
- style: TextStyle(
- color: Color(AppColors.AppBarColor), fontSize: 12)),
- ),
- value: 2,
- ),
- myPop.PopupMenuItem(
- child: Container(
- decoration: BoxDecoration(
- border: Border(
- top: BorderSide(width: 1, color: Colors.grey[300])),
- color: Colors.white,
- ),
- alignment: Alignment.center,
- padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
- child: Text(I18n.of(context).Remark,
- textScaleFactor: 1.0,
- maxLines: 1,
- style: TextStyle(
- color: Color(AppColors.AppBarColor), fontSize: 12)),
- ),
- value: 1,
- ),
- ];
- })));
-
-
-
- return WillPopScope(
- child: Stack(
- children: <Widget>[
- MultiProvider(
- providers: [
- ChangeNotifierProvider(create: (_) => _keyboardIndexProvider),
- Provider<bool>.value(value: false),
- Provider<int>.value(value: widget.friendId),
- ],
- child: GestureDetector(
- onTap: hideKeyBoard,
- child: ExtendedTextSelectionPointerHandler(
- ///选择文字,消除弹窗
-
- builder: (states) {
- return Listener(
- child: Scaffold(
- resizeToAvoidBottomInset: false,
- backgroundColor: const Color(0xFFE2E9F1),
- appBar: AppBar(
- title: Text(
- '${Provider.of<RefNameProvider>(context).getRefName(friendInfo.userId, friendInfo.nickName)}',
- textScaleFactor: 1.0,
- style: TextStyle(
- color: Constants.BlackTextColor,
- fontSize: 16.47),
- ),
- leading: CustomUI.buildCustomLeading(context,onTap:(){
- goBackCheck();
-
- }),
- titleSpacing: -10,
- centerTitle: false,
- elevation: 1,
- actions: actions),
- body: SafeArea(
- child: Column(
- children: <Widget>[
- NetStateWidget(),
- (isTranslateButler&!isTranslateButlerFinish)
- ? _buildTranslationButler()
- : Container(),
- Expanded(child: _buildMessageList()),
- InputBar(sendMsg: sendMsg,isTranslateHK: isTranslateButler,),
- ],
- ))),
- behavior: HitTestBehavior.translucent,
- onPointerDown: (value) {
- for (var state in states) {
- if (!state.containsPosition(value.position)) {
- //clear other selection
- state.clearSelection();
- }
- }
- },
- onPointerMove: (value) {
- //clear other selection
- for (var state in states) {
- if (!state.containsPosition(value.position)) {
- //clear other selection
- state.clearSelection();
- }
- }
- },
- );
- },
- ))),
- isTranslateButler ? getAudioChatView() : Container(),
- isTranslateButler ? zoomAudioButton() : Container()
- ],
- ),
- onWillPop: () {
- goBackCheck();
- return Future.value(true);
- });
- }
-
-
- goBackCheck(){
- if(isTranslateButler && !isTranslateButlerFinish){
- if(UserData().isTranslateUser){
- showToast('翻译服务未结束不能主动结束');
- }else{
- CustomUI.buildTowConfirm(
- context,
- '是否提前结束翻译管家服务?',
- I18n.of(context).confirm,
- (){
- setState(() {
- isTranslateButlerFinish=true;
-
- });
-
- MsgHandler.sendEndTransHKOrderReq();
- Navigator.of(context).pop();
- },
- '取消',
- (){ Navigator.of(context).pop();});
- }
- }else{
- Navigator.of(context).pop();
- }
- }
-
- Widget getAudioChatView() {
- if (friendInfo == null || isTranslateButlerFinish) {
- return Container();
- }
-
- return isActive == null
- ? Container()
- : Offstage(
- offstage: !isShowAudio,
- child: AudioChatPage(
- userInfo: friendInfo,
- isTranslateButler: true,
- isReplay: !TranslateHKMgr().isUser,
- translateButlerCloseCallBack: audioChatPageCallBack,
- ),
- );
- }
-
- audioChatPageCallBack(int args) {
- switch (args) {
- case 1:
- setState(() {
- isShowAudio = !isShowAudio;
- isShowZoomButton = true;
- });
- break;
- case 2:
- setState(() {
- isActive = false;
- });
- break;
- }
- }
-
- bool isShowAudio = false;
-
- ///控住连麦窗口是否显示
- bool isActive = true;
-
- ///控制连麦是否关闭
- bool isShowZoomButton = true;
- GlobalKey mykey = GlobalKey();
-
- double dx = 0 , dy = 0;
- double zoomButtonSize = 60;
-
- void dragEvent(DragUpdateDetails details) {
- final RenderObject box = context.findRenderObject();
- // 获得自定义Widget的大小,用来计算Widget的中心锚点
- dx = details.globalPosition.dx - mykey.currentContext.size.width / 2;
- dy = details.globalPosition.dy - mykey.currentContext.size.height / 2;
-
- // print('dx $dx dy $dy screen width:${Screen.width}');
-
- if (dx > Screen.width - zoomButtonSize) {
- dx = Screen.width - zoomButtonSize;
- } else if (dx < 0) {
- dx = 0;
- }
-
- if (dy > Screen.height - zoomButtonSize) {
- dy = Screen.height - zoomButtonSize;
- } else if (dy < 0) {
- dy = 0;
- }
-
- setState(() {});
- }
-
- Widget zoomAudioButton() {
-
- if (friendInfo == null || !isShowZoomButton) {
- return Container();
- }
-
- Widget button = Container(
- key: mykey,
- width: 57,
- height: 74,
- child: Card(child: Align(child: Icon(
- IconData(0xe67d, fontFamily: Constants.IconFontFamily),
- color: Color(0xFF008AFF),
- size: 35.0,
- ),alignment: Alignment.center,),),
- );
-
- return GestureDetector(
- onHorizontalDragUpdate: dragEvent,
- onVerticalDragUpdate: dragEvent,
- onTap: (){
- setState(() {
- isShowAudio = !isShowAudio;
- isShowZoomButton = !isShowZoomButton;
- });
- },
- child: Container(
-
- child: Transform.translate(
- offset: Offset(dx, dy),
- child: Align(
- alignment: Alignment.topLeft,
- child: button,
- ),
- ),
- ),
- );
- }
-
- Widget _buildTranslationButler() {
- bool hasHeadImg = true;
- if (friendInfo.headimgurl == null || friendInfo.headimgurl.length == 0) {
- hasHeadImg = false;
- }
-
- /// 5H币/1分钟
- String coinTIme = I18n.of(context).translation_butler_coin_time;
- coinTIme = coinTIme.replaceAll('/s1', '5');
- coinTIme = coinTIme.replaceAll('/s2', '1');
-
- return Container(
- padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
- color: Colors.white,
- child: Row(
- children: <Widget>[
- ClipRRect(
- borderRadius: BorderRadius.circular(8),
- child: hasHeadImg
- ? CachedNetworkImage(
- imageUrl: friendInfo.headimgurl,
- placeholder: (context, url) => Image.asset(
- Constants.DefaultHeadImgUrl,
- width: 54,
- height: 54,
- ),
- width: 54,
- height: 54,
- )
- : SizedBox(
- width: 54,
- height: 54,
- child: Image.asset(R.assetsImagesDefaultNorAvatar))),
- Padding(
- padding: EdgeInsets.only(left: 10),
- child: Container(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text(
- I18n.of(context).translation_butler,
- textScaleFactor: 1.0,
- overflow: TextOverflow.ellipsis,
- maxLines: 1,
- style: TextStyle(
- color: AppColors.NewAppbarTextColor, fontSize: 15),
- ),
- SizedBox(
- height: 5,
- ),
- Text(
- coinTIme,
- textScaleFactor: 1.0,
- maxLines: 1,
- style: TextStyle(color: Color(0xFF797979), fontSize: 13),
- )
- ],
- ),
- constraints: BoxConstraints(maxWidth: 135),
- ),
- ),
- TranslateHKMgr().isUser?Expanded(
- child: Container(
- constraints: BoxConstraints(maxWidth: 130),
- width: double.maxFinite,
- child: CountDownButton(
- I18n.of(context).translation_butler_end_service,
- () {
-
- // Navigator.of(context).pop();
- },
- countDownTime: 60*5,
- align: Alignment.centerRight,
- onPress: () {
- MsgHandler.sendEndTransHKOrderReq();
- // Navigator.of(context).pop();
- },
- ),
- // alignment: Alignment(1,0),
- )):Container(),
- ],
- ),
- );
- }
-
-
- Widget _buildMessageList() {
- return Container(
- alignment: Alignment.topCenter,
- child: msgList.length == 0
- ? Padding(
- padding: EdgeInsets.all(8),
- child: Text(
- I18n.of(context).chat_tips,
- textAlign: TextAlign.center,
- textScaleFactor: 1.0,
- style: TextStyle(color: Colors.grey, fontSize: 12),
- ))
- : NotificationListener(
- child: Scrollbar(
- child: ScrollablePositionedList.builder(
- physics: new ClampingScrollPhysics(),
- itemCount: msgList.length,
- itemBuilder: _buildItem,
- itemScrollController: itemScrollController,
- itemPositionsListener: itemPositionListener,
- //padding: EdgeInsets.all(8.0),
- reverse: true,
- hitCallback: hideKeyBoard,
- )),
- onNotification: (notification) {
- if (notification is ScrollNotification) {
- // var offset = notification.metrics.pixels;
- // print('滚动事件 offset $offset');
- }
- return true;
- },
- ),
- );
- }
-
- hideKeyBoard() {
- _keyboardIndexProvider.changeSelectIndex(-1);
- }
-
- readOnly() {
- _keyboardIndexProvider.changeReadOnlyKey(true);
- }
-
- sendMsg(MsgModel msg) {
-
-
- print('对方是否拉黑你 ${friendInfo.isBlackened}');
- if (BlacklistMgr.isBlack(friendInfo.userId)) {
- return;
- }
- print('chat page session id:${msg.sessionId}');
- if (!friendInfo.isCanStrangerNews &&
- !FriendListMgr().isMyFriend(friendInfo.userId)) {
- showToast(I18n.of(context).stranger_close_tips);
- return;
- }
-
- MsgHandler.insertMsgToDB(msg);
- MsgHandler.sendChatMsg(msg);
- if (mounted) {
- setState(() {});
- itemScrollController.jumpTo(index: 0);
- }
- }
-
- MsgModel msg;
- int count = 0;
-
- testBig(MsgModel msg) async {
- for (int k = 0; k < 100; k++) {
- msg.msgContent = utf8.encode('测试$count');
- Int64 time = Int64((DateTime.now()).millisecondsSinceEpoch);
- msg.time = time.toInt();
- MsgHandler.insertMsgToDB(msg);
- MsgHandler.sendChatMsg(msg);
- await Future.delayed(Duration(milliseconds: 500), () {});
- count++;
- }
- count = 0;
- print('发送完毕');
- showToast('发送完毕');
- }
-
- void receiveMsg(args) {
- if (mounted) {
- setState(() {});
- }
- }
-
- _deleteItem(msg) {
- MessageMgr().emit('Cancel Request', msg);
- print('#### 开始删除--');
- msgList.remove(msg);
- setState(() {});
- SqlUtil().deleteSigleRecordWith(msg.sessionId, msg.time);
- }
-
- Widget _buildItem(BuildContext context, int index) {
- var lastMsgTime;
- if (index < msgList.length - 1) {
- lastMsgTime = msgList[index + 1].time;
- }
-
- MsgModel msg = msgList[index];
- if (msg.time == jumpTime) {
- return WhiteOpacityAnim(
- key: Key(msg.time.toString()),
- 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);
- }
- }
- }
|