Hibok
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

1416 wiersze
54 KiB

  1. import 'dart:io';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:chat/data/UserData.dart';
  4. import 'package:chat/data/WebData.dart';
  5. import 'package:chat/data/constants.dart';
  6. import 'package:chat/generated/i18n.dart';
  7. import 'package:chat/home/VerificationCenter.dart';
  8. import 'package:chat/home/VipPage.dart';
  9. import 'package:chat/home/realtimehelper/translation_evaluation_dialog.dart';
  10. import 'package:chat/models/group_info_model.dart';
  11. import 'package:chat/photo/ui/dialog/not_permission_dialog.dart';
  12. import 'package:chat/utils/LoadingDialog.dart';
  13. import 'package:chat/utils/TokenMgr.dart';
  14. import 'package:chat/utils/msgHandler.dart';
  15. import 'package:chat/utils/screen.dart';
  16. import 'package:dio/dio.dart';
  17. import 'package:flutter/cupertino.dart';
  18. import 'package:flutter/material.dart';
  19. import 'package:flutter/painting.dart';
  20. import 'package:flutter/services.dart';
  21. import 'package:oktoast/oktoast.dart';
  22. import 'package:permission_handler/permission_handler.dart';
  23. import 'package:pull_to_refresh/pull_to_refresh.dart';
  24. import 'package:url_launcher/url_launcher.dart';
  25. import 'dart:ui' as ui;
  26. import '../r.dart';
  27. import 'HttpUtil.dart';
  28. import 'PicSwiper.dart';
  29. import 'TutorialOverlay.dart';
  30. import 'app_navigator.dart';
  31. import 'conversation_table.dart';
  32. import 'count_down_button.dart';
  33. class NoKeyboardEditableTextFocusNode extends FocusNode {
  34. // @override
  35. // bool consumeKeyboardToken() {
  36. // return false;
  37. // }
  38. }
  39. class CustomUI {
  40. static Widget buildPageLoading(
  41. BuildContext context, Widget content, bool isShow) {
  42. return Stack(
  43. children: <Widget>[
  44. content,
  45. isShow
  46. ? Scaffold(
  47. backgroundColor: Colors.transparent,
  48. body: LoadingDialog(),
  49. )
  50. : Container(),
  51. ],
  52. );
  53. }
  54. static void showContentDialog(
  55. BuildContext context, int programId, int replyId, int type, callback,
  56. {int replyUserId = 0,
  57. String replyUserName = '',
  58. bool isAd = false,
  59. bool isMyself = false}) {
  60. if (UserData().isMan() && !UserData().isVip && !isMyself) {
  61. CustomUI.buildOneConfirm(
  62. context, I18n.of(context).cant_comment, I18n.of(context).joinvip, () {
  63. Navigator.of(context).pop();
  64. Navigator.of(context).push(
  65. new MaterialPageRoute(
  66. builder: (context) {
  67. return VipPage();
  68. },
  69. ),
  70. );
  71. });
  72. return;
  73. }
  74. if (!UserData().isMan() && !UserData().basicInfo.isAttestation) {
  75. buildNotTrue(context);
  76. return;
  77. }
  78. Navigator.of(context).push(TutorialOverlay(
  79. child: Scaffold(
  80. backgroundColor: Constants.BlackTextColor.withOpacity(0.0),
  81. body: buildInput(context, programId, replyId, type, callback,
  82. replyUserId: replyUserId,
  83. replyUserName: replyUserName,
  84. isAd: isAd,
  85. isMyself: isMyself))));
  86. }
  87. static Widget buildInput(
  88. BuildContext context, int programId, int replyId, int type, callback,
  89. {int replyUserId = 0,
  90. String replyUserName = '',
  91. bool isAd: false,
  92. bool isMyself: false}) {
  93. print('replyUserName $replyUserName');
  94. var content = '';
  95. var hitStr = isMyself
  96. ? I18n.of(context).everyone_comment
  97. : I18n.of(context).your_comment;
  98. Widget input = Container(
  99. alignment: Alignment.topCenter,
  100. padding: EdgeInsets.only(left: 10, right: 10, bottom: 2),
  101. color: Colors.white,
  102. child: Row(
  103. children: <Widget>[
  104. Flexible(
  105. child: Container(
  106. margin: EdgeInsets.only(bottom: 10, right: 10),
  107. decoration: BoxDecoration(
  108. border: Border(
  109. bottom: BorderSide(color: const Color(0xFF0368FF)))),
  110. child: TextField(
  111. keyboardAppearance: Brightness.light,
  112. maxLines: 3,
  113. minLines: 1,
  114. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  115. autofocus: true,
  116. inputFormatters: <TextInputFormatter>[
  117. LengthLimitingTextInputFormatter(30) //限制长度
  118. ],
  119. decoration: new InputDecoration(
  120. hintText: hitStr,
  121. hintMaxLines: 1,
  122. hintStyle: TextStyle(fontSize: 15),
  123. border: InputBorder.none,
  124. ),
  125. onChanged: (str) {
  126. content = str;
  127. },
  128. )),
  129. ),
  130. RaisedButton(
  131. color: const Color(0xFF0368FF),
  132. child: Text(
  133. I18n.of(context).send,
  134. textScaleFactor: 1.0,
  135. style: TextStyle(color: Colors.white),
  136. ),
  137. onPressed: () async {
  138. content = content.trim();
  139. if (content == '' || content == null) {
  140. return;
  141. }
  142. if (isAd) {
  143. Map rdata = {
  144. "userId": UserData().basicInfo.userId,
  145. "adId": programId,
  146. };
  147. rdata['sign'] = TokenMgr().getSign(rdata);
  148. rdata['content'] = content;
  149. Response res = await HttpUtil().post(
  150. 'adActivity/reply/evaluate',
  151. data: rdata,
  152. isShowLoading: true);
  153. var resData = res.data;
  154. var data = {
  155. 'Pid': resData['data'],
  156. 'UserId': UserData().basicInfo.userId,
  157. 'NickName': UserData().basicInfo.nickName,
  158. 'Type': type,
  159. 'ReplyUserId': replyUserId,
  160. 'ReplyNickName': replyUserName,
  161. 'Content': content
  162. };
  163. showToast(resData['msg']);
  164. if (resData['code'] == 0) {
  165. Navigator.of(context).pop();
  166. callback(data);
  167. }
  168. } else {
  169. Map rdata = {
  170. "userId": UserData().basicInfo.userId,
  171. "id": programId,
  172. "type": type,
  173. };
  174. rdata['sign'] = TokenMgr().getSign(rdata);
  175. rdata['content'] = content;
  176. rdata['replyId'] = replyId;
  177. Response res = await HttpUtil().post('station/reply/comment',
  178. data: rdata, isShowLoading: true);
  179. var resData = res.data;
  180. print('station/reply/comment $resData');
  181. var data = {
  182. 'Pid': resData['data'],
  183. 'UserId': UserData().basicInfo.userId,
  184. 'NickName': UserData().basicInfo.nickName,
  185. 'Type': type,
  186. 'ReplyUserId': replyUserId,
  187. 'ReplyNickName': replyUserName,
  188. 'Content': content
  189. };
  190. showToast(resData['msg']);
  191. if (resData['code'] == 0) {
  192. Navigator.of(context).pop();
  193. callback(data);
  194. }
  195. }
  196. },
  197. )
  198. ],
  199. ),
  200. );
  201. Widget button = Expanded(
  202. child: InkWell(
  203. highlightColor: Colors.transparent,
  204. radius: 0,
  205. onTap: () {
  206. Navigator.pop(context);
  207. },
  208. ),
  209. );
  210. return Column(
  211. mainAxisAlignment: MainAxisAlignment.end,
  212. children: <Widget>[
  213. button,
  214. input,
  215. ],
  216. );
  217. }
  218. static void buildNotTrue(BuildContext context) {
  219. buildOneConfirm(context, I18n.of(context).after_authenticate,
  220. I18n.of(context).authenticate_now, () {
  221. Navigator.pop(context);
  222. Navigator.of(context).push(
  223. new MaterialPageRoute(
  224. builder: (context) {
  225. return VerificationCenterPage();
  226. },
  227. ),
  228. );
  229. });
  230. }
  231. static Widget buildCancleBotton(title, callback) {
  232. return InkWell(
  233. onTap: callback,
  234. child: Container(
  235. decoration: BoxDecoration(
  236. color: const Color(0XFFC7E5FF),
  237. borderRadius: BorderRadius.all(
  238. Radius.circular(Constants.LittleButtonRadius))),
  239. margin: EdgeInsets.only(top: 0, bottom: 18.5),
  240. height: 37.5,
  241. width: 200,
  242. alignment: Alignment.center,
  243. child: fixedText(
  244. title,
  245. fontSize: 15,
  246. color: const Color(0xFF5781A6),
  247. )),
  248. );
  249. }
  250. static Widget _buildContentTip(tipTitle) {
  251. return tipTitle == ''
  252. ? Container()
  253. : Container(
  254. padding: EdgeInsets.only(top: 38.5, bottom: 31.5),
  255. child: Text(
  256. tipTitle,
  257. textScaleFactor: 1.0,
  258. style: TextStyle(
  259. fontSize: 14, color: Constants.BlackTextColor, height: 1.30),
  260. textAlign: TextAlign.center,
  261. ));
  262. }
  263. static Widget buildConfirmContent(tip, content) {
  264. return Container(
  265. padding: EdgeInsets.only(left: 40, right: 40),
  266. child: Column(
  267. children: <Widget>[tip, content],
  268. ),
  269. );
  270. }
  271. static Widget buildImgLoding(context, url) {
  272. return Center(
  273. child: CircularProgressIndicator(
  274. valueColor: AlwaysStoppedAnimation(Constants.BlueTextColor)));
  275. }
  276. static Widget buildConfirmBotton(title, callback) {
  277. return InkWell(
  278. onTap: callback,
  279. child: Container(
  280. decoration: Constants.ConfirmBUttonBoxDecoration,
  281. height: 37.5,
  282. width: 200,
  283. alignment: Alignment.center,
  284. child: fixedText(
  285. title,
  286. fontSize: 15,
  287. color: Colors.white,
  288. )),
  289. );
  290. }
  291. static void buildOneConfirm(
  292. BuildContext context, String tipTitle, String buttonTitle, callback,
  293. {title = '', failcallbak}) {
  294. var confirm = buildConfirmBotton(buttonTitle, callback);
  295. buildTip(context, title,
  296. buildConfirmContent(_buildContentTip(tipTitle), confirm),
  297. failcallbak: failcallbak);
  298. }
  299. static void buildContacts(
  300. BuildContext context, String tipTitle, String buttonTitle, callback,
  301. {title = '', failcallbak}) {
  302. var confirm = buildConfirmBotton(buttonTitle, callback);
  303. buildTip(
  304. context,
  305. title,
  306. buildConfirmContent(
  307. Container(
  308. alignment: Alignment.center,
  309. padding: EdgeInsets.only(top: 38.5, bottom: 31.5),
  310. child: Column(
  311. children: <Widget>[
  312. Text(
  313. tipTitle,
  314. textScaleFactor: 1.0,
  315. style: TextStyle(
  316. fontSize: 14,
  317. color: Constants.BlackTextColor,
  318. height: 1.30),
  319. textAlign: TextAlign.center,
  320. ),
  321. SizedBox(
  322. height: 5,
  323. ),
  324. GestureDetector(
  325. child: Text(
  326. I18n.of(context).privacy,
  327. style: TextStyle(color: Colors.blue, fontSize: 14),
  328. ),
  329. onTap: () {
  330. launch(
  331. 'http://datechatagent.chengyouhd.com/zh-CN/Home/Privacy?language=${UserData().language}');
  332. },
  333. )
  334. ],
  335. )),
  336. confirm),
  337. failcallbak: failcallbak);
  338. }
  339. static Widget buildNoData(BuildContext context, {String str, double height}) {
  340. if (height == null) {
  341. height = MediaQuery.of(context).size.height * 0.8;
  342. }
  343. return Container(
  344. width: MediaQuery.of(context).size.width,
  345. height: height,
  346. alignment: Alignment.center,
  347. child: Column(
  348. crossAxisAlignment: CrossAxisAlignment.center,
  349. mainAxisAlignment: MainAxisAlignment.center,
  350. children: <Widget>[
  351. Container(
  352. child: Icon(
  353. IconData(
  354. 0xe869,
  355. fontFamily: 'iconfont',
  356. ),
  357. size: 60,
  358. color: Constants.BlueTextColor,
  359. )),
  360. Container(
  361. alignment: Alignment.center,
  362. child: fixedText(str != null ? str : I18n.of(context).no_data,
  363. color: Constants.BlueTextColor)),
  364. ],
  365. ));
  366. }
  367. static Widget buildImgCover(
  368. int imgId,
  369. List<PicSwiperItem> pics,
  370. String imgUrl,
  371. double width,
  372. double raduis,
  373. bool isWatch,
  374. BuildContext context,
  375. int type,
  376. {bool isMyself = false,
  377. int payStatus = 0,
  378. int state = 1}) {
  379. Color color = isWatch
  380. ? const Color(0xFF999999)
  381. : const Color(0xFFFB5656); //const Color(0xfffb5656);
  382. String bottomStr = '';
  383. if (type == PhotoType.money.index) {
  384. bottomStr = I18n.of(context).red_photo;
  385. } else if (type == PhotoType.destroyMoney.index) {
  386. bottomStr = I18n.of(context).red_photo; //I18n.of(context).red_photo1;
  387. } else if (type == PhotoType.destroy.index) {
  388. bottomStr =
  389. isWatch ? I18n.of(context).destroyed : I18n.of(context).destroy_after;
  390. }
  391. double opacity = 0.5;
  392. Widget normalCover = isMyself && state == 0
  393. ? Positioned(
  394. right: 5,
  395. top: 5,
  396. child: Container(
  397. alignment: Alignment.center,
  398. width: width,
  399. height: width,
  400. decoration: BoxDecoration(
  401. color: Colors.black.withOpacity(opacity),
  402. borderRadius: BorderRadius.all(Radius.circular(raduis - 2))),
  403. child: Text(I18n.of(context).reviewing,
  404. textAlign: TextAlign.center,
  405. textScaleFactor: 1.0,
  406. style: TextStyle(fontSize: 12, color: Colors.white)),
  407. ),
  408. )
  409. : Container(
  410. width: width,
  411. height: width,
  412. decoration: BoxDecoration(
  413. border: Border.all(color: Colors.grey[300], width: 1),
  414. borderRadius: BorderRadius.circular(raduis)),
  415. );
  416. return InkWell(
  417. onTap: () {
  418. Navigator.of(context).push(
  419. new MaterialPageRoute(
  420. builder: (context) {
  421. return PicSwiper(
  422. id: imgId,
  423. pics: pics,
  424. );
  425. },
  426. ),
  427. );
  428. },
  429. child: Stack(
  430. alignment: Alignment.center,
  431. children: <Widget>[
  432. Container(
  433. decoration:
  434. BoxDecoration(borderRadius: BorderRadius.circular(2.0)),
  435. width: width,
  436. height: width,
  437. margin: EdgeInsets.all(5),
  438. child: ClipRRect(
  439. borderRadius: BorderRadius.circular(raduis),
  440. child: CachedNetworkImage(
  441. imageUrl: imgUrl == null ? "" : imgUrl,
  442. placeholder: CustomUI.buildImgLoding,
  443. fit: BoxFit.cover,
  444. ),
  445. )),
  446. (type == PhotoType.free.index ||
  447. (!isMyself &&
  448. type == PhotoType.money.index &&
  449. payStatus == 1))
  450. ? normalCover
  451. : Stack(
  452. alignment: Alignment.center,
  453. children: <Widget>[
  454. Container(
  455. width: width,
  456. height: width,
  457. decoration: BoxDecoration(
  458. border: Border.all(color: color, width: 1),
  459. borderRadius: BorderRadius.circular(raduis),
  460. ),
  461. margin: EdgeInsets.all(5),
  462. child: ClipRRect(
  463. borderRadius: BorderRadius.circular(raduis),
  464. child: BackdropFilter(
  465. //背景滤镜器
  466. filter: ui.ImageFilter.blur(
  467. sigmaX: 10.0,
  468. sigmaY: 10.0), //图片模糊过滤,横向竖向都设置5.0
  469. child: Opacity(
  470. //透明控件
  471. opacity: isMyself ? 0 : 0.5,
  472. child: Container(
  473. decoration: BoxDecoration(
  474. border: Border.all(color: color, width: 0),
  475. borderRadius: BorderRadius.circular(0),
  476. ),
  477. alignment: Alignment.center,
  478. ),
  479. ),
  480. )),
  481. ),
  482. isMyself && state == 0
  483. ? Positioned(
  484. right: 6,
  485. top: 6,
  486. child: Container(
  487. alignment: Alignment.center,
  488. width: width - 2,
  489. height: width - 2,
  490. decoration: BoxDecoration(
  491. color: Colors.black.withOpacity(opacity),
  492. borderRadius: BorderRadius.all(
  493. Radius.circular(raduis - 1))),
  494. child: Text(I18n.of(context).reviewing,
  495. textScaleFactor: 1.0,
  496. style: TextStyle(
  497. fontSize: 12, color: Colors.white)),
  498. ),
  499. )
  500. : Text(''),
  501. Positioned(
  502. left: 0,
  503. top: 0,
  504. child: Container(
  505. width: 18,
  506. height: 18,
  507. margin: EdgeInsets.all(5),
  508. decoration: BoxDecoration(
  509. color: color,
  510. borderRadius: BorderRadius.only(
  511. topLeft: Radius.circular(raduis),
  512. bottomRight: Radius.circular(raduis))),
  513. child: Icon(
  514. IconData(
  515. type == PhotoType.money.index ? 0xe632 : 0xe634,
  516. fontFamily: 'iconfont',
  517. ),
  518. color: Colors.white,
  519. size: 15,
  520. ),
  521. ),
  522. ),
  523. Positioned(
  524. bottom: 6,
  525. child: Container(
  526. width: width - 2,
  527. padding: EdgeInsets.only(
  528. bottom: 1, top: 2, left: 5, right: 5),
  529. decoration: isMyself
  530. ? BoxDecoration(
  531. color: Colors.red.withOpacity(0.7),
  532. borderRadius: BorderRadius.only(
  533. bottomLeft: Radius.circular(raduis - 1),
  534. bottomRight:
  535. Radius.circular(raduis - 1)))
  536. : BoxDecoration(),
  537. child: Text(bottomStr,
  538. textScaleFactor: 1.0,
  539. textAlign: TextAlign.center,
  540. style: TextStyle(
  541. color: isMyself ? Colors.white : color,
  542. fontSize: 10)),
  543. )),
  544. ],
  545. ),
  546. ],
  547. ));
  548. }
  549. static void buildTowConfirm(
  550. BuildContext context,
  551. String tipTitle,
  552. String confirmButtonTitle,
  553. confirmCallback,
  554. cancleButtonTitle,
  555. cancleCallback,
  556. {title = ''}) {
  557. var confirm = buildConfirmBotton(confirmButtonTitle, confirmCallback);
  558. var cancle = buildCancleBotton(cancleButtonTitle, cancleCallback);
  559. buildTip(
  560. context,
  561. title,
  562. buildConfirmContent(
  563. _buildContentTip(tipTitle),
  564. Column(
  565. children: <Widget>[cancle, confirm],
  566. )));
  567. }
  568. static Widget buildTipContent(
  569. BuildContext context, String tips, Widget content,
  570. {failcallbak}) {
  571. return Container(
  572. child: Column(
  573. mainAxisAlignment: MainAxisAlignment.center,
  574. children: <Widget>[
  575. Stack(
  576. children: <Widget>[
  577. Container(
  578. padding: EdgeInsets.only(bottom: 25),
  579. alignment: Alignment.center,
  580. decoration: BoxDecoration(
  581. color: Colors.white,
  582. borderRadius: BorderRadius.circular(10.0)),
  583. width: MediaQuery.of(context).size.width * 0.91,
  584. child: Column(
  585. children: <Widget>[
  586. tips == ''
  587. ? Container()
  588. : Container(
  589. margin:
  590. EdgeInsets.only(top: 15.5, left: 40, right: 40),
  591. padding: EdgeInsets.only(bottom: 10.5),
  592. decoration: BoxDecoration(
  593. border: Border(
  594. bottom: BorderSide(
  595. color: Constants.DividerLineColor))),
  596. alignment: Alignment.center,
  597. child: Text(
  598. tips,
  599. textScaleFactor: 1.0,
  600. style: TextStyle(
  601. color: Constants.BlackTextColor,
  602. fontSize: 16.5,
  603. fontWeight: FontWeight.w400),
  604. textAlign: TextAlign.center,
  605. ),
  606. ),
  607. content
  608. ],
  609. ),
  610. ),
  611. Positioned(
  612. top: -40,
  613. right: 0,
  614. child: InkWell(
  615. highlightColor: Colors.transparent,
  616. radius: 0,
  617. onTap: () {
  618. Navigator.of(context).pop();
  619. if (failcallbak != null) failcallbak();
  620. },
  621. child: Container(
  622. width: 40,
  623. height: 40,
  624. alignment: Alignment.center,
  625. margin: EdgeInsets.only(top: 36.5),
  626. decoration: BoxDecoration(
  627. borderRadius: BorderRadius.circular(50.0)),
  628. child: Icon(
  629. // IconData(
  630. // 0xe679,
  631. // fontFamily: 'iconfont',
  632. // ),
  633. Icons.close,
  634. color: Colors.grey[700],
  635. size: 24,
  636. ),
  637. )))
  638. ],
  639. )
  640. ]));
  641. // return Container(
  642. // child: Column(
  643. // mainAxisAlignment: MainAxisAlignment.center,
  644. // children: <Widget>[
  645. // Container(
  646. // padding: EdgeInsets.only(bottom: 25),
  647. // alignment: Alignment.center,
  648. // decoration: BoxDecoration(
  649. // color: Colors.white, borderRadius: BorderRadius.circular(10.0)),
  650. // width: MediaQuery.of(context).size.width * 0.91,
  651. // child: Column(
  652. // children: <Widget>[
  653. // tips == ''
  654. // ? Container()
  655. // : Container(
  656. // margin: EdgeInsets.only(top: 15.5, left: 40, right: 40),
  657. // padding: EdgeInsets.only(bottom: 10.5),
  658. // decoration: BoxDecoration(
  659. // border: Border(
  660. // bottom: BorderSide(
  661. // color: Constants.DividerLineColor))),
  662. // alignment: Alignment.center,
  663. // child: Text(
  664. // tips,
  665. // textScaleFactor: 1.0,
  666. // style: TextStyle(
  667. // color: Constants.BlackTextColor,
  668. // fontSize: 16.5,
  669. // fontWeight: FontWeight.w400),
  670. // textAlign: TextAlign.center,
  671. // ),
  672. // ),
  673. // content
  674. // ],
  675. // ),
  676. // ),
  677. // InkWell(
  678. // highlightColor: Colors.transparent,
  679. // radius: 0,
  680. // onTap: () {
  681. // Navigator.of(context).pop();
  682. // if (failcallbak != null) failcallbak();
  683. // },
  684. // child: Container(
  685. // width: 40,
  686. // height: 40,
  687. // alignment: Alignment.center,
  688. // margin: EdgeInsets.only(top: 36.5),
  689. // decoration: BoxDecoration(
  690. // color: Colors.white,
  691. // borderRadius: BorderRadius.circular(50.0)),
  692. // child: Icon(
  693. // IconData(
  694. // 0xe679,
  695. // fontFamily: 'iconfont',
  696. // ),
  697. // size: 20,
  698. // ),
  699. // ))
  700. // ]));
  701. }
  702. static void buildTip(BuildContext context, String tips, Widget content,
  703. {failcallbak}) {
  704. Navigator.of(context).push(TutorialOverlay(
  705. child:
  706. buildTipContent(context, tips, content, failcallbak: failcallbak)));
  707. }
  708. static Future<bool> showIosDialog(BuildContext context, String title,
  709. Function sureFunction, Function cancelFunction) async {
  710. bool isDismiss = await showDialog(
  711. context: context,
  712. builder: (context) {
  713. return CupertinoAlertDialog(
  714. title: fixedText(title),
  715. actions: <Widget>[
  716. CupertinoDialogAction(
  717. child: fixedText(I18n.of(context).determine),
  718. onPressed: sureFunction),
  719. CupertinoDialogAction(
  720. child: fixedText(I18n.of(context).cancel),
  721. onPressed: cancelFunction),
  722. ],
  723. );
  724. });
  725. return isDismiss;
  726. }
  727. static Widget buildTopTip(double leftPadding, str,
  728. {double fontSize = 15, bool showStar = false}) {
  729. return Container(
  730. decoration: BoxDecoration(
  731. color: Colors.white,
  732. border: Border(bottom: Constants.GreyBorderSide)),
  733. margin: EdgeInsets.only(top: 20),
  734. padding: EdgeInsets.only(left: leftPadding, top: 8, bottom: 8),
  735. alignment: Alignment.centerLeft,
  736. child: Row(
  737. children: <Widget>[
  738. showStar
  739. ? Padding(
  740. padding: EdgeInsets.only(top: 2, right: 2),
  741. child: Text(
  742. '*',
  743. style: TextStyle(color: Colors.red),
  744. ))
  745. : Text(''),
  746. Container(
  747. width: Screen.width - leftPadding * 2,
  748. child: Text(str,
  749. textScaleFactor: 1.0,
  750. style: TextStyle(
  751. color: Constants.BlackTextColor,
  752. fontSize: fontSize,
  753. fontWeight: FontWeight.w500)),
  754. )
  755. ],
  756. ),
  757. );
  758. }
  759. static Widget buildAudioContaniner(double height) {
  760. return ClipRRect(
  761. borderRadius: BorderRadius.circular(2.5),
  762. child: Container(
  763. height: height,
  764. color: const Color(0xFF04A4FE),
  765. width: 5,
  766. ),
  767. );
  768. }
  769. static Widget buildBox(nums, str) {
  770. return Container(
  771. width: (Screen.width - 80) / 3,
  772. child: Column(
  773. children: <Widget>[
  774. Container(
  775. alignment: Alignment.center,
  776. margin: EdgeInsets.only(top: 10),
  777. width: 58.1,
  778. height: 24.85,
  779. decoration: BoxDecoration(
  780. color: nums > 0 ? Constants.BlueTextColor : Colors.grey[200],
  781. borderRadius:
  782. BorderRadius.circular(Constants.LittleButtonRadius)),
  783. child: Text(
  784. nums > 99 ? '99+' : nums.toString(),
  785. textScaleFactor: 1.0,
  786. style: TextStyle(
  787. fontSize: 17.76,
  788. color: nums > 0 ? Colors.white : Colors.grey),
  789. ),
  790. ),
  791. Container(
  792. margin: EdgeInsets.only(top: 5),
  793. alignment: Alignment.center,
  794. child: Text(
  795. str,
  796. textScaleFactor: 1.0,
  797. style: TextStyle(color: Constants.BlackTextColor, fontSize: 12),
  798. ),
  799. ),
  800. ],
  801. ),
  802. );
  803. }
  804. static Future<bool> _willPop(BuildContext context, bool isForceUpdate) async {
  805. print('_willPop $isForceUpdate');
  806. if (isForceUpdate) {
  807. await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
  808. } else {
  809. Navigator.pop(context);
  810. }
  811. return null;
  812. }
  813. static void buildVersionUpdate(
  814. BuildContext context,
  815. String versionName,
  816. ///版本号
  817. bool isForceUpdate,
  818. ///强制升级
  819. String describe,
  820. ///版本描述
  821. ValueNotifier<String> updateProgress,
  822. ///进度更新
  823. Function go
  824. ///点击开始体验回调
  825. ) {
  826. Navigator.of(context).push(TutorialOverlay(
  827. child: WillPopScope(
  828. child: Container(
  829. alignment: Alignment.center,
  830. width: 296,
  831. child: Container(
  832. width: 296,
  833. height: 387,
  834. child: Stack(
  835. children: <Widget>[
  836. Positioned(
  837. top: 10,
  838. child: Container(
  839. height: 307,
  840. width: 296,
  841. child: Column(
  842. children: <Widget>[
  843. SizedBox(
  844. height: 75,
  845. ),
  846. Container(
  847. padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
  848. height: 161,
  849. width: 296,
  850. child: SingleChildScrollView(
  851. child: Text(
  852. describe ?? '',
  853. textAlign: TextAlign.left,
  854. style: TextStyle(
  855. fontSize: 15,
  856. fontWeight: FontWeight.w300),
  857. ),
  858. ),
  859. ),
  860. ValueListenableBuilder(
  861. builder: (BuildContext context, String value,
  862. Widget child) {
  863. return value == '-1'
  864. ? GestureDetector(
  865. onTap: go,
  866. child: Container(
  867. alignment: Alignment.center,
  868. width: 164,
  869. height: 40,
  870. child: Text(
  871. I18n.of(context).test_it,
  872. style: TextStyle(
  873. fontWeight: FontWeight.w500,
  874. color: Colors.white,
  875. fontSize: 17),
  876. ),
  877. decoration: BoxDecoration(
  878. color: Color(0xff3875E9),
  879. borderRadius:
  880. BorderRadius.all(
  881. Radius.circular(
  882. 3.0))),
  883. ),
  884. )
  885. : Container(
  886. alignment: Alignment.center,
  887. width: 164,
  888. height: 40,
  889. child: Stack(
  890. children: <Widget>[
  891. SizedBox(
  892. //限制进度条的高度
  893. height: 40,
  894. //限制进度条的宽度
  895. width: 164,
  896. child: ClipRRect(
  897. borderRadius:
  898. BorderRadius.all(
  899. Radius.circular(
  900. 3.0)),
  901. child:
  902. LinearProgressIndicator(
  903. //0~1的浮点数,用来表示进度多少;如果 value 为 null 或空,则显示一个动画,否则显示一个定值
  904. value: double.parse(
  905. value) /
  906. 100,
  907. //背景颜色
  908. backgroundColor:
  909. Color(
  910. 0xff4E5D7A),
  911. //进度颜色
  912. valueColor:
  913. new AlwaysStoppedAnimation<
  914. Color>(
  915. Color(
  916. 0xff65A5FC))),
  917. ),
  918. ),
  919. Container(
  920. alignment: Alignment.center,
  921. child: Text(
  922. '$value %',
  923. style: TextStyle(
  924. fontWeight:
  925. FontWeight.w500,
  926. color: Colors.white,
  927. fontSize: 19),
  928. ),
  929. )
  930. ],
  931. ),
  932. decoration: BoxDecoration(
  933. color: Color(0xff3875E9),
  934. borderRadius: BorderRadius.all(
  935. Radius.circular(3.0))),
  936. );
  937. },
  938. valueListenable: updateProgress,
  939. )
  940. ],
  941. ),
  942. decoration: BoxDecoration(
  943. color: Colors.white,
  944. borderRadius: BorderRadius.circular(12)))),
  945. Container(
  946. height: 81,
  947. child: Stack(
  948. children: <Widget>[
  949. Image.asset(
  950. R.assetsImagesImgUpdateBg,
  951. height: 81,
  952. ),
  953. Positioned.fill(
  954. child: Align(
  955. alignment: Alignment.center,
  956. child: Text(
  957. '${I18n.of(context).found_new} ($versionName)',
  958. style:
  959. TextStyle(color: Colors.white, fontSize: 18),
  960. ),
  961. )),
  962. Positioned.fill(
  963. child: Offstage(
  964. offstage: isForceUpdate,
  965. child: Align(
  966. alignment: Alignment.topRight,
  967. child: Container(
  968. width: 50,
  969. height: 50,
  970. child: GestureDetector(
  971. onTap: () {
  972. Navigator.of(context).pop();
  973. },
  974. child: Icon(
  975. IconData(
  976. 0xe679,
  977. fontFamily: 'iconfont',
  978. ),
  979. size: 16,
  980. color: Color(0xffa4c1fe),
  981. ),
  982. ),
  983. ),
  984. ),
  985. ))
  986. ],
  987. ),
  988. )
  989. ],
  990. ),
  991. ),
  992. ),
  993. onWillPop: () => _willPop(context, isForceUpdate))));
  994. }
  995. ///访问相册权限
  996. static Future<bool> showPhotoPermissionSetting(BuildContext context) async {
  997. return showPermissionSetting(
  998. context,
  999. Platform.isAndroid ? PermissionGroup.storage : PermissionGroup.photos,
  1000. Platform.isAndroid
  1001. ? I18n.of(context).location_permission
  1002. : I18n.of(context).photo_permission);
  1003. }
  1004. ///权限申请被拒后 弹窗提示到设置界面打开
  1005. static Future<bool> showPermissionSetting(BuildContext context,
  1006. PermissionGroup permissionGroup, String tips) async {
  1007. final PermissionStatus addStatus =
  1008. await PermissionHandler().checkPermissionStatus(permissionGroup);
  1009. print('check :$permissionGroup addStatus: $addStatus');
  1010. if (addStatus == PermissionStatus.granted) {
  1011. return true;
  1012. } else {
  1013. /// ios第一次-发起询问权限 || android 第一次发起请求或者被拒过
  1014. if (addStatus == PermissionStatus.unknown ||
  1015. (addStatus == PermissionStatus.denied && Platform.isAndroid)) {
  1016. Map<PermissionGroup, PermissionStatus> permissionRequestResult =
  1017. await PermissionHandler().requestPermissions([permissionGroup]);
  1018. PermissionStatus status = permissionRequestResult[permissionGroup];
  1019. print('status: $status');
  1020. if (status == PermissionStatus.granted) {
  1021. return true;
  1022. } else {
  1023. var result = await showDialog(
  1024. context: context,
  1025. builder: (ctx) => NotPermissionDialog(tips),
  1026. );
  1027. if (result == true) {
  1028. PermissionHandler().openAppSettings();
  1029. }
  1030. return false;
  1031. }
  1032. } else {
  1033. ///被用户禁用,所以弹窗去设置打开权限
  1034. var result = await showDialog(
  1035. context: context,
  1036. builder: (ctx) => NotPermissionDialog(tips),
  1037. );
  1038. if (result == true) {
  1039. PermissionHandler().openAppSettings();
  1040. }
  1041. return false;
  1042. }
  1043. }
  1044. }
  1045. goScanPage(BuildContext context) async {
  1046. if (await CustomUI.showPermissionSetting(
  1047. context, PermissionGroup.camera, I18n.of(context).camera_permission)) {
  1048. AppNavigator.pushScannerPage(context);
  1049. }
  1050. }
  1051. getSearchResult(String searchKey, List<FriendModel> sourceList) {
  1052. List<FriendModel> res = [];
  1053. for (var i = 0; i < sourceList.length; i++) {
  1054. var friendModel = sourceList[i];
  1055. if ((friendModel.refName != null &&
  1056. friendModel.refName.contains(searchKey)) ||
  1057. friendModel.name.contains(searchKey)) {
  1058. res.add(friendModel);
  1059. }
  1060. }
  1061. return res;
  1062. }
  1063. getGroupSearchResult(
  1064. String searchKey, List<GroupInfoModel> sourceList, Map refMap) {
  1065. List<GroupInfoModel> res = [];
  1066. for (var i = 0; i < sourceList.length; i++) {
  1067. var groupModel = sourceList[i];
  1068. if ((groupModel.name.contains(searchKey)) ||
  1069. groupModel.getGroupName(refMap).contains(searchKey)) {
  1070. res.add(groupModel);
  1071. }
  1072. }
  1073. return res;
  1074. }
  1075. static Widget buildLoaingAnim(BuildContext context,
  1076. {String str, double height}) {
  1077. if (height == null) {
  1078. height = MediaQuery.of(context).size.height * 0.8;
  1079. }
  1080. return Container(
  1081. width: MediaQuery.of(context).size.width,
  1082. height: height,
  1083. alignment: Alignment.topCenter,
  1084. child: Container(
  1085. width: 40,
  1086. height: 40,
  1087. margin: EdgeInsets.only(top: 20),
  1088. padding: EdgeInsets.all(10),
  1089. decoration: BoxDecoration(
  1090. shape: BoxShape.circle,
  1091. color: Colors.white,
  1092. boxShadow: [BoxShadow(blurRadius: 3.0, color: Colors.black26)]),
  1093. child: new CircularProgressIndicator(
  1094. strokeWidth: 2,
  1095. ),
  1096. ));
  1097. }
  1098. static Widget buildLoadingFooter() {
  1099. return CustomFooter(
  1100. builder: (BuildContext context, LoadStatus mode) {
  1101. Widget body = Container();
  1102. if (mode == LoadStatus.idle) {
  1103. //body = Text("pull up load");
  1104. } else if (mode == LoadStatus.loading) {
  1105. body = CupertinoActivityIndicator();
  1106. } else if (mode == LoadStatus.failed) {
  1107. //body = Text("Load Failed!Click retry!");
  1108. } else if (mode == LoadStatus.canLoading) {
  1109. //body = Text("release to load more");
  1110. } else {
  1111. //body = Text("No more Data");
  1112. }
  1113. return Container(
  1114. //height: 50.0,
  1115. child: Center(child: body),
  1116. );
  1117. },
  1118. );
  1119. }
  1120. static PreferredSizeWidget buildSearchButton(BuildContext context, callback,
  1121. {double bottom = 14}) {
  1122. return PreferredSize(
  1123. preferredSize: Size.fromHeight(49),
  1124. child: InkWell(
  1125. onTap: callback,
  1126. child: Container(
  1127. alignment: Alignment.center,
  1128. margin: EdgeInsets.only(bottom: bottom, left: 12.5, right: 12.5),
  1129. height: 35,
  1130. decoration: BoxDecoration(
  1131. color: const Color(0xFFEEEEEE),
  1132. borderRadius: BorderRadius.all(Radius.circular(8))),
  1133. child: Row(
  1134. crossAxisAlignment: CrossAxisAlignment.center,
  1135. children: <Widget>[
  1136. Container(
  1137. margin: EdgeInsets.only(left: 15, right: 15, bottom: 0),
  1138. child: Icon(
  1139. IconData(
  1140. 0xe664,
  1141. fontFamily: Constants.IconFontFamily,
  1142. ),
  1143. color: const Color(0xFFA0A0A0),
  1144. size: 18,
  1145. ),
  1146. ),
  1147. Container(
  1148. margin: EdgeInsets.only(bottom: 0),
  1149. child: Text(I18n.of(context).search,
  1150. style:
  1151. TextStyle(fontSize: 14.5, color: Colors.grey))),
  1152. ],
  1153. ))),
  1154. );
  1155. }
  1156. static Widget buildCustomLeading(BuildContext context,
  1157. {onTap, double iconPadding = 10}) {
  1158. return InkWell(
  1159. onTap: onTap == null
  1160. ? () {
  1161. Navigator.of(context).pop();
  1162. }
  1163. : onTap,
  1164. child: Container(
  1165. margin:
  1166. EdgeInsets.only(top: 2, left: iconPadding, right: iconPadding),
  1167. child: Image.asset(
  1168. 'assets/images/back.png',
  1169. scale: 2,
  1170. )),
  1171. );
  1172. }
  1173. static Widget buildImageLabel(String url, int nums,
  1174. {bool isLeft = true, double imgOpc = 0.6, double imgHeight = 14}) {
  1175. double radius = 2.75;
  1176. return Container(
  1177. margin: EdgeInsets.only(top: 16, bottom: 14),
  1178. height: 18.5,
  1179. constraints: BoxConstraints(minWidth: 30),
  1180. decoration: BoxDecoration(
  1181. color: const Color(0xFFF0F0F0),
  1182. borderRadius: isLeft
  1183. ? BorderRadius.only(
  1184. topLeft: Radius.circular(radius),
  1185. bottomLeft: Radius.circular(radius))
  1186. : BorderRadius.only(
  1187. topRight: Radius.circular(radius),
  1188. bottomRight: Radius.circular(radius))),
  1189. child: Row(
  1190. children: <Widget>[
  1191. Container(
  1192. margin: EdgeInsets.only(top: 2.5, bottom: 2.5),
  1193. width: !isLeft ? 0.5 : 0,
  1194. color: const Color(0xFFDEDEDE),
  1195. ),
  1196. Opacity(
  1197. opacity: imgOpc,
  1198. child: Container(
  1199. height: imgHeight,
  1200. margin: EdgeInsets.only(left: 5.5),
  1201. child: Image.asset(url))),
  1202. Opacity(
  1203. opacity: 0.8,
  1204. child: Container(
  1205. margin: EdgeInsets.only(left: 7, right: 7),
  1206. child: Text(
  1207. nums.toString(),
  1208. style:
  1209. TextStyle(color: const Color(0xFF4C4C4C), fontSize: 12),
  1210. ))),
  1211. ],
  1212. ),
  1213. );
  1214. }
  1215. ///** isUser 是否是用户,或为 翻译
  1216. static void buildTranslationHelperOrderDialog(
  1217. BuildContext context, bool isUser,
  1218. {String orderId, int scenes = 0, String desc}) {
  1219. var scenesList = [
  1220. I18n.of(context).translation_scenes_1,
  1221. I18n.of(context).translation_scenes_2,
  1222. I18n.of(context).translation_scenes_3,
  1223. I18n.of(context).translation_scenes_4,
  1224. ];
  1225. Navigator.of(context).push(TutorialOverlay(
  1226. child: InkWell(
  1227. onTap: () {
  1228. Navigator.of(context).pop();
  1229. },
  1230. child: UnconstrainedBox(
  1231. alignment: Alignment.topCenter,
  1232. child: InkWell(
  1233. onTap: () {},
  1234. child: Container(
  1235. alignment: Alignment.topCenter,
  1236. // height: 180,
  1237. width: Screen.width - 20,
  1238. margin: EdgeInsets.all(10),
  1239. child: Card(
  1240. elevation: 2, // 阴影
  1241. shape: RoundedRectangleBorder(
  1242. borderRadius: BorderRadius.circular(10),
  1243. // side: BorderSide(color: Colors.green,width: 25),
  1244. ),
  1245. child: Container(
  1246. // color: Colors.yellow,
  1247. width: double.maxFinite,
  1248. padding: EdgeInsets.all(16),
  1249. child: Column(
  1250. crossAxisAlignment: CrossAxisAlignment.start,
  1251. children: <Widget>[
  1252. Padding(
  1253. padding: EdgeInsets.only(bottom: 15),
  1254. child: Text(
  1255. I18n.of(context).translation_butler_dialog_title,
  1256. textScaleFactor: 1.0,
  1257. textAlign: TextAlign.left,
  1258. style: TextStyle(
  1259. fontWeight: FontWeight.w500,
  1260. color: AppColors.NewAppbarTextColor,
  1261. fontSize: 17),
  1262. ),
  1263. ),
  1264. Text(
  1265. I18n.of(context)
  1266. .translation_butler_dialog_order
  1267. .replaceAll(
  1268. '/s1', isUser ? I18n.of(context).you : 'xxx'),
  1269. textScaleFactor: 1.0,
  1270. textAlign: TextAlign.left,
  1271. style: TextStyle(
  1272. color: AppColors.NewAppbarTextColor, fontSize: 14),
  1273. ),
  1274. SizedBox(
  1275. height: 10,
  1276. ),
  1277. Text(
  1278. '时间:今天11:45 时长:5分钟',
  1279. textScaleFactor: 1.0,
  1280. textAlign: TextAlign.left,
  1281. style:
  1282. TextStyle(color: Color(0xFF797979), fontSize: 11),
  1283. ),
  1284. isUser
  1285. ? Container()
  1286. : Text(
  1287. '场景:${scenesList[scenes]}',
  1288. textScaleFactor: 1.0,
  1289. textAlign: TextAlign.left,
  1290. style: TextStyle(
  1291. color: Color(0xFF797979), fontSize: 11),
  1292. ),
  1293. isUser
  1294. ? Container()
  1295. : Text(
  1296. '更多描述:$desc}',
  1297. textScaleFactor: 1.0,
  1298. textAlign: TextAlign.left,
  1299. style: TextStyle(
  1300. color: Color(0xFF797979), fontSize: 11),
  1301. ),
  1302. //
  1303. Container(
  1304. margin: EdgeInsets.only(
  1305. left: 30, right: 30, top: 20, bottom: 10),
  1306. child: isUser
  1307. ? Container(
  1308. margin: EdgeInsets.only(top: 10),
  1309. height: 36,
  1310. alignment: Alignment.center,
  1311. child: RaisedButton(
  1312. color: Color(0xff3875E9),
  1313. shape: RoundedRectangleBorder(
  1314. borderRadius: BorderRadius.all(
  1315. Radius.circular(10))),
  1316. child: Padding(
  1317. padding:
  1318. EdgeInsets.only(left: 10, right: 10),
  1319. child: Text(
  1320. I18n.of(context)
  1321. .translation_butler_dialog_start_chat,
  1322. textScaleFactor: 1.0,
  1323. style: TextStyle(
  1324. color: Colors.white,
  1325. fontSize: 15,
  1326. fontWeight: FontWeight.w500),
  1327. ),
  1328. ),
  1329. onPressed: () {
  1330. Navigator.of(context)..pop();
  1331. }),
  1332. )
  1333. : CountDownButton(
  1334. I18n.of(context)
  1335. .translation_butler_dialog_start_service,
  1336. () {
  1337. Navigator.of(context).pop();
  1338. },onPress: (){
  1339. MsgHandler.sendReceiveOrder();
  1340. Navigator.of(context).pop();
  1341. },),
  1342. )
  1343. ],
  1344. ),
  1345. ),
  1346. ),
  1347. ),
  1348. ),
  1349. ),
  1350. ),
  1351. ));
  1352. }
  1353. static void buildTranslationEvaluationDialog(BuildContext context) {
  1354. Navigator.of(context).push(TutorialOverlay(
  1355. child: TravelEvaluationPage(),
  1356. ));
  1357. }
  1358. }