mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-17 06:15:10 +00:00
chore: Follow up new spaces design
This commit is contained in:
parent
5c23453e66
commit
254f21ce00
5 changed files with 90 additions and 67 deletions
|
@ -200,7 +200,7 @@ class ChatListController extends State<ChatList>
|
|||
if (result.error != null) return;
|
||||
}
|
||||
|
||||
void onChatTap(Room room, BuildContext context) async {
|
||||
void onChatTap(Room room) async {
|
||||
if (room.isSpace) {
|
||||
setActiveSpace(room.id);
|
||||
return;
|
||||
|
|
|
@ -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 = <String, Room>{};
|
||||
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 = <String>{};
|
||||
|
||||
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,
|
||||
);
|
||||
|
|
|
@ -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: <Widget>[
|
||||
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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue