chore: Follow up spaces UX

This commit is contained in:
Christian Kußowski 2025-10-19 13:00:47 +02:00
parent 7fa7941f84
commit 765bff9e32
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
5 changed files with 25 additions and 89 deletions

View file

@ -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"
}
}
}
}

View file

@ -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);

View file

@ -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

View file

@ -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<SpaceView> {
.where((s) => s.hasRoomUpdate)
.rateLimit(const Duration(seconds: 1)),
builder: (context, snapshot) {
final childrenIds = room.spaceChildren
.map((c) => c.roomId)
.whereType<String>()
.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<Room>()
.toList();
final filter = _filterController.text.trim().toLowerCase();
return CustomScrollView(
slivers: [
@ -575,47 +552,6 @@ class _SpaceViewState extends State<SpaceView> {
),
),
),
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<SpaceView> {
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<SpaceView> {
contentPadding:
const EdgeInsets.symmetric(horizontal: 8),
onTap: joinedRoom != null
? () => widget.onChatTab(joinedRoom)
? () => widget.onChatTab(joinedRoom!)
: () => _joinChildRoom(item),
onLongPress: isAdmin
? () => _showSpaceChildEditMenu(

View file

@ -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,