2022-03-12 08:47:58 +00:00
import ' dart:math ' ;
2019-04-23 12:35:41 +00:00
import ' package:comunic/enums/load_error_level.dart ' ;
2022-03-18 18:11:06 +00:00
import ' package:comunic/enums/report_target_type.dart ' ;
2019-04-23 12:35:41 +00:00
import ' package:comunic/helpers/conversations_helper.dart ' ;
2020-04-18 12:33:07 +00:00
import ' package:comunic/helpers/events_helper.dart ' ;
2021-04-06 16:04:16 +00:00
import ' package:comunic/helpers/groups_helper.dart ' ;
2019-04-23 15:29:58 +00:00
import ' package:comunic/helpers/users_helper.dart ' ;
import ' package:comunic/lists/conversations_list.dart ' ;
2021-04-06 16:04:16 +00:00
import ' package:comunic/lists/groups_list.dart ' ;
import ' package:comunic/lists/users_list.dart ' ;
2019-05-01 08:52:10 +00:00
import ' package:comunic/models/conversation.dart ' ;
2022-03-18 18:11:06 +00:00
import ' package:comunic/models/report_target.dart ' ;
import ' package:comunic/ui/dialogs/report_dialog.dart ' ;
2020-05-05 11:21:37 +00:00
import ' package:comunic/ui/routes/main_route/main_route.dart ' ;
2020-04-16 12:58:02 +00:00
import ' package:comunic/ui/screens/create_conversation_screen.dart ' ;
2019-04-23 12:35:41 +00:00
import ' package:comunic/ui/tiles/conversation_tile.dart ' ;
2020-04-18 12:33:07 +00:00
import ' package:comunic/ui/widgets/safe_state.dart ' ;
2019-04-23 12:35:41 +00:00
import ' package:comunic/utils/intl_utils.dart ' ;
import ' package:comunic/utils/ui_utils.dart ' ;
import ' package:flutter/material.dart ' ;
/// Conversations screen
///
/// @author Pierre HUBERT
2019-04-24 15:46:25 +00:00
class ConversationsListScreen extends StatefulWidget {
2020-05-09 05:10:18 +00:00
final bool useSmallFAB ;
2022-03-10 18:39:57 +00:00
final Function ( ) ? onOpen ;
2020-05-09 05:10:18 +00:00
2020-05-09 05:28:17 +00:00
const ConversationsListScreen ( {
2022-03-10 18:39:57 +00:00
Key ? key ,
2020-05-09 05:28:17 +00:00
this . useSmallFAB = false ,
this . onOpen ,
2022-03-11 16:02:06 +00:00
} ) : super ( key: key ) ;
2020-05-09 05:10:18 +00:00
2019-04-23 12:35:41 +00:00
@ override
State < StatefulWidget > createState ( ) = > _ConversationScreenState ( ) ;
}
2020-04-18 12:33:07 +00:00
class _ConversationScreenState extends SafeState < ConversationsListScreen > {
2019-04-23 12:35:41 +00:00
final ConversationsHelper _conversationsHelper = ConversationsHelper ( ) ;
2019-04-23 15:29:58 +00:00
final UsersHelper _usersHelper = UsersHelper ( ) ;
2022-03-10 18:39:57 +00:00
ConversationsList ? _list ;
late UsersList _users ;
GroupsList ? _groups ;
2019-04-23 12:35:41 +00:00
LoadErrorLevel _error = LoadErrorLevel . NONE ;
2019-05-04 07:21:40 +00:00
final GlobalKey < RefreshIndicatorState > _refreshIndicatorKey =
GlobalKey < RefreshIndicatorState > ( ) ;
2019-04-23 12:35:41 +00:00
@ override
2020-04-18 12:33:07 +00:00
void initState ( ) {
super . initState ( ) ;
this . listen < NewNumberUnreadConversations > (
2022-03-10 18:39:57 +00:00
( d ) = > _refreshIndicatorKey . currentState ! . show ( ) ) ;
2019-04-23 12:35:41 +00:00
}
2019-05-01 15:10:23 +00:00
@ override
2020-04-18 12:33:07 +00:00
void didChangeDependencies ( ) {
super . didChangeDependencies ( ) ;
_loadConversations ( ) ;
2019-05-01 15:10:23 +00:00
}
2019-04-23 12:35:41 +00:00
void setError ( LoadErrorLevel err ) = > setState ( ( ) = > _error = err ) ;
2019-04-24 13:03:36 +00:00
/// Get the list of conversations, once from the cache, once from the server
Future < void > _loadConversations ( ) async {
await _loadConversationsList ( true ) ;
await _loadConversationsList ( false ) ;
}
2019-04-23 12:35:41 +00:00
/// Load the list of conversations
2019-04-24 13:03:36 +00:00
Future < void > _loadConversationsList ( bool cached ) async {
2019-04-23 12:35:41 +00:00
setError ( LoadErrorLevel . NONE ) ;
2021-03-10 16:54:41 +00:00
try {
ConversationsList list = cached
? await _conversationsHelper . getCachedList ( )
: await _conversationsHelper . downloadList ( ) ;
2019-05-01 15:10:23 +00:00
2021-04-06 16:04:16 +00:00
// Get information about the members of the conversations
_users = await _usersHelper . getList ( list . allUsersID ) ;
_groups = await GroupsHelper ( ) . getListOrThrow ( list . allGroupsID ) ;
2019-04-23 12:35:41 +00:00
2021-03-10 16:54:41 +00:00
setState ( ( ) = > _list = list ) ;
} catch ( e , s ) {
debugPrint ( " Failed to get conversations list! $ e => $ s " , wrapWidth: 1024 ) ;
setError ( _list = = null ? LoadErrorLevel . MAJOR : LoadErrorLevel . MINOR ) ;
}
2019-04-23 12:35:41 +00:00
}
/// Build an error card
Widget _buildErrorCard ( ) {
return buildErrorCard (
tr ( " Could not retrieve the list of conversations! " ) ,
actions: < Widget > [
2021-03-13 14:28:34 +00:00
TextButton (
2022-03-10 18:39:57 +00:00
onPressed: ( ) = > _refreshIndicatorKey . currentState ! . show ( ) ,
2019-04-23 12:35:41 +00:00
child: Text (
2022-03-10 18:39:57 +00:00
tr ( " Retry " ) ! . toUpperCase ( ) ,
2019-04-23 12:35:41 +00:00
style: TextStyle (
color: Colors . white ,
) ,
) ,
)
] ,
) ;
}
2019-04-24 15:46:25 +00:00
/// Open a conversation
2021-04-06 16:22:45 +00:00
void _openConversation ( Conversation conv ) {
2022-03-10 18:39:57 +00:00
MainController . of ( context ) ! . openConversation ( conv ) ;
if ( widget . onOpen ! = null ) widget . onOpen ! ( ) ;
2019-04-24 15:46:25 +00:00
}
2019-04-27 14:23:08 +00:00
/// Create a new conversation
2020-04-16 12:58:02 +00:00
void _createConversation ( ) {
2022-03-10 18:39:57 +00:00
MainController . of ( context ) ! . push (
2021-04-24 08:14:56 +00:00
CreateConversationScreen ( ) ,
canShowAsDialog: true ,
hideNavBar: true ,
) ;
2022-03-10 18:39:57 +00:00
if ( widget . onOpen ! = null ) widget . onOpen ! ( ) ;
2019-04-27 14:23:08 +00:00
}
2019-05-01 08:58:45 +00:00
/// Handle conversations updated requests
void _updateConversation ( Conversation conversation ) {
2022-03-10 18:39:57 +00:00
MainController . of ( context ) ! . openConversationSettingsRoute ( conversation ) ;
2019-05-01 08:58:45 +00:00
}
/// Handle conversation deletion request
2021-03-13 11:07:16 +00:00
Future < void > _requestLeaveConversation ( Conversation conversation ) async {
2021-04-06 16:04:16 +00:00
if ( conversation . isGroupConversation ) {
showAlert (
context: context ,
title: tr ( " Group conversation " ) ,
message: tr (
" This conversation is managed by a group. You can not leave it this way. If you do not want to receive notifications from this conversation anymore, you can stop following it in the conversation settings " ) ) ;
return ;
}
2021-03-13 11:07:16 +00:00
final result = await showConfirmDialog (
context: context ,
message: conversation . isLastAdmin
? tr (
" Do you really want to leave this conversation ? As you are its last admin, it will be completely deleted! " )
: tr ( " Do you really want to leave this conversation ? " ) ) ;
2019-05-01 08:52:10 +00:00
2022-03-11 16:02:06 +00:00
if ( ! result ) return ;
2019-05-01 08:52:10 +00:00
// Request the conversation to be deleted now
2021-03-10 16:54:41 +00:00
try {
await _conversationsHelper . deleteConversation ( conversation . id ) ;
} catch ( e , s ) {
2021-03-13 11:07:16 +00:00
print ( " Failed to leave conversation! $ e => $ s " ) ;
2021-03-13 14:28:34 +00:00
ScaffoldMessenger . of ( context ) . showSnackBar (
2022-03-10 18:39:57 +00:00
SnackBar ( content: Text ( tr ( " Could not leave the conversation! " ) ! ) ) ) ;
2021-03-10 16:54:41 +00:00
}
2019-05-01 08:52:10 +00:00
// Reload the list of conversations
_loadConversationsList ( false ) ;
}
2022-03-18 18:11:06 +00:00
/// Handle conversation report request
void _reportConversation ( Conversation conversation ) = > showReportDialog (
ctx: context ,
target: ReportTarget ( ReportTargetType . Conversation , conversation . id ! ) ) ;
2019-04-23 12:35:41 +00:00
@ override
Widget build ( BuildContext context ) {
if ( _error = = LoadErrorLevel . MAJOR ) return _buildErrorCard ( ) ;
if ( _list = = null ) return buildCenteredProgressBar ( ) ;
// Show the list of conversations
2019-04-24 13:03:36 +00:00
return Stack (
children: < Widget > [
Column (
children: < Widget > [
Container (
child: _error = = LoadErrorLevel . MINOR ? _buildErrorCard ( ) : null ,
) ,
Expanded (
2019-05-04 07:21:40 +00:00
child: RefreshIndicator (
onRefresh: ( ) = > _loadConversationsList ( false ) ,
key: _refreshIndicatorKey ,
child: ListView . builder (
physics: AlwaysScrollableScrollPhysics ( ) ,
controller: ScrollController ( ) ,
itemBuilder: ( context , index ) {
2022-03-12 08:47:58 +00:00
if ( _list ! . isEmpty )
return Padding (
padding: const EdgeInsets . all ( 8.0 ) ,
child: Center (
child: Text (
tr ( " You do not have any conversation yet! " ) ! ) ) ,
) ;
2022-03-10 18:39:57 +00:00
if ( _list ! [ index ] . isGroupConversation & &
! _list ! [ index ] . following ) return Container ( ) ;
2021-04-06 16:04:16 +00:00
2019-05-04 07:21:40 +00:00
return ConversationTile (
2022-03-10 18:39:57 +00:00
conversation: _list ! . elementAt ( index ) ,
2021-04-06 16:04:16 +00:00
usersList: _users ,
groupsList: _groups ,
2019-05-04 07:21:40 +00:00
onOpen: ( c ) {
2021-04-06 16:22:45 +00:00
_openConversation ( c ) ;
2019-05-04 07:21:40 +00:00
} ,
onRequestUpdate: _updateConversation ,
2021-03-13 11:07:16 +00:00
onRequestLeave: _requestLeaveConversation ,
2022-03-18 18:11:06 +00:00
onReport: _reportConversation ,
2019-05-04 07:21:40 +00:00
) ;
} ,
2022-03-12 08:47:58 +00:00
itemCount: max ( _list ! . length , 1 ) ,
2019-05-04 07:21:40 +00:00
) ,
2019-04-24 13:03:36 +00:00
) ,
) ,
] ,
) ,
2019-04-27 14:23:08 +00:00
// Add conversation button
Positioned (
2020-05-09 05:10:18 +00:00
right: widget . useSmallFAB ? 5.0 : 20.0 ,
bottom: widget . useSmallFAB ? 5.0 : 20.0 ,
2019-04-27 14:23:08 +00:00
child: FloatingActionButton (
2020-05-09 05:10:18 +00:00
mini: widget . useSmallFAB ,
2020-04-16 12:58:02 +00:00
onPressed: ( ) = > _createConversation ( ) ,
2019-04-27 14:23:08 +00:00
child: Icon ( Icons . add ) ,
) ,
) ,
2019-04-24 13:03:36 +00:00
] ,
2019-04-23 12:35:41 +00:00
) ;
}
}