diff --git a/dialer/lib/domain/services/message_service.dart b/dialer/lib/domain/services/message_service.dart new file mode 100644 index 0000000..2c0da6f --- /dev/null +++ b/dialer/lib/domain/services/message_service.dart @@ -0,0 +1,18 @@ +import 'dart:io' show Platform; +import 'package:flutter/foundation.dart'; +import 'package:url_launcher/url_launcher.dart'; + +/// A service to handle sending SMS messages using the url_launcher package. +class MessageService { + /// Launches the SMS dialer for the given [phoneNumber]. + Future sendSms(String phoneNumber) async { + // Sanitize number (keep only digits and plus sign) + final sanitized = phoneNumber.replaceAll(RegExp(r'[^0-9+]'), ''); + + Uri uri; + + uri = Uri(scheme: 'sms', path: sanitized); + + await launchUrl(uri); + } +} diff --git a/dialer/lib/presentation/features/contacts/widgets/contact_modal.dart b/dialer/lib/presentation/features/contacts/widgets/contact_modal.dart index a0a1dce..e5d53e3 100644 --- a/dialer/lib/presentation/features/contacts/widgets/contact_modal.dart +++ b/dialer/lib/presentation/features/contacts/widgets/contact_modal.dart @@ -7,6 +7,7 @@ import '../../../../domain/services/obfuscate_service.dart'; import '../../../../domain/services/block_service.dart'; import '../../../../domain/services/contact_service.dart'; import '../../../../domain/services/call_service.dart'; +import '../../../../domain/services/message_service.dart'; class ContactModal extends StatefulWidget { final Contact contact; @@ -32,6 +33,7 @@ class _ContactModalState extends State { final ObfuscateService _obfuscateService = ObfuscateService(); final CallService _callService = CallService(); final ContactService _contactService = ContactService(); + final MessageService _messageService = MessageService(); @override void initState() { @@ -60,7 +62,7 @@ class _ContactModalState extends State { ); return; } - + if (isBlocked) { await BlockService().unblockNumber(phoneNumber); if (mounted) { @@ -80,30 +82,12 @@ class _ContactModalState extends State { if (phoneNumber != 'No phone number' && mounted) { _checkIfBlocked(); } - + if (mounted) { 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)) { @@ -246,7 +230,8 @@ class _ContactModalState extends State { padding: const EdgeInsets.all(16.0), child: Column( children: [ - widget.contact.thumbnail != null && widget.contact.thumbnail!.isNotEmpty + widget.contact.thumbnail != null && + widget.contact.thumbnail!.isNotEmpty ? ClipOval( child: Image.memory( widget.contact.thumbnail!, @@ -260,7 +245,8 @@ class _ContactModalState extends State { radius: 50, child: Text( widget.contact.displayName.isNotEmpty - ? widget.contact.displayName[0].toUpperCase() + ? widget.contact.displayName[0] + .toUpperCase() : '?', style: TextStyle( color: darken(avatarColor), @@ -287,7 +273,8 @@ class _ContactModalState extends State { child: Column( children: [ ListTile( - leading: const Icon(Icons.phone, color: Colors.green), + leading: + const Icon(Icons.phone, color: Colors.green), title: Text( _obfuscateService.obfuscateData(phoneNumber), style: const TextStyle(color: Colors.white), @@ -300,19 +287,21 @@ class _ContactModalState extends State { }, ), ListTile( - leading: const Icon(Icons.message, color: Colors.blue), + 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); + _messageService.sendSms(phoneNumber); } }, ), ListTile( - leading: const Icon(Icons.email, color: Colors.orange), + leading: + const Icon(Icons.email, color: Colors.orange), title: Text( email, style: const TextStyle(color: Colors.white), @@ -326,7 +315,8 @@ class _ContactModalState extends State { const Divider(color: Colors.grey), // Favorite, Edit, and Block/Unblock Buttons Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + padding: + const EdgeInsets.symmetric(horizontal: 16.0), child: Column( children: [ // Favorite button @@ -342,8 +332,9 @@ class _ContactModalState extends State { icon: Icon(widget.isFavorite ? Icons.star : Icons.star_border), - label: Text( - widget.isFavorite ? 'Unfavorite' : 'Favorite'), + label: Text(widget.isFavorite + ? 'Unfavorite' + : 'Favorite'), ), ), const SizedBox(height: 10), @@ -362,9 +353,11 @@ class _ContactModalState extends State { width: double.infinity, child: ElevatedButton.icon( onPressed: _toggleBlockState, - icon: Icon( - isBlocked ? Icons.block : Icons.block_flipped), - label: Text(isBlocked ? 'Unblock' : 'Block'), + icon: Icon(isBlocked + ? Icons.block + : Icons.block_flipped), + label: + Text(isBlocked ? 'Unblock' : 'Block'), ), ), ],