mirror of
				https://gitlab.com/famedly/fluffychat.git
				synced 2025-10-31 03:57:27 +01:00 
			
		
		
		
	 9f8a7f79f2
			
		
	
	
		9f8a7f79f2
		
	
	
	
	
		
			
			- fix spaces animation direction - animate chat list app bar title - fix ink splash radius in account selector - fix missing asset fallback in content banner Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
		
			
				
	
	
		
			215 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/cupertino.dart';
 | |
| import 'package:flutter/material.dart';
 | |
| 
 | |
| import 'package:flutter_gen/gen_l10n/l10n.dart';
 | |
| import 'package:matrix/matrix.dart';
 | |
| 
 | |
| import 'package:fluffychat/config/app_config.dart';
 | |
| import 'package:fluffychat/utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
 | |
| import '../../widgets/matrix.dart';
 | |
| 
 | |
| // This is not necessarily a Space, but an abstract categorization of a room.
 | |
| // More to the point, it's a selectable entry that *could* be a Space.
 | |
| // Note that view code is in spaces_bottom_bar.dart because of type-specific UI.
 | |
| // So only really generic functions (so far, anything ChatList cares about) go here.
 | |
| // If getRoom returns something non-null, then it gets the avatar and such of a Space.
 | |
| // Otherwise it gets to look like All Rooms. Future work impending.
 | |
| abstract class SpacesEntry {
 | |
|   const SpacesEntry();
 | |
| 
 | |
|   // Gets the (translated) name of this entry.
 | |
|   String getName(BuildContext context);
 | |
|   // Gets an icon for this entry (avoided if a space is given)
 | |
|   Icon getIcon(bool active) => active
 | |
|       ? const Icon(CupertinoIcons.chat_bubble_2_fill)
 | |
|       : const Icon(CupertinoIcons.chat_bubble_2);
 | |
|   // If this is a specific Room, returns the space Room for various purposes.
 | |
|   Room? getSpace(BuildContext context) => null;
 | |
|   // Gets a list of rooms - this is done as part of _ChatListViewBodyState to get the full list of rooms visible from this SpacesEntry.
 | |
|   List<Room> getRooms(BuildContext context);
 | |
|   // Checks that this entry is still valid.
 | |
|   bool stillValid(BuildContext context) => true;
 | |
|   // Returns true if the Stories header should be shown.
 | |
|   bool shouldShowStoriesHeader(BuildContext context) => false;
 | |
| }
 | |
| 
 | |
| // Common room validity checks
 | |
| bool _roomCheckCommon(Room room, BuildContext context) {
 | |
|   if (room.isSpace && room.membership == Membership.join && !room.isUnread) {
 | |
|     return false;
 | |
|   }
 | |
|   if (room.getState(EventTypes.RoomCreate)?.content.tryGet<String>('type') ==
 | |
|       ClientStoriesExtension.storiesRoomType) {
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool _roomInsideSpace(Room room, Room space) {
 | |
|   if (space.spaceChildren.any((child) => child.roomId == room.id)) {
 | |
|     return true;
 | |
|   }
 | |
|   if (room.spaceParents.any((parent) => parent.roomId == space.id)) {
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| // "All rooms" entry.
 | |
| class AllRoomsSpacesEntry extends SpacesEntry {
 | |
|   static final AllRoomsSpacesEntry _value = AllRoomsSpacesEntry._();
 | |
|   AllRoomsSpacesEntry._();
 | |
|   factory AllRoomsSpacesEntry() {
 | |
|     return _value;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   String getName(BuildContext context) => L10n.of(context)!.allChats;
 | |
| 
 | |
|   @override
 | |
|   List<Room> getRooms(BuildContext context) {
 | |
|     return Matrix.of(context)
 | |
|         .client
 | |
|         .rooms
 | |
|         .where((room) => _roomCheckCommon(room, context))
 | |
|         .toList();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   bool shouldShowStoriesHeader(BuildContext context) => true;
 | |
| 
 | |
|   @override
 | |
|   bool operator ==(Object other) {
 | |
|     return runtimeType == other.runtimeType;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   int get hashCode => runtimeType.hashCode;
 | |
| }
 | |
| 
 | |
| // "Direct Chats" entry.
 | |
| class DirectChatsSpacesEntry extends SpacesEntry {
 | |
|   static final DirectChatsSpacesEntry _value = DirectChatsSpacesEntry._();
 | |
|   DirectChatsSpacesEntry._();
 | |
|   factory DirectChatsSpacesEntry() {
 | |
|     return _value;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   String getName(BuildContext context) => L10n.of(context)!.directChats;
 | |
| 
 | |
|   @override
 | |
|   List<Room> getRooms(BuildContext context) {
 | |
|     return Matrix.of(context)
 | |
|         .client
 | |
|         .rooms
 | |
|         .where((room) => room.isDirectChat && _roomCheckCommon(room, context))
 | |
|         .toList();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   bool shouldShowStoriesHeader(BuildContext context) => true;
 | |
| 
 | |
|   @override
 | |
|   bool operator ==(Object other) {
 | |
|     return runtimeType == other.runtimeType;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   int get hashCode => runtimeType.hashCode;
 | |
| }
 | |
| 
 | |
| // "Groups" entry.
 | |
| class GroupsSpacesEntry extends SpacesEntry {
 | |
|   static final GroupsSpacesEntry _value = GroupsSpacesEntry._();
 | |
|   GroupsSpacesEntry._();
 | |
|   factory GroupsSpacesEntry() {
 | |
|     return _value;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   String getName(BuildContext context) => L10n.of(context)!.groups;
 | |
| 
 | |
|   @override
 | |
|   Icon getIcon(bool active) =>
 | |
|       active ? const Icon(Icons.group) : const Icon(Icons.group_outlined);
 | |
| 
 | |
|   @override
 | |
|   List<Room> getRooms(BuildContext context) {
 | |
|     final rooms = Matrix.of(context).client.rooms;
 | |
|     // Needs to match ChatList's definition of a space.
 | |
|     final spaces = rooms.where((room) => room.isSpace).toList();
 | |
|     return rooms
 | |
|         .where((room) =>
 | |
|             (!room.isDirectChat) &&
 | |
|             _roomCheckCommon(room, context) &&
 | |
|             separatedGroup(room, spaces))
 | |
|         .toList();
 | |
|   }
 | |
| 
 | |
|   bool separatedGroup(Room room, List<Room> spaces) {
 | |
|     return !spaces.any((space) => _roomInsideSpace(room, space));
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   bool operator ==(Object other) {
 | |
|     return runtimeType == other.runtimeType;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   int get hashCode => runtimeType.hashCode;
 | |
| }
 | |
| 
 | |
| // All rooms associated with a specific space.
 | |
| class SpaceSpacesEntry extends SpacesEntry {
 | |
|   final Room space;
 | |
|   const SpaceSpacesEntry(this.space);
 | |
| 
 | |
|   @override
 | |
|   String getName(BuildContext context) => space.displayname;
 | |
| 
 | |
|   @override
 | |
|   Room? getSpace(BuildContext context) => space;
 | |
| 
 | |
|   @override
 | |
|   List<Room> getRooms(BuildContext context) {
 | |
|     return Matrix.of(context)
 | |
|         .client
 | |
|         .rooms
 | |
|         .where((room) => roomCheck(room, context))
 | |
|         .toList();
 | |
|   }
 | |
| 
 | |
|   bool roomCheck(Room room, BuildContext context) {
 | |
|     if (!_roomCheckCommon(room, context)) {
 | |
|       return false;
 | |
|     }
 | |
|     if (_roomInsideSpace(room, space)) {
 | |
|       return true;
 | |
|     }
 | |
|     if (AppConfig.showDirectChatsInSpaces) {
 | |
|       if (room.isDirectChat &&
 | |
|           room.summary.mHeroes != null &&
 | |
|           room.summary.mHeroes!.any((userId) {
 | |
|             final user = space.getState(EventTypes.RoomMember, userId)?.asUser;
 | |
|             return user != null && user.membership == Membership.join;
 | |
|           })) {
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   bool stillValid(BuildContext context) =>
 | |
|       Matrix.of(context).client.getRoomById(space.id) != null;
 | |
| 
 | |
|   @override
 | |
|   bool operator ==(Object other) {
 | |
|     return hashCode == other.hashCode;
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   int get hashCode => space.id.hashCode;
 | |
| }
 |