import 'package:flutter/material.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:dialer/widgets/username_color_generator.dart'; import '../../../widgets/block_service.dart'; class ContactModal extends StatefulWidget { final Contact contact; final Function onEdit; final Function onToggleFavorite; final bool isFavorite; const ContactModal({ super.key, required this.contact, required this.onEdit, required this.onToggleFavorite, required this.isFavorite, }); @override _ContactModalState createState() => _ContactModalState(); } class _ContactModalState extends State { late String phoneNumber; bool isBlocked = false; @override void initState() { super.initState(); phoneNumber = widget.contact.phones.isNotEmpty ? widget.contact.phones.first.number : 'No phone number'; _checkIfBlocked(); } Future _checkIfBlocked() async { if (phoneNumber != 'No phone number') { bool blocked = await BlockService().isNumberBlocked(phoneNumber); setState(() { isBlocked = blocked; }); } } Future _toggleBlockState() async { if (phoneNumber == 'No phone number') { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('No phone number to block or unblock')), ); } else if (isBlocked) { await BlockService().unblockNumber(phoneNumber); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('$phoneNumber has been unblocked')), ); } else { await BlockService().blockNumber(phoneNumber); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('$phoneNumber has been blocked')), ); } if (phoneNumber != 'No phone number') { _checkIfBlocked(); } Navigator.of(context).pop(); } void _launchPhoneDialer(String phoneNumber) async { final uri = Uri(scheme: 'tel', path: phoneNumber); if (await canLaunchUrl(uri)) { await launchUrl(uri); } else { debugPrint('Could not launch $phoneNumber'); } } void _launchSms(String phoneNumber) async { final uri = Uri(scheme: 'sms', path: phoneNumber); if (await canLaunchUrl(uri)) { await launchUrl(uri); } else { debugPrint('Could not launch SMS to $phoneNumber'); } } void _launchEmail(String email) async { final uri = Uri(scheme: 'mailto', path: email); if (await canLaunchUrl(uri)) { await launchUrl(uri); } else { debugPrint('Could not launch email to $email'); } } void _deleteContact() async { final bool shouldDelete = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Delete Contact'), content: Text('Are you sure you want to delete ${widget.contact.displayName}?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('Delete'), ), ], ), ); if (shouldDelete) { try { // Delete the contact await FlutterContacts.deleteContact(widget.contact); // Show success message ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('${widget.contact.displayName} deleted')), ); // Close the modal Navigator.of(context).pop(); } catch (e) { // Handle errors and show a failure message ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Failed to delete ${widget.contact.displayName}: $e')), ); } } } @override Widget build(BuildContext context) { String email = widget.contact.emails.isNotEmpty ? widget.contact.emails.first.address : 'No email'; return GestureDetector( onTap: () => Navigator.of(context).pop(), child: Container( color: Colors.black.withOpacity(0.5), child: GestureDetector( onTap: () {}, child: FractionallySizedBox( child: Container( decoration: BoxDecoration( color: Colors.grey[900], borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Modal Handle and Three-Dot Menu Stack( children: [ Align( alignment: Alignment.center, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Container( width: 50, height: 5, decoration: BoxDecoration( color: Colors.grey.shade300, borderRadius: BorderRadius.circular(5), ), ), ), ), Align( alignment: Alignment.topRight, child: Padding( padding: const EdgeInsets.only(top: 10, right: 10), child: PopupMenuButton( icon: const Icon(Icons.more_vert, color: Colors.white), onSelected: (String choice) { if (choice == 'delete') { _deleteContact(); } }, itemBuilder: (BuildContext context) { return [ const PopupMenuItem( value: 'show_associated_contacts', child: Text('Show associated contacts'), ), const PopupMenuItem( value: 'delete', child: Text('Delete'), ), const PopupMenuItem( value: 'share', child: Text('Share (via QR code)'), ), const PopupMenuItem( value: 'create_shortcut', child: Text('Create shortcut (to home screen)'), ), const PopupMenuItem( value: 'set_ringtone', child: Text('Set ringtone'), ), ]; }, ), ), ), ], ), // Contact Profile Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ CircleAvatar( radius: 50, backgroundImage: (widget.contact.thumbnail != null && widget.contact.thumbnail!.isNotEmpty) ? MemoryImage(widget.contact.thumbnail!) : null, backgroundColor: generateColorFromName(widget.contact.displayName), child: (widget.contact.thumbnail == null || widget.contact.thumbnail!.isEmpty) ? Text( widget.contact.displayName.isNotEmpty ? widget.contact.displayName[0] .toUpperCase() : '?', style: const TextStyle( fontSize: 40, color: Colors.white), ) : null, ), const SizedBox(height: 10), Text( widget.contact.displayName, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold), ), ], ), ), const Divider(), // Contact Actions ListTile( leading: const Icon(Icons.phone, color: Colors.green), title: Text(phoneNumber), onTap: () { if (widget.contact.phones.isNotEmpty) { _launchPhoneDialer(phoneNumber); } }, ), ListTile( leading: const Icon(Icons.message, color: Colors.blue), title: Text(phoneNumber), onTap: () { if (widget.contact.phones.isNotEmpty) { _launchSms(phoneNumber); } }, ), ListTile( leading: const Icon(Icons.email, color: Colors.orange), title: Text(email), onTap: () { if (widget.contact.emails.isNotEmpty) { _launchEmail(email); } }, ), const Divider(), // Favorite, Edit, and Block/Unblock Buttons Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( children: [ // Favorite button SizedBox( width: double .infinity, // This makes the button take full width child: ElevatedButton.icon( onPressed: () { Navigator.of(context).pop(); widget.onToggleFavorite(); }, icon: Icon(widget.isFavorite ? Icons.star : Icons.star_border), label: Text( widget.isFavorite ? 'Unfavorite' : 'Favorite'), ), ), const SizedBox(height: 10), // Space between buttons // Edit button SizedBox( width: double .infinity, // This makes the button take full width child: ElevatedButton.icon( onPressed: () => widget.onEdit(), icon: const Icon(Icons.edit), label: const Text('Edit Contact'), ), ), const SizedBox(height: 10), // Space between buttons // Block/Unblock button SizedBox( width: double .infinity, // This makes the button take full width child: ElevatedButton.icon( onPressed: _toggleBlockState, icon: Icon( isBlocked ? Icons.block : Icons.block_flipped), label: Text(isBlocked ? 'Unblock' : 'Block'), ), ), ], ), ), const SizedBox(height: 16), ], ), ), ), ), ), ); } }