monorepo/dialer/lib/domain/services/block_service.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

153 lines
4.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// Service for managing blocked phone numbers
class BlockService {
static const String _blockedNumbersKey = 'blocked_numbers';
static const MethodChannel _channel = MethodChannel('com.example.block');
// Private constructor
BlockService._privateConstructor();
// Singleton instance
static final BlockService _instance = BlockService._privateConstructor();
// Factory constructor to return the same instance
factory BlockService() {
return _instance;
}
/// Block a phone number (syncs with system and app)
Future<bool> blockNumber(String phoneNumber) async {
try {
// First try to block in system
try {
await _channel.invokeMethod('blockNumber', {'number': phoneNumber});
} catch (e) {
debugPrint('Failed to block in system: $e');
}
// Always save to app storage as backup
final prefs = await SharedPreferences.getInstance();
final blockedNumbers = prefs.getStringList(_blockedNumbersKey) ?? [];
// Don't add if already blocked
if (!blockedNumbers.contains(phoneNumber)) {
blockedNumbers.add(phoneNumber);
await prefs.setStringList(_blockedNumbersKey, blockedNumbers);
}
return true; // Return true if either system or app blocking succeeded
} catch (e) {
debugPrint('Error blocking number: $e');
return false;
}
}
/// Unblock a phone number (syncs with system and app)
Future<bool> unblockNumber(String phoneNumber) async {
try {
// First try to unblock from system
try {
await _channel.invokeMethod('unblockNumber', {'number': phoneNumber});
} catch (e) {
debugPrint('Failed to unblock from system: $e');
}
// Always remove from app storage
final prefs = await SharedPreferences.getInstance();
final blockedNumbers = prefs.getStringList(_blockedNumbersKey) ?? [];
if (blockedNumbers.contains(phoneNumber)) {
blockedNumbers.remove(phoneNumber);
await prefs.setStringList(_blockedNumbersKey, blockedNumbers);
}
return true;
} catch (e) {
debugPrint('Error unblocking number: $e');
return false;
}
}
/// Check if a number is blocked (checks both system and app)
Future<bool> isNumberBlocked(String phoneNumber) async {
try {
// Check system first
try {
bool systemBlocked = await _channel.invokeMethod('isNumberBlocked', {'number': phoneNumber});
if (systemBlocked) return true;
} catch (e) {
debugPrint('Failed to check system blocked status: $e');
}
// Check app storage as fallback
final prefs = await SharedPreferences.getInstance();
final blockedNumbers = prefs.getStringList(_blockedNumbersKey) ?? [];
return blockedNumbers.contains(phoneNumber);
} catch (e) {
debugPrint('Error checking if number is blocked: $e');
return false;
}
}
/// Get all blocked numbers (merges system and app blocked numbers)
Future<List<String>> getBlockedNumbers() async {
try {
Set<String> allBlockedNumbers = {};
// Get system blocked numbers
try {
List<dynamic> systemBlocked = await _channel.invokeMethod('getBlockedNumbers');
allBlockedNumbers.addAll(systemBlocked.cast<String>());
} catch (e) {
debugPrint('Failed to get system blocked numbers: $e');
}
// Get app blocked numbers
try {
final prefs = await SharedPreferences.getInstance();
final appBlocked = prefs.getStringList(_blockedNumbersKey) ?? [];
allBlockedNumbers.addAll(appBlocked);
} catch (e) {
debugPrint('Failed to get app blocked numbers: $e');
}
return allBlockedNumbers.toList()..sort();
} catch (e) {
debugPrint('Error getting blocked numbers: $e');
return [];
}
}
/// Sync app blocked numbers with system blocked numbers
Future<void> syncWithSystem() async {
try {
// Get system blocked numbers
List<String> systemBlocked = [];
try {
List<dynamic> result = await _channel.invokeMethod('getBlockedNumbers');
systemBlocked = result.cast<String>();
} catch (e) {
debugPrint('Failed to get system blocked numbers for sync: $e');
return;
}
// Get app blocked numbers
final prefs = await SharedPreferences.getInstance();
List<String> appBlocked = prefs.getStringList(_blockedNumbersKey) ?? [];
// Merge them (system takes precedence)
Set<String> mergedBlocked = {...systemBlocked, ...appBlocked};
// Update app storage with merged list
await prefs.setStringList(_blockedNumbersKey, mergedBlocked.toList());
debugPrint('Synced ${mergedBlocked.length} blocked numbers with system');
} catch (e) {
debugPrint('Error syncing with system: $e');
}
}
}