Hibok
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

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