import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; import 'package:keyboard_shortcuts/keyboard_shortcuts.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/chat_list/navi_rail_item.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/widgets/avatar.dart'; import '../../widgets/matrix.dart'; import 'chat_list_body.dart'; class ChatListView extends StatelessWidget { final ChatListController controller; const ChatListView(this.controller, {super.key}); @override Widget build(BuildContext context) { return StreamBuilder( stream: Matrix.of(context).onShareContentChanged.stream, builder: (_, __) { final selectMode = controller.selectMode; return PopScope( canPop: controller.selectMode == SelectMode.normal && !controller.isSearchMode, onPopInvoked: (pop) { if (pop) return; final selMode = controller.selectMode; if (controller.isSearchMode) { controller.cancelSearch(); return; } if (selMode != SelectMode.normal) { controller.cancelAction(); return; } }, child: Row( children: [ if (FluffyThemes.isColumnMode(context) && controller.widget.displayNavigationRail) ...[ Builder( builder: (context) { final allSpaces = Matrix.of(context) .client .rooms .where((room) => room.isSpace); final rootSpaces = allSpaces .where( (space) => !allSpaces.any( (parentSpace) => parentSpace.spaceChildren .any((child) => child.roomId == space.id), ), ) .toList(); return SizedBox( width: FluffyThemes.navRailWidth, child: ListView.builder( scrollDirection: Axis.vertical, itemCount: rootSpaces.length + 2, itemBuilder: (context, i) { if (i == 0) { return NaviRailItem( isSelected: controller.activeSpaceId == null, onTap: controller.clearActiveSpace, icon: const Icon(Icons.forum_outlined), selectedIcon: const Icon(Icons.forum), toolTip: L10n.of(context)!.chats, unreadBadgeFilter: (room) => true, ); } i--; if (i == rootSpaces.length) { return NaviRailItem( isSelected: false, onTap: () => context.go('/rooms/newspace'), icon: const Icon(Icons.add), toolTip: L10n.of(context)!.createNewSpace, ); } final space = rootSpaces[i]; final displayname = rootSpaces[i].getLocalizedDisplayname( MatrixLocals(L10n.of(context)!), ); final spaceChildrenIds = space.spaceChildren.map((c) => c.roomId).toSet(); return NaviRailItem( toolTip: displayname, isSelected: controller.activeSpaceId == space.id, onTap: () => controller.setActiveSpace(rootSpaces[i].id), unreadBadgeFilter: (room) => spaceChildrenIds.contains(room.id), icon: Avatar( mxContent: rootSpaces[i].avatar, name: displayname, size: 32, borderRadius: BorderRadius.circular( AppConfig.borderRadius / 4, ), ), ); }, ), ); }, ), Container( color: Theme.of(context).dividerColor, width: 1, ), ], Expanded( child: GestureDetector( onTap: FocusManager.instance.primaryFocus?.unfocus, excludeFromSemantics: true, behavior: HitTestBehavior.translucent, child: Scaffold( body: ChatListViewBody(controller), floatingActionButton: KeyBoardShortcuts( keysToPress: { LogicalKeyboardKey.controlLeft, LogicalKeyboardKey.keyN, }, onKeysPressed: () => context.go('/rooms/newprivatechat'), helpLabel: L10n.of(context)!.newChat, child: selectMode == SelectMode.normal && !controller.isSearchMode ? FloatingActionButton.extended( onPressed: controller.addChatAction, icon: const Icon(Icons.add_outlined), label: Text( L10n.of(context)!.chat, overflow: TextOverflow.fade, ), ) : const SizedBox.shrink(), ), ), ), ), ], ), ); }, ); } }