deprecation: whereNotNull

This commit is contained in:
Thibault Deckers 2024-10-26 00:19:43 +02:00
parent 884baae602
commit 8de8d26756
53 changed files with 82 additions and 101 deletions

@ -1 +1 @@
Subproject commit b1c77b7ed32346fe829c0ca97bd85d19290d54ae
Subproject commit 603104015dd692ea3403755b55d07813d5cf8965

View file

@ -41,7 +41,7 @@ class CountryTopology {
return Map.fromEntries(numericMap.entries.map((kv) {
final code = _countryOfNumeric(kv.key);
return code != null ? MapEntry(code, kv.value) : null;
}).whereNotNull());
}).nonNulls);
}
// returns a map of the given positions by the ISO 3166-1 numeric code of the country containing them

View file

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:convert';
import 'dart:isolate';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
// cf https://github.com/topojson/topojson-specification
@ -60,7 +59,7 @@ class Topology extends TopologyJsonObject {
final name = kv.key;
final geometry = Geometry.build(kv.value);
return geometry != null ? MapEntry(name, geometry) : null;
}).whereNotNull()),
}).nonNulls),
arcs = (data['arcs'] as List).cast<List>().map((arc) => arc.cast<List>().map((position) => position.cast<num>()).toList()).toList(),
transform = data.containsKey('transform') ? Transform.parse((data['transform'] as Map).cast<String, dynamic>()) : null,
super.parse();
@ -238,7 +237,7 @@ class GeometryCollection extends Geometry {
final List<Geometry> geometries;
GeometryCollection.parse(super.data)
: geometries = (data['geometries'] as List).cast<Map<String, dynamic>>().map(Geometry.build).whereNotNull().toList(),
: geometries = (data['geometries'] as List).cast<Map<String, dynamic>>().map(Geometry.build).nonNulls.toList(),
super.parse();
@override

View file

@ -71,7 +71,7 @@ class Package {
currentLabel,
englishLabel,
...ownedDirs,
].whereNotNull().map(normalizePotentialDir).toSet();
].nonNulls.map(normalizePotentialDir).toSet();
static String normalizePotentialDir(String dir) {
return dir.replaceAll('_', ' ').trim().toLowerCase();

View file

@ -146,7 +146,7 @@ class Covers {
if (colorValue != null) 'color': colorValue,
};
})
.whereNotNull()
.nonNulls
.toList();
return jsonList.isNotEmpty ? jsonList : null;
}

View file

@ -1,5 +1,4 @@
import 'package:aves/model/db/db_sqflite.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:sqflite/sqflite.dart';
@ -338,11 +337,11 @@ class LocalMediaDbUpgrader {
// clean duplicates introduced before Aves v1.7.1
final duplicatedContentIdRows = await db.query(entryTable, columns: ['contentId'], groupBy: 'contentId', having: 'COUNT(id) > 1 AND contentId IS NOT NULL');
final duplicatedContentIds = duplicatedContentIdRows.map((row) => row['contentId'] as int?).whereNotNull().toSet();
final duplicatedContentIds = duplicatedContentIdRows.map((row) => row['contentId'] as int?).nonNulls.toSet();
final duplicateIds = <int>{};
await Future.forEach(duplicatedContentIds, (contentId) async {
final rows = await db.query(entryTable, columns: ['id'], where: 'contentId = ?', whereArgs: [contentId]);
final ids = rows.map((row) => row['id'] as int?).whereNotNull().toList()..sort();
final ids = rows.map((row) => row['id'] as int?).nonNulls.toList()..sort();
if (ids.length > 1) {
ids.removeAt(0);
duplicateIds.addAll(ids);

View file

@ -12,7 +12,6 @@ import 'package:aves/theme/format.dart';
import 'package:aves/utils/time_utils.dart';
import 'package:aves_model/aves_model.dart';
import 'package:aves_utils/aves_utils.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
enum EntryDataType { basic, aspectRatio, catalog, address, references }
@ -392,7 +391,7 @@ class AvesEntry with AvesEntryBase {
_addressDetails?.countryName,
_addressDetails?.adminArea,
_addressDetails?.locality,
}.whereNotNull().where((v) => v.isNotEmpty).join(', ');
}.nonNulls.where((v) => v.isNotEmpty).join(', ');
}
Future<void> applyNewFields(Map newFields, {required bool persist}) async {

View file

@ -141,7 +141,7 @@ extension ExtraAvesEntryInfo on AvesEntry {
final rawTags = formatCount.map((key, value) {
final count = value.length;
// remove duplicate names, so number of displayed names may not match displayed count
final names = value.whereNotNull().toSet().toList()..sort(compareAsciiUpperCase);
final names = value.nonNulls.toSet().toList()..sort(compareAsciiUpperCase);
return MapEntry(key, '$count items: ${names.join(', ')}');
});
directories.add(MetadataDirectory('Attachments', _toSortedTags(rawTags)));
@ -157,7 +157,7 @@ extension ExtraAvesEntryInfo on AvesEntry {
if (value.isEmpty) return null;
final tagName = tagKV.key as String;
return MapEntry(tagName, value);
}).whereNotNull()));
}).nonNulls));
return tags;
}
}

View file

@ -58,7 +58,7 @@ class Favourites with ChangeNotifier {
Map<String, List<String>>? export(CollectionSource source) {
final visibleEntries = source.visibleEntries;
final ids = favourites.all;
final paths = visibleEntries.where((entry) => ids.contains(entry.id)).map((entry) => entry.path).whereNotNull().toSet();
final paths = visibleEntries.where((entry) => ids.contains(entry.id)).map((entry) => entry.path).nonNulls.toSet();
final byVolume = groupBy<String, StorageVolume?>(paths, androidFileUtils.getStorageVolume);
final jsonMap = Map.fromEntries(byVolume.entries.map((kv) {
final volume = kv.key?.path;
@ -66,7 +66,7 @@ class Favourites with ChangeNotifier {
final rootLength = volume.length;
final relativePaths = kv.value.map((v) => v.substring(rootLength)).toList();
return MapEntry(volume, relativePaths);
}).whereNotNull());
}).nonNulls);
return jsonMap.isNotEmpty ? jsonMap : null;
}

View file

@ -35,7 +35,7 @@ class OrFilter extends CollectionFilter {
factory OrFilter.fromMap(Map<String, dynamic> json) {
return OrFilter(
(json['filters'] as List).cast<String>().map(CollectionFilter.fromJson).whereNotNull().toSet(),
(json['filters'] as List).cast<String>().map(CollectionFilter.fromJson).nonNulls.toSet(),
reversed: json['reversed'] ?? false,
);
}

View file

@ -210,7 +210,7 @@ class MetadataFieldNamingProcessor extends NamingProcessor {
}
@override
Set<MetadataField> getRequiredFields() => {field}.whereNotNull().toSet();
Set<MetadataField> getRequiredFields() => {field}.nonNulls.toSet();
@override
String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) {
@ -268,7 +268,7 @@ class HashNamingProcessor extends NamingProcessor {
}
@override
Set<MetadataField> getRequiredFields() => {function}.whereNotNull().toSet();
Set<MetadataField> getRequiredFields() => {function}.nonNulls.toSet();
@override
String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) {

View file

@ -2,7 +2,6 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart';
import 'package:aves/widgets/aves_app.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/widgets.dart';
mixin AppSettings on SettingsAccess {
@ -99,15 +98,15 @@ mixin AppSettings on SettingsAccess {
set entryRenamingPattern(String newValue) => set(SettingKeys.entryRenamingPatternKey, newValue);
List<int>? get topEntryIds => getStringList(SettingKeys.topEntryIdsKey)?.map(int.tryParse).whereNotNull().toList();
List<int>? get topEntryIds => getStringList(SettingKeys.topEntryIdsKey)?.map(int.tryParse).nonNulls.toList();
set topEntryIds(List<int>? newValue) => set(SettingKeys.topEntryIdsKey, newValue?.map((id) => id.toString()).whereNotNull().toList());
set topEntryIds(List<int>? newValue) => set(SettingKeys.topEntryIdsKey, newValue?.map((id) => id.toString()).nonNulls.toList());
List<String> get recentDestinationAlbums => getStringList(SettingKeys.recentDestinationAlbumsKey) ?? [];
set recentDestinationAlbums(List<String> newValue) => set(SettingKeys.recentDestinationAlbumsKey, newValue.take(recentFilterHistoryMax).toList());
List<CollectionFilter> get recentTags => (getStringList(SettingKeys.recentTagsKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList();
List<CollectionFilter> get recentTags => (getStringList(SettingKeys.recentTagsKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toList();
set recentTags(List<CollectionFilter> newValue) => set(SettingKeys.recentTagsKey, newValue.take(recentFilterHistoryMax).map((filter) => filter.toJson()).toList());
}

View file

@ -1,7 +1,6 @@
import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin FilterGridsSettings on SettingsAccess {
AlbumChipGroupFactor get albumGroupFactor => getEnumOrDefault(SettingKeys.albumGroupFactorKey, SettingsDefaults.albumGroupFactor, AlbumChipGroupFactor.values);
@ -48,7 +47,7 @@ mixin FilterGridsSettings on SettingsAccess {
set tagSortReverse(bool newValue) => set(SettingKeys.tagSortReverseKey, newValue);
Set<CollectionFilter> get pinnedFilters => (getStringList(SettingKeys.pinnedFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
Set<CollectionFilter> get pinnedFilters => (getStringList(SettingKeys.pinnedFiltersKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
set pinnedFilters(Set<CollectionFilter> newValue) => set(SettingKeys.pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList());

View file

@ -1,7 +1,6 @@
import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin NavigationSettings on SettingsAccess {
bool get mustBackTwiceToExit => getBool(SettingKeys.mustBackTwiceToExitKey) ?? SettingsDefaults.mustBackTwiceToExit;
@ -14,7 +13,7 @@ mixin NavigationSettings on SettingsAccess {
HomePageSetting get homePage => getEnumOrDefault(SettingKeys.homePageKey, SettingsDefaults.homePage, HomePageSetting.values);
Set<CollectionFilter> get homeCustomCollection => (getStringList(SettingKeys.homeCustomCollectionKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
Set<CollectionFilter> get homeCustomCollection => (getStringList(SettingKeys.homeCustomCollectionKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
String? get homeCustomExplorerPath => getString(SettingKeys.homeCustomExplorerPathKey);

View file

@ -1,10 +1,9 @@
import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/modules/search.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin PrivacySettings on SettingsAccess, SearchSettings {
Set<CollectionFilter> get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
Set<CollectionFilter> get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
set hiddenFilters(Set<CollectionFilter> newValue) => set(SettingKeys.hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList());
@ -24,7 +23,7 @@ mixin PrivacySettings on SettingsAccess, SearchSettings {
hiddenFilters = _hiddenFilters;
}
Set<CollectionFilter> get deactivatedHiddenFilters => (getStringList(SettingKeys.deactivatedHiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
Set<CollectionFilter> get deactivatedHiddenFilters => (getStringList(SettingKeys.deactivatedHiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
set deactivatedHiddenFilters(Set<CollectionFilter> newValue) => set(SettingKeys.deactivatedHiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList());

View file

@ -1,14 +1,13 @@
import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin SearchSettings on SettingsAccess {
bool get saveSearchHistory => getBool(SettingKeys.saveSearchHistoryKey) ?? SettingsDefaults.saveSearchHistory;
set saveSearchHistory(bool newValue) => set(SettingKeys.saveSearchHistoryKey, newValue);
List<CollectionFilter> get searchHistory => (getStringList(SettingKeys.searchHistoryKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList();
List<CollectionFilter> get searchHistory => (getStringList(SettingKeys.searchHistoryKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toList();
set searchHistory(List<CollectionFilter> newValue) => set(SettingKeys.searchHistoryKey, newValue.map((filter) => filter.toJson()).toList());
}

View file

@ -243,7 +243,7 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings
set screenSaverInterval(int newValue) => set(SettingKeys.screenSaverIntervalKey, newValue);
Set<CollectionFilter> get screenSaverCollectionFilters => (getStringList(SettingKeys.screenSaverCollectionFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
Set<CollectionFilter> get screenSaverCollectionFilters => (getStringList(SettingKeys.screenSaverCollectionFiltersKey) ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
set screenSaverCollectionFilters(Set<CollectionFilter> newValue) => set(SettingKeys.screenSaverCollectionFiltersKey, newValue.map((filter) => filter.toJson()).toList());
@ -287,7 +287,7 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings
void setWidgetShape(int widgetId, WidgetShape newValue) => set('${SettingKeys.widgetShapePrefixKey}$widgetId', newValue.toString());
Set<CollectionFilter> getWidgetCollectionFilters(int widgetId) => (getStringList('${SettingKeys.widgetCollectionFiltersPrefixKey}$widgetId') ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
Set<CollectionFilter> getWidgetCollectionFilters(int widgetId) => (getStringList('${SettingKeys.widgetCollectionFiltersPrefixKey}$widgetId') ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
void setWidgetCollectionFilters(int widgetId, Set<CollectionFilter> newValue) => set('${SettingKeys.widgetCollectionFiltersPrefixKey}$widgetId', newValue.map((filter) => filter.toJson()).toList());

View file

@ -71,7 +71,7 @@ mixin AlbumMixin on SourceBase {
void addDirectories({required Set<String?> albums, bool notify = true}) {
if (!_directories.containsAll(albums)) {
_directories.addAll(albums.whereNotNull());
_directories.addAll(albums.nonNulls);
_onAlbumChanged(notify: notify);
}
}
@ -119,7 +119,7 @@ mixin AlbumMixin on SourceBase {
} else {
directories ??= {};
if (entries != null) {
directories.addAll(entries.map((entry) => entry.directory).whereNotNull());
directories.addAll(entries.map((entry) => entry.directory).nonNulls);
}
directories.forEach((directory) {
_filterEntryCountMap.remove(directory);
@ -202,7 +202,7 @@ mixin AlbumMixin on SourceBase {
return dirPath;
}
final otherAlbumsOnDevice = _directories.whereNotNull().where((item) => item != dirPath).map((v) => v.toLowerCase()).toSet();
final otherAlbumsOnDevice = _directories.nonNulls.where((item) => item != dirPath).map((v) => v.toLowerCase()).toSet();
final uniqueNameInDevice = unique(dirPath, otherAlbumsOnDevice);
if (uniqueNameInDevice.length <= relativeDir.length) {
return uniqueNameInDevice;

View file

@ -54,7 +54,7 @@ class CollectionLens with ChangeNotifier {
this.stackDevelopedRaws = true,
this.fixedSort = false,
this.fixedSelection,
}) : filters = (filters ?? {}).whereNotNull().toSet(),
}) : filters = (filters ?? {}).nonNulls.toSet(),
burstPatterns = settings.collectionBurstPatterns,
sectionFactor = settings.collectionSectionFactor,
sortFactor = settings.collectionSortFactor,

View file

@ -74,7 +74,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
settings.updateStream.where((event) => event.key == SettingKeys.hiddenFiltersKey).listen((event) {
final oldValue = event.oldValue;
if (oldValue is List<String>?) {
final oldHiddenFilters = (oldValue ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
final oldHiddenFilters = (oldValue ?? []).map(CollectionFilter.fromJson).nonNulls.toSet();
final newlyVisibleFilters = oldHiddenFilters.whereNot(settings.hiddenFilters.contains).toSet();
_onFilterVisibilityChanged(newlyVisibleFilters);
}
@ -337,7 +337,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
final existingEntry = _rawEntries.firstWhereOrNull((entry) => entry.path == targetPath && !entry.trashed);
return existingEntry?.uri;
})
.whereNotNull()
.nonNulls
.toSet();
await removeEntries(replacedUris, includeTrash: false);
@ -367,8 +367,8 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
}
});
await localMediaDb.insertEntries(movedEntries);
await localMediaDb.saveCatalogMetadata(movedEntries.map((entry) => entry.catalogMetadata).whereNotNull().toSet());
await localMediaDb.saveAddresses(movedEntries.map((entry) => entry.addressDetails).whereNotNull().toSet());
await localMediaDb.saveCatalogMetadata(movedEntries.map((entry) => entry.catalogMetadata).nonNulls.toSet());
await localMediaDb.saveAddresses(movedEntries.map((entry) => entry.addressDetails).nonNulls.toSet());
} else {
await Future.forEach<MoveOpEvent>(movedOps, (movedOp) async {
final newFields = movedOp.newFields;
@ -393,7 +393,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
addEntries(movedEntries);
case MoveType.move:
case MoveType.export:
cleanEmptyAlbums(fromAlbums.whereNotNull().toSet());
cleanEmptyAlbums(fromAlbums.nonNulls.toSet());
addDirectories(albums: destinationAlbums);
case MoveType.toBin:
case MoveType.fromBin:

View file

@ -23,7 +23,7 @@ mixin CountryMixin on SourceBase {
} else {
countryCodes ??= {};
if (entries != null) {
countryCodes.addAll(entries.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.countryCode).whereNotNull());
countryCodes.addAll(entries.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.countryCode).nonNulls);
}
countryCodes.forEach((countryCode) {
_filterEntryCountMap.remove(countryCode);

View file

@ -152,9 +152,9 @@ mixin LocationMixin on CountryMixin, StateMixin {
}
void updateLocations() {
final locations = visibleEntries.map((entry) => entry.addressDetails).whereNotNull().toList();
final locations = visibleEntries.map((entry) => entry.addressDetails).nonNulls.toList();
final updatedPlaces = locations.map((address) => address.place).whereNotNull().where((v) => v.isNotEmpty).toSet().toList()..sort(compareAsciiUpperCase);
final updatedPlaces = locations.map((address) => address.place).nonNulls.where((v) => v.isNotEmpty).toSet().toList()..sort(compareAsciiUpperCase);
if (!listEquals(updatedPlaces, sortedPlaces)) {
sortedPlaces = List.unmodifiable(updatedPlaces);
eventBus.fire(PlacesChangedEvent());
@ -195,7 +195,7 @@ mixin LocationMixin on CountryMixin, StateMixin {
final code = getCode(address);
if (code == null || code.isEmpty) return null;
return MapEntry(code, getName(address));
}).whereNotNull());
}).nonNulls);
return namesByCode.entries.map((kv) {
final code = kv.key;
final name = kv.value;

View file

@ -23,7 +23,7 @@ mixin PlaceMixin on SourceBase {
} else {
places ??= {};
if (entries != null) {
places.addAll(entries.map((entry) => entry.addressDetails?.place).whereNotNull());
places.addAll(entries.map((entry) => entry.addressDetails?.place).nonNulls);
}
places.forEach((place) {
_filterEntryCountMap.remove(place);

View file

@ -23,7 +23,7 @@ mixin StateMixin on SourceBase {
} else {
stateCodes ??= {};
if (entries != null) {
stateCodes.addAll(entries.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.stateCode).whereNotNull());
stateCodes.addAll(entries.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.stateCode).nonNulls);
}
stateCodes.forEach((stateCode) {
_filterEntryCountMap.remove(stateCode);

View file

@ -265,11 +265,11 @@ class MediaStoreSource extends CollectionSource {
final contentId = int.tryParse(idString);
if (contentId == null) return null;
return MapEntry(contentId, uri);
}).whereNotNull());
}).nonNulls);
// clean up obsolete entries
final obsoleteContentIds = (await mediaStoreService.checkObsoleteContentIds(changedUriByContentId.keys.toList())).toSet();
final obsoleteUris = obsoleteContentIds.map((contentId) => changedUriByContentId[contentId]).whereNotNull().toSet();
final obsoleteUris = obsoleteContentIds.map((contentId) => changedUriByContentId[contentId]).nonNulls.toSet();
await removeEntries(obsoleteUris, includeTrash: false);
obsoleteContentIds.forEach(changedUriByContentId.remove);

View file

@ -41,7 +41,7 @@ mixin TrashMixin on SourceBase {
Future<Set<AvesEntry>> recoverUntrackedTrashItems() async {
final newEntries = <AvesEntry>{};
final knownPaths = allEntries.map((v) => v.trashDetails?.path).whereNotNull().toSet();
final knownPaths = allEntries.map((v) => v.trashDetails?.path).nonNulls.toSet();
final untrackedPaths = await storageService.getUntrackedTrashPaths(knownPaths);
if (untrackedPaths.isNotEmpty) {
debugPrint('Recovering ${untrackedPaths.length} untracked bin items');

View file

@ -53,7 +53,7 @@ class Vaults extends ChangeNotifier {
}
Future<void> remove(Set<String> dirPaths) async {
final details = dirPaths.map(detailsForPath).whereNotNull().toSet();
final details = dirPaths.map(detailsForPath).nonNulls.toSet();
if (details.isEmpty) return;
await localMediaDb.removeVaults(details);
@ -160,7 +160,7 @@ class Vaults extends ChangeNotifier {
final vaultName = detailsForPath(dirPath)?.name;
if (vaultName == null) return newEntries;
final knownPaths = source.allEntries.where((v) => v.origin == EntryOrigins.vault && v.directory == dirPath).map((v) => v.path).whereNotNull().toSet();
final knownPaths = source.allEntries.where((v) => v.origin == EntryOrigins.vault && v.directory == dirPath).map((v) => v.path).nonNulls.toSet();
final untrackedPaths = await storageService.getUntrackedVaultPaths(vaultName, knownPaths);
if (untrackedPaths.isNotEmpty) {
debugPrint('Recovering ${untrackedPaths.length} untracked vault items');

View file

@ -3,7 +3,6 @@ import 'dart:async';
import 'package:aves/model/filters/filters.dart';
import 'package:aves/services/app_service.dart';
import 'package:aves/services/common/services.dart';
import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
import 'package:streams_channel/streams_channel.dart';
@ -54,7 +53,7 @@ class IntentService {
'initialFilters': initialFilters?.map((filter) => filter.toJson()).toList(),
}).listen(
(data) {
final result = (data as List?)?.cast<String>().map(CollectionFilter.fromJson).whereNotNull().toSet();
final result = (data as List?)?.cast<String>().map(CollectionFilter.fromJson).nonNulls.toSet();
completer.complete(result);
},
onError: completer.completeError,

View file

@ -7,7 +7,6 @@ import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves_model/aves_model.dart';
import 'package:aves_report/aves_report.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:stack_trace/stack_trace.dart';
@ -65,7 +64,7 @@ class PlatformMetadataEditService implements MetadataEditService {
'entry': entry.toPlatformEntryMap(),
'dateMillis': modifier.setDateTime?.millisecondsSinceEpoch,
'shiftSeconds': modifier.shiftSeconds,
'fields': modifier.fields.where((v) => v.type == MetadataType.exif).map((v) => v.toPlatform).whereNotNull().toList(),
'fields': modifier.fields.where((v) => v.type == MetadataType.exif).map((v) => v.toPlatform).nonNulls.toList(),
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {

View file

@ -82,7 +82,7 @@ class SvgMetadataService {
..._textElements.map((name) {
final value = root.getElement(name)?.innerText;
return value != null ? MapEntry(formatKey(name), value) : null;
}).whereNotNull(),
}).nonNulls,
]);
final metadata = root.getElement(_metadataElement);

View file

@ -1,4 +1,4 @@
import 'package:collection/collection.dart';
extension ExtraList<E> on List<E> {
bool replace(E old, E newItem) {
@ -11,7 +11,7 @@ extension ExtraList<E> on List<E> {
}
extension ExtraMapNullableKey<K extends Object, V> on Map<K?, V> {
Map<K, V> whereNotNullKey() => <K, V>{for (var v in keys.whereNotNull()) v: this[v] as V};
Map<K, V> whereNotNullKey() => <K, V>{for (var v in keys.nonNulls) v: this[v] as V};
}
extension ExtraMapNullableValue<K extends Object, V> on Map<K, V?> {
@ -19,7 +19,7 @@ extension ExtraMapNullableValue<K extends Object, V> on Map<K, V?> {
}
extension ExtraMapNullableKeyValue<K extends Object, V> on Map<K?, V?> {
Map<K, V?> whereNotNullKey() => <K, V?>{for (var v in keys.whereNotNull()) v: this[v]};
Map<K, V?> whereNotNullKey() => <K, V?>{for (var v in keys.nonNulls) v: this[v]};
Map<K?, V> whereNotNullValue() => <K?, V>{for (var kv in entries.where((kv) => kv.value != null)) kv.key: kv.value as V};
}

View file

@ -655,7 +655,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
final shouldReset = _exitedMainByPop;
_exitedMainByPop = false;
if (!shouldReset && (intentData ?? {}).values.whereNotNull().isEmpty) {
if (!shouldReset && (intentData ?? {}).values.nonNulls.isEmpty) {
reportService.log('Relaunch');
return;
}

View file

@ -36,7 +36,6 @@ import 'package:aves/widgets/dialogs/tile_view_dialog.dart';
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
import 'package:aves/widgets/search/search_delegate.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart';
@ -357,7 +356,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
return [
...EntrySetActions.general,
...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing,
].whereNotNull().where(isVisible).map((action) {
].nonNulls.where(isVisible).map((action) {
final enabled = canApply(action);
return CaptionedButton(
iconButtonBuilder: (context, focusNode) => _buildButtonIcon(

View file

@ -302,7 +302,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
final l10n = context.l10n;
final source = context.read<CollectionSource>();
final storageDirs = entries.map((e) => e.storageDirectory).whereNotNull().toSet();
final storageDirs = entries.map((e) => e.storageDirectory).nonNulls.toSet();
final todoCount = entries.length;
if (!await showSkippableConfirmationDialog(
@ -408,14 +408,14 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
Future<Set<EntryDataType>> Function(AvesEntry entry) op, {
bool showResult = true,
}) async {
final selectionDirs = todoItems.map((e) => e.directory).whereNotNull().toSet();
final selectionDirs = todoItems.map((e) => e.directory).nonNulls.toSet();
final todoCount = todoItems.length;
if (!await checkStoragePermissionForAlbums(context, selectionDirs, entries: todoItems)) return;
Set<String> obsoleteTags = todoItems.expand((entry) => entry.tags).toSet();
Set<String> obsoleteCountryCodes = todoItems.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.countryCode).whereNotNull().toSet();
Set<String> obsoleteStateCodes = todoItems.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.stateCode).whereNotNull().toSet();
Set<String> obsoleteCountryCodes = todoItems.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.countryCode).nonNulls.toSet();
Set<String> obsoleteStateCodes = todoItems.where((entry) => entry.hasAddress).map((entry) => entry.addressDetails?.stateCode).nonNulls.toSet();
final dataTypes = <EntryDataType>{};
final source = context.read<CollectionSource>();

View file

@ -109,7 +109,7 @@ mixin EntryEditorMixin {
Future<Set<String>> getTagsFromFilters(Set<CollectionFilter> filters, AvesEntry entry) async {
final tags = filters.whereType<TagFilter>().map((v) => v.tag).toSet();
final placeholderTags = await Future.wait(filters.whereType<PlaceholderFilter>().map((v) => v.toTag(entry)));
tags.addAll(placeholderTags.whereNotNull().where((v) => v.isNotEmpty));
tags.addAll(placeholderTags.nonNulls.where((v) => v.isNotEmpty));
return tags;
}

View file

@ -106,7 +106,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
onDone: (processed) async {
final successOps = processed.where((e) => e.success).toSet();
final exportedOps = successOps.where((e) => !e.skipped).toSet();
final newUris = exportedOps.map((v) => v.newFields['uri'] as String?).whereNotNull().toSet();
final newUris = exportedOps.map((v) => v.newFields['uri'] as String?).nonNulls.toSet();
final isMainMode = context.read<ValueNotifier<AppMode>>().value == AppMode.main;
source.resumeMonitoring();
@ -176,7 +176,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
if (!await checkStoragePermissionForAlbums(context, destinationAlbums)) return;
// permission for modification at origins
final originAlbums = entries.map((e) => e.directory).whereNotNull().toSet();
final originAlbums = entries.map((e) => e.directory).nonNulls.toSet();
if ({MoveType.move, MoveType.toBin}.contains(moveType) && !await checkStoragePermissionForAlbums(context, originAlbums, entries: entries)) return;
final hasEnoughSpaceByDestination = await Future.wait(destinationAlbums.map((destinationAlbum) {
@ -232,7 +232,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
// move
final movedOps = successOps.where((v) => !v.skipped && !v.deleted).toSet();
final movedEntries = movedOps.map((v) => v.uri).map((uri) => entries.firstWhereOrNull((entry) => entry.uri == uri)).whereNotNull().toSet();
final movedEntries = movedOps.map((v) => v.uri).map((uri) => entries.firstWhereOrNull((entry) => entry.uri == uri)).nonNulls.toSet();
await source.updateAfterMove(
todoEntries: entries,
moveType: moveType,

View file

@ -7,12 +7,11 @@ import 'package:aves/view/view.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
mixin PermissionAwareMixin {
Future<bool> checkStoragePermission(BuildContext context, Set<AvesEntry> entries) {
final storageDirs = entries.map((e) => e.storageDirectory).whereNotNull().toSet();
final storageDirs = entries.map((e) => e.storageDirectory).nonNulls.toSet();
return checkStoragePermissionForAlbums(context, storageDirs, entries: entries);
}

View file

@ -398,7 +398,7 @@ class _GeoMapState extends State<GeoMap> {
)
: null;
})
.whereNotNull()
.nonNulls
.toList();
return Fluster<GeoEntry<AvesEntry>>(

View file

@ -39,7 +39,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
if (_collection != null) {
final entries = _collection.sortedEntries;
if (entries.isNotEmpty) {
final coverEntries = _collection.filters.map((filter) => covers.of(filter)?.$1).whereNotNull().map((id) => entries.firstWhereOrNull((entry) => entry.id == id)).whereNotNull();
final coverEntries = _collection.filters.map((filter) => covers.of(filter)?.$1).nonNulls.map((id) => entries.firstWhereOrNull((entry) => entry.id == id)).nonNulls;
_coverEntry = coverEntries.firstOrNull ?? entries.first;
}
}

View file

@ -282,7 +282,7 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
final source = context.read<CollectionSource>();
final todoEntries = source.visibleEntries.where((entry) => filters.any((f) => f.test(entry))).toSet();
final todoAlbums = filters.map((v) => v.album).toSet();
final filledAlbums = todoEntries.map((e) => e.directory).whereNotNull().toSet();
final filledAlbums = todoEntries.map((e) => e.directory).nonNulls.toSet();
final emptyAlbums = todoAlbums.whereNot(filledAlbums.contains).toSet();
if (enableBin && filledAlbums.isNotEmpty) {
@ -338,7 +338,7 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
if (todoEntries.isEmpty) return;
final source = context.read<CollectionSource>();
final filledAlbums = todoEntries.map((e) => e.directory).whereNotNull().toSet();
final filledAlbums = todoEntries.map((e) => e.directory).nonNulls.toSet();
final l10n = context.l10n;
final messenger = ScaffoldMessenger.of(context);

View file

@ -8,7 +8,6 @@ import 'package:aves/widgets/filter_grids/common/action_delegates/chip_set.dart'
import 'package:aves/widgets/filter_grids/countries_page.dart';
import 'package:aves/widgets/filter_grids/states_page.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
class CountryChipSetActionDelegate extends ChipSetActionDelegate<LocationFilter> {
@ -95,7 +94,7 @@ class CountryChipSetActionDelegate extends ChipSetActionDelegate<LocationFilter>
void _showStates(BuildContext context) {
final filters = getSelectedFilters(context);
final countryCodes = filters.map((v) => v.code).where(GeoStates.stateCountryCodes.contains).whereNotNull().toSet();
final countryCodes = filters.map((v) => v.code).where(GeoStates.stateCountryCodes.contains).nonNulls.toSet();
Navigator.maybeOf(context)?.push(
MaterialPageRoute(
settings: const RouteSettings(name: StateListPage.routeName),

View file

@ -22,7 +22,6 @@ import 'package:aves/widgets/filter_grids/common/action_delegates/chip_set.dart'
import 'package:aves/widgets/filter_grids/common/query_bar.dart';
import 'package:aves/widgets/search/search_delegate.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart';
@ -301,7 +300,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
return [
...ChipSetActions.general,
...isSelecting ? ChipSetActions.selection : ChipSetActions.browsing,
].whereNotNull().where(isVisible).map((action) {
].nonNulls.where(isVisible).map((action) {
final enabled = canApply(action);
return CaptionedButton(
iconButtonBuilder: (context, focusNode) => _buildButtonIcon(

View file

@ -114,7 +114,7 @@ class _HomePageState extends State<HomePage> {
unawaited(appInventory.initAppNames());
}
if (intentData.values.whereNotNull().isNotEmpty) {
if (intentData.values.nonNulls.isNotEmpty) {
await reportService.log('Intent data=$intentData');
var intentUri = intentData[IntentDataKeys.uri] as String?;
final intentMimeType = intentData[IntentDataKeys.mimeType] as String?;
@ -186,7 +186,7 @@ class _HomePageState extends State<HomePage> {
}
if (_initialFilters == null) {
final extraFilters = (intentData[IntentDataKeys.filters] as List?)?.cast<String>();
_initialFilters = extraFilters?.map(CollectionFilter.fromJson).whereNotNull().toSet();
_initialFilters = extraFilters?.map(CollectionFilter.fromJson).nonNulls.toSet();
}
_initialExplorerPath = intentData[IntentDataKeys.explorerPath] as String?;

View file

@ -29,7 +29,6 @@ import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:aves/widgets/common/search/delegate.dart';
import 'package:aves/widgets/common/search/page.dart';
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -124,7 +123,7 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
filters: [
queryFilter,
...visibleTypeFilters,
].whereNotNull().where((f) => containQuery(f.getLabel(context))).toList(),
].nonNulls.where((f) => containQuery(f.getLabel(context))).toList(),
// usually perform hero animation only on tapped chips,
// but we also need to animate the query chip when it is selected by submitting the search query
heroTypeBuilder: (filter) => filter == queryFilter ? HeroType.always : HeroType.onTap,

View file

@ -22,7 +22,6 @@ import 'package:aves/widgets/settings/app_export/selection_dialog.dart';
import 'package:aves/widgets/settings/settings_page.dart';
import 'package:aves/widgets/settings/settings_search.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
@ -113,7 +112,7 @@ class _SettingsMobilePageState extends State<SettingsMobilePage> with FeedbackMi
final allMap = Map.fromEntries(toExport.map((v) {
final jsonMap = v.export(source);
return jsonMap != null ? MapEntry(v.name, jsonMap) : null;
}).whereNotNull());
}).nonNulls);
allMap[exportVersionKey] = exportVersion;
final allJsonString = jsonEncode(allMap);

View file

@ -5,7 +5,6 @@ import 'package:aves/widgets/common/identity/highlight_title.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/common/search/delegate.dart';
import 'package:aves/widgets/settings/settings_definition.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
class SettingsSearchDelegate extends AvesSearchDelegate {
@ -64,7 +63,7 @@ class SettingsSearchDelegate extends AvesSearchDelegate {
final loaders = snapshot.data;
if (loaders == null) return const SizedBox();
final children = loaders.whereNotNull().expand((builder) => builder(context)).toList();
final children = loaders.nonNulls.expand((builder) => builder(context)).toList();
return children.isEmpty
? EmptyContent(
icon: AIcons.settings,

View file

@ -78,7 +78,7 @@ class _HistogramState extends State<Histogram> with AutomaticKeepAliveClientMixi
_firstDate = normalizeDate(firstDate);
_lastDate = normalizeDate(lastDate);
final dates = entriesByDateDescending.map((entry) => entry.bestDate).whereNotNull();
final dates = entriesByDateDescending.map((entry) => entry.bestDate).nonNulls;
_entryCountPerDate.addAll(groupBy<DateTime, DateTime>(dates, normalizeDate).map((k, v) => MapEntry(k, v.length)));
if (_entryCountPerDate.isNotEmpty) {
// discrete points

View file

@ -163,7 +163,7 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
context: context,
builder: (context) => VideoStreamSelectionDialog(
streams: Map.fromEntries(streams.map((stream) {
final selectedStream = currentSelectedStreams.whereNotNull().firstWhereOrNull((v) => v.type == stream.type);
final selectedStream = currentSelectedStreams.nonNulls.firstWhereOrNull((v) => v.type == stream.type);
final selected = selectedStream != null && selectedStream.index == stream.index;
return MapEntry(stream, selected);
})),

View file

@ -7,7 +7,6 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/highlight_title.dart';
import 'package:aves/widgets/viewer/info/common.dart';
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
typedef XmpExtractedCard = (Map<String, XmpProp>, List<XmpCardData>?);
@ -28,7 +27,7 @@ class XmpCard extends StatefulWidget {
}) {
directStruct = structByIndex[null];
final length = structByIndex.keys.whereNotNull().fold(0, max);
final length = structByIndex.keys.nonNulls.fold(0, max);
indexedStructs = length > 0 ? [for (var i = 0; i < length; i++) structByIndex[i + 1] ?? const ({}, null)] : null;
}

View file

@ -99,7 +99,7 @@ class XmpNamespace extends Equatable {
cards.forEach((card) => extracted |= card.extract(prop));
return extracted ? null : prop;
})
.whereNotNull()
.nonNulls
.toList()
..sort();

View file

@ -50,7 +50,7 @@ abstract class XmpGoogleNamespace extends XmpNamespace {
},
))
: null;
}).whereNotNull());
}).nonNulls);
}
}

View file

@ -2,7 +2,6 @@ import 'package:aves/ref/unicode.dart';
import 'package:aves/widgets/viewer/visual/video/subtitle/line.dart';
import 'package:aves/widgets/viewer/visual/video/subtitle/span.dart';
import 'package:aves/widgets/viewer/visual/video/subtitle/style.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
class AssParser {
@ -471,7 +470,7 @@ class AssParser {
pathPattern.allMatches(commands).forEach((match) {
if (match.groupCount == 2) {
final command = match.group(1)!;
final params = match.group(2)!.trim().split(' ').map(double.tryParse).whereNotNull().map((v) => v / scale).toList();
final params = match.group(2)!.trim().split(' ').map(double.tryParse).nonNulls.map((v) => v / scale).toList();
switch (command) {
case 'b':
if (path != null) {
@ -529,7 +528,7 @@ class AssParser {
if (g != null) {
final params = g.split(',');
if (params.length == 4) {
final points = params.map(double.tryParse).whereNotNull().toList();
final points = params.map(double.tryParse).nonNulls.toList();
if (points.length == 4) {
paths = [
Path()

View file

@ -100,6 +100,6 @@ mixin SettingsAccess {
}
List<T> getEnumListOrDefault<T extends Object>(String key, List<T> defaultValue, Iterable<T> values) {
return store.getStringList(key)?.map((s) => values.firstWhereOrNull((v) => v.toString() == s)).whereNotNull().toList() ?? defaultValue;
return store.getStringList(key)?.map((s) => values.firstWhereOrNull((v) => v.toString() == s)).nonNulls.toList() ?? defaultValue;
}
}