diff --git a/macless_haystack/lib/accessory/accessory_registry.dart b/macless_haystack/lib/accessory/accessory_registry.dart index 1880ab3..f35ba33 100644 --- a/macless_haystack/lib/accessory/accessory_registry.dart +++ b/macless_haystack/lib/accessory/accessory_registry.dart @@ -14,7 +14,7 @@ const accessoryStorageKey = 'ACCESSORIES'; const historStorageKey = 'HISTORY'; class AccessoryRegistry extends ChangeNotifier { - var _storage = const FlutterSecureStorage(); + var _storage = const FlutterSecureStorage(); List _accessories = []; bool loading = false; bool initialLoadFinished = false; @@ -55,7 +55,8 @@ class AccessoryRegistry extends ChangeNotifier { notifyListeners(); } - set setStorage(FlutterSecureStorage s){ + + set setStorage(FlutterSecureStorage s) { _storage = s; } @@ -224,10 +225,12 @@ class AccessoryRegistry extends ChangeNotifier { if (decryptedReports.isNotEmpty) { var lastReport = decryptedReports[decryptedReports.length - 1]; var oldTs = accessory.datePublished; - accessory.lastLocation = - LatLng(lastReport.latitude!, lastReport.longitude!); - accessory.datePublished = lastReport.timestamp ?? lastReport.published; - if (oldTs == null || !oldTs.isAtSameMomentAs(accessory.datePublished!)) { + var latestReportTS = lastReport.timestamp ?? lastReport.published; + if (oldTs == null || oldTs.isBefore(latestReportTS!)) { + //only an actualization if oldTS is not set or is older than the latest of the new ones + accessory.lastLocation = + LatLng(lastReport.latitude!, lastReport.longitude!); + accessory.datePublished = latestReportTS; notifyListeners(); //redraw the UI, if the timestamp has changed } } diff --git a/macless_haystack/test/accessory/accessory_registry_test.dart b/macless_haystack/test/accessory/accessory_registry_test.dart index 8df1785..ece58ea 100644 --- a/macless_haystack/test/accessory/accessory_registry_test.dart +++ b/macless_haystack/test/accessory/accessory_registry_test.dart @@ -21,13 +21,15 @@ void main() { id: '', name: '', hashedPublicKey: '', - datePublished: DateTime.now(), + datePublished: null, additionalKeys: List.empty()); setUp(() { when(locationModel.getAddress(any)) .thenAnswer((_) async => const Placemark()); registry.setStorage = MockFlutterSecureStorage(); accessory.locationModel = locationModel; + accessory.locationHistory.clear(); + accessory.datePublished = null; }); test('Add location history same location unsorted with no entries before', @@ -65,32 +67,7 @@ void main() { test( 'Add location history different location unsorted with no entries before', () async { - List reports = []; - // 8 o'clock 1st location - reports.add(FindMyLocationReport.withHash( - 1, - 2, - DateTime(2024, 1, 1, 8, 0, 0), - DateTime.now().microsecondsSinceEpoch.toString())); - //10 o'clock second location - reports.add(FindMyLocationReport.withHash( - 2, - 2, - DateTime(2024, 1, 1, 10, 0, 0), - DateTime.now().microsecondsSinceEpoch.toString())); - // 9 o'clock first location - reports.add(FindMyLocationReport.withHash( - 1, - 2, - DateTime(2024, 1, 1, 9, 0, 0), - DateTime.now().microsecondsSinceEpoch.toString())); - //12 o'clock 1st location - reports.add(FindMyLocationReport.withHash( - 1, - 2, - DateTime(2024, 1, 1, 12, 0, 0), - DateTime.now().microsecondsSinceEpoch.toString())); - await registry.fillLocationHistory(reports, accessory); + await fillDefaultLocations(registry, accessory); var locationHistory = accessory.locationHistory; expect(3, locationHistory.length); @@ -114,35 +91,68 @@ void main() { test('Add same location entries twice should not change latest anything', () async { - List reports = []; + List reports = + await fillDefaultLocations(registry, accessory); + reports.shuffle(); + await registry.fillLocationHistory(reports, accessory); + var locationHistory = accessory.locationHistory; + expect(3, locationHistory.length); - // 8 o'clock 1st location - reports.add(FindMyLocationReport.withHash( - 1, - 2, - DateTime(2024, 1, 1, 8, 0, 0), - DateTime.now().microsecondsSinceEpoch.toString())); - //10 o'clock second location - reports.add(FindMyLocationReport.withHash( - 2, - 2, - DateTime(2024, 1, 1, 10, 0, 0), - DateTime.now().microsecondsSinceEpoch.toString())); - // 9 o'clock first location + var latest = accessory.datePublished; + var lastLocation = accessory.lastLocation; + var endOfFirstEntry = accessory.latestHistoryEntry(); + + expect(endOfFirstEntry, DateTime(2024, 1, 1, 9, 0, 0)); + expect(latest, DateTime(2024, 1, 1, 12, 0, 0)); + expect(lastLocation, const LatLng(1, 2)); + + expect(locationHistory.elementAt(0).start, DateTime(2024, 1, 1, 8, 0, 0)); + expect(locationHistory.elementAt(0).end, DateTime(2024, 1, 1, 9, 0, 0)); + + expect(locationHistory.elementAt(1).start, DateTime(2024, 1, 1, 10, 0, 0)); + expect(locationHistory.elementAt(1).end, DateTime(2024, 1, 1, 10, 0, 0)); + + expect(locationHistory.elementAt(2).start, DateTime(2024, 1, 1, 12, 0, 0)); + expect(locationHistory.elementAt(2).end, DateTime(2024, 1, 1, 12, 0, 0)); + }); + + test( + 'Add same location at the end should expand and change latestLocationTimestamp', + () async { + List reports = + await fillDefaultLocations(registry, accessory); + reports.clear(); reports.add(FindMyLocationReport.withHash( 1, 2, - DateTime(2024, 1, 1, 9, 0, 0), + DateTime(2024, 1, 2, 8, 0, 0), DateTime.now().microsecondsSinceEpoch.toString())); - //12 o'clock 1st location + await registry.fillLocationHistory(reports, accessory); + var locationHistory = accessory.locationHistory; + expect(3, locationHistory.length); + + var latest = accessory.datePublished; + var lastLocation = accessory.lastLocation; + var endOfFirstEntry = accessory.latestHistoryEntry(); + + expect(endOfFirstEntry, DateTime(2024, 1, 1, 9, 0, 0)); + expect(latest, DateTime(2024, 1, 2, 8, 0, 0)); + expect(lastLocation, const LatLng(1, 2)); + + expect(locationHistory.elementAt(2).start, DateTime(2024, 1, 1, 12, 0, 0)); + expect(locationHistory.elementAt(2).end, DateTime(2024, 1, 2, 8, 0, 0)); + }); + + test('Add same location in the middle should not change anything', () async { + List reports = + await fillDefaultLocations(registry, accessory); + reports.clear(); reports.add(FindMyLocationReport.withHash( 1, 2, - DateTime(2024, 1, 1, 12, 0, 0), + DateTime(2024, 1, 1, 8, 30, 0), DateTime.now().microsecondsSinceEpoch.toString())); await registry.fillLocationHistory(reports, accessory); - reports.shuffle(); - await registry.fillLocationHistory(reports, accessory); var locationHistory = accessory.locationHistory; expect(3, locationHistory.length); @@ -154,13 +164,67 @@ void main() { expect(latest, DateTime(2024, 1, 1, 12, 0, 0)); expect(lastLocation, const LatLng(1, 2)); - expect(locationHistory.elementAt(0).start, DateTime(2024, 1, 1, 8, 0, 0)); - expect(locationHistory.elementAt(0).end, DateTime(2024, 1, 1, 9, 0, 0)); - - expect(locationHistory.elementAt(1).start, DateTime(2024, 1, 1, 10, 0, 0)); - expect(locationHistory.elementAt(1).end, DateTime(2024, 1, 1, 10, 0, 0)); - expect(locationHistory.elementAt(2).start, DateTime(2024, 1, 1, 12, 0, 0)); expect(locationHistory.elementAt(2).end, DateTime(2024, 1, 1, 12, 0, 0)); }); + + test( + 'Add other location at the end should create new entry and change latestLocationTimestamp', + () async { + List reports = + await fillDefaultLocations(registry, accessory); + reports.clear(); + reports.add(FindMyLocationReport.withHash( + 1, + 3, + DateTime(2024, 1, 2, 8, 0, 0), + DateTime.now().microsecondsSinceEpoch.toString())); + await registry.fillLocationHistory(reports, accessory); + var locationHistory = accessory.locationHistory; + expect(4, locationHistory.length); + + var latest = accessory.datePublished; + var lastLocation = accessory.lastLocation; + var endOfFirstEntry = accessory.latestHistoryEntry(); + + expect(endOfFirstEntry, DateTime(2024, 1, 1, 9, 0, 0)); + expect(latest, DateTime(2024, 1, 2, 8, 0, 0)); + expect(lastLocation, const LatLng(1, 3)); + + expect(locationHistory.elementAt(3).start, DateTime(2024, 1, 2, 8, 0, 0)); + expect(locationHistory.elementAt(3).end, DateTime(2024, 1, 2, 8, 0, 0)); + }); +} + +/// +/// Create default entries +/// LAT | Lon | start | end +/// 1 2 8 - 9 +/// 2 2 10 - 10 +/// 1 2 12 - 12 +/// +Future> fillDefaultLocations( + AccessoryRegistry registry, Accessory accessory) async { + List reports = []; + + // 8 o'clock 1st location + reports.add(FindMyLocationReport.withHash(1, 2, DateTime(2024, 1, 1, 8, 0, 0), + DateTime.now().microsecondsSinceEpoch.toString())); + //10 o'clock second location + reports.add(FindMyLocationReport.withHash( + 2, + 2, + DateTime(2024, 1, 1, 10, 0, 0), + DateTime.now().microsecondsSinceEpoch.toString())); + // 9 o'clock first location + reports.add(FindMyLocationReport.withHash(1, 2, DateTime(2024, 1, 1, 9, 0, 0), + DateTime.now().microsecondsSinceEpoch.toString())); + //12 o'clock 1st location + reports.add(FindMyLocationReport.withHash( + 1, + 2, + DateTime(2024, 1, 1, 12, 0, 0), + DateTime.now().microsecondsSinceEpoch.toString())); + await registry.fillLocationHistory(reports, accessory); + return reports; }