feat: can block/unblock in history page (#29)
All checks were successful
/ mirror (push) Successful in 4s

Reviewed-on: #29
Co-authored-by: Florian Griffon <florian.griffon@epitech.eu>
Co-committed-by: Florian Griffon <florian.griffon@epitech.eu>
This commit is contained in:
Florian Griffon 2025-01-30 14:25:04 +00:00 committed by stcb
parent ee1f2ee4b1
commit f99fdaa160

View File

@ -6,6 +6,7 @@ import 'package:intl/intl.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:dialer/features/contacts/contact_state.dart'; import 'package:dialer/features/contacts/contact_state.dart';
import 'package:dialer/widgets/username_color_generator.dart'; import 'package:dialer/widgets/username_color_generator.dart';
import '../../services/block_service.dart';
class History { class History {
final Contact contact; final Contact contact;
@ -30,7 +31,8 @@ class HistoryPage extends StatefulWidget {
_HistoryPageState createState() => _HistoryPageState(); _HistoryPageState createState() => _HistoryPageState();
} }
class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStateMixin { class _HistoryPageState extends State<HistoryPage>
with SingleTickerProviderStateMixin {
List<History> histories = []; List<History> histories = [];
bool loading = true; bool loading = true;
int? _expandedIndex; int? _expandedIndex;
@ -91,7 +93,8 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
List<History> olderHistories = []; List<History> olderHistories = [];
for (var history in historyList) { for (var history in historyList) {
final callDate = DateTime(history.date.year, history.date.month, history.date.day); final callDate =
DateTime(history.date.year, history.date.month, history.date.day);
if (callDate == today) { if (callDate == today) {
todayHistories.add(history); todayHistories.add(history);
} else if (callDate == yesterday) { } else if (callDate == yesterday) {
@ -145,7 +148,8 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
} }
// Filter missed calls // Filter missed calls
List<History> missedCalls = histories.where((h) => h.callStatus == 'missed').toList(); List<History> missedCalls =
histories.where((h) => h.callStatus == 'missed').toList();
final allItems = _buildGroupedList(histories); final allItems = _buildGroupedList(histories);
final missedItems = _buildGroupedList(missedCalls); final missedItems = _buildGroupedList(missedCalls);
@ -215,13 +219,6 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
backgroundColor: avatarColor, backgroundColor: avatarColor,
fallbackInitial: contact.displayName, fallbackInitial: contact.displayName,
), ),
// child: Text(
// contact.displayName.isNotEmpty
// ? contact.displayName[0].toUpperCase()
// : '?',
// style: TextStyle(color: darken(avatarColor, 0.4)),
// ),
// ),
title: Text( title: Text(
_obfuscateService.obfuscateData(contact.displayName), _obfuscateService.obfuscateData(contact.displayName),
style: const TextStyle(color: Colors.white), style: const TextStyle(color: Colors.white),
@ -241,18 +238,20 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
icon: const Icon(Icons.phone, color: Colors.green), icon: const Icon(Icons.phone, color: Colors.green),
onPressed: () async { onPressed: () async {
if (contact.phones.isNotEmpty) { if (contact.phones.isNotEmpty) {
final Uri callUri = final Uri callUri = Uri(
Uri(scheme: 'tel', path: contact.phones.first.number); scheme: 'tel', path: contact.phones.first.number);
if (await canLaunchUrl(callUri)) { if (await canLaunchUrl(callUri)) {
await launchUrl(callUri); await launchUrl(callUri);
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Could not launch call')), const SnackBar(
content: Text('Could not launch call')),
); );
} }
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Contact has no phone number')), const SnackBar(
content: Text('Contact has no phone number')),
); );
} }
}, },
@ -268,56 +267,99 @@ class _HistoryPageState extends State<HistoryPage> with SingleTickerProviderStat
if (isExpanded) if (isExpanded)
Container( Container(
color: Colors.grey[850], color: Colors.grey[850],
child: Row( child: FutureBuilder<bool>(
future: BlockService().isNumberBlocked(
contact.phones.isNotEmpty
? contact.phones.first.number
: ''),
builder: (context, snapshot) {
final isBlocked = snapshot.data ?? false;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
TextButton.icon( TextButton.icon(
onPressed: () async { onPressed: () async {
if (history.contact.phones.isNotEmpty) { if (history.contact.phones.isNotEmpty) {
final Uri smsUri = final Uri smsUri = Uri(
Uri(scheme: 'sms', path: history.contact.phones.first.number); scheme: 'sms',
path: history.contact.phones.first.number);
if (await canLaunchUrl(smsUri)) { if (await canLaunchUrl(smsUri)) {
await launchUrl(smsUri); await launchUrl(smsUri);
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Could not send message')), const SnackBar(
content:
Text('Could not send message')),
); );
} }
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Contact has no phone number')), const SnackBar(
content:
Text('Contact has no phone number')),
); );
} }
}, },
icon: const Icon(Icons.message, color: Colors.white), icon:
label: const Text('Message', style: TextStyle(color: Colors.white)), const Icon(Icons.message, color: Colors.white),
label: const Text('Message',
style: TextStyle(color: Colors.white)),
), ),
TextButton.icon( TextButton.icon(
onPressed: () { onPressed: () {
// Navigate to Call Details page
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => CallDetailsPage(history: history), builder: (_) =>
CallDetailsPage(history: history),
), ),
); );
}, },
icon: const Icon(Icons.info, color: Colors.white), icon: const Icon(Icons.info, color: Colors.white),
label: const Text('Details', style: TextStyle(color: Colors.white)), label: const Text('Details',
style: TextStyle(color: Colors.white)),
), ),
TextButton.icon( TextButton.icon(
onPressed: () { onPressed: () async {
// Implement block number functionality final phoneNumber = contact.phones.isNotEmpty
? contact.phones.first.number
: null;
if (phoneNumber == null) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
content: Text('Number blocked (functionality not implemented)'), content:
Text('Contact has no phone number'),
), ),
); );
return;
}
if (isBlocked) {
await BlockService().unblockNumber(phoneNumber);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('$phoneNumber unblocked')),
);
} else {
await BlockService().blockNumber(phoneNumber);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('$phoneNumber blocked')),
);
}
setState(() {}); // Refresh the button state
}, },
icon: const Icon(Icons.block, color: Colors.white), icon: Icon(
label: const Text('Block', style: TextStyle(color: Colors.white)), isBlocked ? Icons.lock_open : Icons.block,
color: Colors.white),
label: Text(
isBlocked ? 'Unblock' : 'Block',
style: const TextStyle(color: Colors.white),
),
), ),
], ],
);
},
), ),
), ),
], ],
@ -363,7 +405,8 @@ class CallDetailsPage extends StatelessWidget {
fallbackInitial: contact.displayName, fallbackInitial: contact.displayName,
) )
: CircleAvatar( : CircleAvatar(
backgroundColor: generateColorFromName(contact.displayName), backgroundColor:
generateColorFromName(contact.displayName),
radius: 30, radius: 30,
child: Text( child: Text(
contact.displayName.isNotEmpty contact.displayName.isNotEmpty
@ -407,7 +450,8 @@ class CallDetailsPage extends StatelessWidget {
if (contact.phones.isNotEmpty) if (contact.phones.isNotEmpty)
DetailRow( DetailRow(
label: 'Number:', label: 'Number:',
value: _obfuscateService.obfuscateData(contact.phones.first.number), value: _obfuscateService
.obfuscateData(contact.phones.first.number),
), ),
], ],
), ),
@ -420,7 +464,8 @@ class DetailRow extends StatelessWidget {
final String label; final String label;
final String value; final String value;
const DetailRow({Key? key, required this.label, required this.value}) : super(key: key); const DetailRow({Key? key, required this.label, required this.value})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -430,7 +475,8 @@ class DetailRow extends StatelessWidget {
children: [ children: [
Text( Text(
label, label,
style: const TextStyle(color: Colors.white70, fontWeight: FontWeight.bold), style: const TextStyle(
color: Colors.white70, fontWeight: FontWeight.bold),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(