import 'dart:async'; import 'package:chat/data/UserData.dart'; import 'package:chat/data/translate_hk_data_mgr.dart'; import 'package:chat/models/group_info_model.dart'; import 'package:chat/models/money_change.dart'; import 'package:chat/utils/MessageMgr.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:provider/provider.dart'; import '../../data/constants.dart'; import '../../generated/i18n.dart'; import '../../r.dart'; import '../../utils/CustomUI.dart'; import 'package:chat/utils/PopUpMenu.dart' as myPop; class TranslationButlerPage extends StatefulWidget { final GroupInfoModel groupInfoModel; TranslationButlerPage({Key key, this.groupInfoModel}) : super(key: key); @override State createState() { return TranslationButlerPageState(); } } class ValueModel{ String name; var key; ValueModel(this.name,this.key); } class TranslationButlerPageState extends State { int curToLang = 1; int curSourceLang = UserData().language; int curScenes = 0; List langList; ///语言列表 List scenesList; ///场景列表 String extraMsg=''; FocusNode focusNode = new FocusNode(); String textLimitTips=''; ScrollController _scrollController = new ScrollController(); int orderStatus = 0; ///订单状态 int secondsPassed = 1;///等待时间计数 int timeStamp; ///订单开始时间戳 Timer waitTimer;///等待时间计时器 int time60=1; ///60秒一圈计数 int waitNum=0; refreshOrder(args){ orderStatus = TranslateHKMgr().orderStatus; switch(orderStatus){ case TranslateHKMgr.ORDER_STATUS_EMPTY: isCreatingOrder=false; waitTimer?.cancel(); secondsPassed = 0; SPUtils.save(Constants.TranslationHelper,null); break; case TranslateHKMgr.ORDER_STATUS_WAITING: // secondsPassed = 0; print('开始倒计时$secondsPassed'); waitNum = TranslateHKMgr().waitNum; waitTimer = Timer.periodic(Duration(seconds: 1), (Timer t) { handleTick(); }); break; } setState(() {}); } ///订单没有人接,超时,服务器会发送取消订单通知 canceledOrder(args){ TranslateHKMgr().orderStatus = TranslateHKMgr.ORDER_STATUS_EMPTY; refreshOrder(null); } @override void initState() { super.initState(); orderStatus = TranslateHKMgr().orderStatus; waitNum = TranslateHKMgr().waitNum; initData(); MessageMgr().on(MessageMgr.TRANSLATE_HK_REFRESH_ORDER, refreshOrder); MessageMgr().on(MessageMgr.TRANSLATE_HK_CANCEL_ORDER, canceledOrder); WidgetsBinding.instance.addPostFrameCallback((_) { // Future.delayed(Duration(seconds: 1), () { //// CustomUI.buildTranslationHelperOrderDialog(context,true); // Navigator.of(context).push( // new MaterialPageRoute( // builder: (context) { // return ChatPage( // key: Key('Chat'), // friendId: 100029, // isTranslateButler: true, // ); // }, // ), // ); // }); }); } initData() async { String time = (await SPUtils.get(Constants.TranslationHelper)); if (time != null) { print('time:$time'); int second = int.parse(time) ~/ 1000; if((DateTime.now().millisecondsSinceEpoch ~/ 1000 - second)>1800){ ///超过半小时清除缓存记录 SPUtils.save(Constants.TranslationHelper,null); return; } secondsPassed = ((DateTime.now().millisecondsSinceEpoch ~/ 1000 - second)); refreshOrder(null); print('缓存的秒数 $secondsPassed'); } else { print('time: null'); } } bool isCreatingOrder=false; apply() { if(isCreatingOrder){ return; } isCreatingOrder=true; TranslateHKMgr().startWaitTime=DateTime.now().millisecondsSinceEpoch; MsgHandler.sendCreateTranslateOrder(langList[curSourceLang].key,langList[curToLang].key,scenesList[curScenes].key,extraMsg); extraMsg=''; } @override void didChangeDependencies() { super.didChangeDependencies(); textLimitTips = I18n.of(context).translation_input_limit.replaceAll('/s1', '80'); langList = [ ValueModel(I18n.of(context).english,1), ValueModel(I18n.of(context).Vietnamese,2), ValueModel(I18n.of(context).traditional_Chinese,4), ValueModel(I18n.of(context).Simplified_Chinese,8), ValueModel(I18n.of(context).Korean,16), ValueModel(I18n.of(context).Japanese,32), ]; scenesList = [ ValueModel(I18n.of(context).translation_scenes_1,0), ValueModel(I18n.of(context).translation_scenes_2,1), ValueModel(I18n.of(context).translation_scenes_3,2), ValueModel(I18n.of(context).translation_scenes_4,3), ]; } @override void dispose() { waitTimer?.cancel(); MessageMgr().off(MessageMgr.TRANSLATE_HK_REFRESH_ORDER, refreshOrder); MessageMgr().off(MessageMgr.TRANSLATE_HK_CANCEL_ORDER, canceledOrder); if (orderStatus==TranslateHKMgr.ORDER_STATUS_WAITING && timeStamp != null) { print('保存时间戳$timeStamp'); SPUtils.save(Constants.TranslationHelper, timeStamp.toString()); } super.dispose(); } _langPopMenu(bool isSource) { var curIndex = isSource ? curSourceLang : curToLang; return myPop.PopupMenuButton( child: Container( height: 37, width: double.maxFinite, decoration: BoxDecoration( color: Color(0xffD3E7FF), borderRadius: BorderRadius.circular(5)), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Container(padding: EdgeInsets.only(left: 5),alignment: Alignment.center,child: Text( langList[curIndex].name, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, textScaleFactor: 1.0, style: TextStyle(color: Color(0xff4A5E76), fontSize: 14), ),)), Icon(IconData(0xe63b, fontFamily: Constants.IconFontFamily), size: 30, color: Color(0xff4A5E76)) ], ), ), offset: Offset(0, 100), onSelected: (int index) { if (curIndex != index) { if (isSource) { curSourceLang = index; } else { curToLang = index; } print('更换翻译语言'); setState(() {}); } }, itemBuilder: (BuildContext context) { return List>.generate(langList.length, (int i) { return myPop.PopupMenuItem( child: Container( alignment: Alignment.center, color: Colors.white, padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), child: Text(langList[i].name, textScaleFactor: 1.0, maxLines: 1, style: TextStyle( color: i == curIndex ? Colors.blueAccent : Color(AppColors.AppBarColor), fontSize: 14)), ), value: i, ); }); }); } _scenesPopMenu() { var curIndex = curScenes; return myPop.PopupMenuButton( child: Container( height: 40, width: double.maxFinite, decoration:BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(6)), color: Colors.white, boxShadow: [ BoxShadow( color: Color(0x739f9f9f), offset: Offset(0.2, 0.4), blurRadius: 1.0, spreadRadius: 0.6), // BoxShadow( // color: Color(0x9900FF00), offset: Offset(1.0, 1.0)), // BoxShadow(color: Color(0xFF0000FF)) ]), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Text( scenesList[curIndex].name, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, textScaleFactor: 1.0, style: TextStyle(color: Color(0xff3875E9), fontSize: 14), )), Icon(IconData(0xe63b, fontFamily: Constants.IconFontFamily), size: 30, color: Color(0xff4A5E76)) ], ), ), offset: Offset(0, 100), onSelected: (int index) { if (curIndex != index) { curScenes = index; print('更换场景'); setState(() {}); } }, itemBuilder: (BuildContext context) { return List>.generate(scenesList.length, (int i) { return myPop.PopupMenuItem( child: Container( width: Screen.width *0.43, alignment: Alignment.center, color: Colors.white, padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), child: Text(scenesList[i].name, textScaleFactor: 1.0, maxLines: 1, style: TextStyle( color: i == curIndex ? Colors.blueAccent : Color(AppColors.AppBarColor), fontSize: 14)), ), value: i, ); }); }); } @override Widget build(BuildContext context) { Widget appBar = AppBar( backgroundColor: AppColors.NewAppbarBgColor, title: Text( I18n.of(context).translation_butler, textScaleFactor: 1.0, style: TextStyle(color: AppColors.NewAppbarTextColor), ), // leading: CustomUI.buildCustomLeading(context), centerTitle: true, actions: [ Container( child: CustomUI.buildImageLabel(R.assetsImagesCoin, Provider.of(context).money, isLeft: true), decoration: BoxDecoration(borderRadius: BorderRadius.circular(15)), ), SizedBox( width: 10, ) ], ); return Scaffold( appBar: appBar, body: SafeArea( child: Container( color: Color(0xffE8EAF0), child: orderStatus==TranslateHKMgr.ORDER_STATUS_EMPTY ? createOrderPage() : waitPage(), ), ), ); } Widget createOrderPage() { return ListView( controller: _scrollController, children: [ Padding( padding: EdgeInsets.only(left: 20, right: 10, top: 15), child: Row(children: [ Expanded(child: Text( I18n.of(context).translation_butler_tips, textScaleFactor: 1.0, style: TextStyle(color: Color(0xffABABAB), fontSize: 13), )), InkWell(child: Container( width: 40,height: 40,child: Align(child: Icon( IconData(0xe681, fontFamily: Constants.IconFontFamily), color: Color(0xFFFF7E00), size: 28.0, ),alignment: Alignment.center,),),onTap: (){ CustomUI.buildTip(context, I18n.of(context).translation_butler, Padding(padding: EdgeInsets.all(10),child: fixedText(I18n.of(context).translation_butler_introduction,fontSize: 14),)); },) ],), ) , Container( margin: EdgeInsets.all(10), child: Card( elevation: 2, // 阴影 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), // side: BorderSide(color: Colors.green,width: 25), ), child: Container( padding: EdgeInsets.all(10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(bottom: 12), child: Text( I18n.of(context).choose_language, textScaleFactor: 1.0, textAlign: TextAlign.left, style: TextStyle( color: AppColors.NewAppbarTextColor, fontSize: 17), ), ), Row( children: [ SizedBox(width: 15,), Expanded( child: _langPopMenu(true), flex: 5, ), Expanded( child: InkWell( onTap: () { var temp = curSourceLang; curSourceLang = curToLang; curToLang = temp; setState(() {}); }, child: Container( child: Icon( IconData( 0xe669, fontFamily: Constants.IconFontFamily, ), size: 24, color: Color(0xff4A5E76), ), padding: EdgeInsets.symmetric( vertical: 5, horizontal: 5), ), ), flex: 2, ), Expanded( child: _langPopMenu(false), flex: 5, ), SizedBox(width: 15,), ], ), Row( children: [ Expanded( child: Image.asset( R.assetsImagesImgTranslationIcon, width: 195, height: 175, ), flex: 4, ), Expanded( child: Column( children: [ Text( I18n.of(context).translation_butler_scenes, textScaleFactor: 1.0, textAlign: TextAlign.left, style: TextStyle( color: AppColors.NewAppbarTextColor, fontWeight: FontWeight.w700, fontSize: 15), ), SizedBox(height: 10,), _scenesPopMenu(), ], ), flex: 6, ) ], ), Stack(children: [ Container( alignment: Alignment.topLeft, height: 110.5, padding: EdgeInsets.only(bottom: 10), decoration: BoxDecoration( color: Color(0xFFE9EEF4), borderRadius: BorderRadius.all(Radius.circular(10))), child: TextField( keyboardAppearance: Brightness.light, maxLines: 10, focusNode: focusNode, textInputAction: TextInputAction.done, onSubmitted: (input) { focusNode.unfocus(); }, decoration: new InputDecoration( hintText: I18n.of(context).translation_more_desc, hintStyle: TextStyle(fontSize: 14), border: InputBorder.none, ), // maxLines: 1, inputFormatters: [LengthLimitingTextInputFormatter(80)], // obscureText: true, style: TextStyle(textBaseline: TextBaseline.alphabetic), onChanged: (str) { if (_scrollController != null) { ///解决键盘遮挡输入框 _scrollController.position.moveTo( 200, duration: Duration(milliseconds: 100), curve: Curves.easeIn, ); } extraMsg = str; textLimitTips = I18n.of(context).translation_input_limit.replaceAll('/s1', (80-str.length).toString()); setState(() {}); }, ), ), Positioned.fill(child: Container(padding: EdgeInsets.only(bottom: 5,right: 5),alignment: Alignment.bottomRight,child: Text( textLimitTips, textScaleFactor: 1.0, style: TextStyle(color: Color(0xFF95A3B2), fontSize: 11), ),)), ],), Padding(padding: EdgeInsets.only(left: 5,right: 5,top: 5,bottom: 8),child: Text( I18n.of(context).translation_butler_scenes_tips, textScaleFactor: 1.0, style: TextStyle(color: Color(0xFFFA7B3D), fontSize: 12), ),), ], ), ), ), ), Container( margin: EdgeInsets.only(left: 70, right: 70, top: 50), height: 47, child: RaisedButton( color: Color(0xff3875E9), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10))), child: Text( I18n.of(context).translation_butler_call + ' (50h)', textScaleFactor: 1.0, style: TextStyle(color: Colors.white, fontSize: 19), ), onPressed: () { timeStamp = DateTime.now().millisecondsSinceEpoch; apply(); }), ), Container( width: double.maxFinite, alignment: Alignment.center, padding: EdgeInsets.only(left: 10, right: 10, top: 15,bottom: 20), child: Text( I18n.of(context).translation_butler_rules, textScaleFactor: 1.0, style: TextStyle(color: Color(0xffABABAB), fontSize: 13), ), ), ], ); } Widget waitPage() { // ~/ 取整操作 int seconds = secondsPassed % 60; int minutes = secondsPassed ~/ 60; return ListView( children: [ ///当前排队人数过多。。。 Container( margin: EdgeInsets.all(10), child: Card( elevation: 2, // 阴影 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), // side: BorderSide(color: Colors.green,width: 25), ), child: Container( // width: double.maxFinite, // color: Colors.blue, padding: EdgeInsets.fromLTRB(14, 14, 14, 22), child: Column( children: [ Padding( padding: EdgeInsets.only(bottom: 20, top: 10), child: Text( I18n.of(context).translation_butler_tips2, textScaleFactor: 1.0, textAlign: TextAlign.left, style: TextStyle(color: Color(0xff797979), fontSize: 13), ), ), Container( width: double.maxFinite, child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( mainAxisAlignment: MainAxisAlignment.center, children: [ fixedText( I18n.of(context).translation_butler_wait_people, fontSize: 16, color: Colors.black), SizedBox( height: 10, ), RichText( maxLines: 3, textAlign: TextAlign.center, text: TextSpan(children: [ TextSpan( text: '$waitNum', style: TextStyle( color: Color(0xffFF1010), fontSize: 27)), TextSpan( text: ' ' + I18n.of(context) .translation_butler_wait_people_unit, style: TextStyle( color: Colors.black, fontSize: 17)), ])) ], ), Container( width: 1, height: 65, color: Color(0xffD8D8D8), ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ fixedText( I18n.of(context).translation_butler_wait_time, fontSize: 16, color: Colors.black), SizedBox( height: 10, ), RichText( maxLines: 3, textAlign: TextAlign.center, text: TextSpan(children: [ TextSpan( text: '${waitNum*5}', style: TextStyle( color: Color(0xff3875E9), fontSize: 27)), TextSpan( text: ' ' + I18n.of(context).minute, style: TextStyle( color: Colors.black, fontSize: 17)), ])) ], ), ], ), ) ], ), ), ), ), Padding( padding: EdgeInsets.only(left: 20, right: 10, top: 5, bottom: 10), child: Text( I18n.of(context).translation_butler_tips3, textScaleFactor: 1.0, style: TextStyle(color: Colors.black, fontSize: 18), ), ), Stack( alignment: Alignment.center, children: [ UnconstrainedBox( child: Container( //限制进度条的高度 height: 190.0, //限制进度条的宽度 width: 190.0, child: CircularProgressIndicator( //0~1的浮点数,用来表示进度多少;如果 value 为 null 或空,则显示一个动画,否则显示一个定值 value: time60/60, strokeWidth: 5, //背景颜色 backgroundColor: Color(0xffB2B2B2), //进度颜色 valueColor: AlwaysStoppedAnimation(Color(0xff3875E9))), ), ), Column( children: [ Text( I18n.of(context).translation_butler_already_wait, textScaleFactor: 1.0, style: TextStyle(color: Colors.black, fontSize: 19), ), SizedBox( height: 10, ), Text( getFull(minutes) + ' : ' + getFull(seconds), textScaleFactor: 1.0, style: TextStyle(color: Color(0xffFF1010), fontSize: 35), ) ], ) ], ), Container( margin: EdgeInsets.only(left: 70, right: 70, top: 50), height: 47, child: RaisedButton( color: Color(0xff3875E9), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10))), child: Text( I18n.of(context).translation_butler_cancel, textScaleFactor: 1.0, style: TextStyle(color: Colors.white, fontSize: 19), ), onPressed: cancelOrder ), ), ], ); } void cancelOrder()async { await SPUtils.save(Constants.TranslationHelper, null); setState(() { time60=0; TranslateHKMgr().orderStatus = TranslateHKMgr.ORDER_STATUS_EMPTY; refreshOrder(null); MsgHandler.sendCancelTranslateOrder(); }); } void handleTick() { setState(() { secondsPassed = secondsPassed + 1; //需要更新UI time60=time60+1; if(time60==60){ time60=0; } }); } getFull(int sec) { return sec < 10 ? '0$sec' : '$sec'; } }