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.

286 lines
10KB

  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/dash_line_widget.dart';
  5. import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart';
  6. import 'package:farm_tpf/presentation/screens/notification/update_count_noti_bloc.dart';
  7. import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart';
  8. import 'package:farm_tpf/utils/NotificationsBloc.dart';
  9. import 'package:farm_tpf/utils/const_icons.dart';
  10. import 'package:farm_tpf/utils/pref.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter_bloc/flutter_bloc.dart';
  13. import 'package:farm_tpf/utils/formatter.dart';
  14. import 'package:flutter_svg/svg.dart';
  15. import 'bloc/noti_bloc.dart';
  16. class NotificationScreen extends StatefulWidget {
  17. @override
  18. _NotificationScreenState createState() => _NotificationScreenState();
  19. }
  20. class _NotificationScreenState extends State<NotificationScreen> {
  21. var notiBloc = NotiBloc(repository: Repository());
  22. final _scrollController = ScrollController();
  23. final _scrollThreshold = 250.0;
  24. List<NotificationDTO> currentItems = <NotificationDTO>[];
  25. int latestId = 0;
  26. int currentPage = 0;
  27. bool currentHasReachedMax = true;
  28. bool isUpdatingFromApi = true;
  29. Stream<LocalNotification>? _notificationsStream;
  30. var pref = LocalPref();
  31. var token;
  32. Future<Null> getSharedPrefs() async {
  33. _scrollController.addListener(() {
  34. final maxScroll = _scrollController.position.maxScrollExtent;
  35. final currentScroll = _scrollController.position.pixels;
  36. if (maxScroll - currentScroll < _scrollThreshold) {
  37. notiBloc.add(DataFetched());
  38. }
  39. });
  40. token = await pref.getString(DATA_CONST.TOKEN_KEY);
  41. }
  42. @override
  43. void initState() {
  44. getSharedPrefs();
  45. notiBloc.add(DataFetched());
  46. _notificationsStream = NotificationsBloc.instance.notificationsStream;
  47. _notificationsStream?.listen((notification) {
  48. updateCountNotiBloc.getNotifications((data) {}, (err) {});
  49. print('Notification: $notification');
  50. notiBloc.add(OnRefresh());
  51. });
  52. super.initState();
  53. }
  54. @override
  55. Widget build(BuildContext context) {
  56. return BlocBuilder<NotiBloc, NotiState>(
  57. cubit: notiBloc,
  58. builder: (context, state) {
  59. if (state is NotiFailure) {
  60. return Center(child: Text(state.errorString));
  61. } else if (state is NotiSuccess) {
  62. updateCountNotiBloc.getNotifications((data) {}, (err) {});
  63. if (state.items.isEmpty) {
  64. return SafeArea(
  65. child: Column(
  66. crossAxisAlignment: CrossAxisAlignment.start,
  67. children: [
  68. const SizedBox(
  69. height: 8,
  70. ),
  71. const Padding(
  72. padding: EdgeInsets.all(8.0),
  73. child: Text('Thông báo', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22)),
  74. ),
  75. const Expanded(
  76. child: Center(child: Text("Không có thông báo")),
  77. ),
  78. ],
  79. ),
  80. );
  81. }
  82. currentItems = List<NotificationDTO>.from(state.items);
  83. currentPage = state.page;
  84. currentHasReachedMax = state.hasReachedMax;
  85. return SafeArea(
  86. child: Column(
  87. children: <Widget>[
  88. Container(
  89. padding: const EdgeInsets.all(8),
  90. color: Colors.white,
  91. child: Row(
  92. children: [
  93. const SizedBox(
  94. height: 8,
  95. ),
  96. const Expanded(
  97. child: Text(
  98. 'Thông báo',
  99. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  100. )),
  101. FlatButton(
  102. onPressed: () {
  103. notiBloc.add(MarkAllNotificationUpdate(status: "1"));
  104. },
  105. child: const Text('Đánh dấu đã đọc tất cả',
  106. style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.blue)))
  107. ],
  108. )),
  109. Expanded(
  110. child: RefreshIndicator(
  111. child: ListView.builder(
  112. physics: const AlwaysScrollableScrollPhysics(),
  113. itemBuilder: (BuildContext context, int index) {
  114. return index >= state.items.length
  115. ? BottomLoader()
  116. : ItemInfinityWidget(
  117. notiBloc: notiBloc,
  118. unread: state.unread ?? 0,
  119. read: state.read ?? 0,
  120. currentItems: currentItems,
  121. item: state.items[index],
  122. currentPage: state.page,
  123. currentReachedMax: state.hasReachedMax,
  124. );
  125. },
  126. itemCount: state.hasReachedMax ? state.items.length : state.items.length + 1,
  127. controller: _scrollController,
  128. ),
  129. onRefresh: () async {
  130. notiBloc.add(OnRefresh());
  131. }))
  132. ],
  133. ),
  134. );
  135. } else if (state is NotiLoadding) {
  136. return Center(
  137. child: LoadingListPage(),
  138. );
  139. }
  140. return Container();
  141. },
  142. );
  143. }
  144. @override
  145. void dispose() {
  146. _scrollController.dispose();
  147. super.dispose();
  148. }
  149. }
  150. class ItemInfinityWidget extends StatelessWidget {
  151. final int unread;
  152. final int read;
  153. final NotificationDTO item;
  154. final List<NotificationDTO> currentItems;
  155. final int currentPage;
  156. final bool currentReachedMax;
  157. final NotiBloc notiBloc;
  158. const ItemInfinityWidget(
  159. {Key? key,
  160. required this.unread,
  161. required this.read,
  162. required this.currentItems,
  163. required this.item,
  164. required this.currentPage,
  165. required this.currentReachedMax,
  166. required this.notiBloc})
  167. : super(key: key);
  168. @override
  169. Widget build(BuildContext context) {
  170. var type;
  171. try {
  172. type = int.parse(item.type ?? '0');
  173. } catch (_) {
  174. type = -1;
  175. }
  176. return Column(
  177. children: [
  178. GestureDetector(
  179. child: Container(
  180. margin: const EdgeInsets.all(4.0),
  181. child: Column(
  182. children: [
  183. ListTile(
  184. title: Text(item.subject ?? ''),
  185. subtitle: Column(
  186. crossAxisAlignment: CrossAxisAlignment.start,
  187. children: <Widget>[
  188. Text(item.message ?? ''),
  189. Row(children: [
  190. Icon(Icons.access_time, color: item.isRead == 1 ? Colors.grey : Colors.blue, size: 18),
  191. const SizedBox(
  192. width: 4,
  193. ),
  194. Text(item.sendDate?.format_DDMMYY_HHmm() ?? '', style: TextStyle(color: item.isRead == 1 ? Colors.grey : Colors.blue))
  195. ]),
  196. ],
  197. ),
  198. leading: SvgPicture.asset(AppIcons.icNotificationItem)),
  199. ],
  200. )),
  201. onTap: () {
  202. if (item.contents == "ENV_UPDATE") {
  203. Navigator.push(
  204. context,
  205. MaterialPageRoute(
  206. builder: (BuildContext context) => PlotDetailScreen(
  207. cropType: type,
  208. cropId: item.tbCropId,
  209. initialIndex: 0,
  210. ))).then((value) {
  211. if (item.isRead == 0) {
  212. _updateReadNotification(
  213. context: context,
  214. unread: unread,
  215. read: read,
  216. item: item,
  217. currentItems: currentItems,
  218. currentPage: currentPage,
  219. currentReachedMax: currentReachedMax);
  220. }
  221. });
  222. } else if (item.contents == "PIC_UPDATE") {
  223. Navigator.push(
  224. context,
  225. MaterialPageRoute(
  226. builder: (BuildContext context) => PlotDetailScreen(
  227. cropType: type,
  228. cropId: item.tbCropId,
  229. initialIndex: 1,
  230. ))).then((value) {
  231. if (item.isRead == 0) {
  232. _updateReadNotification(
  233. context: context,
  234. unread: unread,
  235. read: read,
  236. item: item,
  237. currentItems: currentItems,
  238. currentPage: currentPage,
  239. currentReachedMax: currentReachedMax);
  240. }
  241. });
  242. } else {}
  243. }),
  244. Container(padding: const EdgeInsets.only(left: 16, right: 16), child: const DashLineWidget())
  245. ],
  246. );
  247. }
  248. _updateReadNotification(
  249. {required BuildContext context,
  250. required int unread,
  251. required int read,
  252. required NotificationDTO item,
  253. required List<NotificationDTO> currentItems,
  254. required int currentPage,
  255. required bool currentReachedMax}) {
  256. var updatedItems = <NotificationDTO>[];
  257. currentItems.forEach((e) {
  258. if (e.id == item.id) {
  259. e.isRead = 1;
  260. } else {}
  261. updatedItems.add(NotificationDTO.clone(e));
  262. });
  263. notiBloc.add(OnUpdate<NotificationDTO>(
  264. unread: unread - 1,
  265. read: read + 1,
  266. currentItemId: item.id,
  267. currentItems: updatedItems,
  268. currentPage: currentPage,
  269. hasReachedMax: currentReachedMax));
  270. }
  271. }