import 'package:comunic/enums/load_error_level.dart'; import 'package:comunic/helpers/conversations_helper.dart'; import 'package:comunic/helpers/events_helper.dart'; import 'package:comunic/helpers/users_helper.dart'; import 'package:comunic/lists/conversations_list.dart'; import 'package:comunic/models/conversation.dart'; import 'package:comunic/ui/routes/main_route/main_route.dart'; import 'package:comunic/ui/routes/update_conversation_route.dart'; import 'package:comunic/ui/screens/create_conversation_screen.dart'; import 'package:comunic/ui/tiles/conversation_tile.dart'; import 'package:comunic/ui/widgets/safe_state.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; /// Conversations screen /// /// @author Pierre HUBERT class ConversationsListScreen extends StatefulWidget { final bool useSmallFAB; final Function() onOpen; const ConversationsListScreen({ Key key, this.useSmallFAB = false, this.onOpen, }) : assert(useSmallFAB != null), super(key: key); @override State createState() => _ConversationScreenState(); } class _ConversationScreenState extends SafeState { final ConversationsHelper _conversationsHelper = ConversationsHelper(); final UsersHelper _usersHelper = UsersHelper(); ConversationsList _list; LoadErrorLevel _error = LoadErrorLevel.NONE; final GlobalKey _refreshIndicatorKey = GlobalKey(); @override void initState() { super.initState(); this.listen( (d) => _refreshIndicatorKey.currentState.show()); } @override void didChangeDependencies() { super.didChangeDependencies(); _loadConversations(); } void setError(LoadErrorLevel err) => setState(() => _error = err); /// Get the list of conversations, once from the cache, once from the server Future _loadConversations() async { await _loadConversationsList(true); await _loadConversationsList(false); } void _gotLoadingError() { setError(_list == null ? LoadErrorLevel.MAJOR : LoadErrorLevel.MINOR); } /// Load the list of conversations Future _loadConversationsList(bool cached) async { setError(LoadErrorLevel.NONE); //Get the list of conversations var list; if (cached) list = await _conversationsHelper.getCachedList(); else list = await _conversationsHelper.downloadList(); if (list == null) return _gotLoadingError(); //Get information about the members of the conversations list.users = await _usersHelper.getUsersInfo(list.allUsersID); if (list.users == null) return _gotLoadingError(); //Save list setState(() { _list = list; }); } /// Build an error card Widget _buildErrorCard() { return buildErrorCard( tr("Could not retrieve the list of conversations!"), actions: [ FlatButton( onPressed: () => _refreshIndicatorKey.currentState.show(), child: Text( tr("Retry").toUpperCase(), style: TextStyle( color: Colors.white, ), ), ) ], ); } /// Open a conversation void _openConversation(int conversationId) { MainController.of(context).openConversation(conversationId); if (widget.onOpen != null) widget.onOpen(); } /// Create a new conversation void _createConversation() { MainController.of(context) .push(CreateConversationScreen(), allowAsDialog: true); if (widget.onOpen != null) widget.onOpen(); } /// Handle conversations updated requests void _updateConversation(Conversation conversation) { MainController.of(context).push( UpdateConversationRoute( conversationID: conversation.id, ), ); } /// Handle conversation deletion request Future _requestDeleteConversation(Conversation conversation) async { final result = await showDialog( context: context, builder: (c) { return AlertDialog( title: Text(tr("Delete conversation")), content: Text(tr( "Do you really want to remove this conversation from your list of conversations ? If you are the owner of this conversation, it will be completely deleted!")), actions: [ FlatButton( onPressed: () => Navigator.pop(context, false), child: Text(tr("cancel").toUpperCase()), ), FlatButton( onPressed: () => Navigator.pop(context, true), child: Text( tr("delete").toUpperCase(), style: TextStyle(color: Colors.red), ), ) ], ); }, ); if (result == null || !result) return; // Request the conversation to be deleted now if (!await _conversationsHelper.deleteConversation(conversation.id)) Scaffold.of(context).showSnackBar( SnackBar(content: Text(tr("Could not delete the conversation!")))); // Reload the list of conversations _loadConversationsList(false); } @override Widget build(BuildContext context) { if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard(); if (_list == null) return buildCenteredProgressBar(); // Show the list of conversations return Stack( children: [ Column( children: [ Container( child: _error == LoadErrorLevel.MINOR ? _buildErrorCard() : null, ), Expanded( child: RefreshIndicator( onRefresh: () => _loadConversationsList(false), key: _refreshIndicatorKey, child: ListView.builder( physics: AlwaysScrollableScrollPhysics(), controller: ScrollController(), itemBuilder: (context, index) { return ConversationTile( conversation: _list.elementAt(index), usersList: _list.users, onOpen: (c) { _openConversation(c.id); }, onRequestUpdate: _updateConversation, onRequestDelete: _requestDeleteConversation, ); }, itemCount: _list.length, ), ), ), ], ), // Add conversation button Positioned( right: widget.useSmallFAB ? 5.0 : 20.0, bottom: widget.useSmallFAB ? 5.0 : 20.0, child: FloatingActionButton( mini: widget.useSmallFAB, onPressed: () => _createConversation(), child: Icon(Icons.add), ), ), ], ); } }