feat(contacts): имена из телефонной книги везде + тумблер в дев-меню
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user