From 254f21ce00251be883c7aae1fdfc1aafa868252b Mon Sep 17 00:00:00 2001 From: Krille Date: Mon, 15 Jul 2024 13:18:15 +0200 Subject: [PATCH] chore: Follow up new spaces design --- lib/pages/chat_list/chat_list.dart | 2 +- lib/pages/chat_list/chat_list_body.dart | 26 ++---- lib/pages/chat_list/chat_list_item.dart | 118 +++++++++++++++--------- lib/pages/chat_list/chat_list_view.dart | 4 + lib/widgets/avatar.dart | 7 +- 5 files changed, 90 insertions(+), 67 deletions(-) diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 9181b1dff..28e78dfe6 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -200,7 +200,7 @@ class ChatListController extends State if (result.error != null) return; } - void onChatTap(Room room, BuildContext context) async { + void onChatTap(Room room) async { if (room.isSpace) { setActiveSpace(room.id); return; diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index a6526989b..fd063ddba 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -32,7 +32,7 @@ class ChatListViewBody extends StatelessWidget { return SpaceView( spaceId: activeSpace, onBack: controller.clearActiveSpace, - onChatTab: (room) => controller.onChatTap(room, context), + onChatTab: (room) => controller.onChatTap(room), onChatContext: (room) => controller.chatContextAction(room), activeChat: controller.activeChat, toParentSpace: controller.setActiveSpace, @@ -62,17 +62,15 @@ class ChatListViewBody extends StatelessWidget { builder: (context, _) { final rooms = controller.filteredRooms; - final spaces = rooms.where((r) => r.isSpace); + final spaces = client.rooms.where((r) => r.isSpace); final spaceDelegateCandidates = {}; for (final space in spaces) { - spaceDelegateCandidates[space.id] = space; for (final spaceChild in space.spaceChildren) { final roomId = spaceChild.roomId; if (roomId == null) continue; spaceDelegateCandidates[roomId] = space; } } - final spaceDelegates = {}; return SafeArea( child: CustomScrollView( @@ -298,26 +296,14 @@ class ChatListViewBody extends StatelessWidget { SliverList.builder( itemCount: rooms.length, itemBuilder: (BuildContext context, int i) { - var room = rooms[i]; - if (controller.activeFilter != ActiveFilter.groups) { - final parent = room.isSpace - ? room - : spaceDelegateCandidates[room.id]; - if (parent != null) { - if (spaceDelegates.contains(parent.id)) { - return const SizedBox.shrink(); - } - spaceDelegates.add(parent.id); - room = parent; - } - } - + final room = rooms[i]; + final space = spaceDelegateCandidates[room.id]; return ChatListItem( room, - lastEventRoom: rooms[i], + space: space, key: Key('chat_list_item_${room.id}'), filter: filter, - onTap: () => controller.onChatTap(room, context), + onTap: () => controller.onChatTap(room), onLongPress: () => controller.chatContextAction(room), activeChat: controller.activeChat == room.id, ); diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 7bf5f6b52..2fcce1839 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -17,7 +17,7 @@ enum ArchivedRoomAction { delete, rejoin } class ChatListItem extends StatelessWidget { final Room room; - final Room? lastEventRoom; + final Room? space; final bool activeChat; final void Function()? onLongPress; final void Function()? onForget; @@ -31,7 +31,7 @@ class ChatListItem extends StatelessWidget { this.onLongPress, this.onForget, this.filter, - this.lastEventRoom, + this.space, super.key, }); @@ -64,21 +64,19 @@ class ChatListItem extends StatelessWidget { @override Widget build(BuildContext context) { final isMuted = room.pushRuleState != PushRuleState.notify; - final lastEventRoom = this.lastEventRoom ?? room; - final typingText = lastEventRoom.getLocalizedTypingText(context); - final lastEvent = lastEventRoom.lastEvent; + final typingText = room.getLocalizedTypingText(context); + final lastEvent = room.lastEvent; final ownMessage = lastEvent?.senderId == room.client.userID; - final unread = - lastEventRoom.isUnread || lastEventRoom.membership == Membership.invite; + final unread = room.isUnread || room.membership == Membership.invite; final theme = Theme.of(context); final directChatMatrixId = room.directChatMatrixID; final isDirectChat = directChatMatrixId != null; - final unreadBubbleSize = unread || lastEventRoom.hasNewMessages - ? lastEventRoom.notificationCount > 0 + final unreadBubbleSize = unread || room.hasNewMessages + ? room.notificationCount > 0 ? 20.0 : 14.0 : 0.0; - final hasNotifications = lastEventRoom.notificationCount > 0; + final hasNotifications = room.notificationCount > 0; final backgroundColor = activeChat ? theme.colorScheme.secondaryContainer : null; final displayname = room.getLocalizedDisplayname( @@ -92,6 +90,7 @@ class ChatListItem extends StatelessWidget { final needLastEventSender = lastEvent == null ? false : room.getState(EventTypes.RoomMember, lastEvent.senderId) == null; + final space = this.space; return Padding( padding: const EdgeInsets.symmetric( @@ -117,15 +116,67 @@ class ChatListItem extends StatelessWidget { duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, scale: hovered ? 1.1 : 1.0, - child: Avatar( - borderRadius: room.isSpace - ? BorderRadius.circular(AppConfig.borderRadius / 3) - : null, - mxContent: room.avatar, - name: displayname, - presenceUserId: directChatMatrixId, - presenceBackgroundColor: backgroundColor, - onTap: onLongPress, + child: SizedBox( + width: Avatar.defaultSize, + height: Avatar.defaultSize, + child: Stack( + children: [ + if (space != null) + Positioned( + top: 0, + left: 0, + child: Avatar( + border: BorderSide( + width: 2, + color: backgroundColor ?? + Theme.of(context).colorScheme.surface, + ), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 4, + ), + mxContent: space.avatar, + size: Avatar.defaultSize * 0.75, + name: space.getLocalizedDisplayname(), + onTap: onLongPress, + ), + ), + Positioned( + bottom: 0, + right: 0, + child: Avatar( + border: space == null + ? room.isSpace + ? BorderSide( + width: 0, + color: Theme.of(context) + .colorScheme + .outline, + ) + : null + : BorderSide( + width: 2, + color: backgroundColor ?? + Theme.of(context) + .colorScheme + .surface, + ), + borderRadius: room.isSpace + ? BorderRadius.circular( + AppConfig.borderRadius / 4, + ) + : null, + mxContent: room.avatar, + size: space != null + ? Avatar.defaultSize * 0.75 + : Avatar.defaultSize, + name: displayname, + presenceUserId: directChatMatrixId, + presenceBackgroundColor: backgroundColor, + onTap: onLongPress, + ), + ), + ], + ), ), ), ), @@ -205,20 +256,6 @@ class ChatListItem extends StatelessWidget { subtitle: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - if (room.isSpace) ...[ - room.id != lastEventRoom.id && - lastEventRoom.isUnreadOrInvited - ? Avatar( - mxContent: lastEventRoom.avatar, - name: lastEventRoom.name, - size: 18, - ) - : const Icon( - Icons.workspaces_outlined, - size: 18, - ), - const SizedBox(width: 4), - ], if (typingText.isEmpty && ownMessage && room.lastEvent!.status.isSending) ...[ @@ -243,7 +280,7 @@ class ChatListItem extends StatelessWidget { ), ), Expanded( - child: room.isSpace && !lastEventRoom.isUnreadOrInvited + child: room.isSpace && room.membership == Membership.join ? Text( L10n.of(context)!.countChatsAndCountParticipants( room.spaceChildren.length.toString(), @@ -297,10 +334,9 @@ class ChatListItem extends StatelessWidget { maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - fontWeight: - unread || lastEventRoom.hasNewMessages - ? FontWeight.bold - : null, + fontWeight: unread || room.hasNewMessages + ? FontWeight.bold + : null, color: theme.colorScheme.onSurfaceVariant, decoration: room.lastEvent?.redacted == true ? TextDecoration.lineThrough @@ -318,9 +354,7 @@ class ChatListItem extends StatelessWidget { width: !hasNotifications && !unread && !room.hasNewMessages ? 0 : (unreadBubbleSize - 9) * - lastEventRoom.notificationCount - .toString() - .length + + room.notificationCount.toString().length + 9, decoration: BoxDecoration( color: room.highlightCount > 0 || @@ -335,7 +369,7 @@ class ChatListItem extends StatelessWidget { child: Center( child: hasNotifications ? Text( - lastEventRoom.notificationCount.toString(), + room.notificationCount.toString(), style: TextStyle( color: room.highlightCount > 0 ? Colors.white diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 798464693..81f765125 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -26,6 +26,10 @@ class ChatListView extends StatelessWidget { controller.activeFilter == ActiveFilter.allChats, onPopInvoked: (pop) async { if (pop) return; + if (controller.activeSpaceId != null) { + controller.clearActiveSpace(); + return; + } final selMode = controller.selectMode; if (controller.isSearchMode) { controller.cancelSearch(); diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 180f3437a..0c280a88b 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -17,6 +17,7 @@ class Avatar extends StatelessWidget { final Color? presenceBackgroundColor; final BorderRadius? borderRadius; final IconData? icon; + final BorderSide? border; const Avatar({ this.mxContent, @@ -27,6 +28,7 @@ class Avatar extends StatelessWidget { this.presenceUserId, this.presenceBackgroundColor, this.borderRadius, + this.border, this.icon, super.key, }); @@ -67,10 +69,7 @@ class Avatar extends StatelessWidget { color: color, shape: RoundedRectangleBorder( borderRadius: borderRadius, - side: BorderSide( - width: 0, - color: Theme.of(context).dividerColor, - ), + side: border ?? BorderSide.none, ), clipBehavior: Clip.hardEdge, child: noPic