From d616e08dec1ddb24c879ea306397e9d7fbfd786e Mon Sep 17 00:00:00 2001 From: otsmr Date: Sun, 2 Nov 2025 14:29:09 +0100 Subject: [PATCH] store group creation action --- lib/src/services/api.service.dart | 2 ++ .../api/client2client/groups.c2c.dart | 29 ++++++++++++------- lib/src/views/chats/chat_messages.view.dart | 5 +++- .../chat_group_action.dart | 18 ++++++++++-- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/lib/src/services/api.service.dart b/lib/src/services/api.service.dart index 35debca..05d8d88 100644 --- a/lib/src/services/api.service.dart +++ b/lib/src/services/api.service.dart @@ -30,6 +30,7 @@ import 'package:twonly/src/services/api/server_messages.dart'; import 'package:twonly/src/services/api/utils.dart'; import 'package:twonly/src/services/fcm.service.dart'; import 'package:twonly/src/services/flame.service.dart'; +import 'package:twonly/src/services/group.services.dart'; import 'package:twonly/src/services/notifications/pushkeys.notifications.dart'; import 'package:twonly/src/services/signal/identity.signal.dart'; import 'package:twonly/src/services/signal/prekeys.signal.dart'; @@ -99,6 +100,7 @@ class ApiService { unawaited(syncFlameCounters()); unawaited(setupNotificationWithUsers()); unawaited(signalHandleNewServerConnection()); + unawaited(fetchGroupStatesForUnjoinedGroups()); } } diff --git a/lib/src/services/api/client2client/groups.c2c.dart b/lib/src/services/api/client2client/groups.c2c.dart index 5e18672..2bba307 100644 --- a/lib/src/services/api/client2client/groups.c2c.dart +++ b/lib/src/services/api/client2client/groups.c2c.dart @@ -14,6 +14,17 @@ Future handleGroupCreate( String groupId, EncryptedContent_GroupCreate newGroup, ) async { + final user = await twonlyDB.contactsDao + .getContactByUserId(fromUserId) + .getSingleOrNull(); + if (user == null) { + // Only contacts can invite other contacts, so this can (via the UI) not happen. + Log.error( + 'User is not a contact. Aborting.', + ); + return; + } + // 1. Store the new group -> e.g. store the stateKey and groupPublicKey // 2. Call function that should fetch all jobs // 1. This function is also called in the main function, in case the state stored on the server could not be loaded @@ -41,16 +52,14 @@ Future handleGroupCreate( return; } - final user = await twonlyDB.contactsDao - .getContactByUserId(fromUserId) - .getSingleOrNull(); - if (user == null) { - // Only contacts can invite other contacts, so this can (via the UI) not happen. - Log.error( - 'User is not a contact. Aborting.', - ); - return; - } + await twonlyDB.groupsDao.insertGroupAction( + GroupHistoriesCompanion( + groupId: Value(groupId), + contactId: Value(fromUserId), + affectedContactId: const Value(null), + type: const Value(GroupActionType.addMember), + ), + ); await twonlyDB.groupsDao.insertGroupMember( GroupMembersCompanion( diff --git a/lib/src/views/chats/chat_messages.view.dart b/lib/src/views/chats/chat_messages.view.dart index 94bc7fc..240ac51 100644 --- a/lib/src/views/chats/chat_messages.view.dart +++ b/lib/src/views/chats/chat_messages.view.dart @@ -381,7 +381,10 @@ class _ChatMessagesViewState extends State { }).toList(), ); } else if (messages[i].isGroupAction) { - return ChatGroupAction(action: messages[i].groupAction!); + return ChatGroupAction( + key: Key(messages[i].groupAction!.groupHistoryId), + action: messages[i].groupAction!, + ); } else { final chatMessage = messages[i].message!; return Transform.translate( diff --git a/lib/src/views/chats/chat_messages_components/chat_group_action.dart b/lib/src/views/chats/chat_messages_components/chat_group_action.dart index f748f7e..0576654 100644 --- a/lib/src/views/chats/chat_messages_components/chat_group_action.dart +++ b/lib/src/views/chats/chat_messages_components/chat_group_action.dart @@ -44,6 +44,7 @@ class _ChatGroupActionState extends State { @override Widget build(BuildContext context) { var text = ''; + IconData? icon; final affected = (affectedContact == null) ? 'you' @@ -56,22 +57,33 @@ class _ChatGroupActionState extends State { text = (contact == null) ? 'You have changed the group name to "${widget.action.newGroupName}".' : '$maker has changed the group name to "${widget.action.newGroupName}".'; + icon = FontAwesomeIcons.pencil; case GroupActionType.createdGroup: + icon = FontAwesomeIcons.penToSquare; + text = (contact == null) + ? 'You have created the group.' + : '$maker has created the group.'; case GroupActionType.removedMember: case GroupActionType.addMember: + icon = FontAwesomeIcons.userPlus; + text = (contact == null) + ? 'You have added $affected to the group.' + : '$maker has added $affected to the group.'; case GroupActionType.leftGroup: break; case GroupActionType.promoteToAdmin: + icon = FontAwesomeIcons.key; text = (contact == null) ? 'You made $affected an admin.' : '$maker made $affected an admin.'; case GroupActionType.demoteToMember: + icon = FontAwesomeIcons.key; text = (contact == null) ? 'You revoked $affected admin rights.' : '$maker revoked $affectedR admin rights.'; } - if (text == '') return Container(); + if (text == '' || icon == null) return Container(); return Padding( padding: const EdgeInsets.all(8), @@ -80,10 +92,10 @@ class _ChatGroupActionState extends State { textAlign: TextAlign.center, text: TextSpan( children: [ - const WidgetSpan( + WidgetSpan( alignment: PlaceholderAlignment.middle, child: FaIcon( - FontAwesomeIcons.pencil, + icon, size: 10, color: Colors.grey, ),