diff --git a/mobile/lib/presentation/pages/search/drift_search.page.dart b/mobile/lib/presentation/pages/search/drift_search.page.dart index 425c4985e9..ebbefcb11b 100644 --- a/mobile/lib/presentation/pages/search/drift_search.page.dart +++ b/mobile/lib/presentation/pages/search/drift_search.page.dart @@ -26,6 +26,7 @@ import 'package:immich_mobile/widgets/search/search_filter/filter_bottom_sheet_s import 'package:immich_mobile/widgets/search/search_filter/location_picker.dart'; import 'package:immich_mobile/widgets/search/search_filter/media_type_picker.dart'; import 'package:immich_mobile/widgets/search/search_filter/people_picker.dart'; +import 'package:immich_mobile/widgets/search/search_filter/quick_date_picker.dart'; import 'package:immich_mobile/widgets/search/search_filter/search_filter_chip.dart'; import 'package:immich_mobile/widgets/search/search_filter/search_filter_utils.dart'; @@ -242,31 +243,7 @@ class DriftSearchPage extends HookConsumerWidget { ); } - showDatePicker() async { - final firstDate = DateTime(1900); - final lastDate = DateTime.now(); - - final date = await showDateRangePicker( - context: context, - firstDate: firstDate, - lastDate: lastDate, - currentDate: DateTime.now(), - initialDateRange: DateTimeRange( - start: filter.value.date.takenAfter ?? lastDate, - end: filter.value.date.takenBefore ?? lastDate, - ), - helpText: 'search_filter_date_title'.t(context: context), - cancelText: 'cancel'.t(context: context), - confirmText: 'select'.t(context: context), - saveText: 'save'.t(context: context), - errorFormatText: 'invalid_date_format'.t(context: context), - errorInvalidText: 'invalid_date'.t(context: context), - fieldStartHintText: 'start_date'.t(context: context), - fieldEndHintText: 'end_date'.t(context: context), - initialEntryMode: DatePickerEntryMode.calendar, - keyboardType: TextInputType.text, - ); - + datePicked(DateTimeRange? date) { if (date == null) { filter.value = filter.value.copyWith(date: SearchDateFilter()); @@ -304,6 +281,55 @@ class DriftSearchPage extends HookConsumerWidget { search(); } + showDatePicker() async { + final firstDate = DateTime(1900); + final lastDate = DateTime.now(); + + final date = await showDateRangePicker( + context: context, + firstDate: firstDate, + lastDate: lastDate, + currentDate: DateTime.now(), + initialDateRange: DateTimeRange( + start: filter.value.date.takenAfter ?? lastDate, + end: filter.value.date.takenBefore ?? lastDate, + ), + helpText: 'search_filter_date_title'.t(context: context), + cancelText: 'cancel'.t(context: context), + confirmText: 'select'.t(context: context), + saveText: 'save'.t(context: context), + errorFormatText: 'invalid_date_format'.t(context: context), + errorInvalidText: 'invalid_date'.t(context: context), + fieldStartHintText: 'start_date'.t(context: context), + fieldEndHintText: 'end_date'.t(context: context), + initialEntryMode: DatePickerEntryMode.calendar, + keyboardType: TextInputType.text, + ); + + datePicked(date); + } + + showQuickDatePicker() { + showFilterBottomSheet( + context: context, + child: FilterBottomSheetScaffold( + title: "Pick date range", + expanded: true, + onClear: () => datePicked(null), + child: QuickDatePicker( + onRequestPicker: () { + context.pop(); + showDatePicker(); + }, + onSelect: (date) { + context.pop(); + datePicked(date); + }, + ), + ), + ); + } + // MEDIA PICKER showMediaTypePicker() { handleOnSelected(AssetType assetType) { @@ -561,7 +587,7 @@ class DriftSearchPage extends HookConsumerWidget { ), SearchFilterChip( icon: Icons.date_range_outlined, - onTap: showDatePicker, + onTap: showQuickDatePicker, label: 'search_filter_date'.t(context: context), currentFilter: dateRangeCurrentFilterWidget.value, ), diff --git a/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart b/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart index e8226b5b3a..dee42ec5a0 100644 --- a/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart +++ b/mobile/lib/widgets/search/search_filter/filter_bottom_sheet_scaffold.dart @@ -6,7 +6,7 @@ class FilterBottomSheetScaffold extends StatelessWidget { const FilterBottomSheetScaffold({ super.key, required this.child, - required this.onSearch, + this.onSearch, required this.onClear, required this.title, this.expanded, @@ -15,7 +15,7 @@ class FilterBottomSheetScaffold extends StatelessWidget { final bool? expanded; final String title; final Widget child; - final Function() onSearch; + final Function()? onSearch; final Function() onClear; @override @@ -48,15 +48,16 @@ class FilterBottomSheetScaffold extends StatelessWidget { }, child: const Text('clear').tr(), ), - const SizedBox(width: 8), - ElevatedButton( - key: const Key('search_filter_apply'), - onPressed: () { - onSearch(); - context.pop(); - }, - child: const Text('search_filter_apply').tr(), - ), + if (onSearch != null) const SizedBox(width: 8), + if (onSearch != null) + ElevatedButton( + key: const Key('search_filter_apply'), + onPressed: () { + onSearch!(); + context.pop(); + }, + child: const Text('search_filter_apply').tr(), + ), ], ), ), diff --git a/mobile/lib/widgets/search/search_filter/quick_date_picker.dart b/mobile/lib/widgets/search/search_filter/quick_date_picker.dart new file mode 100644 index 0000000000..79950bde96 --- /dev/null +++ b/mobile/lib/widgets/search/search_filter/quick_date_picker.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; + +class QuickDatePicker extends HookWidget { + const QuickDatePicker({super.key, required this.onSelect, required this.onRequestPicker}); + + final Function() onRequestPicker; + final Function(DateTimeRange range) onSelect; + + ListTile _monthListTile(String text, int monthsFromNow) { + return ListTile( + title: Text(text), + onTap: () { + final now = DateTime.now(); + final from = DateTime(now.year, now.month - monthsFromNow, now.day); + onSelect(DateTimeRange(start: from, end: now)); + }, + ); + } + + @override + Widget build(BuildContext context) { + return ListView.builder( + itemBuilder: (context, index) { + if (index == 0) { + return ListTile( + title: const Text("Exact date"), + onTap: () { + onRequestPicker(); + }, + ); + } else if (index == 1) { + return _monthListTile("Last month", 1); + } else if (index == 2) { + return _monthListTile("Last 3 months", 3); + } else if (index == 3) { + return _monthListTile("Last 9 months", 9); + } else { + final now = DateTime.now(); + final years = index - 3; + final year = now.year - years; + return ListTile( + title: Text("In $year"), + onTap: () { + final from = DateTime(year, 1, 1); + final to = DateTime(year, 12, 31, 23, 59, 59); + onSelect(DateTimeRange(start: from, end: to)); + }, + ); + } + }, + itemCount: 50, + ); + } +}