add message that a user has changed there name

This commit is contained in:
otsmr 2026-05-05 00:41:13 +02:00
parent 28fffbfce5
commit 52bc628752
10 changed files with 109 additions and 3 deletions

View file

@ -332,4 +332,18 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
return query.map((row) => row.readTable(groups)).watch(); return query.map((row) => row.readTable(groups)).watch();
} }
Future<List<Group>> getGroupsForMember(int contactId) {
final query =
select(groups).join([
innerJoin(
groupMembers,
groupMembers.groupId.equalsExp(groups.groupId),
),
])..where(
groupMembers.contactId.equals(contactId),
);
return query.map((row) => row.readTable(groups)).get();
}
} }

View file

@ -83,6 +83,8 @@ enum GroupActionType {
demoteToMember, demoteToMember,
updatedGroupName, updatedGroupName,
changeDisplayMaxTime, changeDisplayMaxTime,
updatedContactUsername,
updatedContactDisplayName,
} }
@DataClassName('GroupHistory') @DataClassName('GroupHistory')

View file

@ -3049,6 +3049,18 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Example'** /// **'Example'**
String get onboardingExampleLabel; String get onboardingExampleLabel;
/// No description provided for @makerChangedUsername.
///
/// In en, this message translates to:
/// **'{maker} changed their username from {oldName} to {newName}.'**
String makerChangedUsername(Object maker, Object oldName, Object newName);
/// No description provided for @makerChangedDisplayName.
///
/// In en, this message translates to:
/// **'{maker} changed their display name from {oldName} to {newName}.'**
String makerChangedDisplayName(Object maker, Object oldName, Object newName);
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View file

@ -1711,4 +1711,14 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get onboardingExampleLabel => 'Beispiel'; String get onboardingExampleLabel => 'Beispiel';
@override
String makerChangedUsername(Object maker, Object oldName, Object newName) {
return '$maker hat seinen Benutzernamen von $oldName zu $newName geändert.';
}
@override
String makerChangedDisplayName(Object maker, Object oldName, Object newName) {
return '$maker hat seinen Anzeigenamen von $oldName zu $newName geändert.';
}
} }

View file

@ -1696,4 +1696,14 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get onboardingExampleLabel => 'Example'; String get onboardingExampleLabel => 'Example';
@override
String makerChangedUsername(Object maker, Object oldName, Object newName) {
return '$maker changed their username from $oldName to $newName.';
}
@override
String makerChangedDisplayName(Object maker, Object oldName, Object newName) {
return '$maker changed their display name from $oldName to $newName.';
}
} }

@ -1 +1 @@
Subproject commit 73d1af8ca42b10abf6204acf3720d40f9ab6d4a8 Subproject commit 781626f66c5f992ffad861abb7b4937f82319392

View file

@ -4,6 +4,7 @@ import 'dart:convert';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:twonly/locator.dart'; import 'package:twonly/locator.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart'; import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/tables/groups.table.dart';
import 'package:twonly/src/database/twonly.db.dart' hide Message; import 'package:twonly/src/database/twonly.db.dart' hide Message;
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart'; import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
import 'package:twonly/src/services/api/messages.api.dart'; import 'package:twonly/src/services/api/messages.api.dart';
@ -126,6 +127,44 @@ Future<void> handleContactUpdate(
if (contactUpdate.hasDisplayName() && if (contactUpdate.hasDisplayName() &&
contactUpdate.hasUsername() && contactUpdate.hasUsername() &&
senderProfileCounter != null) { senderProfileCounter != null) {
final contact = await twonlyDB.contactsDao
.getContactByUserId(fromUserId)
.getSingleOrNull();
if (contact != null) {
final sharedGroups = await twonlyDB.groupsDao.getGroupsForMember(
fromUserId,
);
if (contact.username != contactUpdate.username) {
for (final group in sharedGroups) {
await twonlyDB.groupsDao.insertGroupAction(
GroupHistoriesCompanion(
groupId: Value(group.groupId),
type: const Value(GroupActionType.updatedContactUsername),
contactId: Value(fromUserId),
oldGroupName: Value('@${contact.username}'),
newGroupName: Value('@${contactUpdate.username}'),
),
);
}
}
if (contact.displayName != contactUpdate.displayName) {
for (final group in sharedGroups) {
await twonlyDB.groupsDao.insertGroupAction(
GroupHistoriesCompanion(
groupId: Value(group.groupId),
type: const Value(GroupActionType.updatedContactDisplayName),
contactId: Value(fromUserId),
oldGroupName: Value(contact.displayName ?? ''),
newGroupName: Value(contactUpdate.displayName),
),
);
}
}
}
await twonlyDB.contactsDao.updateContact( await twonlyDB.contactsDao.updateContact(
fromUserId, fromUserId,
ContactsCompanion( ContactsCompanion(

View file

@ -179,6 +179,8 @@ Future<void> handleGroupUpdate(
), ),
); );
case GroupActionType.createdGroup: case GroupActionType.createdGroup:
case GroupActionType.updatedContactUsername:
case GroupActionType.updatedContactDisplayName:
break; break;
} }
} }

View file

@ -77,7 +77,6 @@ class _ChatMessagesViewState extends State<ChatMessagesView>
contactSub?.cancel(); contactSub?.cancel();
groupActionsSub?.cancel(); groupActionsSub?.cancel();
_nextTypingIndicator?.cancel(); _nextTypingIndicator?.cancel();
textFieldFocus?.dispose();
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
super.dispose(); super.dispose();
} }
@ -108,7 +107,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView>
}); });
protectMessageUpdating.protect(() async { protectMessageUpdating.protect(() async {
if (groupActionsSub == null && !newGroup.isDirectChat) { if (groupActionsSub == null) {
final actionsStream = twonlyDB.groupsDao.watchGroupActions( final actionsStream = twonlyDB.groupsDao.watchGroupActions(
newGroup.groupId, newGroup.groupId,
); );

View file

@ -105,6 +105,24 @@ class _ChatGroupActionState extends State<ChatGroupAction> {
text = (contact == null) text = (contact == null)
? context.lang.youLeftGroup ? context.lang.youLeftGroup
: context.lang.makerLeftGroup(maker); : context.lang.makerLeftGroup(maker);
case GroupActionType.updatedContactUsername:
if (contact != null) {
icon = FontAwesomeIcons.userPen;
text = context.lang.makerChangedUsername(
maker,
widget.action.oldGroupName!,
widget.action.newGroupName!,
);
}
case GroupActionType.updatedContactDisplayName:
if (contact != null) {
icon = FontAwesomeIcons.userPen;
text = context.lang.makerChangedDisplayName(
maker,
widget.action.oldGroupName!,
widget.action.newGroupName!,
);
}
} }
// switch (widget.action.type) { // switch (widget.action.type) {