Skip to content

Commit

Permalink
Merge pull request #2637 from gtalha07/chat_ng-state-events-fix
Browse files Browse the repository at this point in the history
Chat ng member state events fix
  • Loading branch information
gtalha07 authored Feb 24, 2025
2 parents 372784e + a861bd0 commit 59a19ae
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 58 deletions.
3 changes: 3 additions & 0 deletions .changes/2637-chat_ng-state-events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- [Labs] Chat NG:
[Fix]: add missing member state events of room and better wording.
[Improvement]: update selection text color of editor for improved visibility
4 changes: 2 additions & 2 deletions app/lib/common/widgets/html_editor/html_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ class HtmlEditorState extends State<HtmlEditor> {
return EditorStyle.desktop(
padding: widget.editorPadding,
cursorColor: Theme.of(context).colorScheme.primary,
selectionColor: Theme.of(context).colorScheme.secondaryContainer,
selectionColor: Theme.of(context).colorScheme.secondary,
textStyleConfiguration: widget.textStyleConfiguration ??
TextStyleConfiguration(
text: Theme.of(context)
Expand All @@ -483,7 +483,7 @@ class HtmlEditorState extends State<HtmlEditor> {
return EditorStyle.mobile(
padding: widget.editorPadding,
cursorColor: Theme.of(context).colorScheme.primary,
selectionColor: Theme.of(context).colorScheme.secondaryContainer,
selectionColor: Theme.of(context).colorScheme.secondary,
textStyleConfiguration: widget.textStyleConfiguration ??
TextStyleConfiguration(
text: Theme.of(context)
Expand Down
6 changes: 3 additions & 3 deletions app/lib/features/chat/widgets/messages/membership_update.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ class MembershipUpdateWidget extends ConsumerWidget {
}
} else if (msgType == 'Invited') {
if (message.author.id == myUserId) {
textMsg = lang.chatYouInvited;
textMsg = lang.chatYouInvited('');
} else if (firstName != null) {
textMsg = lang.chatInvitedDisplayName(firstName);
textMsg = lang.chatInvitedDisplayName(firstName, '');
} else {
textMsg = lang.chatInvitedUserId(message.author.id);
textMsg = lang.chatInvitedUserId(message.author.id, '');
}
} else {
textMsg = message.metadata?['body'] ?? '';
Expand Down
29 changes: 29 additions & 0 deletions app/lib/features/chat_ng/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,32 @@ Future<void> saveMsgDraft(
}
}
}

// whether event is state event
bool isStateEvent(String eventType) {
return [
'm.policy.rule.room',
'm.policy.rule.server',
'm.policy.rule.user',
'm.room.aliases',
'm.room.avatar',
'm.room.canonical_alias',
'm.room.create',
'm.room.encryption',
'm.room.guest_access',
'm.room.history_visibility',
'm.room.join_rules',
'm.room.name',
'm.room.pinned_events',
'm.room.power_levels',
'm.room.server_acl',
'm.room.third_party_invite',
'm.room.tombstone',
'm.room.topic',
'm.space.child',
'm.space.parent',
].contains(eventType);
}

bool isMemberEvent(String eventType) =>
['m.room.member', 'ProfileChange'].contains(eventType);
18 changes: 17 additions & 1 deletion app/lib/features/chat_ng/widgets/events/chat_event.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:acter/common/providers/common_providers.dart';
import 'package:acter/common/providers/room_providers.dart';
import 'package:acter/features/chat_ng/providers/chat_room_messages_provider.dart';
import 'package:acter/features/chat_ng/utils.dart';
import 'package:acter/features/chat_ng/widgets/events/chat_event_item.dart';
import 'package:acter_avatar/acter_avatar.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -74,13 +75,16 @@ class ChatEvent extends ConsumerWidget {
final canRedact = item.sender() == myId;

final isMe = myId == item.sender();

final bool shouldShowAvatar =
_shouldShowAvatar(item.eventType(), isNextMessageInGroup, isMe);
// TODO: render a regular timeline event
return Row(
mainAxisAlignment:
!isMe ? MainAxisAlignment.start : MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(!isNextMessageInGroup && !isMe)
shouldShowAvatar
? Padding(
padding: const EdgeInsets.only(left: 8),
child: ActerAvatar(options: options),
Expand All @@ -99,4 +103,16 @@ class ChatEvent extends ConsumerWidget {
],
);
}

bool _shouldShowAvatar(
String eventType,
bool isNextMessageInGroup,
bool isMe,
) {
if (isStateEvent(eventType) || isMemberEvent(eventType)) {
return !isMe; // Show avatar only for state messages
}
// For regular messages, follow the grouping
return !isNextMessageInGroup && !isMe;
}
}
5 changes: 3 additions & 2 deletions app/lib/features/chat_ng/widgets/events/chat_event_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ class ChatEventItem extends StatelessWidget {
isNextMessageInGroup: isNextMessageInGroup,
child: EncryptedMessageWidget(),
),
'm.room.member' => MemberUpdateEvent(
'm.room.member' || 'ProfileChange' => MemberUpdateEvent(
isMe: isMe,
roomId: roomId,
item: item,
),
'm.policy.rule.room' ||
Expand Down Expand Up @@ -93,7 +94,7 @@ class ChatEventItem extends StatelessWidget {

Widget _buildUnsupportedMessage(String? msgtype) {
return Text(
'Unsupported event type: $msgtype',
'Unsupported chat event type: $msgtype',
);
}
}
115 changes: 79 additions & 36 deletions app/lib/features/chat_ng/widgets/events/member_update_event.dart
Original file line number Diff line number Diff line change
@@ -1,53 +1,24 @@
import 'package:acter/common/utils/utils.dart';
import 'package:acter/common/providers/room_providers.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'
show RoomEventItem;
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class MemberUpdateEvent extends StatelessWidget {
class MemberUpdateEvent extends ConsumerWidget {
final bool isMe;
final String roomId;
final RoomEventItem item;
const MemberUpdateEvent({
super.key,
required this.isMe,
required this.roomId,
required this.item,
});

@override
Widget build(BuildContext context) {
final lang = L10n.of(context);
late String textMsg;
final senderId = item.sender();
final msgType = item.msgType();
final firstName = simplifyUserId(senderId);

if (msgType == 'Joined') {
if (isMe) {
textMsg = lang.chatYouJoined;
} else if (firstName != null) {
textMsg = lang.chatJoinedDisplayName(firstName);
} else {
textMsg = lang.chatJoinedUserId(senderId);
}
} else if (msgType == 'InvitationAccepted') {
if (isMe) {
textMsg = lang.chatYouAcceptedInvite;
} else if (firstName != null) {
textMsg = lang.chatInvitationAcceptedDisplayName(firstName);
} else {
textMsg = lang.chatInvitationAcceptedUserId(senderId);
}
} else if (msgType == 'Invited') {
if (isMe) {
textMsg = lang.chatYouInvited;
} else if (firstName != null) {
textMsg = lang.chatInvitedDisplayName(firstName);
} else {
textMsg = lang.chatInvitedUserId(senderId);
}
} else {
textMsg = item.msgContent()?.body() ?? '';
}
Widget build(BuildContext context, WidgetRef ref) {
String textMsg = getStateEventStr(context, ref, item);

return Container(
padding: const EdgeInsets.only(
Expand All @@ -63,4 +34,76 @@ class MemberUpdateEvent extends StatelessWidget {
),
);
}

String getStateEventStr(
BuildContext context,
WidgetRef ref,
RoomEventItem item,
) {
final lang = L10n.of(context);

final senderId = item.sender();
final eventType = item.eventType();
final msgType = item.msgType();
final firstName = ref
.watch(memberDisplayNameProvider((roomId: roomId, userId: senderId)))
.valueOrNull;
final msgContent = item.msgContent()?.body() ?? '';

return switch (eventType) {
'ProfileChange' => switch (msgType) {
'ChangedDisplayName' =>
'${lang.chatDisplayNameUpdate(firstName ?? senderId)} $msgContent',
'SetDisplayName' =>
'${lang.chatDisplayNameSet(firstName ?? senderId)}: $msgContent',
'RemoveDisplayName' =>
lang.chatDisplayNameUnset(firstName ?? senderId),
'ChangeProfileAvatar' =>
lang.chatUserAvatarChange(firstName ?? senderId),
_ => msgContent
},
_ => switch (msgType) {
'Joined' => isMe
? lang.chatYouJoined
: firstName != null
? lang.chatJoinedDisplayName(firstName)
: lang.chatJoinedUserId(senderId),
'Left' =>
isMe ? lang.chatYouLeft : lang.chatUserLeft(firstName ?? senderId),
'Banned' => isMe
? lang.chatYouBanned(msgContent)
: lang.chatUserBanned(firstName ?? senderId, msgContent),
'Unbanned' => isMe
? lang.chatYouUnbanned(msgContent)
: lang.chatUserUnbanned(firstName ?? senderId, msgContent),
'Kicked' => isMe
? lang.chatYouKicked(msgContent)
: lang.chatUserKicked(firstName ?? senderId, msgContent),
'KickedAndBanned' => isMe
? lang.chatYouKickedBanned(msgContent)
: lang.chatUserKickedBanned(firstName ?? senderId, msgContent),
'InvitationAccepted' => isMe
? lang.chatYouAcceptedInvite
: firstName != null
? lang.chatInvitationAcceptedDisplayName(firstName)
: lang.chatInvitationAcceptedUserId(senderId),
'Invited' => (() {
final inviteeId = msgContent;
final inviteeName = ref
.watch(
memberDisplayNameProvider(
(roomId: roomId, userId: inviteeId),
),
)
.valueOrNull;
return isMe
? lang.chatYouInvited(inviteeName ?? inviteeId)
: firstName != null && inviteeName != null
? lang.chatInvitedDisplayName(inviteeName, firstName)
: lang.chatInvitedUserId(inviteeId, senderId);
})(),
_ => msgContent
}
};
}
}
33 changes: 30 additions & 3 deletions app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1687,18 +1687,45 @@
"@chatJoinedUserId": {},
"chatYouJoined": "You joined",
"@chatYouJoined": {},
"chatYouLeft" : "You left",
"@chatYouLeft": {},
"chatYouBanned": "You banned {name}",
"@chatYouBanned": {},
"chatYouUnbanned": "You unbanned {name}",
"@chatYouUnbanned": {},
"chatYouKicked": "You kicked {name}",
"@chatYouKicked": {},
"chatYouKickedBanned": "You kicked and banned {name}",
"chatUserLeft": "{name} left",
"@chatUserLeft": {},
"chatUserBanned": "{name} banned {user}",
"@chatUserBanned": {},
"chatUserUnbanned" : "{name} unbanned {user}",
"@chatUserUnbanned": {},
"chatUserKicked" : "{name} kicked {user}",
"@chatUserKicked": {},
"chatUserKickedBanned" : "{name} kicked and banned {user}",
"@chatUserKickedBanned" : {},
"chatYouAcceptedInvite": "You accepted the invite",
"@chatYouAcceptedInvite": {},
"chatYouInvited": "You invited",
"chatYouInvited": "You invited {name}",
"@chatYouInvited": {},
"chatInvitedDisplayName": "{name} invited",
"chatInvitedDisplayName": "{name} invited {invitee}",
"@chatInvitedDisplayName": {},
"chatInvitedUserId": "{userId} invited",
"chatInvitedUserId": "{userId} invited {inviteeId}",
"@chatInvitedUserId": {},
"chatInvitationAcceptedDisplayName": "{name} accepted invitation",
"@chatInvitationAcceptedDisplayName": {},
"chatInvitationAcceptedUserId": "{userId} accepted invitation",
"@chatInvitationAcceptedUserId": {},
"chatDisplayNameUpdate": "{name} updated display name from",
"@chatDisplayNameUpdate": {},
"chatDisplayNameSet": "{name} set display name",
"@chatDisplayNameSet": {},
"chatDisplayNameUnset": "{name} removed display name",
"@chatDisplayNameUnset": {},
"chatUserAvatarChange": "{name} updated profile avatar",
"@chatUserAvatarChange": {},
"dmChat": "DM Chat",
"@dmChat": {},
"regularSpaceOrChat": "Regular Space or Chat",
Expand Down
32 changes: 21 additions & 11 deletions native/acter/src/api/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,23 +201,23 @@ impl RoomEventItem {
}
Some(MembershipChange::Banned) => {
me.msg_type(Some("Banned".to_string()));
"banned".to_string()
m.user_id().to_string()
}
Some(MembershipChange::Unbanned) => {
me.msg_type(Some("Unbanned".to_string()));
"unbanned".to_string()
m.user_id().to_string()
}
Some(MembershipChange::Kicked) => {
me.msg_type(Some("Kicked".to_string()));
"kicked".to_string()
m.user_id().to_string()
}
Some(MembershipChange::Invited) => {
me.msg_type(Some("Invited".to_string()));
"invited".to_string()
m.user_id().to_string()
}
Some(MembershipChange::KickedAndBanned) => {
me.msg_type(Some("KickedAndBanned".to_string()));
"kicked and banned".to_string()
m.user_id().to_string()
}
Some(MembershipChange::InvitationAccepted) => {
me.msg_type(Some("InvitationAccepted".to_string()));
Expand All @@ -233,7 +233,7 @@ impl RoomEventItem {
}
Some(MembershipChange::Knocked) => {
me.msg_type(Some("Knocked".to_string()));
"knocked".to_string()
m.user_id().to_string()
}
Some(MembershipChange::KnockAccepted) => {
me.msg_type(Some("KnockAccepted".to_string()));
Expand Down Expand Up @@ -262,10 +262,17 @@ impl RoomEventItem {
if let Some(change) = p.displayname_change() {
let msg_content = match (&change.old, &change.new) {
(Some(old), Some(new)) => {
MsgContent::from_text(format!("changed name {old} -> {new}"))
me.msg_type(Some(("ChangedDisplayName").to_string()));
MsgContent::from_text(format!("{old} -> {new}"))
}
(None, Some(new)) => {
me.msg_type(Some(("SetDisplayName").to_string()));
MsgContent::from_text(new.to_string())
}
(Some(_), None) => {
me.msg_type(Some(("RemoveDisplayName").to_string()));
MsgContent::from_text("removed display name".to_string())
}
(None, Some(new)) => MsgContent::from_text(format!("set name to {new}")),
(Some(_), None) => MsgContent::from_text("removed name".to_string()),
(None, None) => {
// why would that ever happen?
MsgContent::from_text("kept name unset".to_string())
Expand All @@ -275,8 +282,11 @@ impl RoomEventItem {
}
if let Some(change) = p.avatar_url_change() {
if let Some(uri) = change.new.as_ref() {
let msg_content =
MsgContent::from_image("new_picture".to_string(), uri.clone());
me.msg_type(Some(("ChangeProfileAvatar").to_string()));
let msg_content = MsgContent::from_image(
"updated profile avatar".to_string(),
uri.clone(),
);
me.msg_content(Some(msg_content));
}
}
Expand Down

0 comments on commit 59a19ae

Please sign in to comment.