import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; import '../controls/app_bottom_nav_bar.dart'; import '../controls/current_profile_button.dart'; import '../controls/image_control.dart'; import '../controls/linear_status_indicator.dart'; import '../controls/responsive_max_width.dart'; import '../controls/standard_app_drawer.dart'; import '../controls/status_and_refresh_button.dart'; import '../globals.dart'; import '../models/connection.dart'; import '../routes.dart'; import '../services/connections_manager.dart'; import '../services/network_status_service.dart'; import '../utils/active_profile_selector.dart'; class ContactsScreen extends StatefulWidget { const ContactsScreen({super.key}); @override State createState() => _ContactsScreenState(); } class _ContactsScreenState extends State { static final _logger = Logger('$ContactsScreen'); var filterText = ''; @override Widget build(BuildContext context) { final nss = getIt(); final manager = context .watch>() .activeEntry .value; final allContacts = manager.getMyContacts(); final filterTextLC = filterText.toLowerCase(); final contacts = allContacts .where((c) => filterText.isEmpty || c.name.toLowerCase().contains(filterTextLC) || c.handle.toLowerCase().contains(filterTextLC)) .toList(); contacts.sort((c1, c2) => c1.name.compareTo(c2.name)); _logger.finer( () => '# Contacts: ${allContacts.length}, #filtered: ${contacts.length}', ); late Widget body; if (contacts.isEmpty) { body = const SingleChildScrollView( physics: AlwaysScrollableScrollPhysics(), child: Center( child: Text('No contacts'), )); } else { body = ResponsiveMaxWidth( child: ListView.separated( physics: const AlwaysScrollableScrollPhysics(), itemBuilder: (context, index) { final contact = contacts[index]; return ListTile( onTap: () { context.pushNamed(ScreenPaths.userProfile, pathParameters: {'id': contact.id}); }, leading: ImageControl( imageUrl: contact.avatarUrl.toString(), iconOverride: const Icon(Icons.person), width: 32.0, ), title: Text( '${contact.name} (${contact.handle})', softWrap: true, ), subtitle: Text( 'Last Status: ${contact.lastStatus?.toIso8601String() ?? "Unknown"}', softWrap: true, ), trailing: Text(contact.status.label()), ); }, separatorBuilder: (context, index) => const Divider(), itemCount: contacts.length), ); } return Scaffold( drawer: const StandardAppDrawer(skipPopDismiss: true), body: SafeArea( child: RefreshIndicator( onRefresh: () async { if (nss.connectionUpdateStatus.value) { return; } manager.updateAllContacts(false); return; }, child: Column( children: [ Row( children: [ SizedBox( width: 50.0, child: buildCurrentProfileButton(context)!), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: TextField( onChanged: (value) { setState(() { filterText = value.toLowerCase(); }); }, decoration: InputDecoration( labelText: 'Filter By Name', alignLabelWithHint: true, border: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).highlightColor, ), borderRadius: BorderRadius.circular(5.0), ), ), ), ), ), Padding( padding: const EdgeInsets.all(8.0), child: StatusAndRefreshButton( valueListenable: nss.connectionUpdateStatus, refreshFunction: () async => manager.updateAllContacts(false), ), ) ], ), Text(manager.lastUpdateStatus), StandardLinearProgressIndicator(nss.connectionUpdateStatus), Expanded(child: body), ], ), ), ), bottomNavigationBar: const AppBottomNavBar( currentButton: NavBarButtons.contacts, ), ); } }