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