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.

290 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/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 Scaffold(
  57. backgroundColor: Colors.white,
  58. body: BlocBuilder<NotiBloc, NotiState>(
  59. bloc: notiBloc,
  60. builder: (context, state) {
  61. if (state is NotiFailure) {
  62. return Center(child: Text(state.errorString));
  63. } else if (state is NotiSuccess) {
  64. updateCountNotiBloc.getNotifications((data) {}, (err) {});
  65. if (state.items!.isEmpty) {
  66. return SafeArea(
  67. child: Column(
  68. crossAxisAlignment: CrossAxisAlignment.start,
  69. children: [
  70. SizedBox(
  71. height: 8,
  72. ),
  73. Padding(
  74. padding: const EdgeInsets.all(8.0),
  75. child: Text('Thông báo', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22)),
  76. ),
  77. Expanded(
  78. child: Center(child: Text("Không có thông báo")),
  79. ),
  80. ],
  81. ),
  82. );
  83. }
  84. currentItems = List<NotificationDTO>.from(state.items!);
  85. currentPage = state.page ?? 1;
  86. currentHasReachedMax = state.hasReachedMax ?? false;
  87. return SafeArea(
  88. child: Column(
  89. children: <Widget>[
  90. Container(
  91. padding: EdgeInsets.all(8),
  92. color: Colors.white,
  93. child: Row(
  94. children: [
  95. SizedBox(
  96. height: 8,
  97. ),
  98. Expanded(
  99. child: Text(
  100. 'Thông báo',
  101. style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22),
  102. )),
  103. TextButton(
  104. onPressed: () {
  105. notiBloc.add(MarkAllNotificationUpdate(status: "1"));
  106. },
  107. child:
  108. Text('Đánh dấu đã đọc tất cả', style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.blue)))
  109. ],
  110. )),
  111. Expanded(
  112. child: RefreshIndicator(
  113. child: ListView.builder(
  114. physics: AlwaysScrollableScrollPhysics(),
  115. itemBuilder: (BuildContext context, int index) {
  116. return index >= state.items!.length
  117. ? BottomLoader()
  118. : ItemInfinityWidget(
  119. notiBloc: notiBloc,
  120. unread: state.unread ?? 0,
  121. read: state.read ?? 0,
  122. currentItems: currentItems,
  123. item: state.items![index],
  124. currentPage: state.page ?? 1,
  125. currentReachedMax: state.hasReachedMax ?? false,
  126. );
  127. },
  128. itemCount: (state.hasReachedMax ?? false) ? state.items?.length : (state.items?.length ?? 0) + 1,
  129. controller: _scrollController,
  130. ),
  131. onRefresh: () async {
  132. notiBloc.add(OnRefresh());
  133. }))
  134. ],
  135. ),
  136. );
  137. } else if (state is NotiLoadding) {
  138. return Center(
  139. child: LoadingListPage(),
  140. );
  141. }
  142. return Container();
  143. },
  144. ),
  145. );
  146. }
  147. @override
  148. void dispose() {
  149. _scrollController.dispose();
  150. super.dispose();
  151. }
  152. }
  153. class ItemInfinityWidget extends StatelessWidget {
  154. final int unread;
  155. final int read;
  156. final NotificationDTO item;
  157. final List<NotificationDTO> currentItems;
  158. final int currentPage;
  159. final bool currentReachedMax;
  160. final NotiBloc notiBloc;
  161. const ItemInfinityWidget(
  162. {Key? key,
  163. required this.unread,
  164. required this.read,
  165. required this.currentItems,
  166. required this.item,
  167. required this.currentPage,
  168. required this.currentReachedMax,
  169. required this.notiBloc})
  170. : super(key: key);
  171. @override
  172. Widget build(BuildContext context) {
  173. var type;
  174. try {
  175. type = int.parse(item.type ?? '-1');
  176. } catch (_) {
  177. type = -1;
  178. }
  179. return Column(
  180. children: [
  181. GestureDetector(
  182. child: Container(
  183. margin: EdgeInsets.all(4.0),
  184. child: Column(
  185. children: [
  186. ListTile(
  187. title: Text(item.subject ?? ''),
  188. subtitle: Column(
  189. crossAxisAlignment: CrossAxisAlignment.start,
  190. children: <Widget>[
  191. Text(item.message ?? ''),
  192. Row(children: [
  193. Icon(Icons.access_time, color: item.isRead == 1 ? Colors.grey : Colors.blue, size: 18),
  194. SizedBox(
  195. width: 4,
  196. ),
  197. Text(item.sendDate?.format_DDMMYY_HHmm() ?? '', style: TextStyle(color: item.isRead == 1 ? Colors.grey : Colors.blue))
  198. ]),
  199. ],
  200. ),
  201. leading: SvgPicture.asset(AppIcons.icNotificationItem)),
  202. ],
  203. )),
  204. onTap: () {
  205. if (item.contents == "ENV_UPDATE") {
  206. Navigator.push(
  207. context,
  208. MaterialPageRoute(
  209. builder: (BuildContext context) => PlotDetailScreen(
  210. cropType: type,
  211. cropId: item.tbCropId ?? -1,
  212. initialIndex: 0,
  213. ))).then((value) {
  214. if (item.isRead == 0) {
  215. _updateReadNotification(
  216. context: context,
  217. unread: unread,
  218. read: read,
  219. item: item,
  220. currentItems: currentItems,
  221. currentPage: currentPage,
  222. currentReachedMax: currentReachedMax);
  223. }
  224. });
  225. } else if (item.contents == "PIC_UPDATE") {
  226. Navigator.push(
  227. context,
  228. MaterialPageRoute(
  229. builder: (BuildContext context) => PlotDetailScreen(
  230. cropType: type,
  231. cropId: item.tbCropId ?? -1,
  232. initialIndex: 1,
  233. ))).then((value) {
  234. if (item.isRead == 0) {
  235. _updateReadNotification(
  236. context: context,
  237. unread: unread,
  238. read: read,
  239. item: item,
  240. currentItems: currentItems,
  241. currentPage: currentPage,
  242. currentReachedMax: currentReachedMax);
  243. }
  244. });
  245. } else {}
  246. }),
  247. Container(padding: EdgeInsets.only(left: 16, right: 16), child: DashLineWidget())
  248. ],
  249. );
  250. }
  251. _updateReadNotification(
  252. {BuildContext? context,
  253. int? unread,
  254. int? read,
  255. NotificationDTO? item,
  256. List<NotificationDTO>? currentItems,
  257. int? currentPage,
  258. bool? currentReachedMax}) {
  259. List<NotificationDTO> updatedItems = <NotificationDTO>[];
  260. currentItems?.forEach((e) {
  261. if (e.id == (item?.id ?? -1)) {
  262. e.isRead = 1;
  263. } else {}
  264. updatedItems.add(NotificationDTO.clone(e));
  265. });
  266. notiBloc.add(OnUpdate<NotificationDTO>(
  267. unread: (unread ?? 1) - 1,
  268. read: (read ?? 0) + 1,
  269. currentItemId: item?.id ?? -1,
  270. currentItems: updatedItems,
  271. currentPage: currentPage ?? 1,
  272. hasReachedMax: currentReachedMax ?? false,
  273. ));
  274. }
  275. }