diff --git a/dialer/android/app/src/debug/AndroidManifest.xml b/dialer/android/app/src/debug/AndroidManifest.xml index be93e62..0e34ec0 100644 --- a/dialer/android/app/src/debug/AndroidManifest.xml +++ b/dialer/android/app/src/debug/AndroidManifest.xml @@ -3,6 +3,8 @@ <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.SEND_SMS" /> + <uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS" /> + <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> <!-- The INTERNET permission is required for development. Specifically, the Flutter tool needs it to communicate with the running application diff --git a/dialer/android/app/src/main/AndroidManifest.xml b/dialer/android/app/src/main/AndroidManifest.xml index 4ba2a7b..a4877fe 100644 --- a/dialer/android/app/src/main/AndroidManifest.xml +++ b/dialer/android/app/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.SEND_SMS" /> + <uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS" /> + <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" /> <application android:label="com.example.dialer" android:name="${applicationName}" diff --git a/dialer/android/app/src/profile/AndroidManifest.xml b/dialer/android/app/src/profile/AndroidManifest.xml index 767714e..6904ee8 100644 --- a/dialer/android/app/src/profile/AndroidManifest.xml +++ b/dialer/android/app/src/profile/AndroidManifest.xml @@ -4,6 +4,8 @@ <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.CAMERA"/> + <uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS" /> + <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> <!-- The INTERNET permission is required for development. Specifically, the Flutter tool needs it to communicate with the running application diff --git a/dialer/lib/features/settings/blocked/settings_blocked.dart b/dialer/lib/features/settings/blocked/settings_blocked.dart new file mode 100644 index 0000000..77c3a85 --- /dev/null +++ b/dialer/lib/features/settings/blocked/settings_blocked.dart @@ -0,0 +1,167 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.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(); + + @override + void initState() { + super.initState(); + _loadPreferences(); // Load data on initialization + } + + // Load preferences from local storage + Future<void> _loadPreferences() async { + final prefs = await SharedPreferences.getInstance(); + setState(() { + _blockUnknownNumbers = prefs.getBool('blockUnknownNumbers') ?? false; + _blockedNumbers = prefs.getStringList('blockedNumbers') ?? []; + }); + } + + // 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'), + ), + body: 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), + ) + : null, + ), + ..._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) { + if (number.isNotEmpty && !_blockedNumbers.contains(number)) { + setState(() { + _blockedNumbers.add(number); + _savePreferences(); // Save the updated list + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('$number has been blocked')), + ); + } + } + + // Function to unblock a number + void _unblockNumber(String number) { + setState(() { + _blockedNumbers.remove(number); + _savePreferences(); // Save the updated list + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('$number has been unblocked')), + ); + } + + // 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(); + } +} diff --git a/dialer/lib/features/settings/settings.dart b/dialer/lib/features/settings/settings.dart index bb72951..9735e1b 100644 --- a/dialer/lib/features/settings/settings.dart +++ b/dialer/lib/features/settings/settings.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:dialer/features/settings/call/settingsCall.dart'; import 'package:dialer/features/settings/sim/settings_accounts.dart'; import 'package:dialer/features/settings/key/manage_keys_page.dart'; +import 'package:dialer/features/settings/blocked/settings_blocked.dart'; class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @@ -28,9 +29,15 @@ class SettingsPage extends StatelessWidget { MaterialPageRoute(builder: (context) => const KeyManagementPage()), ); break; - // Add more cases for other settings pages + case 'Blocked numbers': + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const BlockedNumbersPage()), + ); + break; + // Add more cases for other settings pages default: - // Handle default or unknown settings + // Handle default or unknown settings break; } } @@ -41,6 +48,7 @@ class SettingsPage extends StatelessWidget { 'Calling settings', 'Page of telephone accounts', 'Key management', + 'Blocked numbers' ]; return Scaffold( diff --git a/dialer/pubspec.yaml b/dialer/pubspec.yaml index b63777e..6e36f8c 100644 --- a/dialer/pubspec.yaml +++ b/dialer/pubspec.yaml @@ -34,6 +34,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. + shared_preferences: ^2.3.3 # Local storage (no critical data) cupertino_icons: ^1.0.8 flutter_contacts: ^1.1.9+2 permission_handler: ^11.3.1 # For handling permissions