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.

362 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. return Column(
  239. children: [
  240. GestureDetector(
  241. child: Container(
  242. margin: EdgeInsets.all(4.0),
  243. child: Column(
  244. children: [
  245. ListTile(
  246. title: Text(item.subject),
  247. subtitle: Column(
  248. crossAxisAlignment: CrossAxisAlignment.start,
  249. children: <Widget>[
  250. Text(item.message),
  251. Row(children: [
  252. Icon(Icons.access_time,
  253. color: item.isRead == 1
  254. ? Colors.grey
  255. : Colors.blue,
  256. size: 18),
  257. SizedBox(
  258. width: 4,
  259. ),
  260. Text(item.sendDate.format_DDMMYY_HHmm(),
  261. style: TextStyle(
  262. color: item.isRead == 1
  263. ? Colors.grey
  264. : Colors.blue))
  265. ]),
  266. ],
  267. ),
  268. leading: SvgPicture.asset(AppIcons.icNotificationItem)),
  269. ],
  270. )),
  271. onTap: () {
  272. if (item.contents == "ENV_UPDATE") {
  273. Navigator.push(
  274. context,
  275. MaterialPageRoute(
  276. builder: (BuildContext context) => PlotDetailScreen(
  277. cropType: item.type,
  278. cropId: item.tbCropId,
  279. initialIndex: 0,
  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 if (item.contents == "PIC_UPDATE") {
  293. Navigator.push(
  294. context,
  295. MaterialPageRoute(
  296. builder: (BuildContext context) => PlotDetailScreen(
  297. cropType: item.type,
  298. cropId: item.tbCropId,
  299. initialIndex: 1,
  300. ))).then((value) {
  301. if (item.isRead == 0) {
  302. _updateReadNotification(
  303. context: context,
  304. unread: unread,
  305. read: read,
  306. item: item,
  307. currentItems: currentItems,
  308. currentPage: currentPage,
  309. currentReachedMax: currentReachedMax);
  310. }
  311. });
  312. } else {}
  313. }),
  314. Container(
  315. padding: EdgeInsets.only(left: 16, right: 16),
  316. child: DashLineWidget())
  317. ],
  318. );
  319. }
  320. _updateReadNotification(
  321. {BuildContext context,
  322. int unread,
  323. int read,
  324. NotificationDTO item,
  325. List<NotificationDTO> currentItems,
  326. int currentPage,
  327. bool currentReachedMax}) {
  328. List<NotificationDTO> updatedItems = new List<NotificationDTO>();
  329. currentItems.forEach((e) {
  330. if (e.id == item.id) {
  331. e.isRead = 1;
  332. } else {}
  333. updatedItems.add(NotificationDTO.clone(e));
  334. });
  335. notiBloc.add(OnUpdate<NotificationDTO>(
  336. unread: unread - 1,
  337. read: read + 1,
  338. currentItemId: item.id,
  339. currentItems: updatedItems,
  340. currentPage: currentPage,
  341. hasReachedMax: currentReachedMax));
  342. }
  343. }