mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-02-02 14:16:58 +00:00
refactor: Rewrite services cubit to bloc, using ApiRepo streams
This commit is contained in:
parent
a5e7725733
commit
831a0e95eb
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/connection_status/connection_status_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart';
|
||||
|
@ -11,7 +12,6 @@ import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
|
|||
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
|
@ -28,7 +28,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
final serverInstallationCubit = ServerInstallationCubit()..load();
|
||||
final supportSystemCubit = SupportSystemCubit();
|
||||
final usersCubit = UsersCubit(serverInstallationCubit);
|
||||
final servicesCubit = ServicesCubit(serverInstallationCubit);
|
||||
final servicesBloc = ServicesBloc();
|
||||
final backupsBloc = BackupsBloc();
|
||||
final dnsRecordsCubit = DnsRecordsCubit(serverInstallationCubit);
|
||||
final recoveryKeyCubit = RecoveryKeyCubit(serverInstallationCubit);
|
||||
|
@ -61,8 +61,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
lazy: false,
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => servicesCubit..load(),
|
||||
lazy: false,
|
||||
create: (final _) => servicesBloc,
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => backupsBloc,
|
||||
|
@ -92,7 +91,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
BlocProvider(
|
||||
create: (final _) => JobsCubit(
|
||||
usersCubit: usersCubit,
|
||||
servicesCubit: servicesCubit,
|
||||
servicesBloc: servicesBloc,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -193,7 +193,8 @@ class BackupsBloc extends Bloc<BackupsEvent, BackupsState> {
|
|||
);
|
||||
if (result.success == false) {
|
||||
getIt<NavigationService>().showSnackBar(
|
||||
result.message ?? "Couldn't initialize repository on your server.");
|
||||
result.message ?? "Couldn't initialize repository on your server.",
|
||||
);
|
||||
emit(BackupsUnititialized());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,8 @@ class BackupsUnititialized extends BackupsState {
|
|||
final BackblazeBucket? backblazeBucket,
|
||||
}) =>
|
||||
BackupsUnititialized(
|
||||
backblazeBucket: backblazeBucket ?? this.backblazeBucket);
|
||||
backblazeBucket: backblazeBucket ?? this.backblazeBucket,
|
||||
);
|
||||
}
|
||||
|
||||
class BackupsInitializing extends BackupsState {
|
||||
|
@ -86,7 +87,8 @@ class BackupsInitializing extends BackupsState {
|
|||
final BackblazeBucket? backblazeBucket,
|
||||
}) =>
|
||||
BackupsInitializing(
|
||||
backblazeBucket: backblazeBucket ?? this.backblazeBucket);
|
||||
backblazeBucket: backblazeBucket ?? this.backblazeBucket,
|
||||
);
|
||||
}
|
||||
|
||||
class BackupsInitialized extends BackupsState {
|
||||
|
|
144
lib/logic/bloc/services/services_bloc.dart
Normal file
144
lib/logic/bloc/services/services_bloc.dart
Normal file
|
@ -0,0 +1,144 @@
|
|||
import 'dart:async';
|
||||
|
||||
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()) {
|
||||
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 ?? []],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
on<ServicesListUpdate>(
|
||||
_updateList,
|
||||
);
|
||||
on<ServicesReload>(
|
||||
_reload,
|
||||
);
|
||||
on<ServiceRestart>(
|
||||
_restart,
|
||||
);
|
||||
on<ServiceMove>(
|
||||
_move,
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
40
lib/logic/bloc/services/services_event.dart
Normal file
40
lib/logic/bloc/services/services_event.dart
Normal file
|
@ -0,0 +1,40 @@
|
|||
part of 'services_bloc.dart';
|
||||
|
||||
abstract class ServicesEvent extends Equatable {
|
||||
const ServicesEvent();
|
||||
}
|
||||
|
||||
class ServicesListUpdate extends ServicesEvent {
|
||||
const ServicesListUpdate(this.services);
|
||||
|
||||
final List<Service> services;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [services];
|
||||
}
|
||||
|
||||
class ServicesReload extends ServicesEvent {
|
||||
const ServicesReload();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class ServiceRestart extends ServicesEvent {
|
||||
const ServiceRestart(this.service);
|
||||
|
||||
final Service service;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [service];
|
||||
}
|
||||
|
||||
class ServiceMove extends ServicesEvent {
|
||||
const ServiceMove(this.service, this.destination);
|
||||
|
||||
final Service service;
|
||||
final String destination;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [service, destination];
|
||||
}
|
115
lib/logic/bloc/services/services_state.dart
Normal file
115
lib/logic/bloc/services/services_state.dart
Normal file
|
@ -0,0 +1,115 @@
|
|||
part of 'services_bloc.dart';
|
||||
|
||||
abstract class ServicesState extends Equatable {
|
||||
ServicesState({final List<ServiceLock> lockedServices = const []})
|
||||
: _lockedServices =
|
||||
lockedServices.where((final lock) => lock.isLocked).toList();
|
||||
final List<ServiceLock> _lockedServices;
|
||||
List<Service> get services;
|
||||
List<String> get lockedServices => _lockedServices
|
||||
.where((final lock) => lock.isLocked)
|
||||
.map((final lock) => lock.serviceId)
|
||||
.toList();
|
||||
|
||||
List<Service> get servicesThatCanBeBackedUp => services
|
||||
.where(
|
||||
(final service) => service.canBeBackedUp,
|
||||
)
|
||||
.toList();
|
||||
|
||||
bool isServiceLocked(final String serviceId) =>
|
||||
lockedServices.contains(serviceId);
|
||||
|
||||
Service? getServiceById(final String id) {
|
||||
final service = services.firstWhere(
|
||||
(final service) => service.id == id,
|
||||
orElse: () => Service.empty,
|
||||
);
|
||||
if (service.id == 'empty') {
|
||||
return null;
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
ServicesState copyWith({
|
||||
final List<Service>? services,
|
||||
final List<ServiceLock>? lockedServices,
|
||||
});
|
||||
}
|
||||
|
||||
class ServiceLock extends Equatable {
|
||||
ServiceLock({
|
||||
required this.serviceId,
|
||||
required this.lockDuration,
|
||||
}) : lockTime = DateTime.now();
|
||||
|
||||
final String serviceId;
|
||||
final Duration lockDuration;
|
||||
final DateTime lockTime;
|
||||
|
||||
bool get isLocked => DateTime.now().isBefore(lockTime.add(lockDuration));
|
||||
|
||||
@override
|
||||
List<Object?> get props => [serviceId, lockDuration, lockTime];
|
||||
}
|
||||
|
||||
class ServicesInitial extends ServicesState {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
|
||||
@override
|
||||
List<Service> get services => [];
|
||||
|
||||
@override
|
||||
ServicesState copyWith({
|
||||
final List<Service>? services,
|
||||
final List<ServiceLock>? lockedServices,
|
||||
}) =>
|
||||
ServicesInitial();
|
||||
}
|
||||
|
||||
class ServicesLoaded extends ServicesState {
|
||||
ServicesLoaded({
|
||||
required final List<Service> services,
|
||||
required super.lockedServices,
|
||||
}) : _servicesHachCode = Object.hashAll([...services]);
|
||||
|
||||
final int _servicesHachCode;
|
||||
|
||||
final apiConnectionRepository = getIt<ApiConnectionRepository>();
|
||||
|
||||
List<Service> get _services =>
|
||||
apiConnectionRepository.apiData.services.data ?? [];
|
||||
|
||||
@override
|
||||
List<Service> get services => _services;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_servicesHachCode, _lockedServices];
|
||||
|
||||
@override
|
||||
ServicesLoaded copyWith({
|
||||
final List<Service>? services,
|
||||
final List<ServiceLock>? lockedServices,
|
||||
}) =>
|
||||
ServicesLoaded(
|
||||
services: services ?? this.services,
|
||||
lockedServices: lockedServices ?? _lockedServices,
|
||||
);
|
||||
}
|
||||
|
||||
class ServicesReloading extends ServicesLoaded {
|
||||
ServicesReloading({
|
||||
required super.services,
|
||||
required super.lockedServices,
|
||||
});
|
||||
|
||||
ServicesReloading.fromState(final ServicesLoaded state)
|
||||
: super(
|
||||
services: state.services,
|
||||
lockedServices: state._lockedServices,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [services, lockedServices];
|
||||
}
|
|
@ -5,7 +5,7 @@ import 'package:equatable/equatable.dart';
|
|||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/job.dart';
|
||||
|
||||
|
@ -16,12 +16,12 @@ part 'client_jobs_state.dart';
|
|||
class JobsCubit extends Cubit<JobsState> {
|
||||
JobsCubit({
|
||||
required this.usersCubit,
|
||||
required this.servicesCubit,
|
||||
required this.servicesBloc,
|
||||
}) : super(JobsStateEmpty());
|
||||
|
||||
final ServerApi api = ServerApi();
|
||||
final UsersCubit usersCubit;
|
||||
final ServicesCubit servicesCubit;
|
||||
final ServicesBloc servicesBloc;
|
||||
|
||||
void addJob(final ClientJob job) {
|
||||
final jobs = currentJobList;
|
||||
|
@ -90,7 +90,7 @@ class JobsCubit extends Cubit<JobsState> {
|
|||
|
||||
await api.pullConfigurationUpdate();
|
||||
await api.apply();
|
||||
await servicesCubit.load();
|
||||
servicesBloc.add(const ServicesReload());
|
||||
|
||||
emit(JobsStateEmpty());
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
|
||||
part 'services_state.dart';
|
||||
|
||||
class ServicesCubit extends ServerConnectionDependentCubit<ServicesState> {
|
||||
ServicesCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(const ServicesState.empty());
|
||||
final ServerApi api = ServerApi();
|
||||
Timer? timer;
|
||||
@override
|
||||
Future<void> load() async {
|
||||
final List<Service> services = await api.getAllServices();
|
||||
emit(
|
||||
ServicesState(
|
||||
services: services,
|
||||
lockedServices: const [],
|
||||
),
|
||||
);
|
||||
timer = Timer(const Duration(seconds: 10), () => reload(useTimer: true));
|
||||
}
|
||||
|
||||
Future<void> reload({final bool useTimer = false}) async {
|
||||
final List<Service> services = await api.getAllServices();
|
||||
emit(
|
||||
state.copyWith(
|
||||
services: services,
|
||||
),
|
||||
);
|
||||
if (useTimer) {
|
||||
timer = Timer(const Duration(seconds: 60), () => reload(useTimer: true));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restart(final String serviceId) async {
|
||||
emit(state.copyWith(lockedServices: [...state.lockedServices, serviceId]));
|
||||
final result = await api.restartService(serviceId);
|
||||
if (!result.success) {
|
||||
getIt<NavigationService>().showSnackBar('jobs.generic_error'.tr());
|
||||
return;
|
||||
}
|
||||
if (!result.data) {
|
||||
getIt<NavigationService>()
|
||||
.showSnackBar(result.message ?? 'jobs.generic_error'.tr());
|
||||
return;
|
||||
}
|
||||
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
unawaited(reload());
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
emit(
|
||||
state.copyWith(
|
||||
lockedServices: state.lockedServices
|
||||
.where((final element) => element != serviceId)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
unawaited(reload());
|
||||
}
|
||||
|
||||
Future<void> moveService(
|
||||
final String serviceId,
|
||||
final String destination,
|
||||
) async {
|
||||
await api.moveService(serviceId, destination);
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() async {
|
||||
emit(const ServicesState.empty());
|
||||
if (timer != null && timer!.isActive) {
|
||||
timer!.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
part of 'services_cubit.dart';
|
||||
|
||||
class ServicesState extends ServerInstallationDependendState {
|
||||
const ServicesState({
|
||||
required this.services,
|
||||
required this.lockedServices,
|
||||
});
|
||||
|
||||
const ServicesState.empty()
|
||||
: this(services: const [], lockedServices: const []);
|
||||
|
||||
final List<Service> services;
|
||||
final List<String> lockedServices;
|
||||
|
||||
List<Service> get servicesThatCanBeBackedUp => services
|
||||
.where(
|
||||
(final service) => service.canBeBackedUp,
|
||||
)
|
||||
.toList();
|
||||
|
||||
bool isServiceLocked(final String serviceId) =>
|
||||
lockedServices.contains(serviceId);
|
||||
|
||||
Service? getServiceById(final String id) {
|
||||
final service = services.firstWhere(
|
||||
(final service) => service.id == id,
|
||||
orElse: () => Service.empty,
|
||||
);
|
||||
if (service.id == 'empty') {
|
||||
return null;
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
services,
|
||||
lockedServices,
|
||||
];
|
||||
|
||||
ServicesState copyWith({
|
||||
final List<Service>? services,
|
||||
final List<String>? lockedServices,
|
||||
}) =>
|
||||
ServicesState(
|
||||
services: services ?? this.services,
|
||||
lockedServices: lockedServices ?? this.lockedServices,
|
||||
);
|
||||
}
|
|
@ -9,6 +9,7 @@ import 'package:selfprivacy/logic/models/backup.dart';
|
|||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
|
||||
/// Repository for all API calls
|
||||
/// Stores the current state of all data from API and exposes it to Blocs.
|
||||
|
@ -74,6 +75,7 @@ class ApiConnectionRepository {
|
|||
_apiData.serverJobs.data = await api.getServerJobs();
|
||||
_apiData.backupConfig.data = await api.getBackupsConfiguration();
|
||||
_apiData.backups.data = await api.getBackups();
|
||||
_apiData.services.data = await api.getAllServices();
|
||||
_dataStream.add(_apiData);
|
||||
|
||||
connectionStatus = ConnectionStatus.connected;
|
||||
|
@ -109,6 +111,8 @@ class ApiConnectionRepository {
|
|||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.backupConfig
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.services
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
}
|
||||
|
||||
void emitData() {
|
||||
|
@ -132,12 +136,17 @@ class ApiData {
|
|||
backups = ApiDataElement<List<Backup>>(
|
||||
fetchData: () async => api.getBackups(),
|
||||
requiredApiVersion: '>=2.4.2',
|
||||
),
|
||||
services = ApiDataElement<List<Service>>(
|
||||
fetchData: () async => api.getAllServices(),
|
||||
requiredApiVersion: '>=2.4.3',
|
||||
);
|
||||
|
||||
ApiDataElement<List<ServerJob>> serverJobs;
|
||||
ApiDataElement<String> apiVersion;
|
||||
ApiDataElement<BackupConfiguration> backupConfig;
|
||||
ApiDataElement<List<Backup>> backups;
|
||||
ApiDataElement<List<Service>> services;
|
||||
}
|
||||
|
||||
enum ConnectionStatus {
|
||||
|
@ -163,7 +172,9 @@ class ApiDataElement<T> {
|
|||
final Future<T?> Function() fetchData;
|
||||
|
||||
Future<void> refetchData(
|
||||
final Version version, final Function callback) async {
|
||||
final Version version,
|
||||
final Function callback,
|
||||
) async {
|
||||
if (VersionConstraint.parse(requiredApiVersion).allows(version)) {
|
||||
print('Fetching data for $runtimeType');
|
||||
if (isExpired) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/schema.graphql.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/services.graphql.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
|
@ -8,7 +9,7 @@ import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
|||
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_settings.graphql.dart';
|
||||
|
||||
class Service {
|
||||
class Service extends Equatable {
|
||||
Service.fromGraphQL(final Query$AllServices$services$allServices service)
|
||||
: this(
|
||||
id: service.id,
|
||||
|
@ -37,7 +38,7 @@ class Service {
|
|||
[],
|
||||
url: service.url,
|
||||
);
|
||||
Service({
|
||||
const Service({
|
||||
required this.id,
|
||||
required this.displayName,
|
||||
required this.description,
|
||||
|
@ -72,7 +73,7 @@ class Service {
|
|||
return '';
|
||||
}
|
||||
|
||||
static Service empty = Service(
|
||||
static Service empty = const Service(
|
||||
id: 'empty',
|
||||
displayName: '',
|
||||
description: '',
|
||||
|
@ -83,7 +84,7 @@ class Service {
|
|||
backupDescription: '',
|
||||
status: ServiceStatus.off,
|
||||
storageUsage: ServiceStorageUsage(
|
||||
used: const DiskSize(byte: 0),
|
||||
used: DiskSize(byte: 0),
|
||||
volume: '',
|
||||
),
|
||||
svgIcon: '',
|
||||
|
@ -104,16 +105,36 @@ class Service {
|
|||
final String svgIcon;
|
||||
final String? url;
|
||||
final List<DnsRecord> dnsRecords;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
displayName,
|
||||
description,
|
||||
isEnabled,
|
||||
isRequired,
|
||||
isMovable,
|
||||
canBeBackedUp,
|
||||
backupDescription,
|
||||
status,
|
||||
storageUsage,
|
||||
svgIcon,
|
||||
dnsRecords,
|
||||
url,
|
||||
];
|
||||
}
|
||||
|
||||
class ServiceStorageUsage {
|
||||
ServiceStorageUsage({
|
||||
class ServiceStorageUsage extends Equatable {
|
||||
const ServiceStorageUsage({
|
||||
required this.used,
|
||||
required this.volume,
|
||||
});
|
||||
|
||||
final DiskSize used;
|
||||
final String? volume;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [used, volume];
|
||||
}
|
||||
|
||||
enum ServiceStatus {
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
|
@ -39,7 +39,7 @@ class BackupDetailsPage extends StatelessWidget {
|
|||
final bool preventActions = backupsState.preventActions;
|
||||
final List<Backup> backups = backupsState.backups;
|
||||
final List<Service> services =
|
||||
context.watch<ServicesCubit>().state.servicesThatCanBeBackedUp;
|
||||
context.watch<ServicesBloc>().state.servicesThatCanBeBackedUp;
|
||||
final Duration? autobackupPeriod = backupsState.autobackupPeriod;
|
||||
final List<ServerJob> backupJobs = context
|
||||
.watch<ServerJobsBloc>()
|
||||
|
@ -298,7 +298,7 @@ class BackupDetailsPage extends StatelessWidget {
|
|||
children: backups.take(15).map(
|
||||
(final Backup backup) {
|
||||
final service = context
|
||||
.read<ServicesCubit>()
|
||||
.read<ServicesBloc>()
|
||||
.state
|
||||
.getServiceById(backup.serviceId);
|
||||
return ListTile(
|
||||
|
@ -419,7 +419,7 @@ class BackupDetailsPage extends StatelessWidget {
|
|||
: () => {
|
||||
context
|
||||
.read<BackupsBloc>()
|
||||
.add(const ForceSnapshotListUpdate())
|
||||
.add(const ForceSnapshotListUpdate()),
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||
|
@ -43,7 +43,7 @@ class BackupsListPage extends StatelessWidget {
|
|||
...backups.map(
|
||||
(final Backup backup) {
|
||||
final service = context
|
||||
.read<ServicesCubit>()
|
||||
.read<ServicesBloc>()
|
||||
.state
|
||||
.getServiceById(backup.serviceId);
|
||||
return ListTile(
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
|
@ -48,7 +48,7 @@ class _SnapshotModalState extends State<SnapshotModal> {
|
|||
final bool isServiceBusy = busyServices.contains(widget.snapshot.serviceId);
|
||||
|
||||
final Service? service = context
|
||||
.read<ServicesCubit>()
|
||||
.read<ServicesBloc>()
|
||||
.state
|
||||
.getServiceById(widget.snapshot.serviceId);
|
||||
|
||||
|
@ -153,8 +153,12 @@ class _SnapshotModalState extends State<SnapshotModal> {
|
|||
onPressed: isServiceBusy
|
||||
? null
|
||||
: () {
|
||||
context.read<BackupsBloc>().add(RestoreBackup(
|
||||
widget.snapshot.id, selectedStrategy));
|
||||
context.read<BackupsBloc>().add(
|
||||
RestoreBackup(
|
||||
widget.snapshot.id,
|
||||
selectedStrategy,
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
getIt<NavigationService>()
|
||||
.showSnackBar('backup.restore_started'.tr());
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
|
@ -175,9 +175,11 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
|
|||
onPressed: () {
|
||||
for (final service in widget.services) {
|
||||
if (serviceToDisk[service.id] != null) {
|
||||
context.read<ServicesCubit>().moveService(
|
||||
service.id,
|
||||
serviceToDisk[service.id]!,
|
||||
context.read<ServicesBloc>().add(
|
||||
ServiceMove(
|
||||
service,
|
||||
serviceToDisk[service.id]!,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
|
||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||
|
@ -30,8 +30,7 @@ class _ServerStoragePageState extends State<ServerStoragePage> {
|
|||
final bool isReady = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished;
|
||||
|
||||
final List<Service> services =
|
||||
context.watch<ServicesCubit>().state.services;
|
||||
final List<Service> services = context.watch<ServicesBloc>().state.services;
|
||||
|
||||
if (!isReady) {
|
||||
return BrandHeroScreen(
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/job.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||
|
@ -26,7 +26,7 @@ class _ServicePageState extends State<ServicePage> {
|
|||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final Service? service =
|
||||
context.watch<ServicesCubit>().state.getServiceById(widget.serviceId);
|
||||
context.watch<ServicesBloc>().state.getServiceById(widget.serviceId);
|
||||
|
||||
if (service == null) {
|
||||
return const BrandHeroScreen(
|
||||
|
@ -43,7 +43,7 @@ class _ServicePageState extends State<ServicePage> {
|
|||
service.status == ServiceStatus.off;
|
||||
|
||||
final bool serviceLocked =
|
||||
context.watch<ServicesCubit>().state.isServiceLocked(service.id);
|
||||
context.watch<ServicesBloc>().state.isServiceLocked(service.id);
|
||||
|
||||
return BrandHeroScreen(
|
||||
hasBackButton: true,
|
||||
|
@ -81,7 +81,7 @@ class _ServicePageState extends State<ServicePage> {
|
|||
ListTile(
|
||||
iconColor: Theme.of(context).colorScheme.onBackground,
|
||||
onTap: () => {
|
||||
context.read<ServicesCubit>().restart(service.id),
|
||||
context.read<ServicesBloc>().add(ServiceRestart(service)),
|
||||
},
|
||||
leading: const Icon(Icons.restart_alt_outlined),
|
||||
title: Text(
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||
|
@ -30,7 +30,7 @@ class _ServicesPageState extends State<ServicesPage> {
|
|||
final isReady = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished;
|
||||
|
||||
final services = [...context.watch<ServicesCubit>().state.services];
|
||||
final services = [...context.watch<ServicesBloc>().state.services];
|
||||
services
|
||||
.sort((final a, final b) => a.status.index.compareTo(b.status.index));
|
||||
|
||||
|
@ -52,7 +52,8 @@ class _ServicesPageState extends State<ServicesPage> {
|
|||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await context.read<ServicesCubit>().reload();
|
||||
// Create a ServicesRelaod event and wait for the state to change.
|
||||
await context.read<ServicesBloc>().awaitReload();
|
||||
},
|
||||
child: ListView(
|
||||
padding: paddingH15V0,
|
||||
|
|
Loading…
Reference in a new issue