mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-08 18:28:53 +01:00
Set day range of memory albums
This commit is contained in:
parent
3040cd123e
commit
e320b6b741
9 changed files with 271 additions and 30 deletions
|
@ -371,6 +371,19 @@
|
||||||
"@settingsPhotosPageTitle": {
|
"@settingsPhotosPageTitle": {
|
||||||
"description": "Dedicated page for settings related to the Photos tab"
|
"description": "Dedicated page for settings related to the Photos tab"
|
||||||
},
|
},
|
||||||
|
"settingsMemoriesRangeTitle": "Memories range",
|
||||||
|
"@settingsMemoriesRangeTitle": {
|
||||||
|
"description": "How many adjacent days to be inclded in memories for a particular year"
|
||||||
|
},
|
||||||
|
"settingsMemoriesRangeValueText": "{range, plural, =1{+-{range} day} other{+-{range} days}}",
|
||||||
|
"@settingsMemoriesRangeValueText": {
|
||||||
|
"description": "How many adjacent days to be inclded in memories for a particular year, could be 0",
|
||||||
|
"placeholders": {
|
||||||
|
"range": {
|
||||||
|
"example": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"settingsViewerTitle": "Viewer",
|
"settingsViewerTitle": "Viewer",
|
||||||
"settingsViewerDescription": "Customize the image/video viewer",
|
"settingsViewerDescription": "Customize the image/video viewer",
|
||||||
"settingsViewerPageTitle": "Viewer settings",
|
"settingsViewerPageTitle": "Viewer settings",
|
||||||
|
@ -1401,7 +1414,6 @@
|
||||||
"@collectionPlacesLabel": {
|
"@collectionPlacesLabel": {
|
||||||
"description": "Browse photos grouped by place"
|
"description": "Browse photos grouped by place"
|
||||||
},
|
},
|
||||||
|
|
||||||
"errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues",
|
"errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues",
|
||||||
"@errorUnauthenticated": {
|
"@errorUnauthenticated": {
|
||||||
"description": "Error message when server responds with HTTP401"
|
"description": "Error message when server responds with HTTP401"
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
"settingsServerAppSectionTitle",
|
"settingsServerAppSectionTitle",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsMapProviderTitle",
|
"settingsMapProviderTitle",
|
||||||
"settingsAlbumTitle",
|
"settingsAlbumTitle",
|
||||||
"settingsAlbumDescription",
|
"settingsAlbumDescription",
|
||||||
|
@ -170,6 +172,8 @@
|
||||||
"settingsServerAppSectionTitle",
|
"settingsServerAppSectionTitle",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsMapProviderTitle",
|
"settingsMapProviderTitle",
|
||||||
"settingsAlbumTitle",
|
"settingsAlbumTitle",
|
||||||
"settingsAlbumDescription",
|
"settingsAlbumDescription",
|
||||||
|
@ -327,6 +331,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsDoubleTapExitTitle",
|
"settingsDoubleTapExitTitle",
|
||||||
"enhanceStyleTransferStyleDialogTitle",
|
"enhanceStyleTransferStyleDialogTitle",
|
||||||
"doubleTapExitNotification",
|
"doubleTapExitNotification",
|
||||||
|
@ -370,6 +376,8 @@
|
||||||
"settingsLanguageOptionSystemDefaultLabel",
|
"settingsLanguageOptionSystemDefaultLabel",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"rootPickerSkipConfirmationDialogContent2",
|
"rootPickerSkipConfirmationDialogContent2",
|
||||||
"showAllButtonLabel",
|
"showAllButtonLabel",
|
||||||
"gpsPlaceText",
|
"gpsPlaceText",
|
||||||
|
@ -381,6 +389,8 @@
|
||||||
"fi": [
|
"fi": [
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"gpsPlaceText",
|
"gpsPlaceText",
|
||||||
"gpsPlaceAboutDialogTitle",
|
"gpsPlaceAboutDialogTitle",
|
||||||
"gpsPlaceAboutDialogContent",
|
"gpsPlaceAboutDialogContent",
|
||||||
|
@ -396,6 +406,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsPhotoEnhancementTitle",
|
"settingsPhotoEnhancementTitle",
|
||||||
"settingsPhotoEnhancementPageTitle",
|
"settingsPhotoEnhancementPageTitle",
|
||||||
"settingsEnhanceMaxResolutionTitle",
|
"settingsEnhanceMaxResolutionTitle",
|
||||||
|
@ -467,6 +479,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsPhotoEnhancementTitle",
|
"settingsPhotoEnhancementTitle",
|
||||||
"settingsPhotoEnhancementPageTitle",
|
"settingsPhotoEnhancementPageTitle",
|
||||||
"settingsEnhanceMaxResolutionTitle",
|
"settingsEnhanceMaxResolutionTitle",
|
||||||
|
@ -556,6 +570,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsPhotoEnhancementTitle",
|
"settingsPhotoEnhancementTitle",
|
||||||
"settingsPhotoEnhancementPageTitle",
|
"settingsPhotoEnhancementPageTitle",
|
||||||
"settingsEnhanceMaxResolutionTitle",
|
"settingsEnhanceMaxResolutionTitle",
|
||||||
|
@ -624,6 +640,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsPhotoEnhancementTitle",
|
"settingsPhotoEnhancementTitle",
|
||||||
"settingsPhotoEnhancementPageTitle",
|
"settingsPhotoEnhancementPageTitle",
|
||||||
"settingsEnhanceMaxResolutionTitle",
|
"settingsEnhanceMaxResolutionTitle",
|
||||||
|
@ -692,6 +710,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsPhotoEnhancementTitle",
|
"settingsPhotoEnhancementTitle",
|
||||||
"settingsPhotoEnhancementPageTitle",
|
"settingsPhotoEnhancementPageTitle",
|
||||||
"settingsEnhanceMaxResolutionTitle",
|
"settingsEnhanceMaxResolutionTitle",
|
||||||
|
@ -760,6 +780,8 @@
|
||||||
"settingsAccountLabelDescription",
|
"settingsAccountLabelDescription",
|
||||||
"settingsPhotosDescription",
|
"settingsPhotosDescription",
|
||||||
"settingsPhotosPageTitle",
|
"settingsPhotosPageTitle",
|
||||||
|
"settingsMemoriesRangeTitle",
|
||||||
|
"settingsMemoriesRangeValueText",
|
||||||
"settingsPhotoEnhancementTitle",
|
"settingsPhotoEnhancementTitle",
|
||||||
"settingsPhotoEnhancementPageTitle",
|
"settingsPhotoEnhancementPageTitle",
|
||||||
"settingsEnhanceMaxResolutionTitle",
|
"settingsEnhanceMaxResolutionTitle",
|
||||||
|
|
|
@ -244,6 +244,11 @@ class Pref {
|
||||||
Future<bool> setDoubleTapExit(bool value) => _set<bool>(PrefKey.doubleTapExit,
|
Future<bool> setDoubleTapExit(bool value) => _set<bool>(PrefKey.doubleTapExit,
|
||||||
value, (key, value) => provider.setBool(key, value));
|
value, (key, value) => provider.setBool(key, value));
|
||||||
|
|
||||||
|
int? getMemoriesRange() => provider.getInt(PrefKey.memoriesRange);
|
||||||
|
int getMemoriesRangeOr([int def = 2]) => getMemoriesRange() ?? def;
|
||||||
|
Future<bool> setMemoriesRange(int value) => _set<int>(PrefKey.memoriesRange,
|
||||||
|
value, (key, value) => provider.setInt(key, value));
|
||||||
|
|
||||||
Future<bool> _set<T>(PrefKey key, T value,
|
Future<bool> _set<T>(PrefKey key, T value,
|
||||||
Future<bool> Function(PrefKey key, T value) setFn) async {
|
Future<bool> Function(PrefKey key, T value) setFn) async {
|
||||||
if (await setFn(key, value)) {
|
if (await setFn(key, value)) {
|
||||||
|
@ -555,6 +560,7 @@ enum PrefKey {
|
||||||
isPhotosTabSortByName,
|
isPhotosTabSortByName,
|
||||||
shouldProcessExifWifiOnly,
|
shouldProcessExifWifiOnly,
|
||||||
doubleTapExit,
|
doubleTapExit,
|
||||||
|
memoriesRange,
|
||||||
|
|
||||||
// account pref
|
// account pref
|
||||||
isEnableFaceRecognitionApp,
|
isEnableFaceRecognitionApp,
|
||||||
|
@ -624,6 +630,8 @@ extension on PrefKey {
|
||||||
return "shouldProcessExifWifiOnly";
|
return "shouldProcessExifWifiOnly";
|
||||||
case PrefKey.doubleTapExit:
|
case PrefKey.doubleTapExit:
|
||||||
return "doubleTapExit";
|
return "doubleTapExit";
|
||||||
|
case PrefKey.memoriesRange:
|
||||||
|
return "memoriesRange";
|
||||||
|
|
||||||
// account pref
|
// account pref
|
||||||
case PrefKey.isEnableFaceRecognitionApp:
|
case PrefKey.isEnableFaceRecognitionApp:
|
||||||
|
|
|
@ -80,8 +80,9 @@ class PopulateAlbum {
|
||||||
assert(album.provider is AlbumMemoryProvider);
|
assert(album.provider is AlbumMemoryProvider);
|
||||||
final provider = album.provider as AlbumMemoryProvider;
|
final provider = album.provider as AlbumMemoryProvider;
|
||||||
final date = DateTime(provider.year, provider.month, provider.day);
|
final date = DateTime(provider.year, provider.month, provider.day);
|
||||||
final from = date.subtract(const Duration(days: 2));
|
final dayRange = _c.pref.getMemoriesRangeOr();
|
||||||
final to = date.add(const Duration(days: 3));
|
final from = date.subtract(Duration(days: dayRange));
|
||||||
|
final to = date.add(Duration(days: dayRange + 1));
|
||||||
final files = await FileSqliteDbDataSource(_c).listByDate(
|
final files = await FileSqliteDbDataSource(_c).listByDate(
|
||||||
account, from.millisecondsSinceEpoch, to.millisecondsSinceEpoch);
|
account, from.millisecondsSinceEpoch, to.millisecondsSinceEpoch);
|
||||||
return files
|
return files
|
||||||
|
|
|
@ -15,6 +15,10 @@ import 'package:nc_photos/widget/photo_list_item.dart';
|
||||||
import 'package:nc_photos/widget/photo_list_util.dart';
|
import 'package:nc_photos/widget/photo_list_util.dart';
|
||||||
import 'package:nc_photos/widget/selectable_item_stream_list_mixin.dart';
|
import 'package:nc_photos/widget/selectable_item_stream_list_mixin.dart';
|
||||||
|
|
||||||
|
/// Arguments to the photo list item builder
|
||||||
|
///
|
||||||
|
/// If [smartAlbumConfig] != null, the builder will also build smart albums in
|
||||||
|
/// the process
|
||||||
class PhotoListItemBuilderArguments {
|
class PhotoListItemBuilderArguments {
|
||||||
const PhotoListItemBuilderArguments(
|
const PhotoListItemBuilderArguments(
|
||||||
this.account,
|
this.account,
|
||||||
|
@ -22,7 +26,7 @@ class PhotoListItemBuilderArguments {
|
||||||
this.isArchived = false,
|
this.isArchived = false,
|
||||||
required this.sorter,
|
required this.sorter,
|
||||||
this.grouper,
|
this.grouper,
|
||||||
this.shouldBuildSmartAlbums = false,
|
this.smartAlbumConfig,
|
||||||
this.shouldShowFavoriteBadge = false,
|
this.shouldShowFavoriteBadge = false,
|
||||||
required this.locale,
|
required this.locale,
|
||||||
});
|
});
|
||||||
|
@ -32,7 +36,7 @@ class PhotoListItemBuilderArguments {
|
||||||
final bool isArchived;
|
final bool isArchived;
|
||||||
final PhotoListItemSorter? sorter;
|
final PhotoListItemSorter? sorter;
|
||||||
final PhotoListItemGrouper? grouper;
|
final PhotoListItemGrouper? grouper;
|
||||||
final bool shouldBuildSmartAlbums;
|
final PhotoListItemSmartAlbumConfig? smartAlbumConfig;
|
||||||
final bool shouldShowFavoriteBadge;
|
final bool shouldShowFavoriteBadge;
|
||||||
|
|
||||||
/// Locale is needed to get localized string
|
/// Locale is needed to get localized string
|
||||||
|
@ -73,6 +77,12 @@ class PhotoListFileDateGrouper implements PhotoListItemGrouper {
|
||||||
final DateGroupHelper helper;
|
final DateGroupHelper helper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PhotoListItemSmartAlbumConfig {
|
||||||
|
const PhotoListItemSmartAlbumConfig(this.memoriesDayRange);
|
||||||
|
|
||||||
|
final int memoriesDayRange;
|
||||||
|
}
|
||||||
|
|
||||||
int photoListFileDateTimeSorter(File a, File b) =>
|
int photoListFileDateTimeSorter(File a, File b) =>
|
||||||
compareFileDateTimeDescending(a, b);
|
compareFileDateTimeDescending(a, b);
|
||||||
|
|
||||||
|
@ -86,7 +96,7 @@ PhotoListItemBuilderResult buildPhotoListItem(
|
||||||
isArchived: arg.isArchived,
|
isArchived: arg.isArchived,
|
||||||
sorter: arg.sorter,
|
sorter: arg.sorter,
|
||||||
grouper: arg.grouper,
|
grouper: arg.grouper,
|
||||||
shouldBuildSmartAlbums: arg.shouldBuildSmartAlbums,
|
smartAlbumConfig: arg.smartAlbumConfig,
|
||||||
shouldShowFavoriteBadge: arg.shouldShowFavoriteBadge,
|
shouldShowFavoriteBadge: arg.shouldShowFavoriteBadge,
|
||||||
locale: arg.locale,
|
locale: arg.locale,
|
||||||
)(arg.account, arg.files);
|
)(arg.account, arg.files);
|
||||||
|
@ -97,7 +107,7 @@ class _PhotoListItemBuilder {
|
||||||
required this.isArchived,
|
required this.isArchived,
|
||||||
required this.sorter,
|
required this.sorter,
|
||||||
required this.grouper,
|
required this.grouper,
|
||||||
required this.shouldBuildSmartAlbums,
|
required this.smartAlbumConfig,
|
||||||
required this.shouldShowFavoriteBadge,
|
required this.shouldShowFavoriteBadge,
|
||||||
required this.locale,
|
required this.locale,
|
||||||
});
|
});
|
||||||
|
@ -123,8 +133,10 @@ class _PhotoListItemBuilder {
|
||||||
PhotoListItemBuilderResult _fromSortedItems(
|
PhotoListItemBuilderResult _fromSortedItems(
|
||||||
Account account, List<File> files) {
|
Account account, List<File> files) {
|
||||||
final today = DateTime.now();
|
final today = DateTime.now();
|
||||||
final memoryAlbumHelper =
|
final memoryAlbumHelper = smartAlbumConfig != null
|
||||||
shouldBuildSmartAlbums ? MemoryAlbumHelper(today) : null;
|
? MemoryAlbumHelper(
|
||||||
|
today: today, dayRange: smartAlbumConfig!.memoriesDayRange)
|
||||||
|
: null;
|
||||||
final listItems = <SelectableItem>[];
|
final listItems = <SelectableItem>[];
|
||||||
for (int i = 0; i < files.length; ++i) {
|
for (int i = 0; i < files.length; ++i) {
|
||||||
final f = files[i];
|
final f = files[i];
|
||||||
|
@ -173,7 +185,7 @@ class _PhotoListItemBuilder {
|
||||||
final bool isArchived;
|
final bool isArchived;
|
||||||
final PhotoListItemSorter? sorter;
|
final PhotoListItemSorter? sorter;
|
||||||
final PhotoListItemGrouper? grouper;
|
final PhotoListItemGrouper? grouper;
|
||||||
final bool shouldBuildSmartAlbums;
|
final PhotoListItemSmartAlbumConfig? smartAlbumConfig;
|
||||||
final bool shouldShowFavoriteBadge;
|
final bool shouldShowFavoriteBadge;
|
||||||
final Locale locale;
|
final Locale locale;
|
||||||
|
|
||||||
|
|
|
@ -509,6 +509,11 @@ class _HomePhotosState extends State<HomePhotos>
|
||||||
_log.info("[_onPrefUpdated] Update view after changing sort option");
|
_log.info("[_onPrefUpdated] Update view after changing sort option");
|
||||||
_transformItems(_bloc.state.files);
|
_transformItems(_bloc.state.files);
|
||||||
}
|
}
|
||||||
|
} else if (ev.key == PrefKey.memoriesRange) {
|
||||||
|
if (_bloc.state is! ScanAccountDirBlocInit) {
|
||||||
|
_log.info("[_onPrefUpdated] Update view after changing memories");
|
||||||
|
_transformItems(_bloc.state.files);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,6 +553,7 @@ class _HomePhotosState extends State<HomePhotos>
|
||||||
/// Transform a File list to grid items
|
/// Transform a File list to grid items
|
||||||
void _transformItems(List<File> files, {bool isSorted = false}) {
|
void _transformItems(List<File> files, {bool isSorted = false}) {
|
||||||
_log.info("[_transformItems] Queue ${files.length} items");
|
_log.info("[_transformItems] Queue ${files.length} items");
|
||||||
|
final c = KiwiContainer().resolve<DiContainer>();
|
||||||
final PhotoListItemSorter? sorter;
|
final PhotoListItemSorter? sorter;
|
||||||
final PhotoListItemGrouper? grouper;
|
final PhotoListItemGrouper? grouper;
|
||||||
if (Pref().isPhotosTabSortByNameOr()) {
|
if (Pref().isPhotosTabSortByNameOr()) {
|
||||||
|
@ -564,7 +570,8 @@ class _HomePhotosState extends State<HomePhotos>
|
||||||
files,
|
files,
|
||||||
sorter: sorter,
|
sorter: sorter,
|
||||||
grouper: grouper,
|
grouper: grouper,
|
||||||
shouldBuildSmartAlbums: true,
|
smartAlbumConfig:
|
||||||
|
PhotoListItemSmartAlbumConfig(c.pref.getMemoriesRangeOr()),
|
||||||
shouldShowFavoriteBadge: true,
|
shouldShowFavoriteBadge: true,
|
||||||
locale: language_util.getSelectedLocale() ??
|
locale: language_util.getSelectedLocale() ??
|
||||||
PlatformDispatcher.instance.locale,
|
PlatformDispatcher.instance.locale,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/date_time_extension.dart';
|
import 'package:nc_photos/date_time_extension.dart';
|
||||||
|
@ -32,8 +34,11 @@ class DateGroupHelper {
|
||||||
///
|
///
|
||||||
/// Feb 29 is treated as Mar 1 on non leap years
|
/// Feb 29 is treated as Mar 1 on non leap years
|
||||||
class MemoryAlbumHelper {
|
class MemoryAlbumHelper {
|
||||||
MemoryAlbumHelper([DateTime? today])
|
MemoryAlbumHelper({
|
||||||
: today = (today?.toLocal() ?? DateTime.now()).toMidnight();
|
DateTime? today,
|
||||||
|
required int dayRange,
|
||||||
|
}) : today = (today?.toLocal() ?? DateTime.now()).toMidnight(),
|
||||||
|
dayRange = math.max(dayRange, 0);
|
||||||
|
|
||||||
void addFile(File f) {
|
void addFile(File f) {
|
||||||
final date = f.bestDateTime.toLocal().toMidnight();
|
final date = f.bestDateTime.toLocal().toMidnight();
|
||||||
|
@ -43,7 +48,7 @@ class MemoryAlbumHelper {
|
||||||
}
|
}
|
||||||
for (final dy in [0, -1, 1]) {
|
for (final dy in [0, -1, 1]) {
|
||||||
if (today.copyWith(year: date.year + dy).difference(date).abs().inDays <=
|
if (today.copyWith(year: date.year + dy).difference(date).abs().inDays <=
|
||||||
2) {
|
dayRange) {
|
||||||
_log.fine(
|
_log.fine(
|
||||||
"[addFile] Add file (${f.bestDateTime}) to ${date.year + dy}");
|
"[addFile] Add file (${f.bestDateTime}) to ${date.year + dy}");
|
||||||
_addFileToYear(f, date.year + dy);
|
_addFileToYear(f, date.year + dy);
|
||||||
|
@ -85,6 +90,7 @@ class MemoryAlbumHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
final DateTime today;
|
final DateTime today;
|
||||||
|
final int dayRange;
|
||||||
final _data = <int, _MemoryAlbumHelperItem>{};
|
final _data = <int, _MemoryAlbumHelperItem>{};
|
||||||
|
|
||||||
static final _log = Logger("widget.photo_list_util.MemoryAlbumHelper");
|
static final _log = Logger("widget.photo_list_util.MemoryAlbumHelper");
|
||||||
|
|
|
@ -814,6 +814,7 @@ class _PhotosSettingsState extends State<_PhotosSettings> {
|
||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_memoriesRange = Pref().getMemoriesRangeOr();
|
||||||
|
|
||||||
final settings = AccountPref.of(widget.account);
|
final settings = AccountPref.of(widget.account);
|
||||||
_isEnableMemoryAlbum = settings.isEnableMemoryAlbumOr(true);
|
_isEnableMemoryAlbum = settings.isEnableMemoryAlbumOr(true);
|
||||||
|
@ -848,6 +849,14 @@ class _PhotosSettingsState extends State<_PhotosSettings> {
|
||||||
? null
|
? null
|
||||||
: _onEnableMemoryAlbumChanged,
|
: _onEnableMemoryAlbumChanged,
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10n.global().settingsMemoriesRangeTitle),
|
||||||
|
subtitle: Text(L10n.global()
|
||||||
|
.settingsMemoriesRangeValueText(_memoriesRange)),
|
||||||
|
onTap: () => _onMemoriesRangeTap(context),
|
||||||
|
enabled:
|
||||||
|
!Pref().isPhotosTabSortByNameOr() && _isEnableMemoryAlbum,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -855,6 +864,37 @@ class _PhotosSettingsState extends State<_PhotosSettings> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onMemoriesRangeTap(BuildContext context) async {
|
||||||
|
var memoriesRange = _memoriesRange;
|
||||||
|
final result = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => AppTheme(
|
||||||
|
child: AlertDialog(
|
||||||
|
content: _MemoriesRangeSlider(
|
||||||
|
initialRange: _memoriesRange,
|
||||||
|
onChanged: (value) {
|
||||||
|
memoriesRange = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
child: Text(L10n.global().applyButtonLabel),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result != true || memoriesRange == _memoriesRange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unawaited(_setMemoriesRange(memoriesRange));
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _onEnableMemoryAlbumChanged(bool value) async {
|
Future<void> _onEnableMemoryAlbumChanged(bool value) async {
|
||||||
_log.info("[_onEnableMemoryAlbumChanged] New value: $value");
|
_log.info("[_onEnableMemoryAlbumChanged] New value: $value");
|
||||||
final oldValue = _isEnableMemoryAlbum;
|
final oldValue = _isEnableMemoryAlbum;
|
||||||
|
@ -873,11 +913,80 @@ class _PhotosSettingsState extends State<_PhotosSettings> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _setMemoriesRange(int value) async {
|
||||||
|
_log.info("[_setMemoriesRange] New value: $value");
|
||||||
|
final oldValue = _memoriesRange;
|
||||||
|
setState(() {
|
||||||
|
_memoriesRange = value;
|
||||||
|
});
|
||||||
|
if (!await Pref().setMemoriesRange(value)) {
|
||||||
|
_log.severe("[_setMemoriesRange] Failed writing pref");
|
||||||
|
SnackBarManager().showSnackBar(SnackBar(
|
||||||
|
content: Text(L10n.global().writePreferenceFailureNotification),
|
||||||
|
duration: k.snackBarDurationNormal,
|
||||||
|
));
|
||||||
|
setState(() {
|
||||||
|
_memoriesRange = oldValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
late bool _isEnableMemoryAlbum;
|
late bool _isEnableMemoryAlbum;
|
||||||
|
late int _memoriesRange;
|
||||||
|
|
||||||
static final _log = Logger("widget.settings._PhotosSettingsState");
|
static final _log = Logger("widget.settings._PhotosSettingsState");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _MemoriesRangeSlider extends StatefulWidget {
|
||||||
|
const _MemoriesRangeSlider({
|
||||||
|
Key? key,
|
||||||
|
required this.initialRange,
|
||||||
|
this.onChanged,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
createState() => _MemoriesRangeSliderState();
|
||||||
|
|
||||||
|
final int initialRange;
|
||||||
|
final ValueChanged<int>? onChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MemoriesRangeSliderState extends State<_MemoriesRangeSlider> {
|
||||||
|
@override
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
|
_memoriesRange = widget.initialRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
L10n.global().settingsMemoriesRangeValueText(_memoriesRange)),
|
||||||
|
),
|
||||||
|
StatefulSlider(
|
||||||
|
initialValue: _memoriesRange.toDouble(),
|
||||||
|
min: 0,
|
||||||
|
max: 4,
|
||||||
|
divisions: 4,
|
||||||
|
onChangeEnd: (value) async {
|
||||||
|
setState(() {
|
||||||
|
_memoriesRange = value.toInt();
|
||||||
|
});
|
||||||
|
widget.onChanged?.call(_memoriesRange);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late int _memoriesRange;
|
||||||
|
}
|
||||||
|
|
||||||
class _ViewerSettings extends StatefulWidget {
|
class _ViewerSettings extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
createState() => _ViewerSettingsState();
|
createState() => _ViewerSettingsState();
|
||||||
|
|
|
@ -38,6 +38,13 @@ void main() {
|
||||||
group("on dec 31", () {
|
group("on dec 31", () {
|
||||||
test("+jan 1", _onDec31AddJan1);
|
test("+jan 1", _onDec31AddJan1);
|
||||||
});
|
});
|
||||||
|
group("on may 15, range=0", () {
|
||||||
|
test("+may 16", _onMay15AddMay16Range0);
|
||||||
|
test("+may 15", _onMay15AddMay15Range0);
|
||||||
|
});
|
||||||
|
group("on may 15, range<0", () {
|
||||||
|
test("+may 16", _onMay15AddMay16RangeNegative);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +55,7 @@ void main() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _sameYear() {
|
void _sameYear() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2021, 2, 3));
|
path: "", fileId: 0, lastModified: DateTime.utc(2021, 2, 3));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -63,7 +70,7 @@ void _sameYear() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _nextYear() {
|
void _nextYear() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2022, 2, 3));
|
path: "", fileId: 0, lastModified: DateTime.utc(2022, 2, 3));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -77,7 +84,7 @@ void _nextYear() {
|
||||||
/// Expect: [2020]
|
/// Expect: [2020]
|
||||||
void _prevYear() {
|
void _prevYear() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 3));
|
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 3));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -106,7 +113,7 @@ void _prevYear() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _prevYear3DaysBefore() {
|
void _prevYear3DaysBefore() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2020, 1, 31));
|
path: "", fileId: 0, lastModified: DateTime.utc(2020, 1, 31));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -120,7 +127,7 @@ void _prevYear3DaysBefore() {
|
||||||
/// Expect: [2020]
|
/// Expect: [2020]
|
||||||
void _prevYear2DaysBefore() {
|
void _prevYear2DaysBefore() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 1));
|
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 1));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -149,7 +156,7 @@ void _prevYear2DaysBefore() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _prevYear3DaysAfter() {
|
void _prevYear3DaysAfter() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 6));
|
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 6));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -163,7 +170,7 @@ void _prevYear3DaysAfter() {
|
||||||
/// Expect: [2020]
|
/// Expect: [2020]
|
||||||
void _prevYear2DaysAfter() {
|
void _prevYear2DaysAfter() {
|
||||||
final today = DateTime(2021, 2, 3);
|
final today = DateTime(2021, 2, 3);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 5));
|
path: "", fileId: 0, lastModified: DateTime.utc(2020, 2, 5));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -192,7 +199,7 @@ void _prevYear2DaysAfter() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _onFeb29AddFeb26() {
|
void _onFeb29AddFeb26() {
|
||||||
final today = DateTime(2020, 2, 29);
|
final today = DateTime(2020, 2, 29);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2019, 2, 26));
|
path: "", fileId: 0, lastModified: DateTime.utc(2019, 2, 26));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -206,7 +213,7 @@ void _onFeb29AddFeb26() {
|
||||||
/// Expect: [2019]
|
/// Expect: [2019]
|
||||||
void _onFeb29AddFeb27() {
|
void _onFeb29AddFeb27() {
|
||||||
final today = DateTime(2020, 2, 29);
|
final today = DateTime(2020, 2, 29);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2019, 2, 27));
|
path: "", fileId: 0, lastModified: DateTime.utc(2019, 2, 27));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -235,7 +242,7 @@ void _onFeb29AddFeb27() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _onFeb29AddMar4() {
|
void _onFeb29AddMar4() {
|
||||||
final today = DateTime(2020, 2, 29);
|
final today = DateTime(2020, 2, 29);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2019, 3, 4));
|
path: "", fileId: 0, lastModified: DateTime.utc(2019, 3, 4));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -249,7 +256,7 @@ void _onFeb29AddMar4() {
|
||||||
/// Expect: [2019]
|
/// Expect: [2019]
|
||||||
void _onFeb29AddMar3() {
|
void _onFeb29AddMar3() {
|
||||||
final today = DateTime(2020, 2, 29);
|
final today = DateTime(2020, 2, 29);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2019, 3, 3));
|
path: "", fileId: 0, lastModified: DateTime.utc(2019, 3, 3));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -278,7 +285,7 @@ void _onFeb29AddMar3() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _onFeb29AddMar3LeapYear() {
|
void _onFeb29AddMar3LeapYear() {
|
||||||
final today = DateTime(2020, 2, 29);
|
final today = DateTime(2020, 2, 29);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2016, 3, 3));
|
path: "", fileId: 0, lastModified: DateTime.utc(2016, 3, 3));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -292,7 +299,7 @@ void _onFeb29AddMar3LeapYear() {
|
||||||
/// Expect: [2016]
|
/// Expect: [2016]
|
||||||
void _onFeb29AddMar2LeapYear() {
|
void _onFeb29AddMar2LeapYear() {
|
||||||
final today = DateTime(2020, 2, 29);
|
final today = DateTime(2020, 2, 29);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2016, 3, 2));
|
path: "", fileId: 0, lastModified: DateTime.utc(2016, 3, 2));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -321,7 +328,7 @@ void _onFeb29AddMar2LeapYear() {
|
||||||
/// Expect: empty
|
/// Expect: empty
|
||||||
void _onJan1AddDec31() {
|
void _onJan1AddDec31() {
|
||||||
final today = DateTime(2020, 1, 1);
|
final today = DateTime(2020, 1, 1);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2019, 12, 31));
|
path: "", fileId: 0, lastModified: DateTime.utc(2019, 12, 31));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -335,7 +342,7 @@ void _onJan1AddDec31() {
|
||||||
/// Expect: [2019]
|
/// Expect: [2019]
|
||||||
void _onJan1AddDec31PrevYear() {
|
void _onJan1AddDec31PrevYear() {
|
||||||
final today = DateTime(2020, 1, 1);
|
final today = DateTime(2020, 1, 1);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2018, 12, 31));
|
path: "", fileId: 0, lastModified: DateTime.utc(2018, 12, 31));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -364,7 +371,7 @@ void _onJan1AddDec31PrevYear() {
|
||||||
/// Expect: [2019]
|
/// Expect: [2019]
|
||||||
void _onDec31AddJan1() {
|
void _onDec31AddJan1() {
|
||||||
final today = DateTime(2020, 12, 31);
|
final today = DateTime(2020, 12, 31);
|
||||||
final obj = MemoryAlbumHelper(today);
|
final obj = MemoryAlbumHelper(today: today, dayRange: 2);
|
||||||
final file = util.buildJpegFile(
|
final file = util.buildJpegFile(
|
||||||
path: "", fileId: 0, lastModified: DateTime.utc(2020, 1, 1));
|
path: "", fileId: 0, lastModified: DateTime.utc(2020, 1, 1));
|
||||||
obj.addFile(file);
|
obj.addFile(file);
|
||||||
|
@ -386,4 +393,61 @@ void _onDec31AddJan1() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a file with 0 day offset when range = 0
|
||||||
|
///
|
||||||
|
/// Today: 2022-05-15
|
||||||
|
/// File: 2021-05-15
|
||||||
|
/// Expect: [2022]
|
||||||
|
void _onMay15AddMay15Range0() {
|
||||||
|
final today = DateTime(2022, 5, 15);
|
||||||
|
final obj = MemoryAlbumHelper(today: today, dayRange: 0);
|
||||||
|
final file = util.buildJpegFile(
|
||||||
|
path: "", fileId: 0, lastModified: DateTime.utc(2021, 5, 15));
|
||||||
|
obj.addFile(file);
|
||||||
|
expect(
|
||||||
|
obj
|
||||||
|
.build(_nameBuilder)
|
||||||
|
.map((a) => a.copyWith(lastUpdated: OrNull(DateTime(2021))))
|
||||||
|
.toList(),
|
||||||
|
[
|
||||||
|
Album(
|
||||||
|
name: "2021",
|
||||||
|
provider:
|
||||||
|
AlbumMemoryProvider(year: 2021, month: today.month, day: today.day),
|
||||||
|
coverProvider: AlbumManualCoverProvider(coverFile: file),
|
||||||
|
sortProvider: const AlbumTimeSortProvider(isAscending: false),
|
||||||
|
lastUpdated: DateTime(2021),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a file with 1 day offset when range = 0
|
||||||
|
///
|
||||||
|
/// Today: 2022-05-15
|
||||||
|
/// File: 2021-05-16
|
||||||
|
/// Expect: []
|
||||||
|
void _onMay15AddMay16Range0() {
|
||||||
|
final today = DateTime(2022, 5, 15);
|
||||||
|
final obj = MemoryAlbumHelper(today: today, dayRange: 0);
|
||||||
|
final file = util.buildJpegFile(
|
||||||
|
path: "", fileId: 0, lastModified: DateTime.utc(2021, 5, 16));
|
||||||
|
obj.addFile(file);
|
||||||
|
expect(obj.build(_nameBuilder), []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure the builder won't throw when range < 0
|
||||||
|
///
|
||||||
|
/// Today: 2022-05-15
|
||||||
|
/// File: 2021-05-16
|
||||||
|
/// Expect: []
|
||||||
|
void _onMay15AddMay16RangeNegative() {
|
||||||
|
final today = DateTime(2022, 5, 15);
|
||||||
|
final obj = MemoryAlbumHelper(today: today, dayRange: -1);
|
||||||
|
final file = util.buildJpegFile(
|
||||||
|
path: "", fileId: 0, lastModified: DateTime.utc(2021, 5, 16));
|
||||||
|
obj.addFile(file);
|
||||||
|
expect(obj.build(_nameBuilder), []);
|
||||||
|
}
|
||||||
|
|
||||||
String _nameBuilder(int year) => "$year";
|
String _nameBuilder(int year) => "$year";
|
||||||
|
|
Loading…
Reference in a new issue