import 'package:dialer/widgets/username_color_generator.dart'; import 'package:flutter/material.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import '../../../widgets/color_darkener.dart'; import '../contact_state.dart'; import 'add_contact_button.dart'; import 'share_own_qr.dart'; class AlphabetScrollPage extends StatefulWidget { final List contacts; final double scrollOffset; const AlphabetScrollPage({super.key, required this.contacts, required this.scrollOffset}); @override _AlphabetScrollPageState createState() => _AlphabetScrollPageState(); } class _AlphabetScrollPageState extends State { late ScrollController _scrollController; @override void initState() { super.initState(); _scrollController = ScrollController(initialScrollOffset: widget.scrollOffset); _scrollController.addListener(_onScroll); } void _onScroll() { final contactState = ContactState.of(context); contactState.setScrollOffset(_scrollController.offset); } @override Widget build(BuildContext context) { Map> alphabetizedContacts = {}; for (var contact in widget.contacts) { String firstLetter = contact.displayName.isNotEmpty ? contact.displayName[0].toUpperCase() : '#'; if (!alphabetizedContacts.containsKey(firstLetter)) { alphabetizedContacts[firstLetter] = []; } alphabetizedContacts[firstLetter]!.add(contact); } List alphabetKeys = alphabetizedContacts.keys.toList()..sort(); return Scaffold( backgroundColor: Colors.black, body: Column( children: [ // Top buttons row Container( color: Colors.black, padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AddContactButton(), QRCodeButton(contacts: widget.contacts, selfContact: ContactState.of(context).selfContact), ], ), ), // Contact List Expanded( child: ListView.builder( controller: _scrollController, itemCount: alphabetKeys.length, itemBuilder: (context, index) { String letter = alphabetKeys[index]; List contacts = alphabetizedContacts[letter]!; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Alphabet Letter Header Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), child: Text( letter, style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), // Contact Entries ...contacts.map((contact) { String phoneNumber = contact.phones.isNotEmpty ? contact.phones.first.number : 'No phone number'; Color avatarColor = generateColorFromName(contact.displayName); return ListTile( leading: (contact.thumbnail != null && contact.thumbnail!.isNotEmpty) ? CircleAvatar( backgroundImage: MemoryImage(contact.thumbnail!), ) : CircleAvatar( backgroundColor: avatarColor, child: Text( contact.displayName.isNotEmpty ? contact.displayName[0].toUpperCase() : '?', style: TextStyle(color: darken(avatarColor, 0.4)), ), ), title: Text(contact.displayName, style: TextStyle(color: Colors.white)), subtitle: Text(phoneNumber, style: TextStyle(color: Colors.white70)), onTap: () { // Handle contact tap }, ); }), ], ); }, ), ), ], ), ); } @override void dispose() { _scrollController.dispose(); super.dispose(); } }