owntracks-viewer/lib/user_path_bloc.dart

107 lines
3.6 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:ot_viewer_app/global_location_store.dart';
import 'package:rust_core/option.dart';
import 'package:anyhow/anyhow.dart';
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:ot_viewer_app/owntracks_api.dart';
import 'package:ot_viewer_app/settings_page.dart';
import 'package:ws/ws.dart';
part 'user_path_event.dart';
part 'user_path_state.dart';
class UserPathBloc extends Bloc<UserPathEvent, UserPathState> {
final (String, String) deviceId;
SettingsState settingsState;
Option<WebSocketClient> _ws = None;
OwntracksApi get _api =>
OwntracksApi(baseUrl: settingsState.url, username: settingsState.username, pass: settingsState.password);
UserPathBloc(this.deviceId, this.settingsState)
: super(MainUserPathState(
initialPoints: const IListConst([]),
livePoints: const IListConst([]),
from: DateTime.now().subtract(settingsState.historyTime),
to: DateTime.now())) /*.add(const Duration(days: 365 * 100)))) */ {
on<UserPathLoginDataChanged>((event, emit) {
if (event.newSettings == settingsState) {
print('settings states the same, returning. states:\nold: $settingsState\nnew: ${event.newSettings}');
return;
}
settingsState = event.newSettings;
emit(MainUserPathState.copy(
state as MainUserPathState,
from: DateTime.now().subtract(settingsState.historyTime),
));
print('settings states differ, doing full update');
add(UserPathFullUpdate());
});
on<UserPathLiveSubscriptionUpdate>((event, emit) {
print("DEBUG: adding point ${event.point} to bloc $deviceId");
emit(MainUserPathState.copy(
state as MainUserPathState,
// FIXME: inefficient as heck. Maybe use fast_immutable_collections package?
livePoints: (state as MainUserPathState).livePoints.add(event.point),
));
});
on<UserPathFullUpdate>((event, emit) async {
print("fpu");
if (state is MainUserPathState) {
final istate = state as MainUserPathState;
var history = await _api.fetchPointsForDevice(
user: deviceId.$1,
device: deviceId.$2,
from: istate.from,
to: istate.to,
);
history = await history.toFutureResult().map((h) async {
if (h.isEmpty) {
final last = await _api.fetchLastPoint(user: deviceId.$1, device: deviceId.$2);
if (last.isOk()) {
return [last.unwrap()];
}
}
return h;
});
final Result<List<Point>> livePoints = history.map((ok) => ok.isNotEmpty ? [ok.last] : []);
emit(MainUserPathState(
initialPoints: history.expect("Couldn't retrieve path history for $deviceId").lock,
livePoints: livePoints.expect("Couldn\'t retrieve last (current) point").lock,
from: istate.from,
to: istate.to));
}
});
}
@override
void onTransition(Transition<UserPathEvent, UserPathState> transition) {
super.onTransition(transition);
if (transition.nextState is MainUserPathState) {
// add current location to global location thingy
final pt = (transition.nextState as MainUserPathState).livePoints.lastOrNull;
if (pt != null) {
GetIt.I.get<GlobalLocationStoreCubit>().updatePoint(deviceId.$1, deviceId.$2, pt);
}
}
print("upb $deviceId: $transition");
}
}