monorepo/dialer/lib/presentation/features/settings/blocked/settings_blocked.dart
AlexisDanlos 2e8f457889
All checks were successful
/ build (push) Successful in 10m4s
/ build-stealth (push) Successful in 10m9s
/ mirror (push) Successful in 4s
feat: add block management features and sync with system blocklist
2025-06-27 17:15:29 +02:00

228 lines
7.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../domain/services/block_service.dart';
class BlockedNumbersPage extends StatefulWidget {
const BlockedNumbersPage({super.key});
@override
_BlockedNumbersPageState createState() => _BlockedNumbersPageState();
}
class _BlockedNumbersPageState extends State<BlockedNumbersPage> {
bool _blockUnknownNumbers = false; // Toggle for blocking unknown numbers
List<String> _blockedNumbers = []; // List of blocked numbers
final TextEditingController _numberController = TextEditingController();
final BlockService _blockService = BlockService();
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadPreferences(); // Load data on initialization
}
// Load preferences from local storage and sync with system
Future<void> _loadPreferences() async {
setState(() {
_isLoading = true;
});
try {
final prefs = await SharedPreferences.getInstance();
final blockUnknownNumbers = prefs.getBool('blockUnknownNumbers') ?? false;
// Sync with system blocked numbers
await _blockService.syncWithSystem();
// Get all blocked numbers (merged from system and app)
final blockedNumbers = await _blockService.getBlockedNumbers();
setState(() {
_blockUnknownNumbers = blockUnknownNumbers;
_blockedNumbers = blockedNumbers;
_isLoading = false;
});
} catch (e) {
debugPrint('Error loading preferences: $e');
setState(() {
_isLoading = false;
});
}
}
// Save preferences to local storage
Future<void> _savePreferences() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('blockUnknownNumbers', _blockUnknownNumbers);
await prefs.setStringList('blockedNumbers', _blockedNumbers);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Blocked Numbers'),
actions: [
IconButton(
icon: const Icon(Icons.sync),
onPressed: _isLoading ? null : () async {
await _loadPreferences();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Synced with system blocklist')),
);
},
tooltip: 'Sync with system blocklist',
),
],
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: ListView(
padding: const EdgeInsets.all(16),
children: [
SwitchListTile(
title: const Text(
'Block Unknown Numbers',
style: TextStyle(color: Colors.white),
),
value: _blockUnknownNumbers,
onChanged: (bool value) {
setState(() {
_blockUnknownNumbers = value;
_savePreferences(); // Save the state to local storage
});
},
),
const SizedBox(height: 16),
ListTile(
title: const Text(
'Blocked Numbers',
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
),
subtitle: _blockedNumbers.isEmpty
? const Text(
'No blocked numbers',
style: TextStyle(color: Colors.grey),
)
: Text(
'${_blockedNumbers.length} numbers blocked (includes system blocklist)',
style: const TextStyle(color: Colors.grey),
),
),
..._blockedNumbers.map(
(number) => ListTile(
title: Text(
number,
style: const TextStyle(color: Colors.white),
),
trailing: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () => _unblockNumber(number),
),
),
),
const Divider(color: Colors.grey),
ListTile(
title: const Text(
'Block a Number',
style: TextStyle(color: Colors.white),
),
trailing: const Icon(Icons.add, color: Colors.white),
onTap: () => _showBlockNumberDialog(),
),
],
),
);
}
// Function to block a number
void _blockNumber(String number) async {
if (number.isNotEmpty && !_blockedNumbers.contains(number)) {
try {
final success = await _blockService.blockNumber(number);
if (success) {
await _loadPreferences(); // Refresh the list
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('$number has been blocked')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to block $number')),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error blocking $number: $e')),
);
}
}
}
// Function to unblock a number
void _unblockNumber(String number) async {
try {
final success = await _blockService.unblockNumber(number);
if (success) {
await _loadPreferences(); // Refresh the list
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('$number has been unblocked')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to unblock $number')),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error unblocking $number: $e')),
);
}
}
// Dialog for blocking a new number
void _showBlockNumberDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Colors.grey[900],
title: const Text('Block a Number', style: TextStyle(color: Colors.white)),
content: TextField(
controller: _numberController,
keyboardType: TextInputType.phone,
decoration: const InputDecoration(
hintText: 'Enter number',
hintStyle: TextStyle(color: Colors.grey),
),
style: const TextStyle(color: Colors.white),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancel', style: TextStyle(color: Colors.white)),
),
TextButton(
onPressed: () {
_blockNumber(_numberController.text);
_numberController.clear();
Navigator.pop(context);
},
child: const Text('Block', style: TextStyle(color: Colors.red)),
),
],
);
},
);
}
@override
void dispose() {
_numberController.dispose();
super.dispose();
}
}