From 655ce1a3fe72018115656f8b79dab46b42421480 Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Sat, 24 Aug 2024 23:07:25 +0800 Subject: [PATCH] Allow using custom time range in map --- app/lib/controller/pref_controller.dart | 9 +++++ app/lib/controller/pref_controller.g.dart | 9 +++++ app/lib/controller/pref_controller/type.dart | 1 + app/lib/controller/pref_controller/util.dart | 6 ++++ app/lib/entity/pref.dart | 3 ++ app/lib/widget/map_browser/bloc.dart | 35 +++++++++++++++++--- app/lib/widget/map_browser/type.dart | 4 ++- app/lib/widget/map_browser/view.dart | 6 ++-- 8 files changed, 66 insertions(+), 7 deletions(-) diff --git a/app/lib/controller/pref_controller.dart b/app/lib/controller/pref_controller.dart index 8de8a75d..7c609435 100644 --- a/app/lib/controller/pref_controller.dart +++ b/app/lib/controller/pref_controller.dart @@ -204,6 +204,12 @@ class PrefController { value: value, ); + Future setMapDefaultCustomRange(Duration value) => _set( + controller: _mapDefaultCustomRangeController, + setter: (pref, value) => pref.setMapDefaultCustomRange(value), + value: value, + ); + Future _set({ required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, @@ -328,6 +334,9 @@ class PrefController { @npSubjectAccessor late final _mapDefaultRangeTypeController = BehaviorSubject.seeded( pref.getMapDefaultRangeType() ?? PrefMapDefaultRangeType.thisMonth); + @npSubjectAccessor + late final _mapDefaultCustomRangeController = BehaviorSubject.seeded( + pref.getMapDefaultCustomRange() ?? const Duration(days: 30)); } extension PrefControllerExtension on PrefController { diff --git a/app/lib/controller/pref_controller.g.dart b/app/lib/controller/pref_controller.g.dart index dc0ebdfe..af146361 100644 --- a/app/lib/controller/pref_controller.g.dart +++ b/app/lib/controller/pref_controller.g.dart @@ -197,6 +197,15 @@ extension $PrefControllerNpSubjectAccessor on PrefController { mapDefaultRangeType.distinct().skip(1); PrefMapDefaultRangeType get mapDefaultRangeTypeValue => _mapDefaultRangeTypeController.value; +// _mapDefaultCustomRangeController + ValueStream get mapDefaultCustomRange => + _mapDefaultCustomRangeController.stream; + Stream get mapDefaultCustomRangeNew => + mapDefaultCustomRange.skip(1); + Stream get mapDefaultCustomRangeChange => + mapDefaultCustomRange.distinct().skip(1); + Duration get mapDefaultCustomRangeValue => + _mapDefaultCustomRangeController.value; } extension $SecurePrefControllerNpSubjectAccessor on SecurePrefController { diff --git a/app/lib/controller/pref_controller/type.dart b/app/lib/controller/pref_controller/type.dart index d327a556..43c41786 100644 --- a/app/lib/controller/pref_controller/type.dart +++ b/app/lib/controller/pref_controller/type.dart @@ -4,6 +4,7 @@ enum PrefMapDefaultRangeType { thisMonth(0), prevMonth(1), thisYear(2), + custom(3), ; const PrefMapDefaultRangeType(this.value); diff --git a/app/lib/controller/pref_controller/util.dart b/app/lib/controller/pref_controller/util.dart index 64f0b395..3687ee62 100644 --- a/app/lib/controller/pref_controller/util.dart +++ b/app/lib/controller/pref_controller/util.dart @@ -125,6 +125,12 @@ extension on Pref { ?.let(PrefMapDefaultRangeType.fromValue); Future setMapDefaultRangeType(PrefMapDefaultRangeType value) => provider.setInt(PrefKey.mapDefaultRangeType, value.value); + + Duration? getMapDefaultCustomRange() => provider + .getInt(PrefKey.mapDefaultCustomRange) + ?.let((v) => Duration(days: v)); + Future setMapDefaultCustomRange(Duration value) => + provider.setInt(PrefKey.mapDefaultCustomRange, value.inDays); } MapCoord? _tryMapCoordFromJson(dynamic json) { diff --git a/app/lib/entity/pref.dart b/app/lib/entity/pref.dart index 668d2651..ae4b253a 100644 --- a/app/lib/entity/pref.dart +++ b/app/lib/entity/pref.dart @@ -116,6 +116,7 @@ enum PrefKey implements PrefKeyInterface { mapBrowserPrevPosition, isNewHttpEngine, mapDefaultRangeType, + mapDefaultCustomRange, ; @override @@ -208,6 +209,8 @@ enum PrefKey implements PrefKeyInterface { return "isNewHttpEngine"; case PrefKey.mapDefaultRangeType: return "mapDefaultRangeType"; + case PrefKey.mapDefaultCustomRange: + return "mapDefaultCustomRange"; } } } diff --git a/app/lib/widget/map_browser/bloc.dart b/app/lib/widget/map_browser/bloc.dart index e44e99e7..1425b5f7 100644 --- a/app/lib/widget/map_browser/bloc.dart +++ b/app/lib/widget/map_browser/bloc.dart @@ -54,10 +54,24 @@ class _Bloc extends Bloc<_Event, _State> static _State _getInitialState(PrefController prefController) { final dateRangeType = _DateRangeType.fromPref(prefController.mapDefaultRangeTypeValue); - return _State.init( - dateRangeType: dateRangeType, - localDateRange: _calcDateRange(clock.now().toDate(), dateRangeType), - ); + if (dateRangeType == _DateRangeType.custom) { + final today = clock.now().toDate(); + return _State.init( + dateRangeType: dateRangeType, + localDateRange: DateRange( + from: today.add( + day: -prefController.mapDefaultCustomRangeValue.inDays, + ), + to: today, + toBound: TimeRangeBound.inclusive, + ), + ); + } else { + return _State.init( + dateRangeType: dateRangeType, + localDateRange: _calcDateRange(clock.now().toDate(), dateRangeType), + ); + } } Future _onLoadData(_LoadData ev, Emitter<_State> emit) async { @@ -118,6 +132,10 @@ class _Bloc extends Bloc<_Event, _State> dateRangeType: _DateRangeType.custom, localDateRange: ev.value, )); + if (prefController.mapDefaultRangeTypeValue == + PrefMapDefaultRangeType.custom) { + _updatePrefDefaultCustomRange(ev.value); + } } void _onSetPrefDateRangeType(_SetPrefDateRangeType ev, Emitter<_State> emit) { @@ -128,6 +146,9 @@ class _Bloc extends Bloc<_Event, _State> void _onSetAsDefaultRange(_SetAsDefaultRange ev, Emitter<_State> emit) { _log.info(ev); prefController.setMapDefaultRangeType(state.dateRangeType.toPref()); + if (state.dateRangeType == _DateRangeType.custom) { + _updatePrefDefaultCustomRange(state.localDateRange); + } } void _onSetError(_SetError ev, Emitter<_State> emit) { @@ -173,6 +194,12 @@ class _Bloc extends Bloc<_Event, _State> } } + void _updatePrefDefaultCustomRange(DateRange value) { + final today = clock.now().toDate(); + final diff = today.difference(value.from!); + prefController.setMapDefaultCustomRange(diff); + } + final DiContainer _c; final Account account; final PrefController prefController; diff --git a/app/lib/widget/map_browser/type.dart b/app/lib/widget/map_browser/type.dart index c20284b2..ba9a3c33 100644 --- a/app/lib/widget/map_browser/type.dart +++ b/app/lib/widget/map_browser/type.dart @@ -259,6 +259,8 @@ enum _DateRangeType { return prevMonth; case PrefMapDefaultRangeType.thisYear: return thisYear; + case PrefMapDefaultRangeType.custom: + return custom; } } @@ -284,7 +286,7 @@ enum _DateRangeType { case thisYear: return PrefMapDefaultRangeType.thisYear; case custom: - throw ArgumentError("Value not supported"); + return PrefMapDefaultRangeType.custom; } } } diff --git a/app/lib/widget/map_browser/view.dart b/app/lib/widget/map_browser/view.dart index bb91fe36..0b1aec47 100644 --- a/app/lib/widget/map_browser/view.dart +++ b/app/lib/widget/map_browser/view.dart @@ -401,10 +401,12 @@ class _SetAsDefaultSwitch extends StatelessWidget { return _BlocBuilder( buildWhen: (previous, current) => previous.dateRangeType != current.dateRangeType || - previous.prefDateRangeType != current.prefDateRangeType, + previous.prefDateRangeType != current.prefDateRangeType || + previous.localDateRange != current.localDateRange, builder: (context, state) { final isChecked = state.dateRangeType == state.prefDateRangeType; - final isEnabled = state.dateRangeType != _DateRangeType.custom; + final isEnabled = state.dateRangeType != _DateRangeType.custom || + state.localDateRange.to == clock.now().toDate(); return InkWell( customBorder: RoundedRectangleBorder(borderRadius: BorderRadius.circular(64)),