// SPDX-FileCopyrightText: 2019-Present Christian Kußowski // SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat // // SPDX-License-Identifier: AGPL-3.0-or-later import 'package:go_router/go_router.dart'; import 'package:material_ui/material_ui.dart'; import 'package:matrix/matrix.dart'; import 'package:tatchat/config/app_config.dart'; import 'package:tatchat/config/themes.dart'; import 'package:tatchat/l10n/l10n.dart'; import 'package:tatchat/pages/chat_list/chat_list.dart'; import 'package:tatchat/pages/chat_list/navi_rail_item.dart'; import 'package:tatchat/pages/chat_list/space_view.dart'; import 'package:tatchat/pages/chat_list/tabs/chat_tab_header.dart'; import 'package:tatchat/pages/chat_list/tabs/home_tab.dart'; import 'package:tatchat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:tatchat/utils/stream_extension.dart'; import 'package:tatchat/widgets/avatar.dart'; import 'package:tatchat/widgets/matrix.dart'; class SpacesTab extends StatefulWidget { final ChatListController controller; const SpacesTab(this.controller, {super.key}); @override State createState() => _SpacesTabState(); } class _SpacesTabState extends State { final TextEditingController _searchController = TextEditingController(); final FocusNode _searchFocusNode = FocusNode(); bool _isSearchMode = false; @override void dispose() { _searchController.dispose(); _searchFocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final client = Matrix.of(context).client; final theme = Theme.of(context); final searchText = _searchController.text.trim().toLowerCase(); return ChatTabScaffold( tab: HomeTab.spaces, isSearchMode: _isSearchMode, onSearchPressed: () => setState(() => _isSearchMode = true), onSearchCancelled: () { setState(() { _isSearchMode = false; _searchController.clear(); }); }, searchController: _searchController, searchFocusNode: _searchFocusNode, onSearchChanged: (_) => setState(() {}), controller: widget.controller, child: StreamBuilder( key: ValueKey(client.userID.toString()), stream: client.onSync.stream .where((s) => s.hasRoomUpdate) .rateLimit(const Duration(seconds: 1)), builder: (context, _) { final spaces = client.rooms .where((room) => room.isSpace) .where( (room) => searchText.isEmpty || room .getLocalizedDisplayname(MatrixLocals(L10n.of(context))) .toLowerCase() .contains(searchText), ) .toList(); final activeSpaceId = widget.controller.activeSpaceId; return Row( children: [ SizedBox( width: FluffyThemes.navRailWidth, child: ColoredBox( color: theme.colorScheme.surfaceContainerHigh, child: Column( children: [ const SizedBox(height: 8), if (spaces.isEmpty) const Expanded(child: SizedBox.shrink()) else Expanded( child: ListView( padding: const EdgeInsets.symmetric(vertical: 4), children: [ for (final space in spaces) NaviRailItem( isSelected: activeSpaceId == space.id, onTap: () => widget.controller.setActiveSpace( space.id, ), toolTip: space.getLocalizedDisplayname( MatrixLocals(L10n.of(context)), ), unreadBadgeFilter: (room) => space .spaceChildren .map((c) => c.roomId) .contains(room.id), icon: Avatar( mxContent: space.avatar, name: space.getLocalizedDisplayname( MatrixLocals(L10n.of(context)), ), shapeBorder: RoundedSuperellipseBorder( side: BorderSide( width: 1, color: theme.dividerColor, ), borderRadius: BorderRadius.circular( AppConfig.spaceBorderRadius, ), ), borderRadius: BorderRadius.circular( AppConfig.spaceBorderRadius, ), ), ), ], ), ), NaviRailItem( isSelected: false, onTap: () => context.go('/rooms/newspace'), icon: const Padding( padding: EdgeInsets.all(12.0), child: Icon(Icons.add), ), toolTip: L10n.of(context).createNewSpace, ), const SizedBox(height: 8), ], ), ), ), if (FluffyThemes.isColumnMode(context)) Container(width: 1, color: theme.dividerColor), Expanded( child: activeSpaceId == null ? Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.workspaces_outlined, size: 80, color: theme.colorScheme.secondary, ), Padding( padding: const EdgeInsets.all(16.0), child: Text( L10n.of(context).selectASpace, textAlign: TextAlign.center, style: TextStyle( fontSize: 18, color: theme.colorScheme.secondary, ), ), ), ], ), ) : SpaceView( key: ValueKey(activeSpaceId), spaceId: activeSpaceId, onBack: widget.controller.clearActiveSpace, onChatTab: widget.controller.onChatTap, activeChat: widget.controller.activeChat, ), ), ], ); }, ), ); } }