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.

355 lines
12KB

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