// Version: 1.0.0 | Created: 2026-04-01 // Main rooms list screen with bottom navigation. import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../profile/presentation/profile_screen.dart'; import '../../spaces/presentation/spaces_screen.dart'; import 'room_tile.dart'; import 'rooms_controller.dart'; class RoomsScreen extends ConsumerStatefulWidget { const RoomsScreen({super.key}); @override ConsumerState createState() => _RoomsScreenState(); } class _RoomsScreenState extends ConsumerState { int _selectedIndex = 0; static const _destinations = [ NavigationDestination( icon: Icon(Icons.chat_bubble_outline), selectedIcon: Icon(Icons.chat_bubble), label: 'Rooms', ), NavigationDestination( icon: Icon(Icons.dashboard_outlined), selectedIcon: Icon(Icons.dashboard), label: 'Spaces', ), NavigationDestination( icon: Icon(Icons.person_outline), selectedIcon: Icon(Icons.person), label: 'Profile', ), ]; Widget _buildBody() { return switch (_selectedIndex) { 0 => const _RoomListBody(), 1 => const SpacesScreen(embedded: true), 2 => const ProfileScreen(embedded: true), _ => const _RoomListBody(), }; } @override Widget build(BuildContext context) { return Scaffold( appBar: _selectedIndex == 0 ? AppBar( title: const Text('M8Chat'), actions: [ IconButton( icon: const Icon(Icons.search), tooltip: 'Search rooms', onPressed: () { // Phase 2: room search }, ), IconButton( icon: const Icon(Icons.edit_square), tooltip: 'New message', onPressed: () { // Phase 2: start a new DM or group chat }, ), ], ) : null, body: _buildBody(), bottomNavigationBar: NavigationBar( selectedIndex: _selectedIndex, onDestinationSelected: (index) => setState(() => _selectedIndex = index), destinations: _destinations, ), ); } } class _RoomListBody extends ConsumerWidget { const _RoomListBody(); @override Widget build(BuildContext context, WidgetRef ref) { final roomsAsync = ref.watch(roomsListProvider); return roomsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (error, _) => Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 48), const SizedBox(height: 16), Text( 'Could not load rooms.', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), Text( error.toString(), textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall, ), const SizedBox(height: 24), ElevatedButton( onPressed: () => ref.refresh(roomsListProvider), child: const Text('Retry'), ), ], ), ), ), data: (rooms) { if (rooms.isEmpty) { return const _EmptyRoomsState(); } return ListView.separated( itemCount: rooms.length, separatorBuilder: (_, __) => const Divider(height: 1, indent: 72), itemBuilder: (context, index) { final room = rooms[index]; return RoomTile( room: room, onTap: () => context.push('/rooms/${Uri.encodeComponent(room.id)}'), ); }, ); }, ); } } class _EmptyRoomsState extends StatelessWidget { const _EmptyRoomsState(); @override Widget build(BuildContext context) { final theme = Theme.of(context); return Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.chat_bubble_outline, size: 64, color: theme.colorScheme.onSurface.withAlpha(77), ), const SizedBox(height: 16), Text( 'No rooms yet', style: theme.textTheme.titleMedium?.copyWith( color: theme.colorScheme.onSurface.withAlpha(153), ), ), const SizedBox(height: 8), Text( 'Rooms you join will appear here.', style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSurface.withAlpha(102), ), ), ], ), ), ); } }