store group creation action

This commit is contained in:
otsmr 2025-11-02 14:29:09 +01:00
parent 8cf57224ce
commit d616e08dec
4 changed files with 40 additions and 14 deletions

View file

@ -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/api/utils.dart';
import 'package:twonly/src/services/fcm.service.dart'; import 'package:twonly/src/services/fcm.service.dart';
import 'package:twonly/src/services/flame.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/notifications/pushkeys.notifications.dart';
import 'package:twonly/src/services/signal/identity.signal.dart'; import 'package:twonly/src/services/signal/identity.signal.dart';
import 'package:twonly/src/services/signal/prekeys.signal.dart'; import 'package:twonly/src/services/signal/prekeys.signal.dart';
@ -99,6 +100,7 @@ class ApiService {
unawaited(syncFlameCounters()); unawaited(syncFlameCounters());
unawaited(setupNotificationWithUsers()); unawaited(setupNotificationWithUsers());
unawaited(signalHandleNewServerConnection()); unawaited(signalHandleNewServerConnection());
unawaited(fetchGroupStatesForUnjoinedGroups());
} }
} }

View file

@ -14,6 +14,17 @@ Future<void> handleGroupCreate(
String groupId, String groupId,
EncryptedContent_GroupCreate newGroup, EncryptedContent_GroupCreate newGroup,
) async { ) 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 // 1. Store the new group -> e.g. store the stateKey and groupPublicKey
// 2. Call function that should fetch all jobs // 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 // 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<void> handleGroupCreate(
return; return;
} }
final user = await twonlyDB.contactsDao await twonlyDB.groupsDao.insertGroupAction(
.getContactByUserId(fromUserId) GroupHistoriesCompanion(
.getSingleOrNull(); groupId: Value(groupId),
if (user == null) { contactId: Value(fromUserId),
// Only contacts can invite other contacts, so this can (via the UI) not happen. affectedContactId: const Value(null),
Log.error( type: const Value(GroupActionType.addMember),
'User is not a contact. Aborting.', ),
); );
return;
}
await twonlyDB.groupsDao.insertGroupMember( await twonlyDB.groupsDao.insertGroupMember(
GroupMembersCompanion( GroupMembersCompanion(

View file

@ -381,7 +381,10 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
}).toList(), }).toList(),
); );
} else if (messages[i].isGroupAction) { } else if (messages[i].isGroupAction) {
return ChatGroupAction(action: messages[i].groupAction!); return ChatGroupAction(
key: Key(messages[i].groupAction!.groupHistoryId),
action: messages[i].groupAction!,
);
} else { } else {
final chatMessage = messages[i].message!; final chatMessage = messages[i].message!;
return Transform.translate( return Transform.translate(

View file

@ -44,6 +44,7 @@ class _ChatGroupActionState extends State<ChatGroupAction> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var text = ''; var text = '';
IconData? icon;
final affected = (affectedContact == null) final affected = (affectedContact == null)
? 'you' ? 'you'
@ -56,22 +57,33 @@ class _ChatGroupActionState extends State<ChatGroupAction> {
text = (contact == null) text = (contact == null)
? 'You have changed the group name to "${widget.action.newGroupName}".' ? 'You have changed the group name to "${widget.action.newGroupName}".'
: '$maker has changed the group name to "${widget.action.newGroupName}".'; : '$maker has changed the group name to "${widget.action.newGroupName}".';
icon = FontAwesomeIcons.pencil;
case GroupActionType.createdGroup: case GroupActionType.createdGroup:
icon = FontAwesomeIcons.penToSquare;
text = (contact == null)
? 'You have created the group.'
: '$maker has created the group.';
case GroupActionType.removedMember: case GroupActionType.removedMember:
case GroupActionType.addMember: 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: case GroupActionType.leftGroup:
break; break;
case GroupActionType.promoteToAdmin: case GroupActionType.promoteToAdmin:
icon = FontAwesomeIcons.key;
text = (contact == null) text = (contact == null)
? 'You made $affected an admin.' ? 'You made $affected an admin.'
: '$maker made $affected an admin.'; : '$maker made $affected an admin.';
case GroupActionType.demoteToMember: case GroupActionType.demoteToMember:
icon = FontAwesomeIcons.key;
text = (contact == null) text = (contact == null)
? 'You revoked $affected admin rights.' ? 'You revoked $affected admin rights.'
: '$maker revoked $affectedR admin rights.'; : '$maker revoked $affectedR admin rights.';
} }
if (text == '') return Container(); if (text == '' || icon == null) return Container();
return Padding( return Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
@ -80,10 +92,10 @@ class _ChatGroupActionState extends State<ChatGroupAction> {
textAlign: TextAlign.center, textAlign: TextAlign.center,
text: TextSpan( text: TextSpan(
children: [ children: [
const WidgetSpan( WidgetSpan(
alignment: PlaceholderAlignment.middle, alignment: PlaceholderAlignment.middle,
child: FaIcon( child: FaIcon(
FontAwesomeIcons.pencil, icon,
size: 10, size: 10,
color: Colors.grey, color: Colors.grey,
), ),