From 1a64075027aed63a8c39372cf6f9f6eaebb7e24e Mon Sep 17 00:00:00 2001 From: Fynn Petersen-Frey <10599762+fyfrey@users.noreply.github.com> Date: Sat, 15 Apr 2023 03:50:58 +0200 Subject: [PATCH] fix(mobile): fix asset removal edge cases (#2251) Co-authored-by: Fynn Petersen-Frey Co-authored-by: Alex --- mobile/lib/shared/services/sync.service.dart | 3 ++ mobile/lib/utils/builtin_extensions.dart | 17 +++++++++++ mobile/test/builtin_extensions_text.dart | 31 ++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/mobile/lib/shared/services/sync.service.dart b/mobile/lib/shared/services/sync.service.dart index 432b79b999..41db14f585 100644 --- a/mobile/lib/shared/services/sync.service.dart +++ b/mobile/lib/shared/services/sync.service.dart @@ -9,6 +9,7 @@ import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/models/user.dart'; import 'package:immich_mobile/shared/providers/db.provider.dart'; import 'package:immich_mobile/utils/async_mutex.dart'; +import 'package:immich_mobile/utils/builtin_extensions.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/tuple.dart'; import 'package:isar/isar.dart'; @@ -674,7 +675,9 @@ Pair, List> _handleAssetRemoval( return const Pair([], []); } deleteCandidates.sort(Asset.compareById); + deleteCandidates.uniqueConsecutive((a) => a.id); existing.sort(Asset.compareById); + existing.uniqueConsecutive((a) => a.id); final triple = _diffAssets( existing, deleteCandidates, diff --git a/mobile/lib/utils/builtin_extensions.dart b/mobile/lib/utils/builtin_extensions.dart index da02bf8e70..9be774c527 100644 --- a/mobile/lib/utils/builtin_extensions.dart +++ b/mobile/lib/utils/builtin_extensions.dart @@ -18,3 +18,20 @@ extension DurationExtension on String { return int.parse(this); } } + +extension ListExtension on List { + List uniqueConsecutive([T Function(E element)? key]) { + key ??= (E e) => e as T; + int i = 1, j = 1; + for (; i < length; i++) { + if (key(this[i]) != key(this[i - 1])) { + if (i != j) { + this[j] = this[i]; + } + j++; + } + } + length = length == 0 ? 0 : j; + return this; + } +} diff --git a/mobile/test/builtin_extensions_text.dart b/mobile/test/builtin_extensions_text.dart index 4f5e7aa75d..9e4924e44e 100644 --- a/mobile/test/builtin_extensions_text.dart +++ b/mobile/test/builtin_extensions_text.dart @@ -15,4 +15,35 @@ void main() { expect("a:b:c".toDuration(), null); }); }); + group('Test uniqueConsecutive', () { + test('empty', () { + final a = []; + expect(a.uniqueConsecutive(), []); + }); + + test('singleElement', () { + final a = [5]; + expect(a.uniqueConsecutive(), [5]); + }); + + test('noDuplicates', () { + final a = [1, 2, 3]; + expect(a.uniqueConsecutive(), [1, 2, 3]); + }); + + test('unsortedDuplicates', () { + final a = [1, 2, 1, 3]; + expect(a.uniqueConsecutive(), [1, 2, 1, 3]); + }); + + test('sortedDuplicates', () { + final a = [6, 6, 2, 3, 3, 3, 4, 5, 1, 1]; + expect(a.uniqueConsecutive(), [6, 2, 3, 4, 5, 1]); + }); + + test('withKey', () { + final a = ["a", "bb", "cc", "ddd"]; + expect(a.uniqueConsecutive((s) => s.length), ["a", "bb", "ddd"]); + }); + }); }