diff --git a/lib/lists/conversations_list.dart b/lib/lists/conversations_list.dart index 99d03d6..447f59c 100644 --- a/lib/lists/conversations_list.dart +++ b/lib/lists/conversations_list.dart @@ -1,6 +1,5 @@ import 'dart:collection'; -import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/conversation.dart'; /// Conversations list @@ -9,7 +8,6 @@ import 'package:comunic/models/conversation.dart'; class ConversationsList extends ListBase { final List _list = []; - UsersList users; set length(l) => _list.length = l; @@ -27,4 +25,9 @@ class ConversationsList extends ListBase { forEach((c) => c.members.forEach((member) => list.add(member.userID))); return list; } + + /// Get the entire lists of groups ID in this list + Set get allGroupsID => where((element) => element.isGroupConversation) + .map((e) => e.groupID) + .toSet(); } diff --git a/lib/models/conversation.dart b/lib/models/conversation.dart index ba4d70e..f26e05c 100644 --- a/lib/models/conversation.dart +++ b/lib/models/conversation.dart @@ -75,7 +75,9 @@ class Conversation extends SerializableElement { bool get sawLastMessage => lastActivity <= membership.lastAccessTime; /// Check out whether a conversation is managed or not - bool get isManaged => groupID != null; + bool get isManaged => isGroupConversation; + + bool get isGroupConversation => groupID != null; bool get hasLogo => logoURL != null; diff --git a/lib/ui/screens/conversations_list_screen.dart b/lib/ui/screens/conversations_list_screen.dart index 2d03b59..f001653 100644 --- a/lib/ui/screens/conversations_list_screen.dart +++ b/lib/ui/screens/conversations_list_screen.dart @@ -1,8 +1,11 @@ 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/groups_helper.dart'; import 'package:comunic/helpers/users_helper.dart'; import 'package:comunic/lists/conversations_list.dart'; +import 'package:comunic/lists/groups_list.dart'; +import 'package:comunic/lists/users_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'; @@ -36,6 +39,8 @@ class _ConversationScreenState extends SafeState { final ConversationsHelper _conversationsHelper = ConversationsHelper(); final UsersHelper _usersHelper = UsersHelper(); ConversationsList _list; + UsersList _users; + GroupsList _groups; LoadErrorLevel _error = LoadErrorLevel.NONE; final GlobalKey _refreshIndicatorKey = GlobalKey(); @@ -72,8 +77,10 @@ class _ConversationScreenState extends SafeState { : await _conversationsHelper.downloadList(); assert(list != null); - //Get information about the members of the conversations - list.users = await _usersHelper.getList(list.allUsersID); + // Get information about the members of the conversations + _users = await _usersHelper.getList(list.allUsersID); + + _groups = await GroupsHelper().getListOrThrow(list.allGroupsID); setState(() => _list = list); } catch (e, s) { @@ -124,6 +131,15 @@ class _ConversationScreenState extends SafeState { /// Handle conversation deletion request Future _requestLeaveConversation(Conversation conversation) async { + 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; + } + final result = await showConfirmDialog( context: context, message: conversation.isLastAdmin @@ -167,9 +183,13 @@ class _ConversationScreenState extends SafeState { physics: AlwaysScrollableScrollPhysics(), controller: ScrollController(), itemBuilder: (context, index) { + if (_list[index].isGroupConversation && + !_list[index].following) return Container(); + return ConversationTile( conversation: _list.elementAt(index), - usersList: _list.users, + usersList: _users, + groupsList: _groups, onOpen: (c) { _openConversation(c.id); }, diff --git a/lib/ui/tiles/conversation_tile.dart b/lib/ui/tiles/conversation_tile.dart index 39454e4..a070dde 100644 --- a/lib/ui/tiles/conversation_tile.dart +++ b/lib/ui/tiles/conversation_tile.dart @@ -1,4 +1,5 @@ import 'package:comunic/helpers/conversations_helper.dart'; +import 'package:comunic/lists/groups_list.dart'; import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/conversation.dart'; import 'package:comunic/ui/routes/main_route/main_route.dart'; @@ -21,6 +22,7 @@ enum _PopupMenuChoices { UPDATE, LEAVE } class ConversationTile extends StatelessWidget { final Conversation conversation; final UsersList usersList; + final GroupsList groupsList; final OpenConversationCallback onOpen; final RequestUpdateConversationCallback onRequestUpdate; final RequestLeaveConversationCallback onRequestLeave; @@ -29,6 +31,7 @@ class ConversationTile extends StatelessWidget { Key key, @required this.conversation, @required this.usersList, + @required this.groupsList, @required this.onOpen, @required this.onRequestUpdate, @required this.onRequestLeave, @@ -86,17 +89,24 @@ class ConversationTile extends StatelessWidget { children: [ _buildSubInformation(Icons.access_time, diffTimeFromNowToStr(conversation.lastActivity)), - _buildSubInformation( - Icons.group, - conversation.members.length == 1 - ? tr("1 member") - : tr( - "%num% members", - args: { - "num": conversation.members.length.toString(), - }, - ), - ), + conversation.isGroupConversation + ? _buildSubInformation( + Icons.link, + tr("Group: %group_name%", args: { + "group_name": + groupsList.getGroup(conversation.groupID).name + })) + : _buildSubInformation( + Icons.group, + conversation.members.length == 1 + ? tr("1 member") + : tr( + "%num% members", + args: { + "num": conversation.members.length.toString(), + }, + ), + ), ], ), diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index b85eeec..ad5a81d 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -1,7 +1,9 @@ + import 'package:comunic/helpers/preferences_helper.dart'; import 'package:comunic/main.dart'; import 'package:comunic/ui/routes/full_screen_image.dart'; import 'package:comunic/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart'; +import 'package:comunic/ui/widgets/dialogs/cancel_dialog_button.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_emoji/flutter_emoji.dart'; @@ -220,6 +222,20 @@ Future showConfirmDialog({ return result != null && result; } +/// Show a simple alert dialog +Future showAlert({ + @required BuildContext context, + @required String message, + String title, +}) async => + await showDialog( + context: context, + builder: (c) => AlertDialog( + title: title == null ? null : Text(title), + content: Text(message), + actions: [CancelDialogButton()], + )); + /// Smart [InputCounterWidgetBuilder] that show text limit only when some /// text has already been entered by the user Widget smartInputCounterWidgetBuilder(