import 'dart:async'; import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/models/service.dart'; part 'services_event.dart'; part 'services_state.dart'; class ServicesBloc extends Bloc { ServicesBloc() : super(ServicesInitial()) { on( _updateList, transformer: sequential(), ); on( _reload, transformer: droppable(), ); on( _restart, transformer: sequential(), ); on( _move, transformer: sequential(), ); final connectionRepository = getIt(); _apiDataSubscription = connectionRepository.dataStream.listen( (final ApiData apiData) { add( ServicesListUpdate([...apiData.services.data ?? []]), ); }, ); if (connectionRepository.connectionStatus == ConnectionStatus.connected) { add( ServicesListUpdate( [...connectionRepository.apiData.services.data ?? []], ), ); } } Future _updateList( final ServicesListUpdate event, final Emitter emit, ) async { if (event.services.isEmpty) { emit(ServicesInitial()); return; } final newState = ServicesLoaded( services: event.services, lockedServices: state._lockedServices, ); emit(newState); } Future _reload( final ServicesReload event, final Emitter emit, ) async { final currentState = state; if (currentState is ServicesLoaded) { emit(ServicesReloading.fromState(currentState)); getIt().apiData.services.invalidate(); await getIt().reload(null); } } Future awaitReload() async { final currentState = state; if (currentState is ServicesLoaded) { getIt().apiData.services.invalidate(); await getIt().reload(null); } } Future _restart( final ServiceRestart event, final Emitter emit, ) async { emit( state.copyWith( lockedServices: [ ...state._lockedServices, ServiceLock( serviceId: event.service.id, lockDuration: const Duration(seconds: 15), ), ], ), ); final result = await getIt() .api .restartService(event.service.id); if (!result.success) { getIt().showSnackBar('jobs.generic_error'.tr()); return; } if (!result.data) { getIt() .showSnackBar(result.message ?? 'jobs.generic_error'.tr()); return; } } Future _move( final ServiceMove event, final Emitter emit, ) async { final migrationJob = await getIt() .api .moveService(event.service.id, event.destination); if (!migrationJob.success) { getIt() .showSnackBar(migrationJob.message ?? 'jobs.generic_error'.tr()); } if (migrationJob.data != null) { getIt() .apiData .serverJobs .data ?.add(migrationJob.data!); getIt().emitData(); } } late StreamSubscription _apiDataSubscription; @override void onChange(final Change change) { super.onChange(change); } @override Future close() { _apiDataSubscription.cancel(); return super.close(); } }