selfprivacy.org.app/lib/logic/bloc/services/services_bloc.dart
2024-01-31 16:17:27 +04:00

150 lines
3.8 KiB
Dart

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<ServicesEvent, ServicesState> {
ServicesBloc() : super(ServicesInitial()) {
on<ServicesListUpdate>(
_updateList,
transformer: sequential(),
);
on<ServicesReload>(
_reload,
transformer: droppable(),
);
on<ServiceRestart>(
_restart,
transformer: sequential(),
);
on<ServiceMove>(
_move,
transformer: sequential(),
);
final connectionRepository = getIt<ApiConnectionRepository>();
_apiDataSubscription = connectionRepository.dataStream.listen(
(final ApiData apiData) {
add(
ServicesListUpdate([...apiData.services.data ?? []]),
);
},
);
if (connectionRepository.connectionStatus == ConnectionStatus.connected) {
add(
ServicesListUpdate(
[...connectionRepository.apiData.services.data ?? []],
),
);
}
}
Future<void> _updateList(
final ServicesListUpdate event,
final Emitter<ServicesState> emit,
) async {
if (event.services.isEmpty) {
emit(ServicesInitial());
return;
}
final newState = ServicesLoaded(
services: event.services,
lockedServices: state._lockedServices,
);
emit(newState);
}
Future<void> _reload(
final ServicesReload event,
final Emitter<ServicesState> emit,
) async {
final currentState = state;
if (currentState is ServicesLoaded) {
emit(ServicesReloading.fromState(currentState));
getIt<ApiConnectionRepository>().apiData.services.invalidate();
await getIt<ApiConnectionRepository>().reload(null);
}
}
Future<void> awaitReload() async {
final currentState = state;
if (currentState is ServicesLoaded) {
getIt<ApiConnectionRepository>().apiData.services.invalidate();
await getIt<ApiConnectionRepository>().reload(null);
}
}
Future<void> _restart(
final ServiceRestart event,
final Emitter<ServicesState> emit,
) async {
emit(
state.copyWith(
lockedServices: [
...state._lockedServices,
ServiceLock(
serviceId: event.service.id,
lockDuration: const Duration(seconds: 15),
),
],
),
);
final result = await getIt<ApiConnectionRepository>()
.api
.restartService(event.service.id);
if (!result.success) {
getIt<NavigationService>().showSnackBar('jobs.generic_error'.tr());
return;
}
if (!result.data) {
getIt<NavigationService>()
.showSnackBar(result.message ?? 'jobs.generic_error'.tr());
return;
}
}
Future<void> _move(
final ServiceMove event,
final Emitter<ServicesState> emit,
) async {
final migrationJob = await getIt<ApiConnectionRepository>()
.api
.moveService(event.service.id, event.destination);
if (!migrationJob.success) {
getIt<NavigationService>()
.showSnackBar(migrationJob.message ?? 'jobs.generic_error'.tr());
}
if (migrationJob.data != null) {
getIt<ApiConnectionRepository>()
.apiData
.serverJobs
.data
?.add(migrationJob.data!);
getIt<ApiConnectionRepository>().emitData();
}
}
late StreamSubscription _apiDataSubscription;
@override
void onChange(final Change<ServicesState> change) {
super.onChange(change);
}
@override
Future<void> close() {
_apiDataSubscription.cancel();
return super.close();
}
}