import 'package:farm_tpf/custom_model/NotificationDTO.dart'; import 'package:farm_tpf/data/repository/repository.dart'; import 'package:farm_tpf/presentation/custom_widgets/bottom_loader.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/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 '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, appBar: AppBar( centerTitle: true, title: Text("Thông báo"), actions: [ BlocBuilder( cubit: notiBloc, builder: (context, state) { if (state is NotiSuccess) { if (state.items.length > 0) { return IconButton( icon: Icon(Icons.done_all), onPressed: () { notiBloc.add(MarkAllNotificationUpdate(status: "1")); }); } else { return SizedBox(); } } else { return SizedBox(); } }, ) ], ), 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(); // final SocketService socketService = injector.get(); 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 Center(child: Text("Dữ liệu rỗng")); } currentItems = List.from(state.items); currentPage = state.page; currentHasReachedMax = state.hasReachedMax; return Column( children: [ Container( child: countNotification(unread: state.unread, read: state.read), ), Expanded( child: RefreshIndicator( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return index >= state.items.length ? BottomLoader() : ItemInfinityWidget( 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(); }, ); } Widget countNotification({num unread, num read}) { return Container( child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [ Expanded( child: OutlineButton( child: RichText( text: TextSpan( text: "Chưa đọc ", style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold), children: [ TextSpan( text: "($unread)", style: TextStyle(color: Colors.blue)), ])), onPressed: () {})), Expanded( child: OutlineButton( child: RichText( text: TextSpan( text: "Đã đọc ", style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold), children: [ TextSpan( text: "($read)", style: TextStyle(color: Colors.grey)), ])), onPressed: () {})) ], ), ); } @override void dispose() { _scrollController.dispose(); // socketService.disconnect(); super.dispose(); } } class ItemInfinityWidget extends StatelessWidget { final int unread; final int read; final NotificationDTO item; final List currentItems; final int currentPage; final bool currentReachedMax; const ItemInfinityWidget( {Key key, @required this.unread, @required this.read, @required this.currentItems, @required this.item, @required this.currentPage, @required this.currentReachedMax}) : super(key: key); @override Widget build(BuildContext context) { return GestureDetector( child: Card( margin: EdgeInsets.all(4.0), child: ListTile( title: Text(item.subject), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.message), Text( item.sendDate.format_DDMMYY_HHmm(), style: TextStyle( color: item.isRead == 1 ? Colors.grey : Colors.blue), ), ], ), leading: Icon( Icons.notifications_active, color: item.isRead == 1 ? Colors.grey : Colors.blue, ))), onTap: () { if (item.contents == "ENV_UPDATE") { Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => PlotDetailScreen(cropId: item.tbCropId))).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, ))).then((value) { if (item.isRead == 0) { _updateReadNotification( context: context, unread: unread, read: read, item: item, currentItems: currentItems, currentPage: currentPage, currentReachedMax: currentReachedMax); } }); } else {} }); } _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)); }); BlocProvider.of(context).add(OnUpdate( unread: unread - 1, read: read + 1, currentItemId: item.id, currentItems: updatedItems, currentPage: currentPage, hasReachedMax: currentReachedMax)); } }