2024-07-08 18:57:03 +02:00
|
|
|
part of '../map_browser.dart';
|
|
|
|
|
|
|
|
@npLog
|
|
|
|
class _Bloc extends Bloc<_Event, _State>
|
|
|
|
with BlocLogger, BlocForEachMixin<_Event, _State> {
|
|
|
|
_Bloc(
|
|
|
|
this._c, {
|
|
|
|
required this.account,
|
2024-07-19 21:34:46 +02:00
|
|
|
required this.prefController,
|
2024-07-14 19:42:39 +02:00
|
|
|
}) : super(_State.init(
|
|
|
|
dateRangeType: _DateRangeType.thisMonth,
|
|
|
|
localDateRange:
|
|
|
|
_calcDateRange(clock.now().toDate(), _DateRangeType.thisMonth),
|
|
|
|
)) {
|
|
|
|
on<_LoadData>(_onLoadData);
|
|
|
|
on<_OpenDataRangeControlPanel>(_onOpenDataRangeControlPanel);
|
|
|
|
on<_CloseControlPanel>(_onCloseControlPanel);
|
|
|
|
on<_SetDateRangeType>(_onSetDateRangeType);
|
|
|
|
on<_SetLocalDateRange>(_onSetDateRange);
|
2024-07-08 18:57:03 +02:00
|
|
|
on<_SetError>(_onSetError);
|
2024-07-14 19:42:39 +02:00
|
|
|
|
2024-07-22 17:16:26 +02:00
|
|
|
_subscriptions.add(stream
|
|
|
|
.distinctByIgnoreFirst((state) => state.localDateRange)
|
|
|
|
.listen((state) {
|
2024-07-14 19:42:39 +02:00
|
|
|
add(const _LoadData());
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void> close() {
|
|
|
|
for (final s in _subscriptions) {
|
|
|
|
s.cancel();
|
|
|
|
}
|
|
|
|
return super.close();
|
2024-07-08 18:57:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
String get tag => _log.fullName;
|
|
|
|
|
|
|
|
@override
|
|
|
|
void onError(Object error, StackTrace stackTrace) {
|
|
|
|
// we need this to prevent onError being triggered recursively
|
|
|
|
if (!isClosed && !_isHandlingError) {
|
|
|
|
_isHandlingError = true;
|
|
|
|
try {
|
|
|
|
add(_SetError(error, stackTrace));
|
|
|
|
} catch (_) {}
|
|
|
|
_isHandlingError = false;
|
|
|
|
}
|
|
|
|
super.onError(error, stackTrace);
|
|
|
|
}
|
|
|
|
|
2024-07-14 19:42:39 +02:00
|
|
|
Future<void> _onLoadData(_LoadData ev, Emitter<_State> emit) async {
|
2024-07-08 18:57:03 +02:00
|
|
|
_log.info(ev);
|
2024-07-14 19:42:39 +02:00
|
|
|
// convert local DateRange to TimeRange in UTC
|
|
|
|
final localTimeRange = state.localDateRange.toLocalTimeRange();
|
|
|
|
final utcTimeRange = localTimeRange.copyWith(
|
|
|
|
from: localTimeRange.from?.toUtc(),
|
|
|
|
to: localTimeRange.to?.toUtc(),
|
|
|
|
);
|
|
|
|
final raw = await _c.imageLocationRepo.getLocations(account, utcTimeRange);
|
|
|
|
_log.info("[_onLoadData] Loaded ${raw.length} markers");
|
2024-07-19 21:34:46 +02:00
|
|
|
if (state.initialPoint == null) {
|
|
|
|
final initialPoint =
|
|
|
|
raw.firstOrNull?.let((obj) => MapCoord(obj.latitude, obj.longitude));
|
|
|
|
if (initialPoint != null) {
|
|
|
|
unawaited(prefController.setMapBrowserPrevPosition(initialPoint));
|
|
|
|
}
|
|
|
|
emit(state.copyWith(
|
|
|
|
data: raw.map(_DataPoint.fromImageLatLng).toList(),
|
|
|
|
initialPoint: initialPoint,
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
emit(state.copyWith(
|
|
|
|
data: raw.map(_DataPoint.fromImageLatLng).toList(),
|
|
|
|
));
|
|
|
|
}
|
2024-07-08 18:57:03 +02:00
|
|
|
}
|
|
|
|
|
2024-07-14 19:42:39 +02:00
|
|
|
void _onOpenDataRangeControlPanel(
|
|
|
|
_OpenDataRangeControlPanel ev, Emitter<_State> emit) {
|
|
|
|
_log.info(ev);
|
|
|
|
emit(state.copyWith(
|
|
|
|
isShowDataRangeControlPanel: true,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onCloseControlPanel(_CloseControlPanel ev, Emitter<_State> emit) {
|
|
|
|
_log.info(ev);
|
|
|
|
emit(state.copyWith(
|
|
|
|
isShowDataRangeControlPanel: false,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onSetDateRangeType(_SetDateRangeType ev, Emitter<_State> emit) {
|
|
|
|
_log.info(ev);
|
|
|
|
emit(state.copyWith(
|
|
|
|
dateRangeType: ev.value,
|
|
|
|
localDateRange: ev.value == _DateRangeType.custom
|
|
|
|
? null
|
|
|
|
: _calcDateRange(clock.now().toDate(), ev.value),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onSetDateRange(_SetLocalDateRange ev, Emitter<_State> emit) {
|
|
|
|
_log.info(ev);
|
|
|
|
emit(state.copyWith(
|
|
|
|
dateRangeType: _DateRangeType.custom,
|
|
|
|
localDateRange: ev.value,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2024-07-08 18:57:03 +02:00
|
|
|
void _onSetError(_SetError ev, Emitter<_State> emit) {
|
|
|
|
_log.info(ev);
|
|
|
|
emit(state.copyWith(error: ExceptionEvent(ev.error, ev.stackTrace)));
|
|
|
|
}
|
|
|
|
|
2024-07-14 19:42:39 +02:00
|
|
|
static DateRange _calcDateRange(Date today, _DateRangeType type) {
|
|
|
|
assert(type != _DateRangeType.custom);
|
|
|
|
switch (type) {
|
|
|
|
case _DateRangeType.thisMonth:
|
|
|
|
return DateRange(
|
|
|
|
from: today.copyWith(day: 1),
|
|
|
|
to: today,
|
|
|
|
toBound: TimeRangeBound.inclusive,
|
|
|
|
);
|
|
|
|
case _DateRangeType.prevMonth:
|
|
|
|
if (today.month == 1) {
|
|
|
|
return DateRange(
|
|
|
|
from: Date(today.year - 1, 12, 1),
|
|
|
|
to: Date(today.year - 1, 12, 31),
|
|
|
|
toBound: TimeRangeBound.inclusive,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return DateRange(
|
|
|
|
from: Date(today.year, today.month - 1, 1),
|
|
|
|
to: Date(today.year, today.month, 1).add(day: -1),
|
|
|
|
toBound: TimeRangeBound.inclusive,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
case _DateRangeType.thisYear:
|
|
|
|
return DateRange(
|
|
|
|
from: today.copyWith(month: 1, day: 1),
|
|
|
|
to: today,
|
|
|
|
toBound: TimeRangeBound.inclusive,
|
|
|
|
);
|
|
|
|
case _DateRangeType.custom:
|
|
|
|
return DateRange(
|
|
|
|
from: today,
|
|
|
|
to: today,
|
|
|
|
toBound: TimeRangeBound.inclusive,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-08 18:57:03 +02:00
|
|
|
final DiContainer _c;
|
|
|
|
final Account account;
|
2024-07-19 21:34:46 +02:00
|
|
|
final PrefController prefController;
|
2024-07-08 18:57:03 +02:00
|
|
|
|
2024-07-14 19:42:39 +02:00
|
|
|
final _subscriptions = <StreamSubscription>[];
|
|
|
|
|
2024-07-08 18:57:03 +02:00
|
|
|
var _isHandlingError = false;
|
|
|
|
}
|