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

747 Zeilen
25 KiB

  1. import 'dart:async';
  2. import 'package:chat/data/UserData.dart';
  3. import 'package:chat/data/translate_hk_data_mgr.dart';
  4. import 'package:chat/models/group_info_model.dart';
  5. import 'package:chat/models/money_change.dart';
  6. import 'package:chat/utils/MessageMgr.dart';
  7. import 'package:chat/utils/msgHandler.dart';
  8. import 'package:chat/utils/screen.dart';
  9. import 'package:chat/utils/sp_utils.dart';
  10. import 'package:flutter/cupertino.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter/services.dart';
  13. import 'package:provider/provider.dart';
  14. import '../../data/constants.dart';
  15. import '../../generated/i18n.dart';
  16. import '../../r.dart';
  17. import '../../utils/CustomUI.dart';
  18. import 'package:chat/utils/PopUpMenu.dart' as myPop;
  19. class TranslationButlerPage extends StatefulWidget {
  20. final GroupInfoModel groupInfoModel;
  21. TranslationButlerPage({Key key, this.groupInfoModel}) : super(key: key);
  22. @override
  23. State<StatefulWidget> createState() {
  24. return TranslationButlerPageState();
  25. }
  26. }
  27. class ValueModel{
  28. String name;
  29. var key;
  30. ValueModel(this.name,this.key);
  31. }
  32. class TranslationButlerPageState extends State<TranslationButlerPage> {
  33. int curToLang = 1;
  34. int curSourceLang = UserData().language;
  35. int curScenes = 0;
  36. List<ValueModel> langList; ///语言列表
  37. List<ValueModel> scenesList; ///场景列表
  38. String extraMsg='';
  39. FocusNode focusNode = new FocusNode();
  40. String textLimitTips='';
  41. ScrollController _scrollController = new ScrollController();
  42. int orderStatus = 0; ///订单状态
  43. int secondsPassed = 1;///等待时间计数
  44. int timeStamp; ///订单开始时间戳
  45. Timer waitTimer;///等待时间计时器
  46. int time60=1; ///60秒一圈计数
  47. int waitNum=0;
  48. refreshOrder(args){
  49. orderStatus = TranslateHKMgr().orderStatus;
  50. switch(orderStatus){
  51. case TranslateHKMgr.ORDER_STATUS_EMPTY:
  52. isCreatingOrder=false;
  53. waitTimer?.cancel();
  54. secondsPassed = 0;
  55. SPUtils.save(Constants.TranslationHelper,null);
  56. break;
  57. case TranslateHKMgr.ORDER_STATUS_WAITING:
  58. secondsPassed = 0;
  59. waitNum = TranslateHKMgr().waitNum;
  60. waitTimer = Timer.periodic(Duration(seconds: 1), (Timer t) {
  61. handleTick();
  62. });
  63. break;
  64. }
  65. setState(() {});
  66. }
  67. @override
  68. void initState() {
  69. super.initState();
  70. orderStatus = TranslateHKMgr().orderStatus;
  71. waitNum = TranslateHKMgr().waitNum;
  72. initData();
  73. MessageMgr().on(MessageMgr.TRANSLATE_HK_REFRESH_ORDER, refreshOrder);
  74. WidgetsBinding.instance.addPostFrameCallback((_) {
  75. // Future.delayed(Duration(seconds: 1), () {
  76. //// CustomUI.buildTranslationHelperOrderDialog(context,true);
  77. // Navigator.of(context).push(
  78. // new MaterialPageRoute(
  79. // builder: (context) {
  80. // return ChatPage(
  81. // key: Key('Chat'),
  82. // friendId: 100029,
  83. // isTranslateButler: true,
  84. // );
  85. // },
  86. // ),
  87. // );
  88. // });
  89. });
  90. }
  91. initData() async {
  92. String time = (await SPUtils.get(Constants.TranslationHelper));
  93. if (time != null) {
  94. print('time:$time');
  95. int second = int.parse(time) ~/ 1000;
  96. if((DateTime.now().millisecondsSinceEpoch ~/ 1000 - second)>8*3600){ ///超过5小时清除缓存记录
  97. SPUtils.save(Constants.TranslationHelper,null);
  98. return;
  99. }
  100. secondsPassed =
  101. ((DateTime.now().millisecondsSinceEpoch ~/ 1000 - second));
  102. } else {
  103. print('time: null');
  104. }
  105. }
  106. bool isCreatingOrder=false;
  107. apply() {
  108. if(isCreatingOrder){
  109. return;
  110. }
  111. isCreatingOrder=true;
  112. MsgHandler.sendCreateTranslateOrder(langList[curSourceLang].key,langList[curToLang].key,scenesList[curScenes].key,extraMsg);
  113. extraMsg='';
  114. }
  115. @override
  116. void didChangeDependencies() {
  117. super.didChangeDependencies();
  118. textLimitTips = I18n.of(context).translation_input_limit.replaceAll('/s1', '80');
  119. langList = [
  120. ValueModel(I18n.of(context).english,1),
  121. ValueModel(I18n.of(context).Vietnamese,2),
  122. ValueModel(I18n.of(context).traditional_Chinese,4),
  123. ValueModel(I18n.of(context).Simplified_Chinese,8),
  124. ValueModel(I18n.of(context).Korean,16),
  125. ValueModel(I18n.of(context).Japanese,32),
  126. ];
  127. scenesList = [
  128. ValueModel(I18n.of(context).translation_scenes_1,0),
  129. ValueModel(I18n.of(context).translation_scenes_2,1),
  130. ValueModel(I18n.of(context).translation_scenes_3,2),
  131. ValueModel(I18n.of(context).translation_scenes_4,3),
  132. ];
  133. }
  134. @override
  135. void dispose() {
  136. waitTimer?.cancel();
  137. MessageMgr().off(MessageMgr.TRANSLATE_HK_REFRESH_ORDER, refreshOrder);
  138. if (orderStatus==TranslateHKMgr.ORDER_STATUS_WAITING && timeStamp != null) {
  139. print('保存时间戳$timeStamp');
  140. SPUtils.save(Constants.TranslationHelper, timeStamp.toString());
  141. }
  142. super.dispose();
  143. }
  144. _langPopMenu(bool isSource) {
  145. var curIndex = isSource ? curSourceLang : curToLang;
  146. return myPop.PopupMenuButton(
  147. child: Container(
  148. height: 37,
  149. width: double.maxFinite,
  150. decoration: BoxDecoration(
  151. color: Color(0xffD3E7FF),
  152. borderRadius: BorderRadius.circular(5)),
  153. child: Row(
  154. mainAxisAlignment: MainAxisAlignment.start,
  155. children: <Widget>[
  156. Expanded(
  157. child: Container(padding: EdgeInsets.only(left: 5),alignment: Alignment.center,child: Text(
  158. langList[curIndex].name,
  159. textAlign: TextAlign.center,
  160. overflow: TextOverflow.ellipsis,
  161. textScaleFactor: 1.0,
  162. style: TextStyle(color: Color(0xff4A5E76), fontSize: 14),
  163. ),)),
  164. Icon(IconData(0xe63b, fontFamily: Constants.IconFontFamily),
  165. size: 30, color: Color(0xff4A5E76))
  166. ],
  167. ),
  168. ),
  169. offset: Offset(0, 100),
  170. onSelected: (int index) {
  171. if (curIndex != index) {
  172. if (isSource) {
  173. curSourceLang = index;
  174. } else {
  175. curToLang = index;
  176. }
  177. print('更换翻译语言');
  178. setState(() {});
  179. }
  180. },
  181. itemBuilder: (BuildContext context) {
  182. return List<myPop.PopupMenuItem<int>>.generate(langList.length,
  183. (int i) {
  184. return myPop.PopupMenuItem(
  185. child: Container(
  186. alignment: Alignment.center,
  187. color: Colors.white,
  188. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
  189. child: Text(langList[i].name,
  190. textScaleFactor: 1.0,
  191. maxLines: 1,
  192. style: TextStyle(
  193. color: i == curIndex
  194. ? Colors.blueAccent
  195. : Color(AppColors.AppBarColor),
  196. fontSize: 14)),
  197. ),
  198. value: i,
  199. );
  200. });
  201. });
  202. }
  203. _scenesPopMenu() {
  204. var curIndex = curScenes;
  205. return myPop.PopupMenuButton(
  206. child: Container(
  207. height: 40,
  208. width: double.maxFinite,
  209. decoration:BoxDecoration(
  210. borderRadius: BorderRadius.all(Radius.circular(6)),
  211. color: Colors.white,
  212. boxShadow: [
  213. BoxShadow(
  214. color: Color(0x739f9f9f),
  215. offset: Offset(0.2, 0.4),
  216. blurRadius: 1.0,
  217. spreadRadius: 0.6),
  218. // BoxShadow(
  219. // color: Color(0x9900FF00), offset: Offset(1.0, 1.0)),
  220. // BoxShadow(color: Color(0xFF0000FF))
  221. ]),
  222. child: Row(
  223. mainAxisAlignment: MainAxisAlignment.start,
  224. children: <Widget>[
  225. Expanded(
  226. child: Text(
  227. scenesList[curIndex].name,
  228. textAlign: TextAlign.center,
  229. overflow: TextOverflow.ellipsis,
  230. textScaleFactor: 1.0,
  231. style: TextStyle(color: Color(0xff3875E9), fontSize: 14),
  232. )),
  233. Icon(IconData(0xe63b, fontFamily: Constants.IconFontFamily),
  234. size: 30, color: Color(0xff4A5E76))
  235. ],
  236. ),
  237. ),
  238. offset: Offset(0, 100),
  239. onSelected: (int index) {
  240. if (curIndex != index) {
  241. curScenes = index;
  242. print('更换场景');
  243. setState(() {});
  244. }
  245. },
  246. itemBuilder: (BuildContext context) {
  247. return List<myPop.PopupMenuItem<int>>.generate(scenesList.length,
  248. (int i) {
  249. return myPop.PopupMenuItem(
  250. child: Container(
  251. width: Screen.width *0.43,
  252. alignment: Alignment.center,
  253. color: Colors.white,
  254. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
  255. child: Text(scenesList[i].name,
  256. textScaleFactor: 1.0,
  257. maxLines: 1,
  258. style: TextStyle(
  259. color: i == curIndex
  260. ? Colors.blueAccent
  261. : Color(AppColors.AppBarColor),
  262. fontSize: 14)),
  263. ),
  264. value: i,
  265. );
  266. });
  267. });
  268. }
  269. @override
  270. Widget build(BuildContext context) {
  271. Widget appBar = AppBar(
  272. backgroundColor: AppColors.NewAppbarBgColor,
  273. title: Text(
  274. I18n.of(context).translation_butler,
  275. textScaleFactor: 1.0,
  276. style: TextStyle(color: AppColors.NewAppbarTextColor),
  277. ),
  278. // leading: CustomUI.buildCustomLeading(context),
  279. centerTitle: true,
  280. actions: <Widget>[
  281. Container(
  282. child: CustomUI.buildImageLabel(R.assetsImagesCoin,
  283. Provider.of<MoneyChangeProvider>(context).money,
  284. isLeft: true),
  285. decoration: BoxDecoration(borderRadius: BorderRadius.circular(15)),
  286. ),
  287. SizedBox(
  288. width: 10,
  289. )
  290. ],
  291. );
  292. return Scaffold(
  293. appBar: appBar,
  294. body: SafeArea(
  295. child: Container(
  296. color: Color(0xffE8EAF0),
  297. child: orderStatus==TranslateHKMgr.ORDER_STATUS_EMPTY ? createOrderPage() : waitPage(),
  298. ),
  299. ),
  300. );
  301. }
  302. Widget createOrderPage() {
  303. return ListView(
  304. controller: _scrollController,
  305. children: <Widget>[
  306. Padding(
  307. padding: EdgeInsets.only(left: 20, right: 10, top: 15),
  308. child: Text(
  309. I18n.of(context).translation_butler_tips,
  310. textScaleFactor: 1.0,
  311. style: TextStyle(color: Color(0xffABABAB), fontSize: 13),
  312. ),
  313. ),
  314. Container(
  315. margin: EdgeInsets.all(10),
  316. child: Card(
  317. elevation: 2, // 阴影
  318. shape: RoundedRectangleBorder(
  319. borderRadius: BorderRadius.circular(10),
  320. // side: BorderSide(color: Colors.green,width: 25),
  321. ),
  322. child: Container(
  323. padding: EdgeInsets.all(10),
  324. child: Column(
  325. crossAxisAlignment: CrossAxisAlignment.start,
  326. children: <Widget>[
  327. Padding(
  328. padding: EdgeInsets.only(bottom: 12),
  329. child: Text(
  330. I18n.of(context).choose_language,
  331. textScaleFactor: 1.0,
  332. textAlign: TextAlign.left,
  333. style: TextStyle(
  334. color: AppColors.NewAppbarTextColor, fontSize: 17),
  335. ),
  336. ),
  337. Row(
  338. children: <Widget>[
  339. SizedBox(width: 15,),
  340. Expanded(
  341. child: _langPopMenu(true),
  342. flex: 5,
  343. ),
  344. Expanded(
  345. child: InkWell(
  346. onTap: () {
  347. var temp = curSourceLang;
  348. curSourceLang = curToLang;
  349. curToLang = temp;
  350. setState(() {});
  351. },
  352. child: Container(
  353. child: Icon(
  354. IconData(
  355. 0xe669,
  356. fontFamily: Constants.IconFontFamily,
  357. ),
  358. size: 24,
  359. color: Color(0xff4A5E76),
  360. ),
  361. padding: EdgeInsets.symmetric(
  362. vertical: 5, horizontal: 5),
  363. ),
  364. ),
  365. flex: 2,
  366. ),
  367. Expanded(
  368. child: _langPopMenu(false),
  369. flex: 5,
  370. ),
  371. SizedBox(width: 15,),
  372. ],
  373. ),
  374. Row(
  375. children: <Widget>[
  376. Expanded(
  377. child: Image.asset(
  378. R.assetsImagesImgTranslationIcon,
  379. width: 195,
  380. height: 175,
  381. ),
  382. flex: 4,
  383. ),
  384. Expanded(
  385. child: Column(
  386. children: <Widget>[
  387. Text(
  388. I18n.of(context).translation_butler_scenes,
  389. textScaleFactor: 1.0,
  390. textAlign: TextAlign.left,
  391. style: TextStyle(
  392. color: AppColors.NewAppbarTextColor,
  393. fontWeight: FontWeight.w700,
  394. fontSize: 15),
  395. ),
  396. SizedBox(height: 10,),
  397. _scenesPopMenu(),
  398. ],
  399. ),
  400. flex: 6,
  401. )
  402. ],
  403. ),
  404. Stack(children: <Widget>[
  405. Container(
  406. alignment: Alignment.topLeft,
  407. height: 110.5,
  408. padding: EdgeInsets.only(bottom: 10),
  409. decoration: BoxDecoration(
  410. color: Color(0xFFE9EEF4),
  411. borderRadius: BorderRadius.all(Radius.circular(10))),
  412. child: TextField(
  413. keyboardAppearance: Brightness.light,
  414. maxLines: 10,
  415. focusNode: focusNode,
  416. textInputAction: TextInputAction.done,
  417. onSubmitted: (input) {
  418. focusNode.unfocus();
  419. },
  420. decoration: new InputDecoration(
  421. hintText: I18n.of(context).translation_more_desc,
  422. hintStyle: TextStyle(fontSize: 14),
  423. border: InputBorder.none,
  424. ),
  425. // maxLines: 1,
  426. inputFormatters: [LengthLimitingTextInputFormatter(80)],
  427. // obscureText: true,
  428. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  429. onChanged: (str) {
  430. if (_scrollController != null) {
  431. ///解决键盘遮挡输入框
  432. _scrollController.position.moveTo(
  433. 200,
  434. duration: Duration(milliseconds: 100),
  435. curve: Curves.easeIn,
  436. );
  437. }
  438. extraMsg = str;
  439. textLimitTips = I18n.of(context).translation_input_limit.replaceAll('/s1', (80-str.length).toString());
  440. setState(() {});
  441. },
  442. ),
  443. ),
  444. Positioned.fill(child: Container(padding: EdgeInsets.only(bottom: 5,right: 5),alignment: Alignment.bottomRight,child: Text(
  445. textLimitTips,
  446. textScaleFactor: 1.0,
  447. style: TextStyle(color: Color(0xFF95A3B2), fontSize: 11),
  448. ),)),
  449. ],),
  450. Padding(padding: EdgeInsets.only(left: 5,right: 5,top: 5,bottom: 8),child: Text(
  451. I18n.of(context).translation_butler_scenes_tips,
  452. textScaleFactor: 1.0,
  453. style: TextStyle(color: Color(0xFFFA7B3D), fontSize: 12),
  454. ),),
  455. ],
  456. ),
  457. ),
  458. ),
  459. ),
  460. Container(
  461. margin: EdgeInsets.only(left: 70, right: 70, top: 50),
  462. height: 47,
  463. child: RaisedButton(
  464. color: Color(0xff3875E9),
  465. shape: RoundedRectangleBorder(
  466. borderRadius: BorderRadius.all(Radius.circular(10))),
  467. child: Text(
  468. I18n.of(context).translation_butler_call + ' (50h)',
  469. textScaleFactor: 1.0,
  470. style: TextStyle(color: Colors.white, fontSize: 19),
  471. ),
  472. onPressed: () {
  473. timeStamp = DateTime.now().millisecondsSinceEpoch;
  474. apply();
  475. }),
  476. ),
  477. Container(
  478. width: double.maxFinite,
  479. alignment: Alignment.center,
  480. padding: EdgeInsets.only(left: 10, right: 10, top: 15,bottom: 20),
  481. child: Text(
  482. I18n.of(context).translation_butler_rules,
  483. textScaleFactor: 1.0,
  484. style: TextStyle(color: Color(0xffABABAB), fontSize: 13),
  485. ),
  486. ),
  487. ],
  488. );
  489. }
  490. Widget waitPage() {
  491. // ~/ 取整操作
  492. int seconds = secondsPassed % 60;
  493. int minutes = secondsPassed ~/ 60;
  494. return ListView(
  495. children: <Widget>[
  496. ///当前排队人数过多。。。
  497. Container(
  498. margin: EdgeInsets.all(10),
  499. child: Card(
  500. elevation: 2, // 阴影
  501. shape: RoundedRectangleBorder(
  502. borderRadius: BorderRadius.circular(10),
  503. // side: BorderSide(color: Colors.green,width: 25),
  504. ),
  505. child: Container(
  506. // width: double.maxFinite,
  507. // color: Colors.blue,
  508. padding: EdgeInsets.fromLTRB(14, 14, 14, 22),
  509. child: Column(
  510. children: <Widget>[
  511. Padding(
  512. padding: EdgeInsets.only(bottom: 20, top: 10),
  513. child: Text(
  514. I18n.of(context).translation_butler_tips2,
  515. textScaleFactor: 1.0,
  516. textAlign: TextAlign.left,
  517. style: TextStyle(color: Color(0xff797979), fontSize: 13),
  518. ),
  519. ),
  520. Container(
  521. width: double.maxFinite,
  522. child: Row(
  523. mainAxisSize: MainAxisSize.max,
  524. mainAxisAlignment: MainAxisAlignment.spaceAround,
  525. children: <Widget>[
  526. Column(
  527. mainAxisAlignment: MainAxisAlignment.center,
  528. children: <Widget>[
  529. fixedText(
  530. I18n.of(context).translation_butler_wait_people,
  531. fontSize: 16,
  532. color: Colors.black),
  533. SizedBox(
  534. height: 10,
  535. ),
  536. RichText(
  537. maxLines: 3,
  538. textAlign: TextAlign.center,
  539. text: TextSpan(children: [
  540. TextSpan(
  541. text: '$waitNum',
  542. style: TextStyle(
  543. color: Color(0xffFF1010),
  544. fontSize: 27)),
  545. TextSpan(
  546. text: ' ' +
  547. I18n.of(context)
  548. .translation_butler_wait_people_unit,
  549. style: TextStyle(
  550. color: Colors.black, fontSize: 17)),
  551. ]))
  552. ],
  553. ),
  554. Container(
  555. width: 1,
  556. height: 65,
  557. color: Color(0xffD8D8D8),
  558. ),
  559. Column(
  560. mainAxisAlignment: MainAxisAlignment.center,
  561. children: <Widget>[
  562. fixedText(
  563. I18n.of(context).translation_butler_wait_time,
  564. fontSize: 16,
  565. color: Colors.black),
  566. SizedBox(
  567. height: 10,
  568. ),
  569. RichText(
  570. maxLines: 3,
  571. textAlign: TextAlign.center,
  572. text: TextSpan(children: [
  573. TextSpan(
  574. text: '${waitNum*5}',
  575. style: TextStyle(
  576. color: Color(0xff3875E9),
  577. fontSize: 27)),
  578. TextSpan(
  579. text: ' ' + I18n.of(context).minute,
  580. style: TextStyle(
  581. color: Colors.black, fontSize: 17)),
  582. ]))
  583. ],
  584. ),
  585. ],
  586. ),
  587. )
  588. ],
  589. ),
  590. ),
  591. ),
  592. ),
  593. Padding(
  594. padding: EdgeInsets.only(left: 20, right: 10, top: 5, bottom: 10),
  595. child: Text(
  596. I18n.of(context).translation_butler_tips3,
  597. textScaleFactor: 1.0,
  598. style: TextStyle(color: Colors.black, fontSize: 18),
  599. ),
  600. ),
  601. Stack(
  602. alignment: Alignment.center,
  603. children: <Widget>[
  604. UnconstrainedBox(
  605. child: Container(
  606. //限制进度条的高度
  607. height: 190.0,
  608. //限制进度条的宽度
  609. width: 190.0,
  610. child: CircularProgressIndicator(
  611. //0~1的浮点数,用来表示进度多少;如果 value 为 null 或空,则显示一个动画,否则显示一个定值
  612. value: time60/60,
  613. strokeWidth: 5,
  614. //背景颜色
  615. backgroundColor: Color(0xffB2B2B2),
  616. //进度颜色
  617. valueColor:
  618. AlwaysStoppedAnimation<Color>(Color(0xff3875E9))),
  619. ),
  620. ),
  621. Column(
  622. children: <Widget>[
  623. Text(
  624. I18n.of(context).translation_butler_already_wait,
  625. textScaleFactor: 1.0,
  626. style: TextStyle(color: Colors.black, fontSize: 19),
  627. ),
  628. SizedBox(
  629. height: 10,
  630. ),
  631. Text(
  632. getFull(minutes) + ' : ' + getFull(seconds),
  633. textScaleFactor: 1.0,
  634. style: TextStyle(color: Color(0xffFF1010), fontSize: 35),
  635. )
  636. ],
  637. )
  638. ],
  639. ),
  640. Container(
  641. margin: EdgeInsets.only(left: 70, right: 70, top: 50),
  642. height: 47,
  643. child: RaisedButton(
  644. color: Color(0xff3875E9),
  645. shape: RoundedRectangleBorder(
  646. borderRadius: BorderRadius.all(Radius.circular(10))),
  647. child: Text(
  648. I18n.of(context).translation_butler_cancel,
  649. textScaleFactor: 1.0,
  650. style: TextStyle(color: Colors.white, fontSize: 19),
  651. ),
  652. onPressed: cancelOrder ),
  653. ),
  654. ],
  655. );
  656. }
  657. void cancelOrder()async {
  658. await SPUtils.save(Constants.TranslationHelper, null);
  659. setState(() {
  660. TranslateHKMgr().orderStatus = TranslateHKMgr.ORDER_STATUS_EMPTY;
  661. refreshOrder(null);
  662. MsgHandler.sendCancelTranslateOrder();
  663. });
  664. }
  665. void handleTick() {
  666. setState(() {
  667. secondsPassed = secondsPassed + 1; //需要更新UI
  668. time60=time60+1;
  669. if(time60==60){
  670. time60=0;
  671. }
  672. });
  673. }
  674. getFull(int sec) {
  675. return sec < 10 ? '0$sec' : '$sec';
  676. }
  677. }