diff --git a/dialer/lib/features/composition/composition.dart b/dialer/lib/features/composition/composition.dart index 783fcf9..488b4a5 100644 --- a/dialer/lib/features/composition/composition.dart +++ b/dialer/lib/features/composition/composition.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../../widgets/contact_service.dart'; +import '../contacts/widgets/add_contact_button.dart'; class CompositionPage extends StatefulWidget { const CompositionPage({super.key}); @@ -22,11 +24,9 @@ class _CompositionPageState extends State { } Future _fetchContacts() async { - if (await FlutterContacts.requestPermission()) { - _allContacts = await _contactService.fetchContacts(); - _filteredContacts = _allContacts; - setState(() {}); - } + _allContacts = await _contactService.fetchContacts(); + _filteredContacts = _allContacts; + setState(() {}); } void _filterContacts() { @@ -65,9 +65,24 @@ class _CompositionPageState extends State { }); } - // Placeholder function for adding contact - void addContact(String number) { - // This function is empty for now + // Function to call a contact's number + 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'); + } + } + + // Function to send an SMS to a contact's number + void _launchSms(String phoneNumber) async { + final uri = Uri(scheme: 'sms', path: phoneNumber); + if (await canLaunchUrl(uri)) { + await launchUrl(uri); + } else { + debugPrint('Could not send SMS to $phoneNumber'); + } } @override @@ -81,9 +96,9 @@ class _CompositionPageState extends State { // Top half: Display contacts matching dialed number Expanded( flex: 2, - child: - Container( - padding: const EdgeInsets.only(top: 42.0, left: 16.0, right: 16.0, bottom: 16.0), + child: Container( + padding: const EdgeInsets.only( + top: 42.0, left: 16.0, right: 16.0, bottom: 16.0), color: Colors.black, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -92,32 +107,39 @@ class _CompositionPageState extends State { child: ListView( children: _filteredContacts.isNotEmpty ? _filteredContacts.map((contact) { + final phoneNumber = contact.phones.isNotEmpty + ? contact.phones.first.number + : 'No phone number'; return ListTile( title: Text( contact.displayName, - style: const TextStyle(color: Colors.white), + style: + const TextStyle(color: Colors.white), + ), + subtitle: Text( + phoneNumber, + style: + const TextStyle(color: Colors.grey), ), - subtitle: contact.phones.isNotEmpty - ? Text( - contact.phones.first.number, - style: const TextStyle(color: Colors.grey), - ) - : null, trailing: Row( mainAxisSize: MainAxisSize.min, children: [ // Call button IconButton( - icon: Icon(Icons.phone, color: Colors.green[300], size: 20), + icon: Icon(Icons.phone, + color: Colors.green[300], + size: 20), onPressed: () { - print('Calling ${contact.displayName}'); + _launchPhoneDialer(phoneNumber); }, ), - // Text button + // Message button IconButton( - icon: Icon(Icons.message, color: Colors.blue[300], size: 20), + icon: Icon(Icons.message, + color: Colors.blue[300], + size: 20), onPressed: () { - print('Texting ${contact.displayName}'); + _launchSms(phoneNumber); }, ), ], @@ -127,7 +149,12 @@ class _CompositionPageState extends State { }, ); }).toList() - : [Center(child: Text('No contacts found', style: TextStyle(color: Colors.white)))], + : [ + Center( + child: Text('No contacts found', + style: + TextStyle(color: Colors.white))) + ], ), ), ], @@ -152,14 +179,16 @@ class _CompositionPageState extends State { alignment: Alignment.center, child: Text( dialedNumber, - style: const TextStyle(fontSize: 24, color: Colors.white), + style: const TextStyle( + fontSize: 24, color: Colors.white), overflow: TextOverflow.ellipsis, ), ), ), IconButton( onPressed: _onClearPress, - icon: const Icon(Icons.backspace, color: Colors.white), + icon: const Icon(Icons.backspace, + color: Colors.white), ), ], ), @@ -172,7 +201,8 @@ class _CompositionPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('1'), _buildDialButton('2'), @@ -180,7 +210,8 @@ class _CompositionPageState extends State { ], ), Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('4'), _buildDialButton('5'), @@ -188,7 +219,8 @@ class _CompositionPageState extends State { ], ), Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('7'), _buildDialButton('8'), @@ -196,7 +228,8 @@ class _CompositionPageState extends State { ], ), Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('*'), _buildDialButton('0'), @@ -211,20 +244,19 @@ class _CompositionPageState extends State { ), ), ), - - // Add Contact Button with empty function call - Padding( - padding: const EdgeInsets.only(bottom: 20.0), - child: FloatingActionButton( - backgroundColor: Colors.blue, - onPressed: () { - addContact(dialedNumber); - }, - child: const Icon(Icons.person_add, color: Colors.white), - ), - ), ], ), + + // Add Contact Button + Positioned( + bottom: 20.0, + left: 0, + right: 0, + child: Center( + child: AddContactButton(), + ), + ), + // Top Row with Back Arrow Positioned( top: 40.0,