controller.dart 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import 'package:clean/base/base_controller.dart';
  2. import 'package:clean/module/contact/contact_state.dart';
  3. import 'package:clean/utils/toast_util.dart';
  4. import 'package:flutter_contacts/contact.dart';
  5. import 'package:flutter_contacts/flutter_contacts.dart';
  6. import 'package:get/get_rx/src/rx_types/rx_types.dart';
  7. class ContactDuplicateController extends BaseController {
  8. // 是否为编辑状态
  9. RxBool isEdit = false.obs;
  10. // 是否全选
  11. RxBool isAllSelected = false.obs;
  12. RxMap<String, List<Contact>> contactsByPhoneNumber = <String, List<Contact>>{}.obs;
  13. var contactCount = 0;
  14. // RxMap<String, List<Contact>> contactsByPhoneNumber = <String, List<Contact>>{}.obs;
  15. // 存储选中的联系人ID
  16. final RxSet<String> selectedContacts = <String>{}.obs;
  17. @override
  18. void onInit() {
  19. // TODO: implement onInit
  20. super.onInit();
  21. loadDuplicateContacts();
  22. }
  23. Future<void> loadDuplicateContacts() async {
  24. Map<String, List<Contact>> groupedContacts = {};
  25. // 获取所有联系人
  26. List<Contact> contacts = await FlutterContacts.getContacts(
  27. withProperties: true,
  28. withPhoto: true,
  29. );
  30. // 按名字的首字母排序
  31. contacts.sort((a, b) => (a.displayName ?? '').compareTo(b.displayName ?? ''));
  32. for (var contact in contacts) {
  33. if (contact.phones.isNotEmpty) {
  34. for (var phone in contact.phones) {
  35. final phoneNumber = phone.number;
  36. if (phoneNumber.isNotEmpty) {
  37. if (!groupedContacts.containsKey(phoneNumber)) {
  38. groupedContacts[phoneNumber] = [];
  39. }
  40. groupedContacts[phoneNumber]!.add(contact);
  41. }
  42. }
  43. }
  44. }
  45. Map<String, List<Contact>> tempContacts = {};
  46. tempContacts.addAll(groupedContacts);
  47. for (var key in groupedContacts.keys) {
  48. if (groupedContacts[key]?.length == 1) {
  49. tempContacts.remove(key);
  50. }
  51. }
  52. contactsByPhoneNumber.value = tempContacts;
  53. contactCount = 0;
  54. for (var key in contactsByPhoneNumber.keys) {
  55. if (contactsByPhoneNumber[key] != null) {
  56. contactCount += contactsByPhoneNumber[key]!.length;
  57. }
  58. }
  59. }
  60. // 选择/取消选择联系人
  61. void toggleSelectContact(String phoneNumber) {
  62. // final asset = ContactState.contactList.firstWhere((contact) => contact.id == selectContact.id);
  63. final contacts = contactsByPhoneNumber[phoneNumber];
  64. if (contacts != null) {
  65. for (var contact in contacts) {
  66. if (selectedContacts.contains(contact.id)) {
  67. selectedContacts.remove(contact.id);
  68. } else {
  69. selectedContacts.add(contact.id);
  70. }
  71. }
  72. }
  73. // 更新全选状态
  74. isAllSelected.value = selectedContacts.length == contactCount;
  75. }
  76. // 全选/取消全选
  77. void toggleSelectAll() {
  78. if (isAllSelected.value) {
  79. selectedContacts.clear();
  80. } else {
  81. for (var key in contactsByPhoneNumber.keys) {
  82. if (contactsByPhoneNumber[key] != null) {
  83. for (var contact in contactsByPhoneNumber[key]!) {
  84. selectedContacts.add(contact.id);
  85. }
  86. }
  87. }
  88. }
  89. isAllSelected.value = !isAllSelected.value;
  90. }
  91. // 退出编辑模式时清空选择
  92. void exitEditMode() {
  93. isEdit.value = false;
  94. selectedContacts.clear();
  95. isAllSelected.value = false;
  96. }
  97. Future<void> mergeBtnClick(List<Contact> contacts) async {
  98. Contact? contactWithMostInfo;
  99. int maxInfoCount = 0;
  100. for (var contact in contacts) {
  101. final infoCount = _countContactInfo(contact);
  102. if (infoCount > maxInfoCount) {
  103. maxInfoCount = infoCount;
  104. contactWithMostInfo = contact;
  105. }
  106. }
  107. for (var contact in contacts) {
  108. if (contact.id != contactWithMostInfo?.id) {
  109. await contact.delete();
  110. }
  111. }
  112. ToastUtil.show("Successful");
  113. exitEditMode();
  114. await loadDuplicateContacts();
  115. }
  116. void deleteBtnClick() {
  117. // 获取要删除的资产
  118. final contactToDelete =
  119. ContactState.contactList.where((contact) => selectedContacts.contains(contact.id)).toList();
  120. for (var contact in contactToDelete) {
  121. contact.delete();
  122. }
  123. ToastUtil.show("Successful");
  124. exitEditMode();
  125. ContactState.loadContacts();
  126. }
  127. // 统计联系人的信息数量
  128. int _countContactInfo(Contact contact) {
  129. int count = 0;
  130. // 统计姓名
  131. if (contact.name.first.isNotEmpty || contact.name.last.isNotEmpty) {
  132. count++;
  133. }
  134. // 统计电话号码
  135. if (contact.phones.isNotEmpty) {
  136. count += contact.phones.length;
  137. }
  138. // 统计电子邮件
  139. if (contact.emails.isNotEmpty) {
  140. count += contact.emails.length;
  141. }
  142. // 统计地址
  143. if (contact.addresses.isNotEmpty) {
  144. count += contact.addresses.length;
  145. }
  146. if (contact.events.isNotEmpty) {
  147. count += contact.events.length;
  148. }
  149. if (contact.notes.isNotEmpty) {
  150. count += contact.notes.length;
  151. }
  152. if (contact.socialMedias.isNotEmpty) {
  153. count += contact.socialMedias.length;
  154. }
  155. if (contact.websites.isNotEmpty) {
  156. count += contact.websites.length;
  157. }
  158. if (contact.organizations.isNotEmpty) {
  159. count += contact.organizations.length;
  160. }
  161. // 统计图片
  162. if (contact.photo != null) {
  163. if (contact.photo!.isNotEmpty) {
  164. count++;
  165. }
  166. }
  167. return count;
  168. }
  169. }