mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-03-11 17:24:09 +00:00
refactor: Rewrite services cubit to bloc, using ApiRepo streams
This commit is contained in:
parent
a5e7725733
commit
831a0e95eb
18 changed files with 382 additions and 173 deletions
lib
config
logic
bloc
backups
services
cubit
get_it
models
ui/pages
backups
server_storage
services
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/backups/backups_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/connection_status/connection_status_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_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/cubit/client_jobs/client_jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.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/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/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_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 serverInstallationCubit = ServerInstallationCubit()..load();
|
||||||
final supportSystemCubit = SupportSystemCubit();
|
final supportSystemCubit = SupportSystemCubit();
|
||||||
final usersCubit = UsersCubit(serverInstallationCubit);
|
final usersCubit = UsersCubit(serverInstallationCubit);
|
||||||
final servicesCubit = ServicesCubit(serverInstallationCubit);
|
final servicesBloc = ServicesBloc();
|
||||||
final backupsBloc = BackupsBloc();
|
final backupsBloc = BackupsBloc();
|
||||||
final dnsRecordsCubit = DnsRecordsCubit(serverInstallationCubit);
|
final dnsRecordsCubit = DnsRecordsCubit(serverInstallationCubit);
|
||||||
final recoveryKeyCubit = RecoveryKeyCubit(serverInstallationCubit);
|
final recoveryKeyCubit = RecoveryKeyCubit(serverInstallationCubit);
|
||||||
|
@ -61,8 +61,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
lazy: false,
|
lazy: false,
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (final _) => servicesCubit..load(),
|
create: (final _) => servicesBloc,
|
||||||
lazy: false,
|
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (final _) => backupsBloc,
|
create: (final _) => backupsBloc,
|
||||||
|
@ -92,7 +91,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (final _) => JobsCubit(
|
create: (final _) => JobsCubit(
|
||||||
usersCubit: usersCubit,
|
usersCubit: usersCubit,
|
||||||
servicesCubit: servicesCubit,
|
servicesBloc: servicesBloc,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -193,7 +193,8 @@ class BackupsBloc extends Bloc<BackupsEvent, BackupsState> {
|
||||||
);
|
);
|
||||||
if (result.success == false) {
|
if (result.success == false) {
|
||||||
getIt<NavigationService>().showSnackBar(
|
getIt<NavigationService>().showSnackBar(
|
||||||
result.message ?? "Couldn't initialize repository on your server.");
|
result.message ?? "Couldn't initialize repository on your server.",
|
||||||
|
);
|
||||||
emit(BackupsUnititialized());
|
emit(BackupsUnititialized());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ class BackupsUnititialized extends BackupsState {
|
||||||
final BackblazeBucket? backblazeBucket,
|
final BackblazeBucket? backblazeBucket,
|
||||||
}) =>
|
}) =>
|
||||||
BackupsUnititialized(
|
BackupsUnititialized(
|
||||||
backblazeBucket: backblazeBucket ?? this.backblazeBucket);
|
backblazeBucket: backblazeBucket ?? this.backblazeBucket,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackupsInitializing extends BackupsState {
|
class BackupsInitializing extends BackupsState {
|
||||||
|
@ -86,7 +87,8 @@ class BackupsInitializing extends BackupsState {
|
||||||
final BackblazeBucket? backblazeBucket,
|
final BackblazeBucket? backblazeBucket,
|
||||||
}) =>
|
}) =>
|
||||||
BackupsInitializing(
|
BackupsInitializing(
|
||||||
backblazeBucket: backblazeBucket ?? this.backblazeBucket);
|
backblazeBucket: backblazeBucket ?? this.backblazeBucket,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackupsInitialized extends BackupsState {
|
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:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.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/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/cubit/users/users_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/job.dart';
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
|
|
||||||
|
@ -16,12 +16,12 @@ part 'client_jobs_state.dart';
|
||||||
class JobsCubit extends Cubit<JobsState> {
|
class JobsCubit extends Cubit<JobsState> {
|
||||||
JobsCubit({
|
JobsCubit({
|
||||||
required this.usersCubit,
|
required this.usersCubit,
|
||||||
required this.servicesCubit,
|
required this.servicesBloc,
|
||||||
}) : super(JobsStateEmpty());
|
}) : super(JobsStateEmpty());
|
||||||
|
|
||||||
final ServerApi api = ServerApi();
|
final ServerApi api = ServerApi();
|
||||||
final UsersCubit usersCubit;
|
final UsersCubit usersCubit;
|
||||||
final ServicesCubit servicesCubit;
|
final ServicesBloc servicesBloc;
|
||||||
|
|
||||||
void addJob(final ClientJob job) {
|
void addJob(final ClientJob job) {
|
||||||
final jobs = currentJobList;
|
final jobs = currentJobList;
|
||||||
|
@ -90,7 +90,7 @@ class JobsCubit extends Cubit<JobsState> {
|
||||||
|
|
||||||
await api.pullConfigurationUpdate();
|
await api.pullConfigurationUpdate();
|
||||||
await api.apply();
|
await api.apply();
|
||||||
await servicesCubit.load();
|
servicesBloc.add(const ServicesReload());
|
||||||
|
|
||||||
emit(JobsStateEmpty());
|
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_details.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
|
|
||||||
/// Repository for all API calls
|
/// Repository for all API calls
|
||||||
/// Stores the current state of all data from API and exposes it to Blocs.
|
/// 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.serverJobs.data = await api.getServerJobs();
|
||||||
_apiData.backupConfig.data = await api.getBackupsConfiguration();
|
_apiData.backupConfig.data = await api.getBackupsConfiguration();
|
||||||
_apiData.backups.data = await api.getBackups();
|
_apiData.backups.data = await api.getBackups();
|
||||||
|
_apiData.services.data = await api.getAllServices();
|
||||||
_dataStream.add(_apiData);
|
_dataStream.add(_apiData);
|
||||||
|
|
||||||
connectionStatus = ConnectionStatus.connected;
|
connectionStatus = ConnectionStatus.connected;
|
||||||
|
@ -109,6 +111,8 @@ class ApiConnectionRepository {
|
||||||
.refetchData(version, () => _dataStream.add(_apiData));
|
.refetchData(version, () => _dataStream.add(_apiData));
|
||||||
await _apiData.backupConfig
|
await _apiData.backupConfig
|
||||||
.refetchData(version, () => _dataStream.add(_apiData));
|
.refetchData(version, () => _dataStream.add(_apiData));
|
||||||
|
await _apiData.services
|
||||||
|
.refetchData(version, () => _dataStream.add(_apiData));
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitData() {
|
void emitData() {
|
||||||
|
@ -132,12 +136,17 @@ class ApiData {
|
||||||
backups = ApiDataElement<List<Backup>>(
|
backups = ApiDataElement<List<Backup>>(
|
||||||
fetchData: () async => api.getBackups(),
|
fetchData: () async => api.getBackups(),
|
||||||
requiredApiVersion: '>=2.4.2',
|
requiredApiVersion: '>=2.4.2',
|
||||||
|
),
|
||||||
|
services = ApiDataElement<List<Service>>(
|
||||||
|
fetchData: () async => api.getAllServices(),
|
||||||
|
requiredApiVersion: '>=2.4.3',
|
||||||
);
|
);
|
||||||
|
|
||||||
ApiDataElement<List<ServerJob>> serverJobs;
|
ApiDataElement<List<ServerJob>> serverJobs;
|
||||||
ApiDataElement<String> apiVersion;
|
ApiDataElement<String> apiVersion;
|
||||||
ApiDataElement<BackupConfiguration> backupConfig;
|
ApiDataElement<BackupConfiguration> backupConfig;
|
||||||
ApiDataElement<List<Backup>> backups;
|
ApiDataElement<List<Backup>> backups;
|
||||||
|
ApiDataElement<List<Service>> services;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ConnectionStatus {
|
enum ConnectionStatus {
|
||||||
|
@ -163,7 +172,9 @@ class ApiDataElement<T> {
|
||||||
final Future<T?> Function() fetchData;
|
final Future<T?> Function() fetchData;
|
||||||
|
|
||||||
Future<void> refetchData(
|
Future<void> refetchData(
|
||||||
final Version version, final Function callback) async {
|
final Version version,
|
||||||
|
final Function callback,
|
||||||
|
) async {
|
||||||
if (VersionConstraint.parse(requiredApiVersion).allows(version)) {
|
if (VersionConstraint.parse(requiredApiVersion).allows(version)) {
|
||||||
print('Fetching data for $runtimeType');
|
print('Fetching data for $runtimeType');
|
||||||
if (isExpired) {
|
if (isExpired) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
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/schema.graphql.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/services.graphql.dart';
|
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/services.graphql.dart';
|
||||||
import 'package:selfprivacy/logic/models/disk_size.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';
|
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)
|
Service.fromGraphQL(final Query$AllServices$services$allServices service)
|
||||||
: this(
|
: this(
|
||||||
id: service.id,
|
id: service.id,
|
||||||
|
@ -37,7 +38,7 @@ class Service {
|
||||||
[],
|
[],
|
||||||
url: service.url,
|
url: service.url,
|
||||||
);
|
);
|
||||||
Service({
|
const Service({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.displayName,
|
required this.displayName,
|
||||||
required this.description,
|
required this.description,
|
||||||
|
@ -72,7 +73,7 @@ class Service {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static Service empty = Service(
|
static Service empty = const Service(
|
||||||
id: 'empty',
|
id: 'empty',
|
||||||
displayName: '',
|
displayName: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
@ -83,7 +84,7 @@ class Service {
|
||||||
backupDescription: '',
|
backupDescription: '',
|
||||||
status: ServiceStatus.off,
|
status: ServiceStatus.off,
|
||||||
storageUsage: ServiceStorageUsage(
|
storageUsage: ServiceStorageUsage(
|
||||||
used: const DiskSize(byte: 0),
|
used: DiskSize(byte: 0),
|
||||||
volume: '',
|
volume: '',
|
||||||
),
|
),
|
||||||
svgIcon: '',
|
svgIcon: '',
|
||||||
|
@ -104,16 +105,36 @@ class Service {
|
||||||
final String svgIcon;
|
final String svgIcon;
|
||||||
final String? url;
|
final String? url;
|
||||||
final List<DnsRecord> dnsRecords;
|
final List<DnsRecord> dnsRecords;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [
|
||||||
|
id,
|
||||||
|
displayName,
|
||||||
|
description,
|
||||||
|
isEnabled,
|
||||||
|
isRequired,
|
||||||
|
isMovable,
|
||||||
|
canBeBackedUp,
|
||||||
|
backupDescription,
|
||||||
|
status,
|
||||||
|
storageUsage,
|
||||||
|
svgIcon,
|
||||||
|
dnsRecords,
|
||||||
|
url,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServiceStorageUsage {
|
class ServiceStorageUsage extends Equatable {
|
||||||
ServiceStorageUsage({
|
const ServiceStorageUsage({
|
||||||
required this.used,
|
required this.used,
|
||||||
required this.volume,
|
required this.volume,
|
||||||
});
|
});
|
||||||
|
|
||||||
final DiskSize used;
|
final DiskSize used;
|
||||||
final String? volume;
|
final String? volume;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [used, volume];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ServiceStatus {
|
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/bloc/backups/backups_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.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/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/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
|
@ -39,7 +39,7 @@ class BackupDetailsPage extends StatelessWidget {
|
||||||
final bool preventActions = backupsState.preventActions;
|
final bool preventActions = backupsState.preventActions;
|
||||||
final List<Backup> backups = backupsState.backups;
|
final List<Backup> backups = backupsState.backups;
|
||||||
final List<Service> services =
|
final List<Service> services =
|
||||||
context.watch<ServicesCubit>().state.servicesThatCanBeBackedUp;
|
context.watch<ServicesBloc>().state.servicesThatCanBeBackedUp;
|
||||||
final Duration? autobackupPeriod = backupsState.autobackupPeriod;
|
final Duration? autobackupPeriod = backupsState.autobackupPeriod;
|
||||||
final List<ServerJob> backupJobs = context
|
final List<ServerJob> backupJobs = context
|
||||||
.watch<ServerJobsBloc>()
|
.watch<ServerJobsBloc>()
|
||||||
|
@ -298,7 +298,7 @@ class BackupDetailsPage extends StatelessWidget {
|
||||||
children: backups.take(15).map(
|
children: backups.take(15).map(
|
||||||
(final Backup backup) {
|
(final Backup backup) {
|
||||||
final service = context
|
final service = context
|
||||||
.read<ServicesCubit>()
|
.read<ServicesBloc>()
|
||||||
.state
|
.state
|
||||||
.getServiceById(backup.serviceId);
|
.getServiceById(backup.serviceId);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
|
@ -419,7 +419,7 @@ class BackupDetailsPage extends StatelessWidget {
|
||||||
: () => {
|
: () => {
|
||||||
context
|
context
|
||||||
.read<BackupsBloc>()
|
.read<BackupsBloc>()
|
||||||
.add(const ForceSnapshotListUpdate())
|
.add(const ForceSnapshotListUpdate()),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.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/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||||
|
@ -43,7 +43,7 @@ class BackupsListPage extends StatelessWidget {
|
||||||
...backups.map(
|
...backups.map(
|
||||||
(final Backup backup) {
|
(final Backup backup) {
|
||||||
final service = context
|
final service = context
|
||||||
.read<ServicesCubit>()
|
.read<ServicesBloc>()
|
||||||
.state
|
.state
|
||||||
.getServiceById(backup.serviceId);
|
.getServiceById(backup.serviceId);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.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/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/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.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 bool isServiceBusy = busyServices.contains(widget.snapshot.serviceId);
|
||||||
|
|
||||||
final Service? service = context
|
final Service? service = context
|
||||||
.read<ServicesCubit>()
|
.read<ServicesBloc>()
|
||||||
.state
|
.state
|
||||||
.getServiceById(widget.snapshot.serviceId);
|
.getServiceById(widget.snapshot.serviceId);
|
||||||
|
|
||||||
|
@ -153,8 +153,12 @@ class _SnapshotModalState extends State<SnapshotModal> {
|
||||||
onPressed: isServiceBusy
|
onPressed: isServiceBusy
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
context.read<BackupsBloc>().add(RestoreBackup(
|
context.read<BackupsBloc>().add(
|
||||||
widget.snapshot.id, selectedStrategy));
|
RestoreBackup(
|
||||||
|
widget.snapshot.id,
|
||||||
|
selectedStrategy,
|
||||||
|
),
|
||||||
|
);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
getIt<NavigationService>()
|
getIt<NavigationService>()
|
||||||
.showSnackBar('backup.restore_started'.tr());
|
.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:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_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/disk_size.dart';
|
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
|
@ -175,9 +175,11 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
for (final service in widget.services) {
|
for (final service in widget.services) {
|
||||||
if (serviceToDisk[service.id] != null) {
|
if (serviceToDisk[service.id] != null) {
|
||||||
context.read<ServicesCubit>().moveService(
|
context.read<ServicesBloc>().add(
|
||||||
service.id,
|
ServiceMove(
|
||||||
serviceToDisk[service.id]!,
|
service,
|
||||||
|
serviceToDisk[service.id]!,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.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/service.dart';
|
||||||
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
|
||||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.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
|
final bool isReady = context.watch<ServerInstallationCubit>().state
|
||||||
is ServerInstallationFinished;
|
is ServerInstallationFinished;
|
||||||
|
|
||||||
final List<Service> services =
|
final List<Service> services = context.watch<ServicesBloc>().state.services;
|
||||||
context.watch<ServicesCubit>().state.services;
|
|
||||||
|
|
||||||
if (!isReady) {
|
if (!isReady) {
|
||||||
return BrandHeroScreen(
|
return BrandHeroScreen(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.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/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/job.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
|
@ -26,7 +26,7 @@ class _ServicePageState extends State<ServicePage> {
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) {
|
Widget build(final BuildContext context) {
|
||||||
final Service? service =
|
final Service? service =
|
||||||
context.watch<ServicesCubit>().state.getServiceById(widget.serviceId);
|
context.watch<ServicesBloc>().state.getServiceById(widget.serviceId);
|
||||||
|
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
return const BrandHeroScreen(
|
return const BrandHeroScreen(
|
||||||
|
@ -43,7 +43,7 @@ class _ServicePageState extends State<ServicePage> {
|
||||||
service.status == ServiceStatus.off;
|
service.status == ServiceStatus.off;
|
||||||
|
|
||||||
final bool serviceLocked =
|
final bool serviceLocked =
|
||||||
context.watch<ServicesCubit>().state.isServiceLocked(service.id);
|
context.watch<ServicesBloc>().state.isServiceLocked(service.id);
|
||||||
|
|
||||||
return BrandHeroScreen(
|
return BrandHeroScreen(
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
|
@ -81,7 +81,7 @@ class _ServicePageState extends State<ServicePage> {
|
||||||
ListTile(
|
ListTile(
|
||||||
iconColor: Theme.of(context).colorScheme.onBackground,
|
iconColor: Theme.of(context).colorScheme.onBackground,
|
||||||
onTap: () => {
|
onTap: () => {
|
||||||
context.read<ServicesCubit>().restart(service.id),
|
context.read<ServicesBloc>().add(ServiceRestart(service)),
|
||||||
},
|
},
|
||||||
leading: const Icon(Icons.restart_alt_outlined),
|
leading: const Icon(Icons.restart_alt_outlined),
|
||||||
title: Text(
|
title: Text(
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.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/service.dart';
|
||||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.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
|
final isReady = context.watch<ServerInstallationCubit>().state
|
||||||
is ServerInstallationFinished;
|
is ServerInstallationFinished;
|
||||||
|
|
||||||
final services = [...context.watch<ServicesCubit>().state.services];
|
final services = [...context.watch<ServicesBloc>().state.services];
|
||||||
services
|
services
|
||||||
.sort((final a, final b) => a.status.index.compareTo(b.status.index));
|
.sort((final a, final b) => a.status.index.compareTo(b.status.index));
|
||||||
|
|
||||||
|
@ -52,7 +52,8 @@ class _ServicesPageState extends State<ServicesPage> {
|
||||||
)
|
)
|
||||||
: RefreshIndicator(
|
: RefreshIndicator(
|
||||||
onRefresh: () async {
|
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(
|
child: ListView(
|
||||||
padding: paddingH15V0,
|
padding: paddingH15V0,
|
||||||
|
|
Loading…
Add table
Reference in a new issue