import 'package:clean/base/base_controller.dart'; import 'package:clean/data/repositories/user_repository.dart'; import 'package:clean/dialog/loading_dialog.dart'; import 'package:clean/module/contact/contact_state.dart'; import 'package:clean/module/store/store_view.dart'; import 'package:clean/utils/toast_util.dart'; import 'package:flutter_contacts/contact.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:get/get_rx/src/rx_types/rx_types.dart'; class ContactDuplicateController extends BaseController { // 是否为编辑状态 RxBool isEdit = false.obs; // 是否全选 RxBool isAllSelected = false.obs; RxMap> contactsByPhoneNumber = >{}.obs; var contactCount = 0; // RxMap> contactsByPhoneNumber = >{}.obs; // 存储选中的联系人ID final RxSet selectedContacts = {}.obs; @override void onInit() { // TODO: implement onInit super.onInit(); loadDuplicateContacts(); } // 按共享电话号码分组联系人 Map> groupContactsBySharedPhones( List contacts) { final UnionFind uf = UnionFind(); final Map> phoneToContactsMap = {}; // 获取所有联系人 List contacts = await FlutterContacts.getContacts( withProperties: true, withPhoto: true, ); // 遍历所有联系人,建立电话号码与联系人的映射 for (var contact in contacts) { for (var phone in contact.phones) { if (!phoneToContactsMap.containsKey(phone.number)) { phoneToContactsMap[phone.number] = []; } phoneToContactsMap[phone.number]!.add(contact); } } // 按名字的首字母排序 contacts .sort((a, b) => (a.displayName ?? '').compareTo(b.displayName ?? '')); // 合并拥有相同电话号码的联系人 for (var phone in phoneToContactsMap.keys) { final contactList = phoneToContactsMap[phone]!; for (var i = 1; i < contactList.length; i++) { uf.union(contactList[0], contactList[i]); } } // 整理分组结果 final Map> groupedContacts = {}; for (var contact in contacts) { if (contact.phones.isNotEmpty) { for (var phone in contact.phones) { final phoneNumber = phone.number; if (phoneNumber.isNotEmpty) { if (!groupedContacts.containsKey(phoneNumber)) { groupedContacts[phoneNumber] = []; } groupedContacts[phoneNumber]!.add(contact); } } final root = uf.find(contact); if (!groupedContacts.containsKey(root)) { groupedContacts[root] = []; } groupedContacts[root]!.add(contact); } Map> tempContacts = {}; Map> tempContacts = {}; tempContacts.addAll(groupedContacts); for (var key in groupedContacts.keys) { if (groupedContacts[key]?.length == 1) { tempContacts.remove(key); } } contactsByPhoneNumber.value = tempContacts; return tempContacts; } Future loadDuplicateContacts() async { Map> groupedContacts = {}; // 获取所有联系人 List contacts = await FlutterContacts.getContacts( withProperties: true, withPhoto: true, ); // 按名字的首字母排序 contacts .sort((a, b) => (a.displayName ?? '').compareTo(b.displayName ?? '')); final duplicateContact = groupContactsBySharedPhones(contacts); // for (var contact in contacts) { // if (contact.phones.isNotEmpty) { // for (var phone in contact.phones) { // final phoneNumber = phone.number; // // if (phoneNumber.isNotEmpty) { // if (!groupedContacts.containsKey(phoneNumber)) { // groupedContacts[phoneNumber] = []; // } // groupedContacts[phoneNumber]!.add(contact); // } // } // } // } // // Map> tempContacts = {}; // tempContacts.addAll(groupedContacts); // for (var key in groupedContacts.keys) { // if (groupedContacts[key]?.length == 1) { // tempContacts.remove(key); // } // } contactsByPhoneNumber.value = duplicateContact; contactCount = 0; for (var key in contactsByPhoneNumber.keys) { if (contactsByPhoneNumber[key] != null) { contactCount += contactsByPhoneNumber[key]!.length; } } } // 选择/取消选择联系人 void toggleSelectContact(Contact contact) { // final asset = ContactState.contactList.firstWhere((contact) => contact.id == selectContact.id); final contacts = contactsByPhoneNumber[contact]; if (contacts != null) { for (var contact in contacts) { if (selectedContacts.contains(contact.id)) { selectedContacts.remove(contact.id); } else { selectedContacts.add(contact.id); } } } // 更新全选状态 isAllSelected.value = selectedContacts.length == contactCount; } // 全选/取消全选 void toggleSelectAll() { if (isAllSelected.value) { selectedContacts.clear(); } else { for (var key in contactsByPhoneNumber.keys) { if (contactsByPhoneNumber[key] != null) { for (var contact in contactsByPhoneNumber[key]!) { selectedContacts.add(contact.id); } } } } isAllSelected.value = !isAllSelected.value; } // 退出编辑模式时清空选择 void exitEditMode() { isEdit.value = false; selectedContacts.clear(); isAllSelected.value = false; } // 合并联系人 Future mergeBtnClick(List contacts) async { if (!userRepository.isVip()) { StorePage.start(); return; } LoadingDialog.show(displayTime: 100); Contact newContact = contacts.first; for (var contact in contacts) { if (contact != newContact) { for (var phone in contact.phones) { var canAdd = true; for (var newPhone in newContact.phones) { if (phone.number == newPhone.number) { canAdd = false; } } if (canAdd) { newContact.phones.add(phone); } } if (newContact.thumbnail == null) { if (contact.thumbnail != null) { newContact.thumbnail = contact.thumbnail; } } if (newContact.photo == null) { if (contact.photo != null) { newContact.photo = contact.photo; } } if (newContact.name.first.isEmpty) { if (contact.name.first.isNotEmpty) { newContact.name.first = contact.name.first; } } if (newContact.name.last.isEmpty) { if (contact.name.last.isNotEmpty) { newContact.name.last = contact.name.last; } } if (newContact.name.last.isEmpty) { if (contact.name.last.isNotEmpty) { newContact.name.last = contact.name.last; } } if (contact.emails.isNotEmpty) { for (var email in contact.emails) { newContact.emails.add(email); } } if (contact.addresses.isNotEmpty) { for (var address in contact.addresses) { newContact.addresses.add(address); } } if (contact.organizations.isNotEmpty) { for (var organization in contact.organizations) { newContact.organizations.add(organization); } } if (contact.websites.isNotEmpty) { for (var website in contact.websites) { newContact.websites.add(website); } } if (contact.socialMedias.isNotEmpty) { for (var socialMedia in contact.socialMedias) { newContact.socialMedias.add(socialMedia); } } if (contact.events.isNotEmpty) { for (var event in contact.events) { newContact.events.add(event); } } if (contact.notes.isNotEmpty) { for (var note in contact.notes) { newContact.notes.add(note); } } if (contact.groups.isNotEmpty) { for (var group in contact.groups) { newContact.groups.add(group); } } } } for (var contact in contacts) { await contact.delete(); } newContact.id = ""; await FlutterContacts.insertContact(newContact); exitEditMode(); await loadDuplicateContacts(); ToastUtil.show("Merge Successful"); } void deleteBtnClick() { // 获取要删除的资产 final contactToDelete = ContactState.contactList .where((contact) => selectedContacts.contains(contact.id)) .toList(); LoadingDialog.show(displayTime: 100); for (var contact in contactToDelete) { contact.delete(); } ToastUtil.show("Successful"); exitEditMode(); ContactState.loadContacts(); } // 统计联系人的信息数量 int _countContactInfo(Contact contact) { int count = 0; // 统计姓名 if (contact.name.first.isNotEmpty || contact.name.last.isNotEmpty) { count++; } // 统计电话号码 if (contact.phones.isNotEmpty) { count += contact.phones.length; } // 统计电子邮件 if (contact.emails.isNotEmpty) { count += contact.emails.length; } // 统计地址 if (contact.addresses.isNotEmpty) { count += contact.addresses.length; } if (contact.events.isNotEmpty) { count += contact.events.length; } if (contact.notes.isNotEmpty) { count += contact.notes.length; } if (contact.socialMedias.isNotEmpty) { count += contact.socialMedias.length; } if (contact.websites.isNotEmpty) { count += contact.websites.length; } if (contact.organizations.isNotEmpty) { count += contact.organizations.length; } // 统计图片 if (contact.photo != null) { if (contact.photo!.isNotEmpty) { count++; } } return count; } } // 并查集类 class UnionFind { final Map _parent = {}; // 查找根节点 Contact find(Contact contact) { if (!_parent.containsKey(contact)) { _parent[contact] = contact; } else if (_parent[contact] != contact) { _parent[contact] = find(_parent[contact]!); // 路径压缩 } return _parent[contact]!; } // 合并两个集合 void union(Contact a, Contact b) { final rootA = find(a); final rootB = find(b); if (rootA != rootB) { _parent[rootB] = rootA; } } }