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.

368 lines
13KB

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