LCOV - code coverage report
Current view: top level - lib/models - contactlist.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 68 0.0 %
Date: 2024-11-29 23:41:39 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:cwtch/config.dart';
       2             : import 'package:flutter/widgets.dart';
       3             : 
       4             : import 'contact.dart';
       5             : import 'profileservers.dart';
       6             : 
       7             : class ContactListState extends ChangeNotifier {
       8             :   ProfileServerListState? servers;
       9             :   List<ContactInfoState> _contacts = [];
      10           0 :   int get num => _contacts.length;
      11             : 
      12           0 :   void connectServers(ProfileServerListState servers) {
      13           0 :     this.servers = servers;
      14             :   }
      15             : 
      16           0 :   void addAll(Iterable<ContactInfoState> newContacts) {
      17           0 :     _contacts.addAll(newContacts);
      18           0 :     servers?.clearGroups();
      19           0 :     _contacts.forEach((contact) {
      20           0 :       if (contact.isGroup) {
      21           0 :         servers?.addGroup(contact);
      22             :       }
      23             :     });
      24           0 :     resort();
      25           0 :     notifyListeners();
      26             :   }
      27             : 
      28           0 :   void add(ContactInfoState newContact) {
      29           0 :     _contacts.add(newContact);
      30           0 :     if (newContact.isGroup) {
      31             :       // Copy the current known antispam value for the server
      32             :       // to the new contact. This lets us send messages straight away without
      33             :       // waiting for another update (or restarting the peer)...
      34             :       // Note for NEW servers we expect TokenServerInfo events to arrive after adding the group
      35             :       // this flow is only for existing servers...
      36             :       // FIXME: in Cwtch 1.14
      37             :       // NOTE: This is a bit hacky. Ideally this information would be stored per
      38             :       // Server not per Group, and creating a group would also trigger sharing
      39             :       // this information...on the backend all the accounting is done correctly.
      40           0 :       var otherGroups = servers?.getServer(newContact.server ?? "")?.groups;
      41           0 :       if (otherGroups != null && otherGroups.isNotEmpty) {
      42           0 :         EnvironmentConfig.debugLog("sharing antispam tickets to new group. FIXME: in Cwtch 1.14");
      43           0 :         var antispamTickets = otherGroups[0].antispamTickets;
      44           0 :         _contacts.last.antispamTickets = antispamTickets;
      45             :       }
      46           0 :       servers?.addGroup(newContact);
      47             :     }
      48           0 :     resort();
      49           0 :     notifyListeners();
      50             :   }
      51             : 
      52           0 :   void resort() {
      53           0 :     _contacts.sort((ContactInfoState a, ContactInfoState b) {
      54             :       // return -1 = a first in list
      55             :       // return 1 = b first in list
      56             : 
      57             :       // pinned contacts first
      58           0 :       if (a.pinned != true && b.pinned == true) return 1;
      59           0 :       if (a.pinned == true && b.pinned != true) return -1;
      60             :       // blocked contacts last
      61           0 :       if (a.isBlocked == true && b.isBlocked != true) return 1;
      62           0 :       if (a.isBlocked != true && b.isBlocked == true) return -1;
      63             :       // archive is next...
      64           0 :       if (!a.isArchived && b.isArchived) return -1;
      65           0 :       if (a.isArchived && !b.isArchived) return 1;
      66             : 
      67             :       // unapproved top
      68           0 :       if (a.isInvitation && !b.isInvitation) return -1;
      69           0 :       if (!a.isInvitation && b.isInvitation) return 1;
      70             : 
      71             :       // special sorting for contacts with no messages in either history
      72           0 :       if (a.lastMessageReceivedTime.millisecondsSinceEpoch == 0 && b.lastMessageReceivedTime.millisecondsSinceEpoch == 0) {
      73             :         // online contacts first
      74           0 :         if (a.isOnline() && !b.isOnline()) return -1;
      75           0 :         if (!a.isOnline() && b.isOnline()) return 1;
      76             :         // finally resort to onion
      77           0 :         return a.onion.toString().compareTo(b.onion.toString());
      78             :       }
      79             :       // finally... most recent history first
      80           0 :       if (a.lastMessageReceivedTime.millisecondsSinceEpoch == 0) return 1;
      81           0 :       if (b.lastMessageReceivedTime.millisecondsSinceEpoch == 0) return -1;
      82           0 :       return b.lastMessageReceivedTime.compareTo(a.lastMessageReceivedTime);
      83             :     });
      84             :     //<todo> if(changed) {
      85           0 :     notifyListeners();
      86             :     //} </todo>
      87             :   }
      88             : 
      89           0 :   void updateLastMessageReceivedTime(int forIdentifier, DateTime newMessageTime) {
      90           0 :     var contact = getContact(forIdentifier);
      91             :     if (contact == null) return;
      92             : 
      93             :     // Assert that the new time is after the current last message time AND that
      94             :     // new message time is before the current time.
      95           0 :     if (newMessageTime.isAfter(contact.lastMessageReceivedTime)) {
      96           0 :       if (newMessageTime.isBefore(DateTime.now().toLocal())) {
      97           0 :         contact.lastMessageReceivedTime = newMessageTime;
      98             :       } else {
      99             :         // Otherwise set the last message time to now...
     100           0 :         contact.lastMessageReceivedTime = DateTime.now().toLocal();
     101             :       }
     102           0 :       resort();
     103             :     }
     104             :   }
     105             : 
     106           0 :   List<ContactInfoState> get contacts => _contacts.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
     107             : 
     108           0 :   ContactInfoState? getContact(int identifier) {
     109           0 :     int idx = _contacts.indexWhere((element) => element.identifier == identifier);
     110           0 :     return idx >= 0 ? _contacts[idx] : null;
     111             :   }
     112             : 
     113           0 :   void removeContact(int identifier) {
     114           0 :     int idx = _contacts.indexWhere((element) => element.identifier == identifier);
     115           0 :     if (idx >= 0) {
     116           0 :       _contacts.removeAt(idx);
     117           0 :       notifyListeners();
     118             :     }
     119             :   }
     120             : 
     121           0 :   void removeContactByHandle(String handle) {
     122           0 :     int idx = _contacts.indexWhere((element) => element.onion == handle);
     123           0 :     _contacts.removeAt(idx);
     124           0 :     notifyListeners();
     125             :   }
     126             : 
     127           0 :   ContactInfoState? findContact(String byHandle) {
     128           0 :     int idx = _contacts.indexWhere((element) => element.onion == byHandle);
     129           0 :     return idx >= 0 ? _contacts[idx] : null;
     130             :   }
     131             : 
     132           0 :   void newMessage(int identifier, int messageID, DateTime timestamp, String senderHandle, String senderImage, bool isAuto, String data, String contenthash, bool selectedConversation) {
     133           0 :     getContact(identifier)?.newMessage(identifier, messageID, timestamp, senderHandle, senderImage, isAuto, data, contenthash, selectedConversation);
     134           0 :     updateLastMessageReceivedTime(identifier, DateTime.now());
     135             :   }
     136             : 
     137           0 :   int cacheMemUsage() {
     138           0 :     return _contacts.map((e) => e.messageCache.size()).fold(0, (previousValue, element) => previousValue + element);
     139             :   }
     140             : }

Generated by: LCOV version 1.14