Hibok
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1423 lines
45 KiB

  1. import 'dart:io';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:chat/chat/emoji_text.dart';
  4. import 'package:chat/chat/input_bar.dart';
  5. import 'package:chat/chat/my_special_text_span_builder.dart';
  6. import 'package:chat/data/UserData.dart';
  7. import 'package:chat/data/constants.dart';
  8. import 'package:chat/generated/i18n.dart';
  9. import 'package:chat/home/MyDialogContent.dart';
  10. import 'package:chat/home/SelectPage.dart';
  11. import 'package:chat/home/VerificationCenter.dart';
  12. import 'package:chat/home/VipPage.dart';
  13. import 'package:chat/models/money_change.dart';
  14. import 'package:chat/photo/entity/options.dart';
  15. import 'package:chat/photo/photo.dart';
  16. import 'package:chat/utils/ChargeMoney.dart';
  17. import 'package:chat/utils/CustomUI.dart';
  18. import 'package:chat/utils/HttpUtil.dart';
  19. import 'package:chat/utils/MessageMgr.dart';
  20. import 'package:chat/utils/PicSwiper.dart';
  21. import 'package:chat/utils/file_cache_mgr.dart';
  22. import 'package:chat/utils/keyboard/bottom_area_avoider.dart';
  23. import 'package:chat/utils/keyboard_utils.dart';
  24. import 'package:chat/utils/screen.dart';
  25. import 'package:dio/dio.dart';
  26. import 'package:extended_text_field/extended_text_field.dart';
  27. import 'package:flutter/material.dart';
  28. import 'package:flutter/services.dart';
  29. import 'package:flutter_screenutil/flutter_screenutil.dart';
  30. import 'package:multi_image_picker/multi_image_picker.dart';
  31. import 'package:oktoast/oktoast.dart';
  32. import 'package:photo_manager/photo_manager.dart';
  33. import 'package:provider/provider.dart';
  34. import 'package:shared_preferences/shared_preferences.dart';
  35. import '../utils/ShadowButton.dart';
  36. import '../data/UserData.dart';
  37. import '../utils/TokenMgr.dart';
  38. import '../data/WebData.dart';
  39. class AddProgram extends StatefulWidget {
  40. @required
  41. final bool isProgram;
  42. AddProgram({Key key, this.isProgram = true}) : super(key: key);
  43. _AddProgramState createState() => _AddProgramState();
  44. }
  45. const double LEFT_WIDTH = 80;
  46. const int Max_Img_Num = 4;
  47. class _AddProgramState extends State<AddProgram> {
  48. //期待对象
  49. String lovePeople = "";
  50. Set<String> lovePeopleId = new Set();
  51. //约会范围
  52. String dateRange = "";
  53. Set<String> dateRangeId = new Set();
  54. //开始时间
  55. String beginTime = '';
  56. String beginTimeId = '';
  57. //结束时间
  58. String endTime = '';
  59. var endTimeId = -1;
  60. //List<File> imgFileList = [];
  61. //上传图片地址
  62. List<String> imgUrlList = [];
  63. //禁止评论
  64. bool isCanContent = false;
  65. bool isHidden = false;
  66. int programId = -1;
  67. String programCat = '';
  68. // String content = '';
  69. @override
  70. void initState() {
  71. super.initState();
  72. print('AddProgram initState');
  73. _bloc.start();
  74. getKeyboardHeight();
  75. focusNode.addListener(_focusNodeListener);
  76. msgMgr.on('Keyboard Hide', dealWithKeyboardHide);
  77. }
  78. @override
  79. void dispose() {
  80. focusNode.removeListener(_focusNodeListener);
  81. _bloc.dispose();
  82. msgMgr.off('Keyboard Hide', dealWithKeyboardHide);
  83. super.dispose();
  84. }
  85. ///keyboard相关-----------------------------------------------------------------------------------------------
  86. KeyboardBloc _bloc = KeyboardBloc();
  87. MessageMgr msgMgr = MessageMgr();
  88. double keyboardHeight;
  89. final _keyParent = GlobalKey();
  90. double _offset = 0;
  91. Duration _timeToDismiss = Duration(milliseconds: 120);
  92. OverlayEntry _overlayEntry;
  93. FocusNode focusNode = new FocusNode();
  94. bool get _isShowing {
  95. return _overlayEntry != null;
  96. }
  97. bool isShowEmoji = false;
  98. bool _dismissAnimationNeeded = true;
  99. double _kBarSize = 45.0;
  100. bool isActionFromButton = false;
  101. dealWithKeyboardHide(args) {
  102. if (!isActionFromButton) {
  103. closeEmojiAction();
  104. }
  105. }
  106. TextEditingController _textCtrl = TextEditingController();
  107. final ValueNotifier<bool> _counter = ValueNotifier<bool>(false);
  108. void _insertOverlay() {
  109. print('插入界面');
  110. OverlayState os = Overlay.of(context);
  111. _overlayEntry = OverlayEntry(builder: (context) {
  112. // Update and build footer, if any
  113. final queryData = MediaQuery.of(context);
  114. return Positioned(
  115. bottom: queryData.viewInsets.bottom,
  116. left: 0,
  117. right: 0,
  118. child: SafeArea(
  119. child: Container(
  120. height: _kBarSize,
  121. child: Column(
  122. mainAxisSize: MainAxisSize.min,
  123. children: [
  124. Material(
  125. color: Colors.grey[200],
  126. child: Column(
  127. mainAxisSize: MainAxisSize.min,
  128. children: <Widget>[
  129. Divider(
  130. height: 1,
  131. color: Color(0xffb0b0b0),
  132. ),
  133. InkWell(
  134. child: Container(
  135. padding: EdgeInsets.only(left: 15),
  136. height: 43,
  137. color: Colors.white,
  138. alignment: Alignment.centerLeft,
  139. child: Icon(
  140. IconData(isShowEmoji ? 0xe655 : 0xe651,
  141. fontFamily: Constants.IconFontFamily),
  142. size: 27,
  143. color: Color(0xffb0b0b0)),
  144. ),
  145. onTap: () {
  146. setState(() {
  147. isActionFromButton = true;
  148. isShowEmoji = !isShowEmoji;
  149. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  150. if (isShowEmoji) {
  151. SystemChannels.textInput
  152. .invokeMethod('TextInput.hide');
  153. } else {
  154. SystemChannels.textInput
  155. .invokeMethod('TextInput.show');
  156. }
  157. if (isShowEmoji) {
  158. Future.delayed(Duration(milliseconds: 200), () {
  159. ///150延迟防止界面越界
  160. _counter.value = isShowEmoji;
  161. });
  162. Future.delayed(Duration(milliseconds: 1000), () {
  163. ///缩下键盘的时候-防止表情被关闭
  164. isActionFromButton = false;
  165. });
  166. } else {
  167. _counter.value = isShowEmoji;
  168. Future.delayed(Duration(milliseconds: 360), () {
  169. ///150延迟防止界面越界
  170. isActionFromButton = false;
  171. });
  172. }
  173. });
  174. },
  175. ),
  176. ValueListenableBuilder(
  177. builder:
  178. (BuildContext context, bool value, Widget child) {
  179. return value
  180. ? Container(
  181. width: MediaQuery.of(context).size.width,
  182. child: buildEmojiGird(),
  183. )
  184. : SizedBox(
  185. height: 1,
  186. );
  187. },
  188. valueListenable: _counter,
  189. ),
  190. ],
  191. ),
  192. ),
  193. ],
  194. ),
  195. ),
  196. ),
  197. );
  198. });
  199. os.insert(_overlayEntry);
  200. }
  201. getKeyboardHeight() async {
  202. var sp = await SharedPreferences.getInstance();
  203. keyboardHeight = sp.getDouble(Constants.KeyboardHeight);
  204. print('keyboardHeight : $keyboardHeight');
  205. }
  206. Future<Null> _focusNodeListener() async {
  207. print('监听');
  208. if (isShowEmoji) {
  209. return;
  210. }
  211. _focusChanged(focusNode.hasFocus);
  212. }
  213. _focusChanged(bool showBar) {
  214. print('showBar $showBar _isShowing:$_isShowing');
  215. if (showBar && !_isShowing) {
  216. _insertOverlay();
  217. } else if (!showBar && _isShowing) {
  218. _removeOverlay();
  219. } else if (showBar && _isShowing) {
  220. _overlayEntry.markNeedsBuild();
  221. }
  222. }
  223. /// Remove the overlay bar. Call when losing focus or being dismissed.
  224. void _removeOverlay({bool fromDispose = false}) async {
  225. if (_dismissAnimationNeeded) {
  226. if (mounted && !fromDispose) {
  227. _overlayEntry?.markNeedsBuild();
  228. await Future.delayed(_timeToDismiss);
  229. }
  230. }
  231. _overlayEntry?.remove();
  232. _overlayEntry = null;
  233. if (!fromDispose && _dismissAnimationNeeded) _updateOffset();
  234. _dismissAnimationNeeded = true;
  235. }
  236. void _updateOffset() {
  237. if (!mounted) {
  238. return;
  239. }
  240. if (!_isShowing) {
  241. setState(() {
  242. _offset = 0.0;
  243. });
  244. return;
  245. }
  246. double newOffset = _kBarSize; // offset for the actions bar
  247. newOffset += MediaQuery.of(context)
  248. .viewInsets
  249. .bottom; // + offset for the system keyboard
  250. if (newOffset < 0) newOffset = 0;
  251. // Update state if changed
  252. if (_offset != newOffset) {
  253. setState(() {
  254. _offset = newOffset;
  255. });
  256. }
  257. }
  258. Widget buildEmojiGird() {
  259. return Container(
  260. height: keyboardHeight - 44,
  261. child: Stack(
  262. children: <Widget>[
  263. Padding(
  264. padding: EdgeInsets.fromLTRB(5, 8, 50, 0),
  265. child: GridView.builder(
  266. controller: new ScrollController(keepScrollOffset: false),
  267. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  268. crossAxisCount: 7, crossAxisSpacing: 0, mainAxisSpacing: 0),
  269. itemBuilder: (context, index) {
  270. return GestureDetector(
  271. child: Container(
  272. padding: EdgeInsets.all(7),
  273. child: Image.asset(EmojiUitl
  274. .instance.emojiMap[EmojiText.flag + "${index + 1}]"]),
  275. ),
  276. behavior: HitTestBehavior.translucent,
  277. onTap: () {
  278. if (_textCtrl.value.text.length < 94) {
  279. InputBarState.insertText(
  280. EmojiText.flag + "${index + 1}]", _textCtrl);
  281. }
  282. // setState(() {
  283. // _isComposingMessage = _textCtrl.text.length > 0;
  284. // });
  285. },
  286. );
  287. },
  288. itemCount: EmojiUitl.instance.emojiMap.length,
  289. padding: EdgeInsets.all(5.0),
  290. ),
  291. ),
  292. Positioned.fill(
  293. child: Container(
  294. padding: EdgeInsets.fromLTRB(0, 0, 0, 14),
  295. alignment: Alignment(1, 1),
  296. child: InkWell(
  297. onTap: () {
  298. InputBarState.deleteText(_textCtrl);
  299. },
  300. child: Container(
  301. decoration: BoxDecoration(
  302. color: Color(0x4d0E0E10),
  303. borderRadius: BorderRadius.only(
  304. topLeft: Radius.circular(4.0),
  305. bottomLeft: Radius.circular(4))),
  306. width: 37,
  307. height: 28,
  308. child: Icon(
  309. IconData(
  310. 0xe679,
  311. fontFamily: 'iconfont',
  312. ),
  313. size: 16,
  314. color: Colors.white,
  315. ),
  316. ),
  317. ),
  318. )),
  319. ],
  320. ),
  321. );
  322. }
  323. ///keyboard相关------------------------------------------------------------------------------------------------------------
  324. void closeEmojiAction() {
  325. print('### closeEmojiAction');
  326. FocusScope.of(context).requestFocus(FocusNode());
  327. isShowEmoji = false;
  328. _counter.value = isShowEmoji;
  329. _removeOverlay();
  330. _offset = 0;
  331. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  332. }
  333. ScrollController _scrollController = new ScrollController();
  334. @override
  335. Widget build(BuildContext context) {
  336. Widget appBar = new AppBar(
  337. backgroundColor: AppColors.NewAppbarBgColor,
  338. title: Text(
  339. widget.isProgram
  340. ? I18n.of(context).release_program
  341. : I18n.of(context).release_dynamics,
  342. style: TextStyle(color: AppColors.NewAppbarTextColor),
  343. ),
  344. elevation: 0,
  345. leading: CustomUI.buildCustomLeading(context, onTap: () {
  346. closeEmojiAction();
  347. Navigator.of(context).pop();
  348. }),
  349. centerTitle: true,
  350. );
  351. return WillPopScope(
  352. child: Scaffold(
  353. appBar: appBar,
  354. body: SafeArea(
  355. child: Center(
  356. child: Container(
  357. height: MediaQuery.of(context).size.height,
  358. width: MediaQuery.of(context).size.width,
  359. child: GestureDetector(
  360. onTap: () {
  361. closeEmojiAction();
  362. },
  363. child: Material(
  364. color: Colors.transparent,
  365. child: SizedBox(
  366. width: double.maxFinite,
  367. key: _keyParent,
  368. child: BottomAreaAvoider(
  369. scrollTo: _scrollController,
  370. areaToAvoid: _offset,
  371. duration: Duration(
  372. milliseconds:
  373. (_timeToDismiss.inMilliseconds * 1.8).toInt()),
  374. autoScroll: true,
  375. child: Container(
  376. child: Column(
  377. children: <Widget>[_buildBody()],
  378. ),
  379. ),
  380. ),
  381. ),
  382. ),
  383. ),
  384. ),
  385. )),
  386. ),
  387. onWillPop: () {
  388. closeEmojiAction();
  389. return Future.value(true);
  390. });
  391. }
  392. // Future<bool> _willPop() {
  393. // print('###### willpop');
  394. //// tempDispose=true;
  395. //// closeEmojiAction();
  396. //// print('isshowemoji:$isShowEmoji');
  397. //// _counter.value = false;
  398. //// print('关闭emoji');
  399. //// FocusScope.of(context).requestFocus(FocusNode());
  400. // Navigator.pop(context);
  401. // return new Future.value(false);
  402. // }
  403. BoxDecoration _getCardDecoration() {
  404. return new BoxDecoration(
  405. color: Colors.white,
  406. boxShadow: [
  407. BoxShadow(
  408. color: Color.fromRGBO(230, 230, 230, 1),
  409. offset: Offset(0, 10),
  410. blurRadius: 8,
  411. )
  412. ],
  413. );
  414. }
  415. //节目主题
  416. Widget _buildProgramCat() {
  417. return new Container(
  418. margin: EdgeInsets.only(top: 15),
  419. decoration: _getCardDecoration(),
  420. child: _bottomBorderBox(
  421. I18n.of(context).program_theme,
  422. programCat == '' ? I18n.of(context).choose : programCat,
  423. false,
  424. null, () {
  425. CustomUI.buildTip(
  426. context, I18n.of(context).please_choose, _buildCategoryButton());
  427. }, rightTextGrey: programCat == ''),
  428. );
  429. }
  430. //选择期待对象
  431. void selectLovePeople() {
  432. var tempSet = lovePeopleId.toSet();
  433. List<Widget> actions = [
  434. FlatButton(
  435. child: fixedText(I18n.of(context).close),
  436. onPressed: () {
  437. tempSet.clear();
  438. Navigator.of(context).pop();
  439. },
  440. ),
  441. FlatButton(
  442. child: fixedText(I18n.of(context).determine),
  443. onPressed: () {
  444. Navigator.of(context).pop();
  445. setState(() {
  446. lovePeopleId = tempSet.toSet();
  447. lovePeople = '';
  448. lovePeopleId.forEach((k) {
  449. lovePeople += (lovePeople == '')
  450. ? WebData().loverPeopleMap[k]
  451. : ('/' + WebData().loverPeopleMap[k]);
  452. });
  453. });
  454. },
  455. ),
  456. ];
  457. //约会节目
  458. showDialog(
  459. context: context,
  460. builder: (BuildContext context) {
  461. return AlertDialog(
  462. title: new Align(
  463. alignment: Alignment.center,
  464. child: Text(I18n.of(context).expect_lover, textScaleFactor: 1.0),
  465. ),
  466. content: new MyDialogContent(
  467. mostNum: 4,
  468. dataMap: WebData().loverPeopleMap,
  469. keyList: tempSet,
  470. ),
  471. contentPadding: EdgeInsets.only(top: 10),
  472. actions: actions,
  473. );
  474. });
  475. }
  476. //选择约会地区
  477. void selectDateRange() async {
  478. Navigator.of(context).push(
  479. new MaterialPageRoute(
  480. builder: (context) {
  481. return SelectPage(
  482. mostNum: 4,
  483. dataId: dateRangeId,
  484. title: I18n.of(context).select_city,
  485. provinces: {'VietNam': WebData().provinces['VietNam']},
  486. cities: WebData().cities,
  487. isSingle: true,
  488. callback: (tempRankId) {
  489. dateRangeId = tempRankId.toSet();
  490. dateRange = '';
  491. dateRangeId.forEach((item) {
  492. var city = item.split('-');
  493. dateRange += dateRange == ''
  494. ? WebData().cities[city[0]][city[1]]
  495. : '/${WebData().cities[city[0]][city[1]]}';
  496. });
  497. Navigator.of(context).pop();
  498. },
  499. );
  500. },
  501. ),
  502. );
  503. }
  504. //选择开始时间
  505. void selectBegin() async {
  506. DateTime _date = DateTime.now();
  507. final DateTime picked = await showDatePicker(
  508. context: context,
  509. initialDate: _date,
  510. firstDate: DateTime(_date.year, _date.month, _date.day),
  511. locale: WebData().locale,
  512. lastDate: DateTime(_date.year, _date.month, _date.day + 7));
  513. setState(() {
  514. if (picked != null) {
  515. beginTime = '${picked.year}-${picked.month}-${picked.day}';
  516. beginTimeId = '${picked.year}-${picked.month}-${picked.day}';
  517. }
  518. });
  519. if (picked == null) _date = DateTime.now();
  520. }
  521. //分类按钮
  522. Widget _buildCategoryButton() {
  523. return Container(
  524. padding: EdgeInsets.only(top: 10),
  525. child: Column(
  526. children: <Widget>[
  527. Container(
  528. child: Row(
  529. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  530. children: <Widget>[
  531. _buildIconButton(1, WebData().getProgramName(context, 0),
  532. Constants.Category1Color, 0),
  533. _buildIconButton(2, WebData().getProgramName(context, 1),
  534. Constants.Category2Color, 1),
  535. _buildIconButton(3, WebData().getProgramName(context, 2),
  536. Constants.Category3Color, 2),
  537. _buildIconButton(4, WebData().getProgramName(context, 3),
  538. Constants.Category4Color, 3),
  539. ],
  540. ),
  541. ),
  542. Container(
  543. child: Row(
  544. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  545. children: <Widget>[
  546. _buildIconButton(5, WebData().getProgramName(context, 4),
  547. Constants.Category5Color, 4),
  548. _buildIconButton(6, WebData().getProgramName(context, 5),
  549. Constants.Category6Color, 5),
  550. _buildIconButton(7, WebData().getProgramName(context, 6),
  551. Constants.Category7Color, 6),
  552. _buildIconButton(8, WebData().getProgramName(context, 7),
  553. Constants.Category8Color, 7),
  554. ],
  555. ),
  556. ),
  557. ],
  558. ));
  559. }
  560. Widget _buildIconButton(iconNum, str, strColor, value) {
  561. Widget icon = Container(
  562. padding: EdgeInsets.only(bottom: 10),
  563. child: Image.asset(
  564. 'assets/images/park/qz_icon$iconNum.png',
  565. height: 60,
  566. ));
  567. Widget text = Positioned(
  568. bottom: 0,
  569. child: Container(
  570. child: new Text(str,
  571. textScaleFactor: 1.0,
  572. style: TextStyle(
  573. color: strColor, fontWeight: FontWeight.w700, fontSize: 13)),
  574. ));
  575. return InkWell(
  576. onTap: () {
  577. setState(() {
  578. programId = value;
  579. programCat = WebData().getProgramName(context, value);
  580. Navigator.of(context).pop();
  581. });
  582. },
  583. highlightColor: Colors.transparent,
  584. radius: 0,
  585. child: Container(
  586. width: (MediaQuery.of(context).size.width * 0.9) / 4,
  587. margin: EdgeInsets.only(top: 10),
  588. child: Stack(
  589. alignment: Alignment.center,
  590. children: <Widget>[
  591. icon,
  592. text,
  593. ],
  594. ),
  595. ));
  596. }
  597. Widget _buildTimeSelect(str, value) {
  598. return InkWell(
  599. child: Container(
  600. margin: EdgeInsets.only(top: 5, bottom: 5),
  601. height: 20,
  602. alignment: Alignment.center,
  603. child: Text(
  604. str,
  605. textScaleFactor: 1.0,
  606. style: TextStyle(fontSize: 15, color: Constants.BlackTextColor),
  607. ),
  608. ),
  609. onTap: () async {
  610. if (WebData().testTimeOver(value, beginTimeId)) {
  611. showToast(I18n.of(context).outTime);
  612. return;
  613. }
  614. setState(() {
  615. endTimeId = value;
  616. endTime = str;
  617. Navigator.of(context).pop();
  618. });
  619. },
  620. );
  621. }
  622. //选择结束时间
  623. void selectEnd() async {
  624. Widget title = Container(
  625. margin: EdgeInsets.only(top: 15, bottom: 10),
  626. alignment: Alignment.center,
  627. child: Text(
  628. I18n.of(context).select_time,
  629. textScaleFactor: 1.0,
  630. style: TextStyle(fontSize: 19, color: Constants.BlackTextColor),
  631. ),
  632. );
  633. List<Widget> list = [title];
  634. WebData().getDateTime(context).forEach((k, v) {
  635. list.add(Divider());
  636. list.add(_buildTimeSelect(v, k));
  637. });
  638. if (beginTimeId == '') {
  639. showToast(I18n.of(context).please_choose4);
  640. return;
  641. }
  642. showModalBottomSheet(
  643. context: context,
  644. builder: (BuildContext context) {
  645. return SafeArea(
  646. child: Container(
  647. height: 345,
  648. child: Column(children: list),
  649. ));
  650. },
  651. ).then((val) {});
  652. }
  653. void _sendPicture() async {
  654. closeEmojiAction();
  655. List<Asset> resultList = List<Asset>();
  656. resultList = await MultiImagePicker.pickImages(
  657. maxImages: Max_Img_Num - imgUrlList.length,
  658. enableCamera: false,
  659. selectedAssets: [],
  660. cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
  661. materialOptions: MaterialOptions(
  662. actionBarColor: "#50A7F9",
  663. actionBarTitle: "Hibok",
  664. allViewTitle: "",
  665. useDetailsView: false,
  666. selectCircleStrokeColor: "#000000",
  667. ),
  668. );
  669. if (resultList != null && resultList.length > 0) {
  670. List<File> fileList = [];
  671. for (var i = 0; i < resultList.length; i++) {
  672. Asset photoEntity = resultList[i];
  673. ByteData byteData = await photoEntity.getByteData();
  674. File file = await FileCacheMgr().writeFile('temp-photo-${DateTime.now().millisecondsSinceEpoch}-$i', byteData.buffer.asInt8List(0));
  675. fileList.add(file);
  676. }
  677. Map data = {"type": 7, "userId": UserData().basicInfo.userId};
  678. data['sign'] = TokenMgr().getSign(data);
  679. Response res = await HttpUtil().uploadFiles(
  680. fileList, data, 'upload/post/postfiles', 'image',
  681. isShowLoading: true);
  682. var resData = res.data;
  683. if (resData['code'] == 0 && resData['msg'] != null) {
  684. imgUrlList.addAll(resData['msg'].split("|"));
  685. setState(() {});
  686. }
  687. }
  688. // var photos = await PhotoPicker.pickAsset(
  689. // context: context,
  690. // themeColor: Color(0xFFF0F0F0),
  691. // maxSelected: Max_Img_Num - imgUrlList.length,
  692. // textColor: Color(0xFF3F3F3F),
  693. // pickType: PickType.onlyImage);
  694. //
  695. // if (photos != null && photos.length > 0) {
  696. // List<File> fileList = [];
  697. // for (var i = 0; i < photos.length; i++) {
  698. // AssetEntity photoEntity = photos[i];
  699. // fileList.add(await photoEntity.file);
  700. // }
  701. // Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  702. // data['sign'] = TokenMgr().getSign(data);
  703. // Response res = await HttpUtil().uploadFiles(
  704. // fileList, data, 'upload/post/postfiles', 'image',
  705. // isShowLoading: true);
  706. // var resData = res.data;
  707. // if (resData['code'] == 0 && resData['msg'] != null) {
  708. // imgUrlList.addAll(resData['msg'].split("|"));
  709. // setState(() {});
  710. // }
  711. // }
  712. }
  713. Widget _buildDynicContent() {
  714. Widget moreInfo = Container(
  715. alignment: Alignment.topCenter,
  716. padding: EdgeInsets.only(left: 15, right: 15),
  717. child: ExtendedTextField(
  718. keyboardAppearance: Brightness.light,
  719. onTap: () {
  720. // if(!isActionFromButton){
  721. isShowEmoji = false;
  722. _counter.value = isShowEmoji;
  723. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  724. // }
  725. },
  726. focusNode: focusNode,
  727. specialTextSpanBuilder:
  728. MySpecialTextSpanBuilder(showAtBackground: true, emojiSize: 17.0),
  729. decoration: new InputDecoration(
  730. hintText: I18n.of(context).please_civilization,
  731. hintStyle: TextStyle(fontSize: 13, height: 1.25),
  732. border: InputBorder.none,
  733. ),
  734. maxLines: 6,
  735. controller: _textCtrl,
  736. style: TextStyle(
  737. fontSize: ScreenUtil().setSp(14),
  738. textBaseline: TextBaseline.alphabetic),
  739. inputFormatters: [LengthLimitingTextInputFormatter(100)],
  740. onChanged: (str) {
  741. if (str.length > 100) {
  742. print('超过100了');
  743. _textCtrl.text = _textCtrl.value.text.substring(0, 100);
  744. int length = _textCtrl.text.length;
  745. Future.delayed(Duration(milliseconds: 100), () {
  746. _textCtrl.selection =
  747. TextSelection(baseOffset: length, extentOffset: length);
  748. });
  749. }
  750. },
  751. ));
  752. List<Widget> imgList = imgUrlList.map((f) {
  753. return _buildImg(f);
  754. }).toList();
  755. if (imgList.length < Max_Img_Num) {
  756. imgList.add(_buildUpButton());
  757. }
  758. Widget picture = Container(
  759. alignment: Alignment.centerLeft,
  760. padding: EdgeInsets.only(left: 15, bottom: 15),
  761. child: Wrap(alignment: WrapAlignment.start, children: imgList));
  762. List<Widget> list = [moreInfo, picture];
  763. return new Container(
  764. margin: EdgeInsets.only(top: 15),
  765. decoration: _getCardDecoration(),
  766. child: Column(
  767. children: list,
  768. ),
  769. );
  770. }
  771. Widget _buildUpButton() {
  772. var color = Colors.grey[350];
  773. return Container(
  774. child: InkWell(
  775. onTap: _sendPicture,
  776. child: Container(
  777. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  778. decoration: BoxDecoration(
  779. borderRadius: BorderRadius.circular(10.0),
  780. border: Border.all(color: color)),
  781. width: 75,
  782. height: 75,
  783. child: ClipRRect(
  784. borderRadius: BorderRadius.circular(10),
  785. child: Icon(
  786. IconData(
  787. 0xe616,
  788. fontFamily: 'iconfont',
  789. ),
  790. color: color),
  791. ))));
  792. }
  793. //节目内容
  794. Widget _buildProgramContent() {
  795. Widget moreInfo = Container(
  796. child: Column(
  797. crossAxisAlignment: CrossAxisAlignment.start,
  798. mainAxisAlignment: MainAxisAlignment.start,
  799. children: <Widget>[
  800. Container(
  801. width: Screen.width,
  802. padding: EdgeInsets.only(
  803. top: 15,
  804. ),
  805. margin: EdgeInsets.only(left: 15),
  806. child: Text(
  807. I18n.of(context).describe_details,
  808. textScaleFactor: 1.0,
  809. style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
  810. )),
  811. Container(
  812. padding: EdgeInsets.only(right: 5),
  813. margin: EdgeInsets.only(left: 15),
  814. child: ExtendedTextField(
  815. keyboardAppearance: Brightness.light,
  816. focusNode: focusNode,
  817. onTap: () {
  818. // if(!isActionFromButton){
  819. isShowEmoji = false;
  820. _counter.value = isShowEmoji;
  821. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  822. // }
  823. if (_scrollController != null) {
  824. ///解决键盘遮挡输入框
  825. _scrollController.position.moveTo(
  826. 200,
  827. duration: Duration(milliseconds: 100),
  828. curve: Curves.easeIn,
  829. );
  830. }
  831. },
  832. controller: _textCtrl,
  833. specialTextSpanBuilder: MySpecialTextSpanBuilder(
  834. showAtBackground: true, emojiSize: 17.0),
  835. decoration: new InputDecoration(
  836. contentPadding:
  837. EdgeInsets.only(top: 6, bottom: 10, right: 10),
  838. hintText: I18n.of(context).please_civilization,
  839. hintStyle:
  840. TextStyle(fontSize: 12, height: 1.15),
  841. border: InputBorder.none,
  842. ),
  843. style: TextStyle(
  844. fontSize: 13, textBaseline: TextBaseline.alphabetic),
  845. maxLines: 6,
  846. // inputFormatters: [LengthLimitingTextInputFormatter(100)],
  847. onChanged: (str) {
  848. if (str.length > 100) {
  849. print('超过100了');
  850. _textCtrl.text = _textCtrl.value.text.substring(0, 100);
  851. int length = _textCtrl.text.length;
  852. Future.delayed(Duration(milliseconds: 100), () {
  853. _textCtrl.selection = TextSelection(
  854. baseOffset: length, extentOffset: length);
  855. });
  856. }
  857. },
  858. )),
  859. ],
  860. ),
  861. );
  862. List<Widget> imgList = imgUrlList.map((f) {
  863. return _buildImg(f);
  864. }).toList();
  865. if (imgList.length < Max_Img_Num) {
  866. imgList.add(_buildUpButton());
  867. }
  868. Widget picture = Container(
  869. alignment: Alignment.topCenter,
  870. child: Row(
  871. children: <Widget>[
  872. Container(
  873. alignment: Alignment.centerLeft,
  874. width: LEFT_WIDTH,
  875. margin: EdgeInsets.only(left: 15),
  876. child: fixedText(I18n.of(context).image,
  877. fontSize: 14, fontWeight: FontWeight.w600)),
  878. Expanded(
  879. child: Container(
  880. margin: EdgeInsets.only(top: 10, bottom: 10),
  881. child:
  882. Wrap(alignment: WrapAlignment.start, children: imgList))),
  883. ],
  884. ),
  885. );
  886. List<Widget> list = [
  887. _bottomBorderBox(
  888. I18n.of(context).expect_lover,
  889. lovePeople == '' ? I18n.of(context).choose : lovePeople,
  890. false,
  891. null,
  892. selectLovePeople,
  893. rightTextGrey: lovePeople == ''),
  894. _buildDivider(),
  895. // _bottomBorderBox(
  896. // I18n.of(context).city,
  897. // dateRange == '' ? I18n.of(context).choose : dateRange,
  898. // false,
  899. // null,
  900. // selectDateRange,
  901. // rightTextGrey: dateRange == ''),
  902. // _buildDivider(),
  903. _bottomBorderBox(
  904. I18n.of(context).time,
  905. beginTime == '' ? I18n.of(context).choose : beginTime,
  906. false,
  907. null,
  908. selectBegin,
  909. rightTextGrey: beginTime == ''),
  910. _buildDivider(),
  911. _bottomBorderBox('', endTime == '' ? I18n.of(context).choose : endTime,
  912. false, null, selectEnd,
  913. rightTextGrey: endTime == ''),
  914. _buildDivider(),
  915. moreInfo,
  916. _buildDivider(),
  917. picture
  918. ];
  919. return new Container(
  920. margin: EdgeInsets.only(top: 15),
  921. decoration: _getCardDecoration(),
  922. child: Column(
  923. children: list,
  924. ),
  925. );
  926. }
  927. //下划线
  928. Widget _buildDivider() {
  929. return new Container(
  930. margin: EdgeInsets.zero,
  931. padding: EdgeInsets.zero,
  932. decoration: BoxDecoration(border: Border(top: Constants.GreyBorderSide)),
  933. height: 1,
  934. width: MediaQuery.of(context).size.width * 0.9,
  935. );
  936. }
  937. Widget _buildImg(f) {
  938. return Stack(
  939. children: <Widget>[
  940. InkWell(
  941. onTap: () {
  942. Navigator.of(context).push(
  943. new MaterialPageRoute(
  944. builder: (context) {
  945. return PicSwiper(
  946. id: imgUrlList.indexOf(f),
  947. pics: imgUrlList
  948. .map((f) => PicSwiperItem(
  949. f,
  950. id: imgUrlList.indexOf(f),
  951. ))
  952. .toList(),
  953. );
  954. },
  955. ),
  956. );
  957. },
  958. child: Container(
  959. height: 75,
  960. width: 75,
  961. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  962. decoration: BoxDecoration(
  963. borderRadius: BorderRadius.circular(10.0),
  964. border: Border.all(color: Colors.grey[300], width: 1),
  965. ),
  966. child: ClipRRect(
  967. borderRadius: BorderRadius.circular(10),
  968. child: f == null
  969. ? Container()
  970. : CachedNetworkImage(
  971. imageUrl: f,
  972. fit: BoxFit.cover,
  973. ),
  974. ))),
  975. Positioned(
  976. right: 0,
  977. child: InkWell(
  978. onTap: () {
  979. imgUrlList.remove(f);
  980. setState(() {});
  981. },
  982. child: Image.asset(
  983. 'assets/images/login/delete.png',
  984. height: 20,
  985. )),
  986. )
  987. ],
  988. );
  989. }
  990. //自定义item
  991. Widget _bottomBorderBox(
  992. String textLeft, String textRight, bool flag, controller, callback,
  993. {bool rightTextGrey = true}) {
  994. Widget left = new Container(
  995. width: LEFT_WIDTH,
  996. child: new Text(
  997. textLeft,
  998. textScaleFactor: 1.0,
  999. style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
  1000. ));
  1001. Widget right = flag
  1002. ? new Expanded(
  1003. child: new TextField(
  1004. keyboardAppearance: Brightness.light,
  1005. controller: controller,
  1006. decoration: new InputDecoration(
  1007. hintText: textRight,
  1008. hintStyle: TextStyle(fontSize: 14),
  1009. border: InputBorder.none,
  1010. ),
  1011. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  1012. maxLines: 1,
  1013. onChanged: (str) {
  1014. if (flag && callback != null) callback(str);
  1015. },
  1016. ),
  1017. )
  1018. : new Expanded(
  1019. child: GestureDetector(
  1020. onTap: () {
  1021. if (!flag && callback != null) callback();
  1022. },
  1023. child: Container(
  1024. color: Colors.transparent,
  1025. height: 53,
  1026. width: MediaQuery.of(context).size.width,
  1027. alignment: Alignment.centerLeft,
  1028. padding: EdgeInsets.only(left: 5),
  1029. child: Text(
  1030. textRight,
  1031. textScaleFactor: 1.0,
  1032. style: TextStyle(
  1033. fontSize: 14,
  1034. color: rightTextGrey
  1035. ? Constants.GreyTextColor
  1036. : Constants.BlackTextColor),
  1037. ),
  1038. ),
  1039. ),
  1040. );
  1041. return new Container(
  1042. height: 53,
  1043. margin: EdgeInsets.only(left: 15, bottom: 0),
  1044. child: new Row(
  1045. children: <Widget>[left, right],
  1046. ),
  1047. );
  1048. }
  1049. Widget _buildSwitch(str, value, callback) {
  1050. Widget left = new Text(
  1051. str,
  1052. textScaleFactor: 1.0,
  1053. style: TextStyle(
  1054. fontSize: 14,
  1055. fontWeight: widget.isProgram ? FontWeight.w600 : FontWeight.normal),
  1056. );
  1057. Widget right = new Expanded(
  1058. child: new Align(
  1059. alignment: Alignment.centerRight,
  1060. child: new Switch(
  1061. activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3),
  1062. value: value,
  1063. onChanged: (bool val) {
  1064. callback();
  1065. },
  1066. )));
  1067. return new Container(
  1068. padding: EdgeInsets.only(left: 15),
  1069. height: 53,
  1070. child: new Row(
  1071. children: <Widget>[left, right],
  1072. ),
  1073. );
  1074. }
  1075. Widget _buildSelct() {
  1076. return new Container(
  1077. decoration: _getCardDecoration(),
  1078. //margin: EdgeInsets.only(top: , bottom: 0),
  1079. child: Column(
  1080. children: <Widget>[
  1081. _buildSwitch(I18n.of(context).prohibit_comments, isCanContent, () {
  1082. setState(() {
  1083. isCanContent = !isCanContent;
  1084. });
  1085. }),
  1086. _buildDivider(),
  1087. _buildSwitch(I18n.of(context).same_sex, isHidden, () {
  1088. setState(() {
  1089. isHidden = !isHidden;
  1090. });
  1091. }),
  1092. ],
  1093. ));
  1094. }
  1095. Widget _buildTip() {
  1096. return Container(
  1097. alignment: Alignment.centerLeft,
  1098. margin: EdgeInsets.only(top: 10, bottom: 10, left: 10),
  1099. child: Text(
  1100. I18n.of(context).dont,
  1101. textScaleFactor: 1.0,
  1102. style: TextStyle(fontSize: 12, color: Constants.GreyTextColor),
  1103. ),
  1104. );
  1105. }
  1106. Widget _buildTips() {
  1107. String str = '';
  1108. if (UserData().isMan()) {
  1109. str = I18n.of(context)
  1110. .member_free
  1111. .replaceFirst('/s1', UserData().addProgramPrice.toString());
  1112. } else {
  1113. str = I18n.of(context)
  1114. .certified_free
  1115. .replaceFirst('/s1', UserData().addProgramPrice.toString());
  1116. }
  1117. return Container(
  1118. padding: EdgeInsets.only(bottom: 100, left: 20, right: 20),
  1119. child: Text(
  1120. str,
  1121. textScaleFactor: 1.0,
  1122. style: TextStyle(fontSize: 12, color: Constants.GreyTextColor),
  1123. ),
  1124. );
  1125. }
  1126. Widget _buildBody() {
  1127. List<Widget> program = [
  1128. _buildProgramCat(),
  1129. _buildProgramContent(),
  1130. _buildTip(),
  1131. _buildSelct(),
  1132. _buildLoginButton(),
  1133. _buildTips()
  1134. ];
  1135. List<Widget> dynamics = [
  1136. _buildDynicContent(),
  1137. _buildTip(),
  1138. _buildSelct(),
  1139. _buildLoginButton(),
  1140. _buildTips()
  1141. ];
  1142. return Column(
  1143. children: widget.isProgram ? program : dynamics,
  1144. );
  1145. }
  1146. //构建登陆按钮
  1147. Widget _buildLoginButton() {
  1148. Text text = new Text(I18n.of(context).release,
  1149. textScaleFactor: 1.0,
  1150. style: TextStyle(fontSize: 15, color: Colors.white));
  1151. LinearGradient gradientColor = new LinearGradient(colors: <Color>[
  1152. Constants.ConfrimButtonColor,
  1153. Constants.ConfrimButtonColor
  1154. ]);
  1155. callback() async {
  1156. closeEmojiAction();
  1157. if (widget.isProgram) {
  1158. if (programId == -1) {
  1159. showToast(I18n.of(context).please_choose);
  1160. return;
  1161. }
  1162. if (lovePeopleId.length == 0) {
  1163. showToast(I18n.of(context).please_choose2);
  1164. return;
  1165. }
  1166. // if (dateRangeId.length == 0) {
  1167. // showToast(I18n.of(context).please_choose3);
  1168. // return;
  1169. // }
  1170. if (beginTimeId == '') {
  1171. showToast(I18n.of(context).please_choose4);
  1172. return;
  1173. }
  1174. if (endTimeId == -1) {
  1175. showToast(I18n.of(context).please_choose5);
  1176. return;
  1177. }
  1178. } else {
  1179. if (_textCtrl.value.text.trim().length == 0 && imgUrlList.length == 0) {
  1180. showToast(I18n.of(context).enter_something);
  1181. return;
  1182. }
  1183. }
  1184. payCallback() {
  1185. if (Provider.of<MoneyChangeProvider>(context).money <
  1186. UserData().addProgramPrice) {
  1187. CustomUI.buildOneConfirm(
  1188. context,
  1189. I18n.of(context).balance_insufficien,
  1190. I18n.of(context).recharge, () {
  1191. Navigator.of(context).pop();
  1192. ChargeMoney.showChargeSheet(context, () {
  1193. setState(() {});
  1194. });
  1195. });
  1196. return;
  1197. }
  1198. Navigator.of(context).pop();
  1199. postAddProgram(UserData().addProgramPrice);
  1200. }
  1201. String title = widget.isProgram
  1202. ? I18n.of(context).release_program
  1203. : I18n.of(context).release_dynamics;
  1204. //非会员男士提示付费
  1205. if (!UserData().isVip && UserData().isMan()) {
  1206. bool isMan = UserData().isMan();
  1207. CustomUI.buildTowConfirm(
  1208. context,
  1209. title,
  1210. isMan
  1211. ? I18n.of(context).become_member2
  1212. : I18n.of(context).now_certification,
  1213. () {
  1214. Navigator.of(context).push(
  1215. new MaterialPageRoute(
  1216. builder: (context) {
  1217. return isMan ? VipPage() : VerificationCenterPage();
  1218. },
  1219. ),
  1220. );
  1221. },
  1222. I18n.of(context)
  1223. .raid_release
  1224. .replaceFirst('/s1', UserData().addProgramPrice.toString()),
  1225. payCallback,
  1226. );
  1227. return;
  1228. }
  1229. //免费次数用完提示付费
  1230. if (UserData().basicInfo.usedPublishNum >=
  1231. UserData().basicInfo.publishNum) {
  1232. CustomUI.buildOneConfirm(
  1233. context,
  1234. title,
  1235. I18n.of(context)
  1236. .pay_unlock
  1237. .replaceFirst('/s1', UserData().addProgramPrice.toString()),
  1238. payCallback);
  1239. return;
  1240. }
  1241. HttpUtil().userFreeTime(context, UserData().basicInfo.userId, 3, () {
  1242. UserData().basicInfo.usedPublishNum++;
  1243. postAddProgram(0);
  1244. });
  1245. }
  1246. return new Container(
  1247. margin: EdgeInsets.only(top: 30, bottom: 10),
  1248. height: 44,
  1249. width: MediaQuery.of(context).size.width * 0.8,
  1250. child: ShadowButton().builder(gradientColor, text, callback),
  1251. );
  1252. }
  1253. postAddProgram(price) async {
  1254. var dateRangeStr = '';
  1255. dateRangeId.forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f');
  1256. var hopeObject = '';
  1257. lovePeopleId.forEach((f) => hopeObject += hopeObject == '' ? f : ',$f');
  1258. String temp='';
  1259. String postTemp='';
  1260. imgUrlList.forEach((str) {
  1261. temp += (temp == "" ? str : '|$str');
  1262. postTemp += (postTemp == ""
  1263. ? WebData().deleteDemain(str)
  1264. : '|${WebData().deleteDemain(str)}');
  1265. });
  1266. var type = widget.isProgram ? 0 : 1;
  1267. Map data = {
  1268. "userId": UserData().basicInfo.userId,
  1269. "type": type,
  1270. "price": price,
  1271. };
  1272. data['sign'] = TokenMgr().getSign(data);
  1273. //data['city'] = dateRangeStr;
  1274. data['programType'] = programId;
  1275. data['hopeObject'] = hopeObject;
  1276. data['aboutTime'] = beginTimeId;
  1277. data['content'] = _textCtrl.text;
  1278. data['imgUrl'] = postTemp;
  1279. data['evaluateStatus'] = isCanContent;
  1280. data['sexStatus'] = isHidden;
  1281. data['timeQuantum'] = endTimeId;
  1282. Response res = await HttpUtil()
  1283. .post('station/publish/program', data: data, isShowLoading: true);
  1284. var resData = res.data;
  1285. if (resData['code'] == 0) {
  1286. if (widget.isProgram) {
  1287. UserData().isCanProgram = false;
  1288. }
  1289. MessageMgr().emit('Add_program', {
  1290. 'Id': resData['data'],
  1291. 'UserId': UserData().basicInfo.userId,
  1292. 'NickName': UserData().basicInfo.nickName,
  1293. 'HeadimgUrl': UserData().basicInfo.headimgurl,
  1294. 'Type': type,
  1295. 'Sex': UserData().basicInfo.sex,
  1296. 'IsMember': UserData().basicInfo.isMember,
  1297. 'ProgramType': programId,
  1298. 'HopeObject': hopeObject,
  1299. 'City': dateRangeStr,
  1300. 'AboutTime': beginTimeId,
  1301. 'timeQuantum': endTimeId,
  1302. 'Content': _textCtrl.text,
  1303. 'ImgUrl': temp,
  1304. 'EvaluateStatus': isCanContent ? 1 : 0,
  1305. 'SexStatus': isHidden,
  1306. 'Status': 0,
  1307. 'CreateTime': DateTime.now().toIso8601String(),
  1308. 'FabulousNum': 0,
  1309. 'EvaluateNum': 0,
  1310. 'EnrollNum': 0,
  1311. 'IsAttestation': UserData().basicInfo.isAttestation ? 1 : 0,
  1312. 'IsFabulous': 0,
  1313. 'IsEnroll': 0,
  1314. 'EvaluateList': null,
  1315. "FabulousList": []
  1316. });
  1317. Navigator.of(context).pop();
  1318. focusNode.removeListener(_focusNodeListener);
  1319. } else {
  1320. showToast(resData['msg']);
  1321. }
  1322. }
  1323. }