mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat(mobile): custom date range for map
This commit is contained in:
@@ -9,6 +9,22 @@ import 'package:immich_mobile/providers/map/map_state.provider.dart';
|
||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
class CustomTimeRange {
|
||||
final DateTime? from;
|
||||
final DateTime? to;
|
||||
|
||||
const CustomTimeRange({this.from, this.to});
|
||||
|
||||
bool get isValid => from != null || to != null;
|
||||
|
||||
CustomTimeRange copyWith({DateTime? from, DateTime? to}) {
|
||||
return CustomTimeRange(from: from ?? this.from, to: to ?? this.to);
|
||||
}
|
||||
|
||||
CustomTimeRange clearFrom() => CustomTimeRange(to: to);
|
||||
CustomTimeRange clearTo() => CustomTimeRange(from: from);
|
||||
}
|
||||
|
||||
class MapState {
|
||||
final ThemeMode themeMode;
|
||||
final LatLngBounds bounds;
|
||||
@@ -16,6 +32,7 @@ class MapState {
|
||||
final bool includeArchived;
|
||||
final bool withPartners;
|
||||
final int relativeDays;
|
||||
final CustomTimeRange customTimeRange;
|
||||
|
||||
const MapState({
|
||||
this.themeMode = ThemeMode.system,
|
||||
@@ -24,6 +41,7 @@ class MapState {
|
||||
this.includeArchived = false,
|
||||
this.withPartners = false,
|
||||
this.relativeDays = 0,
|
||||
this.customTimeRange = const CustomTimeRange(),
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -41,6 +59,7 @@ class MapState {
|
||||
bool? includeArchived,
|
||||
bool? withPartners,
|
||||
int? relativeDays,
|
||||
CustomTimeRange? customTimeRange,
|
||||
}) {
|
||||
return MapState(
|
||||
bounds: bounds ?? this.bounds,
|
||||
@@ -49,6 +68,7 @@ class MapState {
|
||||
includeArchived: includeArchived ?? this.includeArchived,
|
||||
withPartners: withPartners ?? this.withPartners,
|
||||
relativeDays: relativeDays ?? this.relativeDays,
|
||||
customTimeRange: customTimeRange ?? this.customTimeRange,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,6 +78,7 @@ class MapState {
|
||||
includeArchived: includeArchived,
|
||||
withPartners: withPartners,
|
||||
relativeDays: relativeDays,
|
||||
customTimeRange: customTimeRange,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,9 +125,22 @@ class MapStateNotifier extends Notifier<MapState> {
|
||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||
}
|
||||
|
||||
void setCustomTimeRange(CustomTimeRange range) {
|
||||
ref
|
||||
.read(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.mapCustomFrom, range.from == null ? "" : range.from!.toIso8601String());
|
||||
ref
|
||||
.read(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.mapCustomTo, range.to == null ? "" : range.to!.toIso8601String());
|
||||
state = state.copyWith(customTimeRange: range);
|
||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||
}
|
||||
|
||||
@override
|
||||
MapState build() {
|
||||
final appSettingsService = ref.read(appSettingsServiceProvider);
|
||||
final customFrom = appSettingsService.getSetting(AppSettingsEnum.mapCustomFrom);
|
||||
final customTo = appSettingsService.getSetting(AppSettingsEnum.mapCustomTo);
|
||||
return MapState(
|
||||
themeMode: ThemeMode.values[appSettingsService.getSetting(AppSettingsEnum.mapThemeMode)],
|
||||
onlyFavorites: appSettingsService.getSetting(AppSettingsEnum.mapShowFavoriteOnly),
|
||||
@@ -114,6 +148,10 @@ class MapStateNotifier extends Notifier<MapState> {
|
||||
withPartners: appSettingsService.getSetting(AppSettingsEnum.mapwithPartners),
|
||||
relativeDays: appSettingsService.getSetting(AppSettingsEnum.mapRelativeDate),
|
||||
bounds: LatLngBounds(northeast: const LatLng(0, 0), southwest: const LatLng(0, 0)),
|
||||
customTimeRange: CustomTimeRange(
|
||||
from: customFrom.isNotEmpty ? DateTime.parse(customFrom) : null,
|
||||
to: customTo.isNotEmpty ? DateTime.parse(customTo) : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,35 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
|
||||
import 'package:immich_mobile/widgets/map/map_settings/map_custom_time_range.dart';
|
||||
import 'package:immich_mobile/widgets/map/map_settings/map_settings_list_tile.dart';
|
||||
import 'package:immich_mobile/widgets/map/map_settings/map_settings_time_dropdown.dart';
|
||||
import 'package:immich_mobile/widgets/map/map_settings/map_theme_picker.dart';
|
||||
|
||||
class DriftMapSettingsSheet extends HookConsumerWidget {
|
||||
class DriftMapSettingsSheet extends ConsumerStatefulWidget {
|
||||
const DriftMapSettingsSheet({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
ConsumerState<DriftMapSettingsSheet> createState() => _DriftMapSettingsSheetState();
|
||||
}
|
||||
|
||||
class _DriftMapSettingsSheetState extends ConsumerState<DriftMapSettingsSheet> {
|
||||
late bool useCustomRange;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final mapState = ref.read(mapStateProvider);
|
||||
useCustomRange = mapState.customTimeRange.isValid;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mapState = ref.watch(mapStateProvider);
|
||||
|
||||
return DraggableScrollableSheet(
|
||||
expand: false,
|
||||
initialChildSize: 0.6,
|
||||
initialChildSize: useCustomRange ? 0.7 : 0.6,
|
||||
builder: (ctx, scrollController) => SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Card(
|
||||
@@ -47,10 +62,41 @@ class DriftMapSettingsSheet extends HookConsumerWidget {
|
||||
selected: mapState.withPartners,
|
||||
onChanged: (withPartners) => ref.read(mapStateProvider.notifier).switchWithPartners(withPartners),
|
||||
),
|
||||
MapTimeDropDown(
|
||||
relativeTime: mapState.relativeDays,
|
||||
onTimeChange: (time) => ref.read(mapStateProvider.notifier).setRelativeTime(time),
|
||||
),
|
||||
if (useCustomRange) ...[
|
||||
MapCustomTimeRange(
|
||||
customTimeRange: mapState.customTimeRange,
|
||||
onChanged: (range) {
|
||||
ref.read(mapStateProvider.notifier).setCustomTimeRange(range);
|
||||
},
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: TextButton(
|
||||
onPressed: () => setState(() {
|
||||
useCustomRange = false;
|
||||
ref.read(mapStateProvider.notifier).setRelativeTime(0);
|
||||
ref.read(mapStateProvider.notifier).setCustomTimeRange(const CustomTimeRange());
|
||||
}),
|
||||
child: Text("remove_custom_date_range".t(context: context)),
|
||||
),
|
||||
),
|
||||
] else ...[
|
||||
MapTimeDropDown(
|
||||
relativeTime: mapState.relativeDays,
|
||||
onTimeChange: (time) => ref.read(mapStateProvider.notifier).setRelativeTime(time),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: TextButton(
|
||||
onPressed: () => setState(() {
|
||||
useCustomRange = true;
|
||||
ref.read(mapStateProvider.notifier).setRelativeTime(0);
|
||||
ref.read(mapStateProvider.notifier).setCustomTimeRange(const CustomTimeRange());
|
||||
}),
|
||||
child: Text("use_custom_date_range".t(context: context)),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user