83 lines
2.4 KiB
Dart
83 lines
2.4 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter_contacts/flutter_contacts.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../config/app_phonebook_names.dart';
|
|
|
|
class DeviceContactsService {
|
|
DeviceContactsService._();
|
|
|
|
static const _grantedKey = 'phonebook_granted';
|
|
|
|
static final Map<String, String> _byLast10 = {};
|
|
static bool _loaded = false;
|
|
|
|
static bool get _supported => Platform.isAndroid || Platform.isIOS;
|
|
|
|
static String? _last10(String raw) {
|
|
final digits = raw.replaceAll(RegExp(r'[^\d]'), '');
|
|
if (digits.length < 10) return null;
|
|
return digits.substring(digits.length - 10);
|
|
}
|
|
|
|
static String? nameForPhone(int phone) {
|
|
if (!AppPhonebookNames.current.value) return null;
|
|
if (_byLast10.isEmpty) return null;
|
|
final key = _last10(phone.toString());
|
|
if (key == null) return null;
|
|
final name = _byLast10[key];
|
|
if (name == null || name.trim().isEmpty) return null;
|
|
return name.trim();
|
|
}
|
|
|
|
static Future<void> loadFromStartup() async {
|
|
if (_loaded || !_supported) return;
|
|
if (!AppPhonebookNames.current.value) return;
|
|
final prefs = await SharedPreferences.getInstance();
|
|
if (prefs.getBool(_grantedKey) != true) return;
|
|
final granted = await FlutterContacts.requestPermission(readonly: true);
|
|
if (!granted) return;
|
|
await _readBook();
|
|
}
|
|
|
|
static Future<bool> ensureLoadedInteractive() async {
|
|
if (_loaded || !_supported) return false;
|
|
if (!AppPhonebookNames.current.value) return false;
|
|
final granted = await FlutterContacts.requestPermission(readonly: true);
|
|
if (!granted) return false;
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_grantedKey, true);
|
|
return _readBook();
|
|
}
|
|
|
|
static Future<bool> reload() async {
|
|
_loaded = false;
|
|
_byLast10.clear();
|
|
return ensureLoadedInteractive();
|
|
}
|
|
|
|
static Future<bool> _readBook() async {
|
|
try {
|
|
final contacts = await FlutterContacts.getContacts(
|
|
withProperties: true,
|
|
);
|
|
_byLast10.clear();
|
|
for (final contact in contacts) {
|
|
final name = contact.displayName.trim();
|
|
if (name.isEmpty) continue;
|
|
for (final phone in contact.phones) {
|
|
final key = _last10(phone.number);
|
|
if (key != null) {
|
|
_byLast10.putIfAbsent(key, () => name);
|
|
}
|
|
}
|
|
}
|
|
_loaded = true;
|
|
return _byLast10.isNotEmpty;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|