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) { return Map.fromEntries(numericMap.entries.map((kv) {
final code = _countryOfNumeric(kv.key); final code = _countryOfNumeric(kv.key);
return code != null ? MapEntry(code, kv.value) : null; 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 // 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:convert';
import 'dart:isolate'; import 'dart:isolate';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
// cf https://github.com/topojson/topojson-specification // cf https://github.com/topojson/topojson-specification
@ -60,7 +59,7 @@ class Topology extends TopologyJsonObject {
final name = kv.key; final name = kv.key;
final geometry = Geometry.build(kv.value); final geometry = Geometry.build(kv.value);
return geometry != null ? MapEntry(name, geometry) : null; 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(), 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, transform = data.containsKey('transform') ? Transform.parse((data['transform'] as Map).cast<String, dynamic>()) : null,
super.parse(); super.parse();
@ -238,7 +237,7 @@ class GeometryCollection extends Geometry {
final List<Geometry> geometries; final List<Geometry> geometries;
GeometryCollection.parse(super.data) 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(); super.parse();
@override @override

View file

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

View file

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

View file

@ -1,5 +1,4 @@
import 'package:aves/model/db/db_sqflite.dart'; import 'package:aves/model/db/db_sqflite.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:sqflite/sqflite.dart'; import 'package:sqflite/sqflite.dart';
@ -338,11 +337,11 @@ class LocalMediaDbUpgrader {
// clean duplicates introduced before Aves v1.7.1 // 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 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>{}; final duplicateIds = <int>{};
await Future.forEach(duplicatedContentIds, (contentId) async { await Future.forEach(duplicatedContentIds, (contentId) async {
final rows = await db.query(entryTable, columns: ['id'], where: 'contentId = ?', whereArgs: [contentId]); 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) { if (ids.length > 1) {
ids.removeAt(0); ids.removeAt(0);
duplicateIds.addAll(ids); 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/utils/time_utils.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:aves_utils/aves_utils.dart'; import 'package:aves_utils/aves_utils.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
enum EntryDataType { basic, aspectRatio, catalog, address, references } enum EntryDataType { basic, aspectRatio, catalog, address, references }
@ -392,7 +391,7 @@ class AvesEntry with AvesEntryBase {
_addressDetails?.countryName, _addressDetails?.countryName,
_addressDetails?.adminArea, _addressDetails?.adminArea,
_addressDetails?.locality, _addressDetails?.locality,
}.whereNotNull().where((v) => v.isNotEmpty).join(', '); }.nonNulls.where((v) => v.isNotEmpty).join(', ');
} }
Future<void> applyNewFields(Map newFields, {required bool persist}) async { 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 rawTags = formatCount.map((key, value) {
final count = value.length; final count = value.length;
// remove duplicate names, so number of displayed names may not match displayed count // 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(', ')}'); return MapEntry(key, '$count items: ${names.join(', ')}');
}); });
directories.add(MetadataDirectory('Attachments', _toSortedTags(rawTags))); directories.add(MetadataDirectory('Attachments', _toSortedTags(rawTags)));
@ -157,7 +157,7 @@ extension ExtraAvesEntryInfo on AvesEntry {
if (value.isEmpty) return null; if (value.isEmpty) return null;
final tagName = tagKV.key as String; final tagName = tagKV.key as String;
return MapEntry(tagName, value); return MapEntry(tagName, value);
}).whereNotNull())); }).nonNulls));
return tags; return tags;
} }
} }

View file

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

View file

@ -35,7 +35,7 @@ class OrFilter extends CollectionFilter {
factory OrFilter.fromMap(Map<String, dynamic> json) { factory OrFilter.fromMap(Map<String, dynamic> json) {
return OrFilter( 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, reversed: json['reversed'] ?? false,
); );
} }

View file

@ -210,7 +210,7 @@ class MetadataFieldNamingProcessor extends NamingProcessor {
} }
@override @override
Set<MetadataField> getRequiredFields() => {field}.whereNotNull().toSet(); Set<MetadataField> getRequiredFields() => {field}.nonNulls.toSet();
@override @override
String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) { String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) {
@ -268,7 +268,7 @@ class HashNamingProcessor extends NamingProcessor {
} }
@override @override
Set<MetadataField> getRequiredFields() => {function}.whereNotNull().toSet(); Set<MetadataField> getRequiredFields() => {function}.nonNulls.toSet();
@override @override
String? process(AvesEntry entry, int index, Map<String, dynamic> fieldValues) { 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/model/settings/defaults.dart';
import 'package:aves/widgets/aves_app.dart'; import 'package:aves/widgets/aves_app.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
mixin AppSettings on SettingsAccess { mixin AppSettings on SettingsAccess {
@ -99,15 +98,15 @@ mixin AppSettings on SettingsAccess {
set entryRenamingPattern(String newValue) => set(SettingKeys.entryRenamingPatternKey, newValue); 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) ?? []; List<String> get recentDestinationAlbums => getStringList(SettingKeys.recentDestinationAlbumsKey) ?? [];
set recentDestinationAlbums(List<String> newValue) => set(SettingKeys.recentDestinationAlbumsKey, newValue.take(recentFilterHistoryMax).toList()); 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()); 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/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart'; import 'package:aves/model/settings/defaults.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin FilterGridsSettings on SettingsAccess { mixin FilterGridsSettings on SettingsAccess {
AlbumChipGroupFactor get albumGroupFactor => getEnumOrDefault(SettingKeys.albumGroupFactorKey, SettingsDefaults.albumGroupFactor, AlbumChipGroupFactor.values); 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 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()); 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/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart'; import 'package:aves/model/settings/defaults.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin NavigationSettings on SettingsAccess { mixin NavigationSettings on SettingsAccess {
bool get mustBackTwiceToExit => getBool(SettingKeys.mustBackTwiceToExitKey) ?? SettingsDefaults.mustBackTwiceToExit; 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); 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); String? get homeCustomExplorerPath => getString(SettingKeys.homeCustomExplorerPathKey);

View file

@ -1,10 +1,9 @@
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/modules/search.dart'; import 'package:aves/model/settings/modules/search.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin PrivacySettings on SettingsAccess, SearchSettings { 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()); 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; 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()); 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/filters/filters.dart';
import 'package:aves/model/settings/defaults.dart'; import 'package:aves/model/settings/defaults.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
mixin SearchSettings on SettingsAccess { mixin SearchSettings on SettingsAccess {
bool get saveSearchHistory => getBool(SettingKeys.saveSearchHistoryKey) ?? SettingsDefaults.saveSearchHistory; bool get saveSearchHistory => getBool(SettingKeys.saveSearchHistoryKey) ?? SettingsDefaults.saveSearchHistory;
set saveSearchHistory(bool newValue) => set(SettingKeys.saveSearchHistoryKey, newValue); 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()); 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 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()); 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()); 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()); 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}) { void addDirectories({required Set<String?> albums, bool notify = true}) {
if (!_directories.containsAll(albums)) { if (!_directories.containsAll(albums)) {
_directories.addAll(albums.whereNotNull()); _directories.addAll(albums.nonNulls);
_onAlbumChanged(notify: notify); _onAlbumChanged(notify: notify);
} }
} }
@ -119,7 +119,7 @@ mixin AlbumMixin on SourceBase {
} else { } else {
directories ??= {}; directories ??= {};
if (entries != null) { if (entries != null) {
directories.addAll(entries.map((entry) => entry.directory).whereNotNull()); directories.addAll(entries.map((entry) => entry.directory).nonNulls);
} }
directories.forEach((directory) { directories.forEach((directory) {
_filterEntryCountMap.remove(directory); _filterEntryCountMap.remove(directory);
@ -202,7 +202,7 @@ mixin AlbumMixin on SourceBase {
return dirPath; 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); final uniqueNameInDevice = unique(dirPath, otherAlbumsOnDevice);
if (uniqueNameInDevice.length <= relativeDir.length) { if (uniqueNameInDevice.length <= relativeDir.length) {
return uniqueNameInDevice; return uniqueNameInDevice;

View file

@ -54,7 +54,7 @@ class CollectionLens with ChangeNotifier {
this.stackDevelopedRaws = true, this.stackDevelopedRaws = true,
this.fixedSort = false, this.fixedSort = false,
this.fixedSelection, this.fixedSelection,
}) : filters = (filters ?? {}).whereNotNull().toSet(), }) : filters = (filters ?? {}).nonNulls.toSet(),
burstPatterns = settings.collectionBurstPatterns, burstPatterns = settings.collectionBurstPatterns,
sectionFactor = settings.collectionSectionFactor, sectionFactor = settings.collectionSectionFactor,
sortFactor = settings.collectionSortFactor, 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) { settings.updateStream.where((event) => event.key == SettingKeys.hiddenFiltersKey).listen((event) {
final oldValue = event.oldValue; final oldValue = event.oldValue;
if (oldValue is List<String>?) { 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(); final newlyVisibleFilters = oldHiddenFilters.whereNot(settings.hiddenFilters.contains).toSet();
_onFilterVisibilityChanged(newlyVisibleFilters); _onFilterVisibilityChanged(newlyVisibleFilters);
} }
@ -337,7 +337,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
final existingEntry = _rawEntries.firstWhereOrNull((entry) => entry.path == targetPath && !entry.trashed); final existingEntry = _rawEntries.firstWhereOrNull((entry) => entry.path == targetPath && !entry.trashed);
return existingEntry?.uri; return existingEntry?.uri;
}) })
.whereNotNull() .nonNulls
.toSet(); .toSet();
await removeEntries(replacedUris, includeTrash: false); await removeEntries(replacedUris, includeTrash: false);
@ -367,8 +367,8 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
} }
}); });
await localMediaDb.insertEntries(movedEntries); await localMediaDb.insertEntries(movedEntries);
await localMediaDb.saveCatalogMetadata(movedEntries.map((entry) => entry.catalogMetadata).whereNotNull().toSet()); await localMediaDb.saveCatalogMetadata(movedEntries.map((entry) => entry.catalogMetadata).nonNulls.toSet());
await localMediaDb.saveAddresses(movedEntries.map((entry) => entry.addressDetails).whereNotNull().toSet()); await localMediaDb.saveAddresses(movedEntries.map((entry) => entry.addressDetails).nonNulls.toSet());
} else { } else {
await Future.forEach<MoveOpEvent>(movedOps, (movedOp) async { await Future.forEach<MoveOpEvent>(movedOps, (movedOp) async {
final newFields = movedOp.newFields; final newFields = movedOp.newFields;
@ -393,7 +393,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
addEntries(movedEntries); addEntries(movedEntries);
case MoveType.move: case MoveType.move:
case MoveType.export: case MoveType.export:
cleanEmptyAlbums(fromAlbums.whereNotNull().toSet()); cleanEmptyAlbums(fromAlbums.nonNulls.toSet());
addDirectories(albums: destinationAlbums); addDirectories(albums: destinationAlbums);
case MoveType.toBin: case MoveType.toBin:
case MoveType.fromBin: case MoveType.fromBin:

View file

@ -23,7 +23,7 @@ mixin CountryMixin on SourceBase {
} else { } else {
countryCodes ??= {}; countryCodes ??= {};
if (entries != null) { 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) { countryCodes.forEach((countryCode) {
_filterEntryCountMap.remove(countryCode); _filterEntryCountMap.remove(countryCode);

View file

@ -152,9 +152,9 @@ mixin LocationMixin on CountryMixin, StateMixin {
} }
void updateLocations() { 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)) { if (!listEquals(updatedPlaces, sortedPlaces)) {
sortedPlaces = List.unmodifiable(updatedPlaces); sortedPlaces = List.unmodifiable(updatedPlaces);
eventBus.fire(PlacesChangedEvent()); eventBus.fire(PlacesChangedEvent());
@ -195,7 +195,7 @@ mixin LocationMixin on CountryMixin, StateMixin {
final code = getCode(address); final code = getCode(address);
if (code == null || code.isEmpty) return null; if (code == null || code.isEmpty) return null;
return MapEntry(code, getName(address)); return MapEntry(code, getName(address));
}).whereNotNull()); }).nonNulls);
return namesByCode.entries.map((kv) { return namesByCode.entries.map((kv) {
final code = kv.key; final code = kv.key;
final name = kv.value; final name = kv.value;

View file

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

View file

@ -23,7 +23,7 @@ mixin StateMixin on SourceBase {
} else { } else {
stateCodes ??= {}; stateCodes ??= {};
if (entries != null) { 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) { stateCodes.forEach((stateCode) {
_filterEntryCountMap.remove(stateCode); _filterEntryCountMap.remove(stateCode);

View file

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

View file

@ -41,7 +41,7 @@ mixin TrashMixin on SourceBase {
Future<Set<AvesEntry>> recoverUntrackedTrashItems() async { Future<Set<AvesEntry>> recoverUntrackedTrashItems() async {
final newEntries = <AvesEntry>{}; 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); final untrackedPaths = await storageService.getUntrackedTrashPaths(knownPaths);
if (untrackedPaths.isNotEmpty) { if (untrackedPaths.isNotEmpty) {
debugPrint('Recovering ${untrackedPaths.length} untracked bin items'); debugPrint('Recovering ${untrackedPaths.length} untracked bin items');

View file

@ -53,7 +53,7 @@ class Vaults extends ChangeNotifier {
} }
Future<void> remove(Set<String> dirPaths) async { 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; if (details.isEmpty) return;
await localMediaDb.removeVaults(details); await localMediaDb.removeVaults(details);
@ -160,7 +160,7 @@ class Vaults extends ChangeNotifier {
final vaultName = detailsForPath(dirPath)?.name; final vaultName = detailsForPath(dirPath)?.name;
if (vaultName == null) return newEntries; 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); final untrackedPaths = await storageService.getUntrackedVaultPaths(vaultName, knownPaths);
if (untrackedPaths.isNotEmpty) { if (untrackedPaths.isNotEmpty) {
debugPrint('Recovering ${untrackedPaths.length} untracked vault items'); 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/model/filters/filters.dart';
import 'package:aves/services/app_service.dart'; import 'package:aves/services/app_service.dart';
import 'package:aves/services/common/services.dart'; import 'package:aves/services/common/services.dart';
import 'package:collection/collection.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:streams_channel/streams_channel.dart'; import 'package:streams_channel/streams_channel.dart';
@ -54,7 +53,7 @@ class IntentService {
'initialFilters': initialFilters?.map((filter) => filter.toJson()).toList(), 'initialFilters': initialFilters?.map((filter) => filter.toJson()).toList(),
}).listen( }).listen(
(data) { (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); completer.complete(result);
}, },
onError: completer.completeError, 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/services/common/services.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:aves_report/aves_report.dart'; import 'package:aves_report/aves_report.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:stack_trace/stack_trace.dart'; import 'package:stack_trace/stack_trace.dart';
@ -65,7 +64,7 @@ class PlatformMetadataEditService implements MetadataEditService {
'entry': entry.toPlatformEntryMap(), 'entry': entry.toPlatformEntryMap(),
'dateMillis': modifier.setDateTime?.millisecondsSinceEpoch, 'dateMillis': modifier.setDateTime?.millisecondsSinceEpoch,
'shiftSeconds': modifier.shiftSeconds, '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>(); if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) { } on PlatformException catch (e, stack) {

View file

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

View file

@ -1,4 +1,4 @@
import 'package:collection/collection.dart';
extension ExtraList<E> on List<E> { extension ExtraList<E> on List<E> {
bool replace(E old, E newItem) { 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> { 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?> { 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?> { 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}; 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; final shouldReset = _exitedMainByPop;
_exitedMainByPop = false; _exitedMainByPop = false;
if (!shouldReset && (intentData ?? {}).values.whereNotNull().isEmpty) { if (!shouldReset && (intentData ?? {}).values.nonNulls.isEmpty) {
reportService.log('Relaunch'); reportService.log('Relaunch');
return; 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/filter_grids/common/action_delegates/chip.dart';
import 'package:aves/widgets/search/search_delegate.dart'; import 'package:aves/widgets/search/search_delegate.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -357,7 +356,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
return [ return [
...EntrySetActions.general, ...EntrySetActions.general,
...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing, ...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing,
].whereNotNull().where(isVisible).map((action) { ].nonNulls.where(isVisible).map((action) {
final enabled = canApply(action); final enabled = canApply(action);
return CaptionedButton( return CaptionedButton(
iconButtonBuilder: (context, focusNode) => _buildButtonIcon( iconButtonBuilder: (context, focusNode) => _buildButtonIcon(

View file

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

View file

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

View file

@ -106,7 +106,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
onDone: (processed) async { onDone: (processed) async {
final successOps = processed.where((e) => e.success).toSet(); final successOps = processed.where((e) => e.success).toSet();
final exportedOps = successOps.where((e) => !e.skipped).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; final isMainMode = context.read<ValueNotifier<AppMode>>().value == AppMode.main;
source.resumeMonitoring(); source.resumeMonitoring();
@ -176,7 +176,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
if (!await checkStoragePermissionForAlbums(context, destinationAlbums)) return; if (!await checkStoragePermissionForAlbums(context, destinationAlbums)) return;
// permission for modification at origins // 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; if ({MoveType.move, MoveType.toBin}.contains(moveType) && !await checkStoragePermissionForAlbums(context, originAlbums, entries: entries)) return;
final hasEnoughSpaceByDestination = await Future.wait(destinationAlbums.map((destinationAlbum) { final hasEnoughSpaceByDestination = await Future.wait(destinationAlbums.map((destinationAlbum) {
@ -232,7 +232,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
// move // move
final movedOps = successOps.where((v) => !v.skipped && !v.deleted).toSet(); 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( await source.updateAfterMove(
todoEntries: entries, todoEntries: entries,
moveType: moveType, 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/common/extensions/build_context.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
mixin PermissionAwareMixin { mixin PermissionAwareMixin {
Future<bool> checkStoragePermission(BuildContext context, Set<AvesEntry> entries) { 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); return checkStoragePermissionForAlbums(context, storageDirs, entries: entries);
} }

View file

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

View file

@ -39,7 +39,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
if (_collection != null) { if (_collection != null) {
final entries = _collection.sortedEntries; final entries = _collection.sortedEntries;
if (entries.isNotEmpty) { 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; _coverEntry = coverEntries.firstOrNull ?? entries.first;
} }
} }

View file

@ -282,7 +282,7 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
final source = context.read<CollectionSource>(); final source = context.read<CollectionSource>();
final todoEntries = source.visibleEntries.where((entry) => filters.any((f) => f.test(entry))).toSet(); final todoEntries = source.visibleEntries.where((entry) => filters.any((f) => f.test(entry))).toSet();
final todoAlbums = filters.map((v) => v.album).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(); final emptyAlbums = todoAlbums.whereNot(filledAlbums.contains).toSet();
if (enableBin && filledAlbums.isNotEmpty) { if (enableBin && filledAlbums.isNotEmpty) {
@ -338,7 +338,7 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
if (todoEntries.isEmpty) return; if (todoEntries.isEmpty) return;
final source = context.read<CollectionSource>(); 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 l10n = context.l10n;
final messenger = ScaffoldMessenger.of(context); 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/countries_page.dart';
import 'package:aves/widgets/filter_grids/states_page.dart'; import 'package:aves/widgets/filter_grids/states_page.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class CountryChipSetActionDelegate extends ChipSetActionDelegate<LocationFilter> { class CountryChipSetActionDelegate extends ChipSetActionDelegate<LocationFilter> {
@ -95,7 +94,7 @@ class CountryChipSetActionDelegate extends ChipSetActionDelegate<LocationFilter>
void _showStates(BuildContext context) { void _showStates(BuildContext context) {
final filters = getSelectedFilters(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( Navigator.maybeOf(context)?.push(
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: StateListPage.routeName), 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/filter_grids/common/query_bar.dart';
import 'package:aves/widgets/search/search_delegate.dart'; import 'package:aves/widgets/search/search_delegate.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -301,7 +300,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
return [ return [
...ChipSetActions.general, ...ChipSetActions.general,
...isSelecting ? ChipSetActions.selection : ChipSetActions.browsing, ...isSelecting ? ChipSetActions.selection : ChipSetActions.browsing,
].whereNotNull().where(isVisible).map((action) { ].nonNulls.where(isVisible).map((action) {
final enabled = canApply(action); final enabled = canApply(action);
return CaptionedButton( return CaptionedButton(
iconButtonBuilder: (context, focusNode) => _buildButtonIcon( iconButtonBuilder: (context, focusNode) => _buildButtonIcon(

View file

@ -114,7 +114,7 @@ class _HomePageState extends State<HomePage> {
unawaited(appInventory.initAppNames()); unawaited(appInventory.initAppNames());
} }
if (intentData.values.whereNotNull().isNotEmpty) { if (intentData.values.nonNulls.isNotEmpty) {
await reportService.log('Intent data=$intentData'); await reportService.log('Intent data=$intentData');
var intentUri = intentData[IntentDataKeys.uri] as String?; var intentUri = intentData[IntentDataKeys.uri] as String?;
final intentMimeType = intentData[IntentDataKeys.mimeType] as String?; final intentMimeType = intentData[IntentDataKeys.mimeType] as String?;
@ -186,7 +186,7 @@ class _HomePageState extends State<HomePage> {
} }
if (_initialFilters == null) { if (_initialFilters == null) {
final extraFilters = (intentData[IntentDataKeys.filters] as List?)?.cast<String>(); 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?; _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/delegate.dart';
import 'package:aves/widgets/common/search/page.dart'; import 'package:aves/widgets/common/search/page.dart';
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart'; import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -124,7 +123,7 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
filters: [ filters: [
queryFilter, queryFilter,
...visibleTypeFilters, ...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, // 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 // 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, 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_page.dart';
import 'package:aves/widgets/settings/settings_search.dart'; import 'package:aves/widgets/settings/settings_search.dart';
import 'package:aves_model/aves_model.dart'; import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.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 allMap = Map.fromEntries(toExport.map((v) {
final jsonMap = v.export(source); final jsonMap = v.export(source);
return jsonMap != null ? MapEntry(v.name, jsonMap) : null; return jsonMap != null ? MapEntry(v.name, jsonMap) : null;
}).whereNotNull()); }).nonNulls);
allMap[exportVersionKey] = exportVersion; allMap[exportVersionKey] = exportVersion;
final allJsonString = jsonEncode(allMap); 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/providers/media_query_data_provider.dart';
import 'package:aves/widgets/common/search/delegate.dart'; import 'package:aves/widgets/common/search/delegate.dart';
import 'package:aves/widgets/settings/settings_definition.dart'; import 'package:aves/widgets/settings/settings_definition.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SettingsSearchDelegate extends AvesSearchDelegate { class SettingsSearchDelegate extends AvesSearchDelegate {
@ -64,7 +63,7 @@ class SettingsSearchDelegate extends AvesSearchDelegate {
final loaders = snapshot.data; final loaders = snapshot.data;
if (loaders == null) return const SizedBox(); 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 return children.isEmpty
? EmptyContent( ? EmptyContent(
icon: AIcons.settings, icon: AIcons.settings,

View file

@ -78,7 +78,7 @@ class _HistogramState extends State<Histogram> with AutomaticKeepAliveClientMixi
_firstDate = normalizeDate(firstDate); _firstDate = normalizeDate(firstDate);
_lastDate = normalizeDate(lastDate); _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))); _entryCountPerDate.addAll(groupBy<DateTime, DateTime>(dates, normalizeDate).map((k, v) => MapEntry(k, v.length)));
if (_entryCountPerDate.isNotEmpty) { if (_entryCountPerDate.isNotEmpty) {
// discrete points // discrete points

View file

@ -163,7 +163,7 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
context: context, context: context,
builder: (context) => VideoStreamSelectionDialog( builder: (context) => VideoStreamSelectionDialog(
streams: Map.fromEntries(streams.map((stream) { 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; final selected = selectedStream != null && selectedStream.index == stream.index;
return MapEntry(stream, selected); 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/common/identity/highlight_title.dart';
import 'package:aves/widgets/viewer/info/common.dart'; import 'package:aves/widgets/viewer/info/common.dart';
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
typedef XmpExtractedCard = (Map<String, XmpProp>, List<XmpCardData>?); typedef XmpExtractedCard = (Map<String, XmpProp>, List<XmpCardData>?);
@ -28,7 +27,7 @@ class XmpCard extends StatefulWidget {
}) { }) {
directStruct = structByIndex[null]; 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; 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)); cards.forEach((card) => extracted |= card.extract(prop));
return extracted ? null : prop; return extracted ? null : prop;
}) })
.whereNotNull() .nonNulls
.toList() .toList()
..sort(); ..sort();

View file

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

View file

@ -100,6 +100,6 @@ mixin SettingsAccess {
} }
List<T> getEnumListOrDefault<T extends Object>(String key, List<T> defaultValue, Iterable<T> values) { 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;
} }
} }