Hibok
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

614 行
21 KiB

  1. import 'package:chat/data/UserData.dart';
  2. import 'package:chat/data/WebData.dart';
  3. import 'package:chat/data/conversation.dart';
  4. import 'package:chat/data/group_data_mgr.dart';
  5. import 'package:chat/generated/i18n.dart';
  6. import 'package:chat/home/InfoList.dart';
  7. import 'package:chat/home/last_chat_record_widget.dart';
  8. import 'package:chat/home/rich_title.dart';
  9. import 'package:chat/home/unread_dot_widget.dart';
  10. import 'package:chat/models/group_info_model.dart';
  11. import 'package:chat/utils/CustomUI.dart';
  12. import 'package:chat/utils/HttpUtil.dart';
  13. import 'package:chat/utils/MessageMgr.dart';
  14. import 'package:chat/utils/TokenMgr.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:shared_preferences/shared_preferences.dart';
  20. import '../data/constants.dart'
  21. show
  22. AppColors,
  23. AppStyles,
  24. Constants,
  25. GlobalSearchPageType,
  26. GroupOperatingPageType;
  27. import 'package:cached_network_image/cached_network_image.dart';
  28. import 'create_group_view.dart';
  29. import 'global_search.dart';
  30. import 'group_item_widget.dart';
  31. class _ConversationItem extends StatelessWidget {
  32. const _ConversationItem(
  33. {Key key,
  34. this.conversation,
  35. this.callback,
  36. this.icon,
  37. this.bgColor,
  38. this.iconSize = 20})
  39. : assert(conversation != null),
  40. super(key: key);
  41. final icon;
  42. final double iconSize;
  43. final Conversation conversation;
  44. final callback;
  45. final bgColor;
  46. @override
  47. Widget build(BuildContext context) {
  48. Widget avatar;
  49. if (icon != null) {
  50. avatar = Container(
  51. height: 47.5,
  52. width: 47.5,
  53. margin: EdgeInsets.only(left: 6),
  54. alignment: Alignment.center,
  55. decoration: BoxDecoration(
  56. gradient: bgColor,
  57. borderRadius: BorderRadius.all(Radius.circular(50))),
  58. child: Image.asset(
  59. icon,
  60. height: iconSize,
  61. ));
  62. } else if (conversation.isAvatarFromNet()) {
  63. avatar = CachedNetworkImage(
  64. imageUrl: conversation.avatar,
  65. placeholder: CustomUI.buildImgLoding,
  66. width: Constants.ConversationAvatarSize,
  67. height: Constants.ConversationAvatarSize,
  68. );
  69. } else {
  70. avatar = Image.asset(
  71. conversation.avatar,
  72. width: Constants.ConversationAvatarSize,
  73. height: Constants.ConversationAvatarSize,
  74. );
  75. }
  76. List<Widget> _rightArea = [
  77. Container(
  78. padding: EdgeInsets.only(top: 4),
  79. alignment: Alignment.center,
  80. child: Text(conversation.updateAt,
  81. textScaleFactor: 1.0,
  82. style: TextStyle(fontSize: 11, color: const Color(0xFFC6C6C6))),
  83. )
  84. ];
  85. if (conversation.unreadMsgCount > 0) {
  86. var countStr = conversation.unreadMsgCount.toString();
  87. if (conversation.unreadMsgCount > 99) {
  88. countStr = '99+';
  89. }
  90. // 未读消息角标
  91. Widget unreadMsgCountText = Container(
  92. width: Constants.UnReadMsgNotifyDotSize,
  93. height: Constants.UnReadMsgNotifyDotSize,
  94. alignment: Alignment.center,
  95. decoration: BoxDecoration(
  96. borderRadius:
  97. BorderRadius.circular(Constants.UnReadMsgNotifyDotSize / 2.0),
  98. color: Color(0xFFFF5454),
  99. ),
  100. child: Text(countStr,
  101. textScaleFactor: 1.0, style: AppStyles.UnreadMsgCountDotStyle),
  102. );
  103. _rightArea.add(Expanded(
  104. child: Align(
  105. alignment: Alignment.bottomCenter,
  106. child: unreadMsgCountText,
  107. )));
  108. }
  109. return InkWell(
  110. child: Container(
  111. padding: const EdgeInsets.all(10.0),
  112. decoration: BoxDecoration(
  113. color: Color(AppColors.ConversationItemBgColor),
  114. ),
  115. child: Row(
  116. crossAxisAlignment: CrossAxisAlignment.center,
  117. children: <Widget>[
  118. avatar,
  119. Container(width: 17.0),
  120. Expanded(
  121. child: Column(
  122. crossAxisAlignment: CrossAxisAlignment.start,
  123. children: <Widget>[
  124. Text(conversation.title,
  125. textScaleFactor: 1.0,
  126. style: TextStyle(
  127. color: Colors.black,
  128. )),
  129. SizedBox(
  130. height: 5,
  131. ),
  132. Text(conversation.desc,
  133. textScaleFactor: 1.0,
  134. style: TextStyle(
  135. fontSize: 12, color: const Color(0xFF9B9B9B)))
  136. ],
  137. ),
  138. ),
  139. // Container(width: 10.0),
  140. SizedBox(
  141. height: Constants.ConversationAvatarSize,
  142. child: Column(
  143. crossAxisAlignment: CrossAxisAlignment.end,
  144. mainAxisAlignment: MainAxisAlignment.start,
  145. children: _rightArea,
  146. ),
  147. )
  148. ],
  149. ),
  150. ),
  151. onTap: () {
  152. callback();
  153. },
  154. );
  155. }
  156. }
  157. class ConversActionPage extends StatefulWidget {
  158. ConversActionPage({Key key}) : super(key: key);
  159. _ConversActionPageState createState() => _ConversActionPageState();
  160. }
  161. Map systemInfo = {
  162. 'applyList': null,
  163. 'applyCount': 0,
  164. 'evaluateList': null,
  165. 'evaluateCount': 0,
  166. 'parkList': null,
  167. 'parkCount': 0,
  168. 'castList': null,
  169. 'castCount': 0,
  170. 'walletList': null,
  171. 'walletCount': 0,
  172. };
  173. int msgNum = 0;
  174. bool isShowMsg() {
  175. return msgNum > 0;
  176. }
  177. getAllResNum(prefs) {
  178. getResNum(prefs, Constants.ApplyCount);
  179. getResNum(prefs, Constants.EvaluateCount);
  180. getResNum(prefs, Constants.ParkCount);
  181. getResNum(prefs, Constants.CastCount);
  182. getResNum(prefs, Constants.WalletCount);
  183. }
  184. getResNum(prefs, url) async {
  185. var count = prefs.getInt(url + UserData().basicInfo.userId.toString());
  186. systemInfo[url] = count == null ? systemInfo[url] : (systemInfo[url] - count);
  187. msgNum += systemInfo[url];
  188. }
  189. setResNum(url) async {
  190. var localKey = url + UserData().basicInfo.userId.toString();
  191. if (systemInfo[url] > 0) {
  192. SharedPreferences prefs = await SharedPreferences.getInstance();
  193. var count = prefs.getInt(localKey);
  194. prefs.setInt(
  195. localKey, count == null ? systemInfo[url] : (systemInfo[url] + count));
  196. msgNum -= systemInfo[url];
  197. systemInfo[url] = 0;
  198. }
  199. }
  200. class _ConversActionPageState extends State<ConversActionPage>
  201. with SingleTickerProviderStateMixin {
  202. TabController tabCtrl;
  203. void getSystemMsg(data) async {
  204. Map data = {
  205. "userId": UserData().basicInfo.userId,
  206. "type": UserData().basicInfo.sex
  207. };
  208. data['sign'] = TokenMgr().getSign(data);
  209. Response res = await HttpUtil().post('message/all/message', data: data);
  210. if (res == null) {
  211. return;
  212. }
  213. Map resData = res.data;
  214. if (resData['code'] == 0) {
  215. SharedPreferences prefs = await SharedPreferences.getInstance();
  216. systemInfo = resData['data'];
  217. msgNum = 0;
  218. getAllResNum(prefs);
  219. if (mounted) {
  220. setState(() {});
  221. }
  222. }
  223. }
  224. @override
  225. void initState() {
  226. super.initState();
  227. MessageMgr().on('update_system', getSystemMsg);
  228. MessageMgr().on('Quit Group', quitGroup);
  229. MessageMgr().on('Update Group List', updateGroupLastMsg);
  230. getSystemMsg(null);
  231. tabCtrl = TabController(length: 3, vsync: this);
  232. }
  233. @override
  234. void dispose() {
  235. tabCtrl.dispose();
  236. MessageMgr().off('update_system', getSystemMsg);
  237. super.dispose();
  238. }
  239. @override
  240. Widget build(BuildContext context) {
  241. List<GroupInfoModel> groupList = GroupInfoMgr().groupInfoList;
  242. return Scaffold(
  243. backgroundColor: Colors.white,
  244. appBar: AppBar(
  245. //backgroundColor: Constants.LightGreyBackgroundColor,
  246. centerTitle: false,
  247. title: Text(
  248. I18n.of(context).message_center,
  249. textScaleFactor: 1.0,
  250. style: Constants.MainTitleStyle,
  251. ),
  252. actions: <Widget>[
  253. Container(
  254. child: IconButton(
  255. icon: CircleAvatar(
  256. backgroundColor: Constants.GreyBackgroundColor,
  257. radius: 13.75,
  258. child: Padding(
  259. padding: EdgeInsets.only(bottom: 1.5),
  260. child: Icon(
  261. IconData(0xe659,
  262. fontFamily: Constants.IconFontFamily),
  263. color: Constants.BlackTextColor,
  264. size: 21,
  265. ))),
  266. onPressed: () {
  267. CustomUI().goScanPage(context);
  268. },
  269. ),
  270. ),
  271. // InkWell(
  272. // onTap: () {
  273. // Navigator.of(context).push(
  274. // new MaterialPageRoute(
  275. // builder: (context) {
  276. // return MessagePushPage();
  277. // },
  278. // ),
  279. // );
  280. // },
  281. // child: Padding(
  282. // padding: EdgeInsets.only(right: 10),
  283. // child: CircleAvatar(
  284. // backgroundColor: Constants.GreyBackgroundColor,
  285. // radius: 13.75,
  286. // child: Icon(
  287. // Icons.settings,
  288. // color: Constants.BlackTextColor,
  289. // size: 22,
  290. // )),
  291. // )),
  292. ],
  293. elevation: 0,
  294. bottom: PreferredSize(
  295. preferredSize: Size.fromHeight(28),
  296. child: Container(
  297. padding: EdgeInsets.only(left: 2),
  298. decoration: BoxDecoration(
  299. //color: Constants.LightGreyBackgroundColor,
  300. border:
  301. Border(bottom: BorderSide(color: Color(0xffeaeaea)))),
  302. alignment: Alignment.centerLeft,
  303. child: TabBar(
  304. isScrollable: true,
  305. indicatorPadding: EdgeInsets.only(left: 9, right: 9),
  306. tabs: <Widget>[
  307. UnreadDot(
  308. child: Container(
  309. margin: EdgeInsets.only(right: 4),
  310. child: Text(I18n.of(context).text_chat,
  311. textScaleFactor: 1.0),
  312. ),
  313. type: 1),
  314. UnreadDot(
  315. child: Container(
  316. margin: EdgeInsets.only(right: 4),
  317. child: Text(I18n.of(context).group_chat,
  318. textScaleFactor: 1.0),
  319. ),
  320. type: 4),
  321. UnreadDot(
  322. child: Container(
  323. margin: EdgeInsets.only(right: 4),
  324. child: Text(I18n.of(context).system_information,
  325. textScaleFactor: 1.0)),
  326. type: 2),
  327. ],
  328. controller: tabCtrl,
  329. ),
  330. )),
  331. ),
  332. body: SafeArea(
  333. child: TabBarView(
  334. children: <Widget>[
  335. LastChatPage(),
  336. ListView.builder(
  337. // controller: _scrollController,
  338. itemBuilder: (BuildContext context, int index) {
  339. if (index == 0) {
  340. return _buildCreateButton();
  341. } else {
  342. var info = groupList[index - 1];
  343. return GroupItem(ValueKey(info), groupInfoModel: info);
  344. }
  345. },
  346. itemCount: groupList.length + 1,
  347. ),
  348. ListView(
  349. children: <Widget>[
  350. SizedBox(height: 8.5),
  351. _ConversationItem(
  352. icon: 'assets/images/chat/icon1.png',
  353. bgColor: Constants.RadioGradient,
  354. conversation: Conversation(
  355. avatar: 'assets/images/ic_tx_news.png',
  356. title: I18n.of(context).radio_message,
  357. desc: RichTitle.normalTitle(
  358. systemInfo['castList'], context, InfoType.Radio),
  359. updateAt: systemInfo['castList'] == null
  360. ? ""
  361. : WebData().getLoginTime(
  362. context, systemInfo['castList']['CreateTime']),
  363. unreadMsgCount: systemInfo['castCount'],
  364. ),
  365. callback: () {
  366. setResNum(Constants.CastCount);
  367. Navigator.of(context).push(
  368. new MaterialPageRoute(
  369. builder: (context) {
  370. return InfoListPage(
  371. title: I18n.of(context).radio_message,
  372. type: InfoType.Radio,
  373. );
  374. },
  375. ),
  376. );
  377. },
  378. ),
  379. _ConversationItem(
  380. icon: 'assets/images/chat/icon4.png',
  381. bgColor: Constants.MoneyGradient,
  382. conversation: Conversation(
  383. avatar: 'assets/images/ic_tx_news.png',
  384. title: I18n.of(context).wallet_reminder,
  385. desc: RichTitle.normalTitle(
  386. systemInfo['walletList'], context, InfoType.Money),
  387. updateAt: systemInfo['walletList'] == null
  388. ? ""
  389. : WebData().getLoginTime(
  390. context, systemInfo['walletList']['CreateTime']),
  391. unreadMsgCount: systemInfo['walletCount'],
  392. ),
  393. callback: () {
  394. setResNum(Constants.WalletCount);
  395. Navigator.of(context).push(
  396. new MaterialPageRoute(
  397. builder: (context) {
  398. return InfoListPage(
  399. title: I18n.of(context).wallet_reminder,
  400. type: InfoType.Money,
  401. );
  402. },
  403. ),
  404. );
  405. },
  406. ),
  407. _ConversationItem(
  408. icon: 'assets/images/chat/icon3.png',
  409. iconSize: 27,
  410. bgColor: Constants.ApplyGradient,
  411. conversation: Conversation(
  412. avatar: 'assets/images/ic_tx_news.png',
  413. title: I18n.of(context).application_notice,
  414. desc: RichTitle.normalTitle(
  415. systemInfo['applyList'], context, InfoType.Apply),
  416. updateAt: systemInfo['applyList'] == null
  417. ? ""
  418. : WebData().getLoginTime(
  419. context, systemInfo['applyList']['CreatTime']),
  420. unreadMsgCount: systemInfo['applyCount'],
  421. ),
  422. callback: () {
  423. setResNum(Constants.ApplyCount);
  424. Navigator.of(context).push(
  425. new MaterialPageRoute(
  426. builder: (context) {
  427. return InfoListPage(
  428. title: I18n.of(context).application_notice,
  429. type: InfoType.Apply,
  430. );
  431. },
  432. ),
  433. );
  434. },
  435. ),
  436. _ConversationItem(
  437. icon: 'assets/images/chat/icon6.png',
  438. bgColor: Constants.EvaGradient,
  439. conversation: Conversation(
  440. avatar: 'assets/images/ic_tx_news.png',
  441. title: I18n.of(context).evaluation_notice,
  442. desc: RichTitle.normalTitle(systemInfo['evaluateList'],
  443. context, InfoType.Evaluation),
  444. updateAt: systemInfo['evaluateList'] == null
  445. ? ''
  446. : WebData().getLoginTime(
  447. context, systemInfo['evaluateList']['CreateTime']),
  448. unreadMsgCount: systemInfo['evaluateCount'],
  449. ),
  450. callback: () {
  451. setResNum(Constants.EvaluateCount);
  452. Navigator.of(context).push(
  453. new MaterialPageRoute(
  454. builder: (context) {
  455. return InfoListPage(
  456. title: I18n.of(context).evaluation_notice,
  457. type: 2,
  458. );
  459. },
  460. ),
  461. );
  462. },
  463. ),
  464. _ConversationItem(
  465. icon: 'assets/images/chat/icon5.png',
  466. bgColor: Constants.ParkGradient,
  467. conversation: Conversation(
  468. avatar: 'assets/images/ic_tx_news.png',
  469. title: I18n.of(context).appName,
  470. desc: RichTitle.normalTitle(
  471. systemInfo['parkList'], context, InfoType.System),
  472. updateAt: systemInfo['parkList'] == null
  473. ? ""
  474. : WebData().getLoginTime(
  475. context, systemInfo['parkList']['CreateTime']),
  476. unreadMsgCount: systemInfo['parkCount'],
  477. ),
  478. callback: () {
  479. setResNum(Constants.ParkCount);
  480. Navigator.of(context).push(
  481. new MaterialPageRoute(
  482. builder: (context) {
  483. return InfoListPage(
  484. title: I18n.of(context).appName,
  485. type: InfoType.System,
  486. );
  487. },
  488. ),
  489. );
  490. },
  491. )
  492. ],
  493. )
  494. ],
  495. controller: tabCtrl,
  496. )));
  497. }
  498. Widget _buildCreateButton() {
  499. List<GroupInfoModel> groupList = GroupInfoMgr().groupInfoList;
  500. Widget _avatarIcon = ClipRRect(
  501. borderRadius: BorderRadius.circular(GroupRadius),
  502. child: Container(
  503. color: const Color(0xFFF2F2F2),
  504. height: AvatarSize,
  505. width: AvatarSize,
  506. child: Icon(
  507. IconData(0xe66f, fontFamily: Constants.IconFontFamily),
  508. color: Constants.BlueTextColor,
  509. size: 35,
  510. ),
  511. ));
  512. Widget _button = InkWell(
  513. onTap: () {
  514. Navigator.of(context).push(
  515. new MaterialPageRoute(
  516. builder: (context) {
  517. return CreateGroupPage(
  518. GroupOperatingPageType.CreateGroup, [], null);
  519. },
  520. ),
  521. );
  522. },
  523. child: Container(
  524. padding: EdgeInsets.only(top: 14, bottom: 14),
  525. color: Constants.GreyBackgroundColor,
  526. child: Container(
  527. height: ItemHeight,
  528. decoration: BoxDecoration(color: Colors.white),
  529. child: Row(
  530. children: <Widget>[
  531. SizedBox(width: LeftPadding),
  532. _avatarIcon,
  533. SizedBox(width: 14.0),
  534. Text(
  535. I18n.of(context).create_group_chat,
  536. style: TextStyle(fontSize: 15.5),
  537. ),
  538. ],
  539. ),
  540. )));
  541. Widget tips = Container(
  542. alignment: Alignment.centerLeft,
  543. width: Screen.width,
  544. height: 33.5,
  545. padding: EdgeInsets.only(left: LeftPadding),
  546. decoration: BoxDecoration(
  547. color: Colors.white,
  548. border: Border(bottom: Constants.GreyBorderSide)),
  549. child: Text(I18n.of(context).group_chat + '(${groupList.length})'),
  550. );
  551. return Column(
  552. children: <Widget>[
  553. SizedBox(
  554. height: 10,
  555. ),
  556. CustomUI.buildSearchButton(context, () {
  557. Navigator.of(context).push(
  558. new MaterialPageRoute(
  559. builder: (context) {
  560. return GlobalSearchPage(
  561. type: GlobalSearchPageType.SearchGroup,
  562. );
  563. },
  564. ),
  565. );
  566. }, bottom: 10),
  567. _button,
  568. tips,
  569. ],
  570. );
  571. }
  572. quitGroup(args) {
  573. if (mounted) {
  574. setState(() {
  575. print('更新群列表');
  576. });
  577. }
  578. }
  579. updateGroupLastMsg(args) async {
  580. await GroupInfoMgr().sortGroupList();
  581. if (mounted) {
  582. setState(() {});
  583. }
  584. }
  585. }