From 765bff9e32af7cbe42867243618155872d16ae34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Sun, 19 Oct 2025 13:00:47 +0200 Subject: [PATCH] chore: Follow up spaces UX --- lib/l10n/intl_en.arb | 11 +++- lib/pages/chat_list/chat_list_body.dart | 3 -- lib/pages/chat_list/chat_list_item.dart | 6 +-- lib/pages/chat_list/space_view.dart | 71 ++----------------------- lib/widgets/navigation_rail.dart | 23 +++----- 5 files changed, 25 insertions(+), 89 deletions(-) diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index f08cb8fa0..c89fd55ef 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -3383,5 +3383,14 @@ "moveToDifferentSpace": "Move to different space", "moveUp": "Move up", "moveDown": "Move down", - "removeFromSpaceDescription": "The chat will be removed from the space but still appear in your chat list." + "removeFromSpaceDescription": "The chat will be removed from the space but still appear in your chat list.", + "countChats": "{chats} chats", + "@countChats": { + "type": "String", + "placeholders": { + "chats": { + "type": "int" + } + } + } } diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index 248ba22d0..a789f3586 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -36,10 +36,7 @@ class ChatListViewBody extends StatelessWidget { spaceId: activeSpace, onBack: controller.clearActiveSpace, onChatTab: (room) => controller.onChatTap(room), - onChatContext: (room, context) => - controller.chatContextAction(room, context), activeChat: controller.activeChat, - toParentSpace: controller.setActiveSpace, ); } final spaces = client.rooms.where((r) => r.isSpace); diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 6a3ea9582..2fcb251a1 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -242,10 +242,8 @@ class ChatListItem extends StatelessWidget { Expanded( child: room.isSpace && room.membership == Membership.join ? Text( - L10n.of(context).countChatsAndCountParticipants( - room.spaceChildren.length, - (room.summary.mJoinedMemberCount ?? 1), - ), + L10n.of(context) + .countChats(room.spaceChildren.length), style: TextStyle(color: theme.colorScheme.outline), ) : typingText.isNotEmpty diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index d9f47938c..a16220c4e 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -38,9 +38,7 @@ enum SpaceActions { class SpaceView extends StatefulWidget { final String spaceId; final void Function() onBack; - final void Function(String spaceId) toParentSpace; final void Function(Room room) onChatTab; - final void Function(Room room, BuildContext context) onChatContext; final String? activeChat; const SpaceView({ @@ -48,8 +46,6 @@ class SpaceView extends StatefulWidget { required this.onBack, required this.onChatTab, required this.activeChat, - required this.toParentSpace, - required this.onChatContext, super.key, }); @@ -525,25 +521,6 @@ class _SpaceViewState extends State { .where((s) => s.hasRoomUpdate) .rateLimit(const Duration(seconds: 1)), builder: (context, snapshot) { - final childrenIds = room.spaceChildren - .map((c) => c.roomId) - .whereType() - .toSet(); - - final joinedRooms = Map.fromEntries( - room.client.rooms - .where((room) => childrenIds.remove(room.id)) - .map((room) => MapEntry(room.id, room)), - ); - - final joinedParents = room.spaceParents - .map((parent) { - final roomId = parent.roomId; - if (roomId == null) return null; - return room.client.getRoomById(roomId); - }) - .whereType() - .toList(); final filter = _filterController.text.trim().toLowerCase(); return CustomScrollView( slivers: [ @@ -575,47 +552,6 @@ class _SpaceViewState extends State { ), ), ), - SliverList.builder( - itemCount: joinedParents.length, - itemBuilder: (context, i) { - final displayname = - joinedParents[i].getLocalizedDisplayname(); - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 1, - ), - child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), - clipBehavior: Clip.hardEdge, - child: ListTile( - minVerticalPadding: 0, - leading: Icon( - Icons.adaptive.arrow_back_outlined, - size: 16, - ), - title: Row( - children: [ - Avatar( - mxContent: joinedParents[i].avatar, - name: displayname, - size: Avatar.defaultSize / 2, - borderRadius: BorderRadius.circular( - AppConfig.borderRadius / 4, - ), - ), - const SizedBox(width: 8), - Expanded(child: Text(displayname)), - ], - ), - onTap: () => - widget.toParentSpace(joinedParents[i].id), - ), - ), - ); - }, - ), SliverList.builder( itemCount: _discoveredChildren.length + 1, itemBuilder: (context, i) { @@ -643,7 +579,10 @@ class _SpaceViewState extends State { if (!displayname.toLowerCase().contains(filter)) { return const SizedBox.shrink(); } - final joinedRoom = joinedRooms[item.roomId]; + var joinedRoom = room.client.getRoomById(item.roomId); + if (joinedRoom?.membership == Membership.leave) { + joinedRoom = null; + } return Padding( padding: const EdgeInsets.symmetric( horizontal: 8, @@ -664,7 +603,7 @@ class _SpaceViewState extends State { contentPadding: const EdgeInsets.symmetric(horizontal: 8), onTap: joinedRoom != null - ? () => widget.onChatTab(joinedRoom) + ? () => widget.onChatTab(joinedRoom!) : () => _joinChildRoom(item), onLongPress: isAdmin ? () => _showSpaceChildEditMenu( diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index d27d84912..7cb4be43b 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -43,15 +43,8 @@ class SpacesNavigationRail extends StatelessWidget { .where((s) => s.hasRoomUpdate) .rateLimit(const Duration(seconds: 1)), builder: (context, _) { - final allSpaces = client.rooms.where((room) => room.isSpace); - final rootSpaces = allSpaces - .where( - (space) => !allSpaces.any( - (parentSpace) => parentSpace.spaceChildren - .any((child) => child.roomId == space.id), - ), - ) - .toList(); + final allSpaces = + client.rooms.where((room) => room.isSpace).toList(); return SizedBox( width: FluffyThemes.isColumnMode(context) @@ -62,7 +55,7 @@ class SpacesNavigationRail extends StatelessWidget { Expanded( child: ListView.builder( scrollDirection: Axis.vertical, - itemCount: rootSpaces.length + 2, + itemCount: allSpaces.length + 2, itemBuilder: (context, i) { if (i == 0) { return NaviRailItem( @@ -81,7 +74,7 @@ class SpacesNavigationRail extends StatelessWidget { ); } i--; - if (i == rootSpaces.length) { + if (i == allSpaces.length) { return NaviRailItem( isSelected: false, onTap: () => context.go('/rooms/newspace'), @@ -92,9 +85,9 @@ class SpacesNavigationRail extends StatelessWidget { toolTip: L10n.of(context).createNewSpace, ); } - final space = rootSpaces[i]; + final space = allSpaces[i]; final displayname = - rootSpaces[i].getLocalizedDisplayname( + allSpaces[i].getLocalizedDisplayname( MatrixLocals(L10n.of(context)), ); final spaceChildrenIds = @@ -102,11 +95,11 @@ class SpacesNavigationRail extends StatelessWidget { return NaviRailItem( toolTip: displayname, isSelected: activeSpaceId == space.id, - onTap: () => onGoToSpaceId(rootSpaces[i].id), + onTap: () => onGoToSpaceId(allSpaces[i].id), unreadBadgeFilter: (room) => spaceChildrenIds.contains(room.id), icon: Avatar( - mxContent: rootSpaces[i].avatar, + mxContent: allSpaces[i].avatar, name: displayname, border: BorderSide( width: 1,