controller.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import 'package:clean/base/base_controller.dart';
  2. import 'package:clean/module/contact/contact_state.dart';
  3. import 'package:flutter/widgets.dart';
  4. import 'package:flutter_contacts/contact.dart';
  5. import 'package:get/get.dart';
  6. import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
  7. import '../../../utils/toast_util.dart';
  8. class ContactInCompleteController extends BaseController {
  9. // 存储不符合要求的联系人
  10. final RxList<Contact> filteredContacts = <Contact>[].obs;
  11. // 存储联系人按首字母分组
  12. final RxMap<String, List<Contact>> groupedContacts =
  13. <String, List<Contact>>{}.obs;
  14. // 存储联系人首字母
  15. final RxList<String> initials = <String>[].obs;
  16. // 是否全选
  17. final RxBool isAllSelected = false.obs;
  18. // 存储选中的联系人
  19. final RxSet<String> selectedContacts = <String>{}.obs;
  20. final ItemScrollController itemScrollController = ItemScrollController();
  21. final ItemPositionsListener itemPositionsListener =
  22. ItemPositionsListener.create();
  23. // isEdit
  24. final RxBool isEdit = false.obs;
  25. @override
  26. void onInit()async {
  27. super.onInit();
  28. }
  29. @override
  30. void onReady() {
  31. // TODO: implement onReady
  32. super.onReady();
  33. filterContacts();
  34. groupContacts();
  35. }
  36. // 过滤联系人
  37. void filterContacts() {
  38. filteredContacts.value = ContactState.contactList.where((contact) {
  39. final hasValidPhone =
  40. contact.phones.any((p) => isValidPhoneNumber(p.number ?? ''));
  41. return contact.phones.isEmpty || !hasValidPhone;
  42. }).toList();
  43. }
  44. bool isValidPhoneNumber(String phone) {
  45. // 如果电话号码为空,则返回false
  46. if (phone.isEmpty) return false;
  47. // 如果电话号码不是数字、空格、+号,则返回false
  48. return RegExp(r'^\+?[0-9 -]+$').hasMatch(phone);
  49. }
  50. Future<void> deleteBtnClick() async {
  51. print("deleteBtnClick selectedContacts: $selectedContacts");
  52. final contactToDelete = ContactState.contactList
  53. .where((contact) => selectedContacts.contains(contact.id))
  54. .toList();
  55. for (var contact in contactToDelete) {
  56. await contact.delete(); // 删除操作必须 `await`
  57. }
  58. ToastUtil.show("删除成功");
  59. exitEditMode();
  60. await ContactState.loadContacts(); // 确保联系人列表更新
  61. filterContacts(); // 重新筛选联系人
  62. groupContacts(); // 重新分组
  63. debugPrint("filteredContacts.length: ${filteredContacts.length}");
  64. }
  65. // 全选/取消全选
  66. void toggleSelectAll() {
  67. if (isAllSelected.value) {
  68. selectedContacts.clear();
  69. } else {
  70. selectedContacts
  71. .addAll(filteredContacts.map((contact) => contact.id));
  72. }
  73. isAllSelected.value = !isAllSelected.value;
  74. }
  75. // 退出编辑模式时清空选择
  76. void exitEditMode() {
  77. isEdit.value = false;
  78. selectedContacts.clear();
  79. isAllSelected.value = false;
  80. }
  81. // 滚动到指定首字母
  82. void groupContacts() {
  83. final Map<String, List<Contact>> map = {};
  84. for (var contact in filteredContacts) {
  85. final initial = contact.displayName.isNotEmpty == true
  86. ? contact.displayName[0].toUpperCase()
  87. : '#';
  88. map.putIfAbsent(initial, () => []).add(contact);
  89. }
  90. final sortedKeys = map.keys.toList()..sort();
  91. groupedContacts.value =
  92. Map.fromEntries(sortedKeys.map((key) => MapEntry(key, map[key]!)));
  93. initials.value = sortedKeys;
  94. }
  95. void scrollToInitial(String initial) {
  96. int index = ContactState.initials.indexOf(initial);
  97. if (index != -1) {
  98. final positions = itemPositionsListener.itemPositions.value;
  99. final isVisible = positions.any((position) => position.index == index);
  100. if (!isVisible) {
  101. itemScrollController.scrollTo(
  102. index: index,
  103. duration: Duration(milliseconds: 300),
  104. );
  105. }
  106. }
  107. }
  108. void toggleSelectContact(Contact selectContact) {
  109. print("selectContact: ${selectContact.displayName}");
  110. if (selectedContacts.contains(selectContact.id)) {
  111. selectedContacts.remove(selectContact.id);
  112. } else {
  113. selectedContacts.add(selectContact.id);
  114. }
  115. isAllSelected.value = selectedContacts.length == filteredContacts.length;
  116. }
  117. }