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.

335 lines
11KB

  1. import 'package:farm_tpf/custom_model/NotificationDTO.dart';
  2. import 'package:farm_tpf/data/repository/repository.dart';
  3. import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart';
  4. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  5. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart';
  6. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_information.dart';
  7. import 'package:farm_tpf/utils/pref.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:flutter_bloc/flutter_bloc.dart';
  10. import 'package:farm_tpf/utils/formatter.dart';
  11. import 'bloc/noti_bloc.dart';
  12. class NotificationScreen extends StatefulWidget {
  13. @override
  14. _NotificationScreenState createState() => _NotificationScreenState();
  15. }
  16. class _NotificationScreenState extends State<NotificationScreen> {
  17. @override
  18. Widget build(BuildContext context) {
  19. return BlocProvider(
  20. create: (context) =>
  21. NotiBloc(repository: Repository())..add(DataFetched()),
  22. child: HoldInfinityWidget(),
  23. );
  24. }
  25. }
  26. class HoldInfinityWidget extends StatelessWidget {
  27. final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  28. @override
  29. Widget build(BuildContext context) {
  30. return Scaffold(
  31. key: _scaffoldKey,
  32. appBar: AppBar(
  33. centerTitle: true,
  34. title: Text("Thông báo"),
  35. actions: <Widget>[
  36. BlocBuilder<NotiBloc, NotiState>(
  37. builder: (context, state) {
  38. if (state is NotiSuccess) {
  39. if (state.items.length > 0) {
  40. return IconButton(
  41. icon: Icon(Icons.done_all),
  42. onPressed: () {
  43. BlocProvider.of<NotiBloc>(context)
  44. .add(MarkAllNotificationUpdate(status: "1"));
  45. });
  46. } else {
  47. return SizedBox();
  48. }
  49. } else {
  50. return SizedBox();
  51. }
  52. },
  53. )
  54. ],
  55. ),
  56. body: InfinityView());
  57. }
  58. }
  59. class InfinityView extends StatefulWidget {
  60. @override
  61. _InfinityViewState createState() => _InfinityViewState();
  62. }
  63. class _InfinityViewState extends State<InfinityView> {
  64. final _scrollController = ScrollController();
  65. final _scrollThreshold = 250.0;
  66. NotiBloc _notiBloc;
  67. List<NotificationDTO> currentItems = new List<NotificationDTO>();
  68. int latestId = 0;
  69. int currentPage = 0;
  70. bool currentHasReachedMax = true;
  71. bool isUpdatingFromApi = true;
  72. var pref = LocalPref();
  73. // final SocketService socketService = injector.get<SocketService>();
  74. var token;
  75. Future<Null> getSharedPrefs() async {
  76. _scrollController.addListener(() {
  77. final maxScroll = _scrollController.position.maxScrollExtent;
  78. final currentScroll = _scrollController.position.pixels;
  79. if (maxScroll - currentScroll < _scrollThreshold) {
  80. _notiBloc.add(DataFetched());
  81. }
  82. });
  83. token = await pref.getString(DATA_CONST.TOKEN_KEY);
  84. // socketService.initial(token);
  85. _notiBloc = BlocProvider.of<NotiBloc>(context);
  86. }
  87. @override
  88. void initState() {
  89. getSharedPrefs();
  90. super.initState();
  91. }
  92. @override
  93. Widget build(BuildContext context) {
  94. return BlocConsumer<NotiBloc, NotiState>(
  95. listener: (context, state) {
  96. //Handle Socket
  97. /*
  98. if (state is NotiLoadding) {
  99. isUpdatingFromApi = true;
  100. }
  101. if (state is NotiSuccess) {
  102. currentItems = List<NotificationDTO>.from(state.items);
  103. latestId = int.parse(currentItems[0].id) > latestId
  104. ? int.parse(currentItems[0].id)
  105. : latestId;
  106. socketService.createSocketNotificationConnection(latestId, (data) {
  107. print("receive data");
  108. if (isUpdatingFromApi == false) {
  109. print("Update from socket");
  110. var notis =
  111. NotificationObjectDTO.fromJson(data, NotificationDTO());
  112. _notiBloc.add(ReceiveDataFromSocket(
  113. currentItems: currentItems,
  114. page: currentPage,
  115. hasReachedMax: currentHasReachedMax,
  116. updatedItemObject: notis));
  117. } else {
  118. //dont need update from socket
  119. print("dont need update from socket");
  120. }
  121. }, (error) {});
  122. isUpdatingFromApi = false;
  123. }
  124. */
  125. },
  126. builder: (context, state) {
  127. if (state is NotiFailure) {
  128. return Center(child: Text(state.errorString));
  129. }
  130. if (state is NotiSuccess) {
  131. if (state.items.isEmpty) {
  132. return Center(child: Text("Dữ liệu rỗng"));
  133. }
  134. currentItems = List<NotificationDTO>.from(state.items);
  135. currentPage = state.page;
  136. currentHasReachedMax = state.hasReachedMax;
  137. return Column(
  138. children: <Widget>[
  139. Container(
  140. child:
  141. countNotification(unread: state.unread, read: state.read),
  142. ),
  143. Expanded(
  144. child: RefreshIndicator(
  145. child: ListView.builder(
  146. itemBuilder: (BuildContext context, int index) {
  147. return index >= state.items.length
  148. ? BottomLoader()
  149. : ItemInfinityWidget(
  150. unread: state.unread,
  151. read: state.read,
  152. currentItems: currentItems,
  153. item: state.items[index],
  154. currentPage: state.page,
  155. currentReachedMax: state.hasReachedMax,
  156. );
  157. },
  158. itemCount: state.hasReachedMax
  159. ? state.items.length
  160. : state.items.length + 1,
  161. controller: _scrollController,
  162. ),
  163. onRefresh: () async {
  164. _notiBloc.add(OnRefresh());
  165. }))
  166. ],
  167. );
  168. }
  169. return Center(
  170. child: LoadingListPage(),
  171. );
  172. },
  173. );
  174. }
  175. Widget countNotification({num unread, num read}) {
  176. return Container(
  177. child: Row(
  178. mainAxisAlignment: MainAxisAlignment.center,
  179. mainAxisSize: MainAxisSize.max,
  180. children: <Widget>[
  181. Expanded(
  182. child: OutlineButton(
  183. child: RichText(
  184. text: TextSpan(
  185. text: "Chưa đọc ",
  186. style: TextStyle(
  187. color: Colors.black, fontWeight: FontWeight.bold),
  188. children: <TextSpan>[
  189. TextSpan(
  190. text: "($unread)",
  191. style: TextStyle(color: Colors.blue)),
  192. ])),
  193. onPressed: () {})),
  194. Expanded(
  195. child: OutlineButton(
  196. child: RichText(
  197. text: TextSpan(
  198. text: "Đã đọc ",
  199. style: TextStyle(
  200. color: Colors.black, fontWeight: FontWeight.bold),
  201. children: <TextSpan>[
  202. TextSpan(
  203. text: "($read)",
  204. style: TextStyle(color: Colors.grey)),
  205. ])),
  206. onPressed: () {}))
  207. ],
  208. ),
  209. );
  210. }
  211. @override
  212. void dispose() {
  213. _scrollController.dispose();
  214. // socketService.disconnect();
  215. super.dispose();
  216. }
  217. }
  218. class ItemInfinityWidget extends StatelessWidget {
  219. final int unread;
  220. final int read;
  221. final NotificationDTO item;
  222. final List<NotificationDTO> currentItems;
  223. final int currentPage;
  224. final bool currentReachedMax;
  225. const ItemInfinityWidget(
  226. {Key key,
  227. @required this.unread,
  228. @required this.read,
  229. @required this.currentItems,
  230. @required this.item,
  231. @required this.currentPage,
  232. @required this.currentReachedMax})
  233. : super(key: key);
  234. @override
  235. Widget build(BuildContext context) {
  236. return GestureDetector(
  237. child: Card(
  238. margin: EdgeInsets.all(4.0),
  239. child: ListTile(
  240. title: Text(item.subject),
  241. subtitle: Column(
  242. crossAxisAlignment: CrossAxisAlignment.start,
  243. children: <Widget>[
  244. Text(item.message),
  245. Text(
  246. item.sendDate.format_DDMMYY_HHmm(),
  247. style: TextStyle(
  248. color: item.isRead == 1 ? Colors.grey : Colors.blue),
  249. ),
  250. ],
  251. ),
  252. leading: Icon(
  253. Icons.notifications_active,
  254. color: item.isRead == 1 ? Colors.grey : Colors.blue,
  255. ))),
  256. onTap: () {
  257. if (item.contents == "ENV_UPDATE") {
  258. Navigator.push(
  259. context,
  260. MaterialPageRoute(
  261. builder: (BuildContext context) =>
  262. PlotDetailScreen(cropId: item.tbCropId))).then((value) {
  263. if (item.isRead == 0) {
  264. _updateReadNotification(
  265. context: context,
  266. unread: unread,
  267. read: read,
  268. item: item,
  269. currentItems: currentItems,
  270. currentPage: currentPage,
  271. currentReachedMax: currentReachedMax);
  272. }
  273. });
  274. } else if (item.contents == "PIC_UPDATE") {
  275. Navigator.push(
  276. context,
  277. MaterialPageRoute(
  278. builder: (BuildContext context) => PlotInformationScreen(
  279. cropId: item.tbCropId,
  280. ))).then((value) {
  281. if (item.isRead == 0) {
  282. _updateReadNotification(
  283. context: context,
  284. unread: unread,
  285. read: read,
  286. item: item,
  287. currentItems: currentItems,
  288. currentPage: currentPage,
  289. currentReachedMax: currentReachedMax);
  290. }
  291. });
  292. } else {}
  293. });
  294. }
  295. _updateReadNotification(
  296. {BuildContext context,
  297. int unread,
  298. int read,
  299. NotificationDTO item,
  300. List<NotificationDTO> currentItems,
  301. int currentPage,
  302. bool currentReachedMax}) {
  303. List<NotificationDTO> updatedItems = new List<NotificationDTO>();
  304. currentItems.forEach((e) {
  305. if (e.id == item.id) {
  306. e.isRead = 1;
  307. } else {}
  308. updatedItems.add(NotificationDTO.clone(e));
  309. });
  310. BlocProvider.of<NotiBloc>(context).add(OnUpdate<NotificationDTO>(
  311. unread: unread - 1,
  312. read: read + 1,
  313. currentItemId: item.id,
  314. currentItems: updatedItems,
  315. currentPage: currentPage,
  316. hasReachedMax: currentReachedMax));
  317. }
  318. }