import 'package:dialer/services/obfuscate_service.dart'; 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 '../../../services/block_service.dart'; import '../../../services/contact_service.dart'; import '../../../services/call_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; final ObfuscateService _obfuscateService = ObfuscateService(); final CallService _callService = CallService(); @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 ${_obfuscateService.obfuscateData(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( '${_obfuscateService.obfuscateData(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')), ); } } } void _shareContactAsQRCode() { // Use the ContactService to show the QR code for the contact's vCard ContactService().showContactQRCodeDialog(context, widget.contact); } @override Widget build(BuildContext context) { String email = widget.contact.emails.isNotEmpty ? _obfuscateService.obfuscateData(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(); } else if (choice == 'share') { _shareContactAsQRCode(); } // Handle other choices if needed }, 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: [ ObfuscatedAvatar( imageBytes: widget.contact.thumbnail, radius: 50, backgroundColor: generateColorFromName(widget.contact.displayName), fallbackInitial: widget.contact.displayName, ), const SizedBox(height: 10), Text( _obfuscateService .obfuscateData(widget.contact.displayName), style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white), ), ], ), ), const Divider(color: Colors.grey), // Contact Actions ListTile( leading: const Icon(Icons.phone, color: Colors.green), title: Text( _obfuscateService.obfuscateData(phoneNumber), style: const TextStyle(color: Colors.white), ), onTap: () async { if (widget.contact.phones.isNotEmpty) { await _callService.makeGsmCall(context, phoneNumber: phoneNumber); } }, ), ListTile( leading: const Icon(Icons.message, color: Colors.blue), title: Text( _obfuscateService.obfuscateData(phoneNumber), style: const TextStyle(color: Colors.white), ), onTap: () { if (widget.contact.phones.isNotEmpty) { _launchSms(phoneNumber); } }, ), ListTile( leading: const Icon(Icons.email, color: Colors.orange), title: Text( email, style: const TextStyle(color: Colors.white), ), onTap: () { if (widget.contact.emails.isNotEmpty) { _launchEmail(email); } }, ), const Divider(color: Colors.grey), // Favorite, Edit, and Block/Unblock Buttons Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( children: [ // Favorite button SizedBox( width: double.infinity, 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), // Edit button SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: () => widget.onEdit(), icon: const Icon(Icons.edit), label: const Text('Edit Contact'), ), ), const SizedBox(height: 10), // Block/Unblock button SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _toggleBlockState, icon: Icon( isBlocked ? Icons.block : Icons.block_flipped), label: Text(isBlocked ? 'Unblock' : 'Block'), ), ), ], ), ), const SizedBox(height: 16), ], ), ), ), ), ), ); } }