From 3faf6df558784a5722b40af6777e1b6ffd2e8032 Mon Sep 17 00:00:00 2001 From: krille-chan Date: Sat, 19 Oct 2024 08:58:02 +0200 Subject: [PATCH] feat: Nicer room creation UI --- lib/pages/chat/chat.dart | 9 ++--- lib/pages/chat/chat_event_list.dart | 4 +- lib/pages/chat/events/message.dart | 4 ++ .../events/room_creation_state_event.dart | 40 +++++++++++++++++++ .../filtered_timeline_extension.dart | 30 ++++++++++++++ 5 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 lib/pages/chat/events/room_creation_state_event.dart diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 9d36f135e..fce1d38a4 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -261,8 +261,7 @@ class ChatController extends State var readMarkerEventIndex = readMarkerEventId.isEmpty ? -1 : timeline!.events - .where((e) => e.isVisibleInGui || e.eventId == readMarkerEventId) - .toList() + .filterByVisibleInGui(exceptionEventId: readMarkerEventId) .indexWhere((e) => e.eventId == readMarkerEventId); // Read marker is existing but not found in first events. Try a single @@ -270,8 +269,7 @@ class ChatController extends State if (readMarkerEventId.isNotEmpty && readMarkerEventIndex == -1) { await timeline?.requestHistory(historyCount: _loadHistoryCount); readMarkerEventIndex = timeline!.events - .where((e) => e.isVisibleInGui || e.eventId == readMarkerEventId) - .toList() + .filterByVisibleInGui(exceptionEventId: readMarkerEventId) .indexWhere((e) => e.eventId == readMarkerEventId); } @@ -868,8 +866,7 @@ class ChatController extends State final eventIndex = foundEvent == null ? -1 : timeline!.events - .where((event) => event.isVisibleInGui || event.eventId == eventId) - .toList() + .filterByVisibleInGui(exceptionEventId: eventId) .indexOf(foundEvent); if (eventIndex == -1) { diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 65c920360..d4614af10 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -25,9 +25,7 @@ class ChatEventList extends StatelessWidget { Widget build(BuildContext context) { final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0; - final events = controller.timeline!.events - .where((event) => event.isVisibleInGui) - .toList(); + final events = controller.timeline!.events.filterByVisibleInGui(); final animateInEventIndex = controller.animateInEventIndex; // create a map of eventId --> index to greatly improve performance of diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 11ffad745..032e8967d 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -6,6 +6,7 @@ import 'package:matrix/matrix.dart'; import 'package:swipe_to_action/swipe_to_action.dart'; import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pages/chat/events/room_creation_state_event.dart'; import 'package:fluffychat/utils/date_time_extension.dart'; import 'package:fluffychat/utils/string_color.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -68,6 +69,9 @@ class Message extends StatelessWidget { if (event.type.startsWith('m.call.')) { return const SizedBox.shrink(); } + if (event.type == EventTypes.RoomCreate) { + return RoomCreationStateEvent(event: event); + } return StateMessage(event); } diff --git a/lib/pages/chat/events/room_creation_state_event.dart b/lib/pages/chat/events/room_creation_state_event.dart new file mode 100644 index 000000000..8960a801f --- /dev/null +++ b/lib/pages/chat/events/room_creation_state_event.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/utils/date_time_extension.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +import 'package:fluffychat/widgets/avatar.dart'; + +class RoomCreationStateEvent extends StatelessWidget { + final Event event; + const RoomCreationStateEvent({required this.event, super.key}); + + @override + Widget build(BuildContext context) { + final l10n = L10n.of(context); + final matrixLocals = MatrixLocals(l10n); + final theme = Theme.of(context); + final roomName = event.room.getLocalizedDisplayname(matrixLocals); + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Avatar( + mxContent: event.room.avatar, + name: roomName, + size: Avatar.defaultSize * 2, + ), + Text( + roomName, + style: theme.textTheme.headlineSmall, + ), + Text( + '${event.originServerTs.localizedTime(context)} | ${l10n.countParticipants((event.room.summary.mJoinedMemberCount ?? 1) + (event.room.summary.mInvitedMemberCount ?? 0))}', + style: theme.textTheme.labelSmall, + ), + const SizedBox(height: 48), + ], + ); + } +} diff --git a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart index bd1cd8e46..cd9d223ee 100644 --- a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart +++ b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart @@ -2,6 +2,36 @@ import 'package:matrix/matrix.dart'; import '../../config/app_config.dart'; +extension VisibleInGuiExtension on List { + List filterByVisibleInGui({String? exceptionEventId}) { + final visibleEvents = + where((e) => e.isVisibleInGui || e.eventId == exceptionEventId) + .toList(); + + // Hide creation state events: + if (visibleEvents.isNotEmpty && + visibleEvents.last.type == EventTypes.RoomCreate) { + var i = visibleEvents.length - 2; + while (i > 0) { + final event = visibleEvents[i]; + if (!event.isState) break; + if (event.type == EventTypes.Encryption) { + i--; + continue; + } + if (event.type == EventTypes.RoomMember && + event.roomMemberChangeType == RoomMemberChangeType.acceptInvite) { + i--; + continue; + } + visibleEvents.removeAt(i); + i--; + } + } + return visibleEvents; + } +} + extension IsStateExtension on Event { bool get isVisibleInGui => // always filter out edit and reaction relationships