Hibok
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

504 satır
16 KiB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:chat/home/global_search.dart';
  3. import 'package:chat/home/new_addfriends.dart';
  4. import 'package:chat/home/new_friends.dart';
  5. import 'package:chat/models/friends_info.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:chat/data/UserData.dart';
  8. import 'package:chat/data/constants.dart';
  9. import 'package:chat/generated/i18n.dart';
  10. import 'package:chat/models/ref_name_provider.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/conversation_table.dart';
  16. import 'package:chat/utils/friend_list_mgr.dart';
  17. import 'package:chat/utils/screen.dart';
  18. import 'package:dio/dio.dart';
  19. import 'package:oktoast/oktoast.dart';
  20. import 'package:provider/provider.dart';
  21. import 'package:shared_preferences/shared_preferences.dart';
  22. List showUserList = [];
  23. bool isHaveNewFriends() {
  24. return showUserList.length > 0;
  25. }
  26. class FriendPage extends StatefulWidget {
  27. @override
  28. _FriendPageState createState() => _FriendPageState();
  29. }
  30. class _FriendPageState extends State<FriendPage> {
  31. String _currentLetter = '';
  32. ScrollController _scrollController;
  33. List<FriendModel> friendList = [];
  34. List<Widget> _functionButtons = [];
  35. final Map _letterPosMap = {INDEX_BAR_WORDS[0]: 0.0};
  36. Set<String> userIdSet = new Set();
  37. //var _contactsFuture;
  38. @override
  39. void initState() {
  40. super.initState();
  41. print('FriendPage initState');
  42. initNewFriendsList([]);
  43. getFriendList();
  44. getNewFriendList(null);
  45. _scrollController = new ScrollController();
  46. MessageMgr().on('Add friend', msgAddfrend);
  47. MessageMgr().on('Delete friend', msgDeletefrend);
  48. MessageMgr().on('do_friend_apply', messageApply);
  49. MessageMgr().on('goto_new_friends', messageNew);
  50. }
  51. messageApply(data) {
  52. getNewFriendList(data);
  53. }
  54. messageNew(data) {
  55. gotoNewFriendsPage();
  56. }
  57. gotoNewFriendsPage() async {
  58. Navigator.of(context).push(
  59. new MaterialPageRoute(
  60. builder: (context) {
  61. return NewFriendsPage();
  62. },
  63. ),
  64. );
  65. SharedPreferences prefs = await SharedPreferences.getInstance();
  66. prefs.setStringList(Constants.NewFriendsList, userIdSet.toList());
  67. showUserList = [];
  68. initNewFriendsList([]);
  69. setState(() {});
  70. }
  71. Widget _buildNewFriends(list) {
  72. if (list.length == 0) {
  73. return FriendsInfo(
  74. avatar: '',
  75. userId: 0,
  76. iconCode: 0xe66c,
  77. title: I18n.of(Constants.getCurrentContext()).new_friends,
  78. gradient: LinearGradient(
  79. begin: Alignment.topCenter,
  80. end: Alignment.bottomCenter,
  81. colors: <Color>[
  82. const Color(0xFF58B7F5),
  83. const Color(0xFF1874C9),
  84. ]),
  85. onPressed: gotoNewFriendsPage);
  86. } else {
  87. return _buildFriendsItem(list);
  88. }
  89. }
  90. Widget _buildAvatar(url) {
  91. return ClipRRect(
  92. borderRadius: BorderRadius.circular(6),
  93. child: CachedNetworkImage(
  94. imageUrl: url,
  95. placeholder: (context, url) => Image.asset(
  96. Constants.DefaultHeadImgUrl,
  97. width: Constants.ContactAvatarSize,
  98. height: Constants.ContactAvatarSize,
  99. ),
  100. width: Constants.ContactAvatarSize,
  101. height: Constants.ContactAvatarSize,
  102. ));
  103. }
  104. Widget _buildFriendsItem(list) {
  105. Widget unreadRedDot = Container(
  106. margin: EdgeInsets.only(right: 15),
  107. width: Constants.UnReadMsgNotifyDotSize,
  108. height: Constants.UnReadMsgNotifyDotSize,
  109. alignment: Alignment.center,
  110. decoration: BoxDecoration(
  111. borderRadius:
  112. BorderRadius.circular(Constants.UnReadMsgNotifyDotSize / 2.0),
  113. color: Color(0xFFFF5454),
  114. ),
  115. child: Text(list.length > 99 ? "99+" : list.length.toString(),
  116. textScaleFactor: 1.0, style: AppStyles.UnreadMsgCountDotStyle),
  117. );
  118. var left;
  119. if (list.length == 1) {
  120. left = Row(
  121. children: <Widget>[
  122. _buildAvatar(list[0]['ApplyUrl']),
  123. SizedBox(width: 10.0),
  124. Expanded(
  125. child: Column(
  126. crossAxisAlignment: CrossAxisAlignment.start,
  127. children: <Widget>[
  128. Text(list[0]['ApplyName'],
  129. textScaleFactor: 1.0, style: TextStyle(fontSize: 12.66)),
  130. SizedBox(
  131. height: 5,
  132. ),
  133. Text(
  134. list[0]['Content'] == null || list[0]['Content'] == ''
  135. ? I18n.of(context).apply_fro_friends
  136. : list[0]['Content'],
  137. textScaleFactor: 1.0,
  138. style:
  139. TextStyle(fontSize: 10, color: const Color(0xFF6A6A6A))),
  140. ],
  141. )),
  142. unreadRedDot,
  143. ],
  144. );
  145. } else {
  146. left = Row(
  147. children: <Widget>[
  148. Expanded(
  149. child: Container(
  150. height: Constants.ContactAvatarSize,
  151. constraints: BoxConstraints(maxWidth: Screen.width - 100),
  152. child: ListView(
  153. scrollDirection: Axis.horizontal,
  154. children: list
  155. .map<Widget>((f) => Container(
  156. child: _buildAvatar(f['ApplyUrl']),
  157. margin: EdgeInsets.only(right: 5),
  158. ))
  159. .toList(),
  160. ))),
  161. unreadRedDot,
  162. ],
  163. );
  164. }
  165. return InkWell(
  166. onTap: gotoNewFriendsPage,
  167. child: Container(
  168. padding: const EdgeInsets.symmetric(
  169. vertical: MARGIN_VERTICAL, horizontal: 16.0),
  170. decoration: BoxDecoration(color: Colors.white),
  171. child: left,
  172. ));
  173. }
  174. // showPermission() async {
  175. // if (await CustomUI.showPermissionSetting(
  176. // Constants.getCurrentContext(),
  177. // PermissionGroup.contacts,
  178. // I18n.of(Constants.getCurrentContext()).contact_permission)) {
  179. // MessageMgr().emit('PostContact');
  180. // Navigator.push(Constants.getCurrentContext(),
  181. // MaterialPageRoute<void>(builder: (BuildContext context) {
  182. // return ContactsPage();
  183. // }));
  184. // }
  185. // }
  186. getFriendList() async {
  187. friendList = await FriendListMgr().getFriendList();
  188. if (mounted) {
  189. setState(() {});
  190. }
  191. }
  192. getNewFriendList(userdata) async {
  193. Map data = {
  194. "userId": UserData().basicInfo.userId,
  195. "type": 1,
  196. };
  197. data['sign'] = TokenMgr().getSign(data);
  198. Response res =
  199. await HttpUtil().post('friendship/newFriends/record', data: data);
  200. if (res == null) {
  201. return;
  202. }
  203. var resData = res.data;
  204. if (resData['code'] == 0) {
  205. if (resData['data'] != null) {
  206. SharedPreferences prefs = await SharedPreferences.getInstance();
  207. List<String> list = prefs.getStringList(Constants.NewFriendsList);
  208. if (list != null) {
  209. userIdSet = new Set.from(list);
  210. } else {
  211. userIdSet = new Set();
  212. }
  213. if (userdata != null && userIdSet.contains(userdata['userId'])) {
  214. userIdSet.remove(userdata['userId']);
  215. }
  216. showUserList = [];
  217. for (int i = 0; i < resData['data'].length; i++) {
  218. if (!userIdSet
  219. .contains(resData['data'][i]['ApplyUserId'].toString())) {
  220. showUserList.add(resData['data'][i]);
  221. userIdSet.add(resData['data'][i]['ApplyUserId'].toString());
  222. }
  223. }
  224. initNewFriendsList(showUserList);
  225. if (mounted) {
  226. setState(() {});
  227. }
  228. MessageMgr().emit('Update UnreadCount');
  229. }
  230. } else {
  231. showToast(resData['msg']);
  232. }
  233. }
  234. initNewFriendsList(showUserList) {
  235. _functionButtons = [_buildNewFriends(showUserList)];
  236. }
  237. msgAddfrend(data) {
  238. getFriendList();
  239. }
  240. msgDeletefrend(data) {
  241. getFriendList();
  242. }
  243. updateIndexPos(List<FriendModel> friendList) {
  244. //计算用于 IndexBar 进行定位的关键通讯录列表项的位置
  245. var _totalPos = _functionButtons.length * FriendsInfo.height(false);
  246. for (var i = 0; i < friendList.length; i++) {
  247. bool _hasGroupTitle = true;
  248. if (i > 0 &&
  249. friendList[i].nameTag.compareTo(friendList[i - 1].nameTag) == 0) {
  250. _hasGroupTitle = false;
  251. }
  252. if (_hasGroupTitle) {
  253. _letterPosMap[friendList[i].nameTag] = _totalPos;
  254. }
  255. _totalPos += FriendsInfo.height(_hasGroupTitle);
  256. }
  257. }
  258. @override
  259. void dispose() {
  260. _scrollController.dispose();
  261. print('FriendPage dispose');
  262. MessageMgr().off('Add friend', msgAddfrend);
  263. MessageMgr().off('Delete friend', msgDeletefrend);
  264. MessageMgr().off('do_friend_apply', messageApply);
  265. MessageMgr().off('goto_new_friends', messageNew);
  266. super.dispose();
  267. }
  268. String getLetter(BuildContext context, double tileHeight, Offset globalPos) {
  269. RenderBox _box = context.findRenderObject();
  270. var local = _box.globalToLocal(globalPos);
  271. int index = (local.dy ~/ tileHeight).clamp(0, INDEX_BAR_WORDS.length - 1);
  272. return INDEX_BAR_WORDS[index];
  273. }
  274. void _jumpToIndex(String letter) {
  275. if (_letterPosMap.isNotEmpty) {
  276. final _pos = _letterPosMap[letter];
  277. if (_pos != null) {
  278. _scrollController.animateTo(_letterPosMap[letter],
  279. curve: Curves.easeInOut, duration: Duration(microseconds: 200));
  280. }
  281. }
  282. }
  283. Widget _buildIndexBar(BuildContext context, BoxConstraints constraints) {
  284. final List<Widget> _letters = INDEX_BAR_WORDS.map((String word) {
  285. return Expanded(
  286. child: Container(
  287. margin: EdgeInsets.only(right: 5),
  288. decoration: BoxDecoration(
  289. shape: BoxShape.circle,
  290. color:
  291. _currentLetter == word ? Colors.blue : Colors.transparent,
  292. ),
  293. alignment: Alignment.center,
  294. padding: EdgeInsets.all(2),
  295. width: 20,
  296. child: Text(
  297. word,
  298. textScaleFactor: 1.0,
  299. style: TextStyle(
  300. fontSize: 10,
  301. color:
  302. _currentLetter == word ? Colors.white : Colors.black),
  303. )));
  304. }).toList();
  305. final _totalHeight = constraints.biggest.height;
  306. final _tileHeight = _totalHeight / _letters.length;
  307. return GestureDetector(
  308. onVerticalDragDown: (DragDownDetails details) {
  309. setState(() {
  310. _currentLetter =
  311. getLetter(context, _tileHeight, details.globalPosition);
  312. _jumpToIndex(_currentLetter);
  313. });
  314. },
  315. onVerticalDragEnd: (DragEndDetails details) {
  316. setState(() {
  317. //_indexBarBgColor = Colors.transparent;
  318. _currentLetter = null;
  319. });
  320. },
  321. onVerticalDragCancel: () {
  322. setState(() {
  323. //_indexBarBgColor = Colors.transparent;
  324. _currentLetter = null;
  325. });
  326. },
  327. onVerticalDragUpdate: (DragUpdateDetails details) {
  328. setState(() {
  329. //var _letter = getLetter(context, _tileHeight, details.globalPosition);
  330. _currentLetter =
  331. getLetter(context, _tileHeight, details.globalPosition);
  332. _jumpToIndex(_currentLetter);
  333. });
  334. },
  335. child: Column(
  336. children: _letters,
  337. ),
  338. );
  339. }
  340. @override
  341. Widget build(BuildContext context) {
  342. final List<Widget> _body = [];
  343. friendList.sort((a, b) => a.nameTag.compareTo(b.nameTag));
  344. updateIndexPos(friendList);
  345. _body.addAll([
  346. ListView.builder(
  347. controller: _scrollController,
  348. itemBuilder: (BuildContext context, int index) {
  349. if (index < _functionButtons.length) {
  350. if (index == 0) {
  351. return Padding(
  352. padding: EdgeInsets.only(top: 7),
  353. child: _functionButtons[index],
  354. );
  355. } else {
  356. return _functionButtons[index];
  357. }
  358. }
  359. var result;
  360. int _contactIndex = index - _functionButtons.length;
  361. bool _isGroupTitle = true;
  362. FriendModel _contact = friendList[_contactIndex];
  363. if (_contactIndex >= 1 &&
  364. _contact.nameTag == friendList[_contactIndex - 1].nameTag) {
  365. _isGroupTitle = false;
  366. }
  367. result = FriendsInfo(
  368. userId: _contact.friendId,
  369. avatar: _contact.avatar,
  370. title: Provider.of<RefNameProvider>(context)
  371. .getRefName(_contact.friendId, _contact.name),
  372. isShowDivder: true,
  373. groupTitle: _isGroupTitle ? _contact.nameTag : null);
  374. if (index == (friendList.length + _functionButtons.length - 1)) {
  375. return result = Column(
  376. children: <Widget>[
  377. result,
  378. Container(
  379. height: 50,
  380. color: Colors.white,
  381. child: Text(I18n.of(context)
  382. .total_friends_nus
  383. .replaceFirst('/s1', friendList.length.toString())),
  384. alignment: Alignment.center,
  385. width: Screen.width,
  386. ),
  387. ],
  388. );
  389. }
  390. return result;
  391. },
  392. itemCount: friendList.length + _functionButtons.length,
  393. ),
  394. Positioned(
  395. width: Constants.IndexBarWidth,
  396. right: 0.0,
  397. top: 0.0,
  398. bottom: 0.0,
  399. child: Container(
  400. //color: _indexBarBgColor,
  401. child: LayoutBuilder(
  402. builder: _buildIndexBar,
  403. ),
  404. ),
  405. )
  406. ]);
  407. if (_currentLetter != null && _currentLetter.isNotEmpty) {
  408. _body.add(Center(
  409. child: Container(
  410. width: Constants.IndexLetterBoxSize,
  411. height: Constants.IndexLetterBoxSize,
  412. decoration: BoxDecoration(
  413. color: AppColors.IndexLetterBoxBgColor,
  414. borderRadius: BorderRadius.all(
  415. Radius.circular(Constants.IndexLetterBoxRadius)),
  416. ),
  417. child: Center(
  418. child: Text(_currentLetter,
  419. textScaleFactor: 1.0, style: AppStyles.IndexLetterBoxTextStyle),
  420. ),
  421. ),
  422. ));
  423. }
  424. return Scaffold(
  425. resizeToAvoidBottomPadding: false,
  426. appBar: AppBar(
  427. backgroundColor: AppColors.NewAppbarBgColor,
  428. title: Text(I18n.of(context).contact,
  429. textScaleFactor: 1.0, style: Constants.MainTitleStyle),
  430. centerTitle: false,
  431. elevation: 1,
  432. actions: <Widget>[
  433. CustomUI.buildCircleIconButton(0xe662,
  434. onPressed: () => Navigator.of(context).push(
  435. new MaterialPageRoute(
  436. builder: (context) {
  437. return NewAddFriendsPage();
  438. },
  439. ),
  440. )),
  441. ],
  442. bottom: CustomUI.buildSearchButton(context, () {
  443. Navigator.of(context).push(
  444. new MaterialPageRoute(
  445. builder: (context) {
  446. return GlobalSearchPage(
  447. type: GlobalSearchPageType.SearchMyFriends,
  448. );
  449. },
  450. ),
  451. );
  452. })),
  453. body: Stack(
  454. children: _body,
  455. ));
  456. }
  457. }