Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

383 lines
13 KiB

  1. import 'package:chat/data/UserData.dart';
  2. import 'package:chat/data/WebData.dart';
  3. import 'package:chat/data/constants.dart';
  4. import 'package:chat/generated/i18n.dart';
  5. import 'package:chat/utils/CustomUI.dart';
  6. import 'package:chat/utils/HttpUtil.dart';
  7. import 'package:chat/utils/MessageMgr.dart';
  8. import 'package:chat/utils/TokenMgr.dart';
  9. import 'package:chat/utils/conversation_table.dart';
  10. import 'package:dio/dio.dart';
  11. import 'package:cached_network_image/cached_network_image.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:flutter/services.dart';
  14. import 'ProfilePage.dart';
  15. class _ContactItem extends StatelessWidget {
  16. _ContactItem(
  17. {@required this.avatar,
  18. @required this.title,
  19. @required this.userId,
  20. this.groupTitle,
  21. this.onPressed,
  22. this.gradient,
  23. this.iconCode,
  24. this.applyId,
  25. this.isShowDivder: true,
  26. this.state});
  27. final int userId;
  28. final int iconCode;
  29. final String avatar;
  30. final String title;
  31. final String groupTitle;
  32. final VoidCallback onPressed;
  33. final Gradient gradient;
  34. final bool isShowDivder;
  35. final int state;
  36. final int applyId;
  37. static const double MARGIN_VERTICAL = 10.0;
  38. static const double GROUP_TITLE_HEIGHT = 24.0;
  39. @override
  40. Widget build(BuildContext context) {
  41. Widget _avatarIcon;
  42. if (iconCode == null) {
  43. _avatarIcon = ClipRRect(
  44. borderRadius: BorderRadius.circular(6),
  45. child: CachedNetworkImage(
  46. imageUrl: this.avatar,
  47. width: Constants.ContactAvatarSize,
  48. height: Constants.ContactAvatarSize,
  49. ));
  50. } else {
  51. _avatarIcon = Container(
  52. width: Constants.ContactAvatarSize,
  53. height: Constants.ContactAvatarSize,
  54. decoration: BoxDecoration(
  55. gradient: gradient, borderRadius: BorderRadius.circular(6)),
  56. child: Icon(
  57. IconData(this.iconCode, fontFamily: Constants.IconFontFamily),
  58. color: Colors.white,
  59. ),
  60. );
  61. }
  62. Widget _button = Container(
  63. padding: const EdgeInsets.symmetric(
  64. vertical: MARGIN_VERTICAL, horizontal: 16.0),
  65. decoration: BoxDecoration(color: Colors.white),
  66. child: Row(
  67. children: <Widget>[
  68. _avatarIcon,
  69. SizedBox(width: 10.0),
  70. Expanded(child: Text(title)),
  71. state == 1
  72. ? Container(
  73. padding: EdgeInsets.symmetric(horizontal: 21, vertical: 7),
  74. child: Text(
  75. I18n.of(context).added,
  76. style: TextStyle(color: const Color(0xFF8A8B8B)),
  77. ),
  78. )
  79. : (state == 0
  80. ? Container(
  81. padding:
  82. EdgeInsets.symmetric(horizontal: 21, vertical: 7),
  83. child: Text(
  84. I18n.of(context).check,
  85. style: TextStyle(color: Constants.BlueTextColor),
  86. ),
  87. )
  88. : Container(
  89. padding:
  90. EdgeInsets.symmetric(horizontal: 21, vertical: 7),
  91. child: Text(
  92. I18n.of(context).rejected,
  93. style: TextStyle(color: const Color(0xFF8A8B8B)),
  94. ),
  95. )),
  96. ],
  97. ),
  98. );
  99. //分组标签
  100. Widget _itemBody;
  101. if (this.groupTitle != null) {
  102. _itemBody = Column(
  103. children: <Widget>[
  104. Container(
  105. height: GROUP_TITLE_HEIGHT,
  106. padding: EdgeInsets.only(left: 16.0, right: 16.0),
  107. color: const Color(AppColors.ContactGroupTitleBgColor),
  108. alignment: Alignment.centerLeft,
  109. child:
  110. Text(this.groupTitle, style: AppStyles.GroupTitleItemTextStyle),
  111. ),
  112. _button,
  113. ],
  114. );
  115. } else {
  116. _itemBody = _button;
  117. }
  118. return InkWell(
  119. onTap: () {
  120. Navigator.of(context).push(
  121. new MaterialPageRoute(
  122. builder: (context) {
  123. return ProfilePage(
  124. userId: userId,
  125. addMode: state == 0 ? 2 : 0,
  126. applyId: applyId,
  127. );
  128. },
  129. ),
  130. );
  131. },
  132. child: Container(
  133. color: Colors.white,
  134. child: Column(
  135. children: <Widget>[
  136. _itemBody,
  137. isShowDivder
  138. ? Container(
  139. height: 1,
  140. color: const Color(0xFFF3F3F3),
  141. margin: EdgeInsets.only(
  142. left: 26 + Constants.ContactAvatarSize),
  143. )
  144. : Container()
  145. ],
  146. )));
  147. }
  148. }
  149. class NewFriendsPage extends StatefulWidget {
  150. @override
  151. _NewFriendsPageState createState() => _NewFriendsPageState();
  152. }
  153. class _NewFriendsPageState extends State<NewFriendsPage> {
  154. String _currentLetter = '';
  155. ScrollController _scrollController;
  156. TextEditingController _txtCtrl = new TextEditingController();
  157. bool _hasdeleteIcon = false;
  158. List<FriendModel> searchList = [];
  159. List<FriendModel> friendList = [];
  160. @override
  161. void initState() {
  162. super.initState();
  163. print('NewFriendsPage initState');
  164. getNewFriendList();
  165. _scrollController = new ScrollController();
  166. MessageMgr().on('do_friend_apply', messageApply);
  167. }
  168. messageApply(data) {
  169. for (int i = 0; i < friendList.length; i++) {
  170. if (friendList[i].friendId == data['userId']) {
  171. setState(() {
  172. friendList[i].state = data['state'];
  173. });
  174. break;
  175. }
  176. }
  177. }
  178. getNewFriendList() async {
  179. Map data = {
  180. "userId": UserData().basicInfo.userId,
  181. "type": 2,
  182. };
  183. data['sign'] = TokenMgr().getSign(data);
  184. Response res =
  185. await HttpUtil().post('friendship/newFriends/record', data: data);
  186. Map resData = res.data;
  187. print(resData['data']);
  188. if (resData['code'] == 0 && resData['data'] != null) {
  189. resData['data'].forEach((f) {
  190. var friend = FriendModel.fromApplyServerJson(f);
  191. if (friend.friendId != UserData().basicInfo.userId)
  192. friendList.add(friend);
  193. });
  194. setState(() {});
  195. }
  196. }
  197. @override
  198. void dispose() {
  199. _scrollController.dispose();
  200. super.dispose();
  201. MessageMgr().off('do_friend_apply', messageApply);
  202. }
  203. @override
  204. Widget build(BuildContext context) {
  205. final List<Widget> _body = [];
  206. if (!_hasdeleteIcon) {
  207. _body.add(ListView.builder(
  208. controller: _scrollController,
  209. itemBuilder: (BuildContext context, int index) {
  210. int _contactIndex = index;
  211. bool _isGroupTitle = true;
  212. FriendModel _contact = friendList[_contactIndex];
  213. bool isThreeDay = WebData().isThreeDayAgo(_contact.creatTime);
  214. if (_contactIndex >= 1 &&
  215. WebData().isThreeDayAgo(_contact.creatTime) ==
  216. WebData()
  217. .isThreeDayAgo(friendList[_contactIndex - 1].creatTime)) {
  218. _isGroupTitle = false;
  219. }
  220. return _ContactItem(
  221. userId: _contact.friendId,
  222. avatar: _contact.avatar,
  223. title: _contact.name,
  224. state: _contact.state,
  225. isShowDivder: true,
  226. applyId: _contact.applyId,
  227. groupTitle: _isGroupTitle
  228. ? (isThreeDay
  229. ? I18n.of(context).before_three_day
  230. : I18n.of(context).after_three_day)
  231. : null);
  232. },
  233. itemCount: friendList.length,
  234. ));
  235. } else {
  236. _body.add(ListView.builder(
  237. controller: _scrollController,
  238. itemBuilder: (BuildContext context, int index) {
  239. FriendModel _contact = searchList[index];
  240. return _ContactItem(
  241. userId: _contact.friendId,
  242. avatar: _contact.avatar,
  243. title: _contact.name,
  244. state: _contact.state,
  245. isShowDivder: true,
  246. applyId: _contact.applyId,
  247. groupTitle: null);
  248. },
  249. itemCount: searchList.length,
  250. ));
  251. }
  252. if (_currentLetter != null &&
  253. _currentLetter.isNotEmpty &&
  254. !_hasdeleteIcon) {
  255. _body.add(Center(
  256. child: Container(
  257. width: Constants.IndexLetterBoxSize,
  258. height: Constants.IndexLetterBoxSize,
  259. decoration: BoxDecoration(
  260. color: AppColors.IndexLetterBoxBgColor,
  261. borderRadius: BorderRadius.all(
  262. Radius.circular(Constants.IndexLetterBoxRadius)),
  263. ),
  264. child: Center(
  265. child:
  266. Text(_currentLetter, style: AppStyles.IndexLetterBoxTextStyle),
  267. ),
  268. ),
  269. ));
  270. }
  271. return Scaffold(
  272. resizeToAvoidBottomPadding: false,
  273. appBar: AppBar(
  274. backgroundColor: AppColors.NewAppbarBgColor,
  275. title: Text(
  276. I18n.of(context).new_friends,
  277. textScaleFactor: 1.0,
  278. style: TextStyle(color: AppColors.NewAppbarTextColor),
  279. ),
  280. centerTitle: true,
  281. leading: CustomUI.buildCustomLeading(context),
  282. elevation: 1,
  283. bottom: PreferredSize(
  284. preferredSize: Size.fromHeight(49),
  285. child: Container(
  286. alignment: Alignment.center,
  287. margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5),
  288. height: 35,
  289. decoration: BoxDecoration(
  290. color: const Color(0xFFEEEEEE),
  291. borderRadius: BorderRadius.all(Radius.circular(8))),
  292. child: TextField(
  293. keyboardAppearance: Brightness.light,
  294. keyboardType: TextInputType.text,
  295. textInputAction: TextInputAction.search,
  296. controller: _txtCtrl,
  297. maxLines: 1,
  298. style: TextStyle(
  299. textBaseline: TextBaseline.alphabetic, fontSize: 14.5),
  300. autofocus: false,
  301. inputFormatters: [
  302. LengthLimitingTextInputFormatter(50),
  303. ],
  304. decoration: InputDecoration(
  305. hintText: I18n.of(context).search,
  306. hintStyle: TextStyle(fontSize: 14.5),
  307. prefixIcon: Icon(
  308. IconData(
  309. 0xe664,
  310. fontFamily: Constants.IconFontFamily,
  311. ),
  312. color: const Color(0xFFA0A0A0),
  313. size: 18,
  314. ),
  315. suffixIcon: Padding(
  316. padding: EdgeInsetsDirectional.only(
  317. start: 2.0, end: _hasdeleteIcon ? 20.0 : 0),
  318. child: _hasdeleteIcon
  319. ? new InkWell(
  320. onTap: (() {
  321. setState(() {
  322. WidgetsBinding.instance
  323. .addPostFrameCallback(
  324. (_) => _txtCtrl.clear());
  325. _hasdeleteIcon = false;
  326. });
  327. }),
  328. child: Icon(
  329. Icons.clear,
  330. size: 18.0,
  331. color: Constants.BlackTextColor,
  332. ))
  333. : new Text('')),
  334. filled: true,
  335. fillColor: Colors.transparent,
  336. border: InputBorder.none,
  337. ),
  338. onChanged: (str) async {
  339. setState(() {
  340. if (str.isEmpty) {
  341. _hasdeleteIcon = false;
  342. } else {
  343. _hasdeleteIcon = true;
  344. searchList = CustomUI().getSearchResult(
  345. str, friendList == null ? [] : friendList);
  346. }
  347. });
  348. },
  349. onEditingComplete: () {}),
  350. )),
  351. ),
  352. body: Stack(
  353. children: _body,
  354. ));
  355. }
  356. }