2023-06-10 20:13:59 +02:00
|
|
|
import 'dart:typed_data';
|
|
|
|
|
2023-05-17 19:36:02 +02:00
|
|
|
import 'package:collection/collection.dart';
|
2024-01-06 05:02:16 +02:00
|
|
|
import 'package:immich_mobile/shared/models/asset.dart';
|
|
|
|
import 'package:immich_mobile/shared/models/user.dart';
|
2023-05-17 19:36:02 +02:00
|
|
|
|
2023-04-15 03:50:58 +02:00
|
|
|
extension ListExtension<E> on List<E> {
|
2023-06-10 20:13:59 +02:00
|
|
|
List<E> uniqueConsecutive({
|
|
|
|
int Function(E a, E b)? compare,
|
|
|
|
void Function(E a, E b)? onDuplicate,
|
|
|
|
}) {
|
|
|
|
compare ??= (E a, E b) => a == b ? 0 : 1;
|
2023-04-15 03:50:58 +02:00
|
|
|
int i = 1, j = 1;
|
|
|
|
for (; i < length; i++) {
|
2023-06-10 20:13:59 +02:00
|
|
|
if (compare(this[i - 1], this[i]) != 0) {
|
2023-04-15 03:50:58 +02:00
|
|
|
if (i != j) {
|
|
|
|
this[j] = this[i];
|
|
|
|
}
|
|
|
|
j++;
|
2023-06-10 20:13:59 +02:00
|
|
|
} else if (onDuplicate != null) {
|
|
|
|
onDuplicate(this[i - 1], this[i]);
|
2023-04-15 03:50:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
length = length == 0 ? 0 : j;
|
|
|
|
return this;
|
|
|
|
}
|
2023-05-17 19:36:02 +02:00
|
|
|
|
|
|
|
ListSlice<E> nestedSlice(int start, int end) {
|
|
|
|
if (this is ListSlice) {
|
|
|
|
final ListSlice<E> self = this as ListSlice<E>;
|
|
|
|
return ListSlice<E>(self.source, self.start + start, self.start + end);
|
|
|
|
}
|
|
|
|
return ListSlice<E>(this, start, end);
|
|
|
|
}
|
2023-04-15 03:50:58 +02:00
|
|
|
}
|
2023-06-10 20:13:59 +02:00
|
|
|
|
|
|
|
extension IntListExtension on Iterable<int> {
|
|
|
|
Int64List toInt64List() {
|
|
|
|
final list = Int64List(length);
|
|
|
|
list.setAll(0, this);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
}
|
2024-01-06 05:02:16 +02:00
|
|
|
|
|
|
|
extension AssetListExtension on Iterable<Asset> {
|
|
|
|
/// Returns the assets that are already available in the Immich server
|
|
|
|
Iterable<Asset> remoteOnly({
|
|
|
|
void Function()? errorCallback,
|
|
|
|
}) {
|
|
|
|
final bool onlyRemote = every((e) => e.isRemote);
|
|
|
|
if (!onlyRemote) {
|
|
|
|
if (errorCallback != null) errorCallback();
|
|
|
|
return where((a) => a.isRemote);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the assets that are owned by the user passed to the [owner] param
|
|
|
|
/// If [owner] is null, an empty list is returned
|
|
|
|
Iterable<Asset> ownedOnly(
|
|
|
|
User? owner, {
|
|
|
|
void Function()? errorCallback,
|
|
|
|
}) {
|
|
|
|
if (owner == null) return [];
|
|
|
|
final userId = owner.isarId;
|
|
|
|
final bool onlyOwned = every((e) => e.ownerId == userId);
|
|
|
|
if (!onlyOwned) {
|
|
|
|
if (errorCallback != null) errorCallback();
|
|
|
|
return where((a) => a.ownerId == userId);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the assets that are present on a file system which has write permission
|
|
|
|
/// This filters out assets on readOnly external library to which we cannot perform any write operation
|
|
|
|
Iterable<Asset> writableOnly({
|
|
|
|
void Function()? errorCallback,
|
|
|
|
}) {
|
|
|
|
final bool onlyWritable = every((e) => !e.isReadOnly);
|
|
|
|
if (!onlyWritable) {
|
|
|
|
if (errorCallback != null) errorCallback();
|
|
|
|
return where((a) => !a.isReadOnly);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Filters out offline assets and returns those that are still accessible by the Immich server
|
|
|
|
Iterable<Asset> nonOfflineOnly({
|
|
|
|
void Function()? errorCallback,
|
|
|
|
}) {
|
|
|
|
final bool onlyLive = every((e) => !e.isOffline);
|
|
|
|
if (!onlyLive) {
|
|
|
|
if (errorCallback != null) errorCallback();
|
|
|
|
return where((a) => !a.isOffline);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
2024-01-15 17:26:13 +02:00
|
|
|
|
|
|
|
extension SortedByProperty<T> on Iterable<T> {
|
|
|
|
Iterable<T> sortedByField(Comparable Function(T e) key) {
|
|
|
|
return sorted((a, b) => key(a).compareTo(key(b)));
|
|
|
|
}
|
|
|
|
}
|