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 { final (String, String) deviceId; SettingsState settingsState; Option _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((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((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((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> 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 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().updatePoint(deviceId.$1, deviceId.$2, pt); } } print("upb $deviceId: $transition"); } }