import 'package:farm_tpf/custom_model/NotificationDTO.dart'; import 'package:farm_tpf/data/repository/repository.dart'; import 'package:farm_tpf/presentation/custom_widgets/app_bar_widget.dart'; import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.dart'; import 'package:farm_tpf/presentation/custom_widgets/dash_line_widget.dart'; import 'package:farm_tpf/presentation/custom_widgets/loading_list_page.dart'; import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_detail.dart'; import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_information.dart'; import 'package:farm_tpf/presentation/screens/plot_detail/sc_plot_parameter.dart'; import 'package:farm_tpf/utils/const_icons.dart'; import 'package:farm_tpf/utils/pref.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:farm_tpf/utils/formatter.dart'; import 'package:flutter_svg/svg.dart'; import 'bloc/noti_bloc.dart'; class NotificationScreen extends StatefulWidget { @override _NotificationScreenState createState() => _NotificationScreenState(); } class _NotificationScreenState extends State { final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); var notiBloc = NotiBloc(repository: Repository()); @override void initState() { super.initState(); _firebaseMessaging.configure( onMessage: (Map message) async { print("onMessage: $message"); try { notiBloc.add(OnRefreshFromNotification()); } catch (e) { print(e); } }); } @override Widget build(BuildContext context) { return BlocBuilder( cubit: notiBloc, builder: (context, state) { return HoldInfinityWidget( notiBloc: notiBloc, ); }); } } class HoldInfinityWidget extends StatelessWidget { final NotiBloc notiBloc; HoldInfinityWidget({@required this.notiBloc}); final GlobalKey _scaffoldKey = new GlobalKey(); @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, backgroundColor: Colors.white, body: BlocBuilder( cubit: notiBloc, builder: (context, state) { return InfinityView( notiBloc: notiBloc, ); }, )); } } class InfinityView extends StatefulWidget { final NotiBloc notiBloc; InfinityView({@required this.notiBloc}); @override _InfinityViewState createState() => _InfinityViewState(); } class _InfinityViewState extends State { final _scrollController = ScrollController(); final _scrollThreshold = 250.0; List currentItems = new List(); int latestId = 0; int currentPage = 0; bool currentHasReachedMax = true; bool isUpdatingFromApi = true; var pref = LocalPref(); var token; Future getSharedPrefs() async { _scrollController.addListener(() { final maxScroll = _scrollController.position.maxScrollExtent; final currentScroll = _scrollController.position.pixels; if (maxScroll - currentScroll < _scrollThreshold) { widget.notiBloc.add(DataFetched()); } }); token = await pref.getString(DATA_CONST.TOKEN_KEY); } @override void initState() { getSharedPrefs(); widget.notiBloc.add(DataFetched()); super.initState(); } @override Widget build(BuildContext context) { return BlocBuilder( cubit: widget.notiBloc, builder: (context, state) { if (state is NotiFailure) { return Center(child: Text(state.errorString)); } else if (state is NotiSuccess) { if (state.items.isEmpty) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: 8, ), Padding( padding: const EdgeInsets.all(8.0), child: Text('Thông báo', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 22)), ), Expanded( child: Center(child: Text("Không có thông báo")), ), ], ); } currentItems = List.from(state.items); currentPage = state.page; currentHasReachedMax = state.hasReachedMax; return Column( children: [ Container( padding: EdgeInsets.all(8), color: Colors.white, child: Row( children: [ SizedBox( height: 8, ), Expanded( child: Text( 'Thông báo', style: TextStyle( fontWeight: FontWeight.w500, fontSize: 22), )), BlocBuilder( cubit: widget.notiBloc, builder: (context, state) { if (state is NotiSuccess) { if (state.items.length > 0) { return FlatButton( onPressed: () { widget.notiBloc.add( MarkAllNotificationUpdate(status: "1")); }, child: Text('Đánh dấu đã đọc tất cả', style: TextStyle( fontWeight: FontWeight.normal, fontSize: 14, color: Colors.blue))); } else { return SizedBox(); } } else { return SizedBox(); } }, ) ], )), Expanded( child: RefreshIndicator( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return index >= state.items.length ? BottomLoader() : ItemInfinityWidget( notiBloc: widget.notiBloc, unread: state.unread, read: state.read, currentItems: currentItems, item: state.items[index], currentPage: state.page, currentReachedMax: state.hasReachedMax, ); }, itemCount: state.hasReachedMax ? state.items.length : state.items.length + 1, controller: _scrollController, ), onRefresh: () async { widget.notiBloc.add(OnRefresh()); })) ], ); } else if (state is NotiLoadding) { return Center( child: LoadingListPage(), ); } return Container(); }, ); } @override void dispose() { _scrollController.dispose(); super.dispose(); } } class ItemInfinityWidget extends StatelessWidget { final int unread; final int read; final NotificationDTO item; final List currentItems; final int currentPage; final bool currentReachedMax; final NotiBloc notiBloc; const ItemInfinityWidget( {Key key, @required this.unread, @required this.read, @required this.currentItems, @required this.item, @required this.currentPage, @required this.currentReachedMax, @required this.notiBloc}) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ GestureDetector( child: Container( margin: EdgeInsets.all(4.0), child: Column( children: [ ListTile( title: Text(item.subject), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.message), Row(children: [ Icon(Icons.access_time, color: item.isRead == 1 ? Colors.grey : Colors.blue, size: 18), SizedBox( width: 4, ), Text(item.sendDate.format_DDMMYY_HHmm(), style: TextStyle( color: item.isRead == 1 ? Colors.grey : Colors.blue)) ]), ], ), leading: SvgPicture.asset(AppIcons.icNotificationItem)), ], )), onTap: () { if (item.contents == "ENV_UPDATE") { Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => PlotParameterScreen( cropId: item.tbCropId, isShowAppbar: true, ))).then((value) { if (item.isRead == 0) { _updateReadNotification( context: context, unread: unread, read: read, item: item, currentItems: currentItems, currentPage: currentPage, currentReachedMax: currentReachedMax); } }); } else if (item.contents == "PIC_UPDATE") { Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => PlotInformationScreen( cropId: item.tbCropId, isShowAppbar: true, ))).then((value) { if (item.isRead == 0) { _updateReadNotification( context: context, unread: unread, read: read, item: item, currentItems: currentItems, currentPage: currentPage, currentReachedMax: currentReachedMax); } }); } else {} }), Container( padding: EdgeInsets.only(left: 16, right: 16), child: DashLineWidget()) ], ); } _updateReadNotification( {BuildContext context, int unread, int read, NotificationDTO item, List currentItems, int currentPage, bool currentReachedMax}) { List updatedItems = new List(); currentItems.forEach((e) { if (e.id == item.id) { e.isRead = 1; } else {} updatedItems.add(NotificationDTO.clone(e)); }); notiBloc.add(OnUpdate( unread: unread - 1, read: read + 1, currentItemId: item.id, currentItems: updatedItems, currentPage: currentPage, hasReachedMax: currentReachedMax)); } }