From 3b9d61604571f57030e7ffbc81a69daaa084b918 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Thu, 1 Feb 2024 18:30:06 +0400 Subject: [PATCH] refactor: Introduce VolumesBloc, remove ServerVolumeCubit --- lib/config/bloc_config.dart | 14 +- .../graphql_maps/server_api/volume_api.dart | 1 + lib/logic/bloc/volumes/volumes_bloc.dart | 163 ++++++++++++++++++ lib/logic/bloc/volumes/volumes_event.dart | 30 ++++ lib/logic/bloc/volumes/volumes_state.dart | 97 +++++++++++ .../provider_volume_cubit.dart | 80 ++++----- .../provider_volume_state.dart | 10 +- .../server_volumes/server_volume_cubit.dart | 73 -------- .../server_volumes/server_volume_state.dart | 38 ---- .../get_it/api_connection_repository.dart | 16 +- lib/logic/models/disk_status.dart | 4 - lib/logic/models/hive/server_details.dart | 1 + lib/logic/models/json/server_disk_volume.dart | 17 +- lib/ui/pages/providers/providers.dart | 4 +- .../server_details/server_details_screen.dart | 4 +- .../server_storage/extending_volume.dart | 10 +- lib/ui/pages/services/service_page.dart | 7 +- 17 files changed, 382 insertions(+), 187 deletions(-) create mode 100644 lib/logic/bloc/volumes/volumes_bloc.dart create mode 100644 lib/logic/bloc/volumes/volumes_event.dart create mode 100644 lib/logic/bloc/volumes/volumes_state.dart delete mode 100644 lib/logic/cubit/server_volumes/server_volume_cubit.dart delete mode 100644 lib/logic/cubit/server_volumes/server_volume_state.dart diff --git a/lib/config/bloc_config.dart b/lib/config/bloc_config.dart index 09d0f361..268048c5 100644 --- a/lib/config/bloc_config.dart +++ b/lib/config/bloc_config.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_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/services/services_bloc.dart'; +import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart'; import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/connection_status/connection_status_bloc.dart'; @@ -12,7 +13,6 @@ import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.d import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; -import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart'; import 'package:selfprivacy/logic/cubit/users/users_cubit.dart'; @@ -34,11 +34,11 @@ class BlocAndProviderConfigState extends State { late final DnsRecordsCubit dnsRecordsCubit; late final RecoveryKeyCubit recoveryKeyCubit; late final ApiDevicesCubit apiDevicesCubit; - late final ApiProviderVolumeCubit apiVolumesCubit; - late final ApiServerVolumeCubit apiServerVolumesCubit; + late final ProviderVolumeCubit apiVolumesCubit; late final ServerJobsBloc serverJobsBloc; late final ConnectionStatusBloc connectionStatusBloc; late final ServerDetailsCubit serverDetailsCubit; + late final VolumesBloc volumesBloc; @override void initState() { @@ -51,11 +51,11 @@ class BlocAndProviderConfigState extends State { dnsRecordsCubit = DnsRecordsCubit(); recoveryKeyCubit = RecoveryKeyCubit(); apiDevicesCubit = ApiDevicesCubit(); - apiVolumesCubit = ApiProviderVolumeCubit(); - apiServerVolumesCubit = ApiServerVolumeCubit(apiVolumesCubit); + apiVolumesCubit = ProviderVolumeCubit(); serverJobsBloc = ServerJobsBloc(); connectionStatusBloc = ConnectionStatusBloc(); serverDetailsCubit = ServerDetailsCubit(); + volumesBloc = VolumesBloc(); } @override @@ -101,9 +101,6 @@ class BlocAndProviderConfigState extends State { BlocProvider( create: (final _) => apiVolumesCubit, ), - BlocProvider( - create: (final _) => apiServerVolumesCubit, - ), BlocProvider( create: (final _) => serverJobsBloc, ), @@ -111,6 +108,7 @@ class BlocAndProviderConfigState extends State { BlocProvider( create: (final _) => serverDetailsCubit, ), + BlocProvider(create: (final _) => volumesBloc), BlocProvider( create: (final _) => JobsCubit( usersCubit: usersCubit, diff --git a/lib/logic/api_maps/graphql_maps/server_api/volume_api.dart b/lib/logic/api_maps/graphql_maps/server_api/volume_api.dart index 050b1de0..713544eb 100644 --- a/lib/logic/api_maps/graphql_maps/server_api/volume_api.dart +++ b/lib/logic/api_maps/graphql_maps/server_api/volume_api.dart @@ -11,6 +11,7 @@ mixin VolumeApi on GraphQLApiMap { if (response.hasException) { print(response.exception.toString()); } + // TODO: Rewrite to use fromGraphQL volumes = response.data!['storage']['volumes'] .map((final e) => ServerDiskVolume.fromJson(e)) .toList(); diff --git a/lib/logic/bloc/volumes/volumes_bloc.dart b/lib/logic/bloc/volumes/volumes_bloc.dart new file mode 100644 index 00000000..ed365b3a --- /dev/null +++ b/lib/logic/bloc/volumes/volumes_bloc.dart @@ -0,0 +1,163 @@ +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/disk_status.dart'; +import 'package:selfprivacy/logic/models/hive/server_details.dart'; +import 'package:selfprivacy/logic/models/json/server_disk_volume.dart'; +import 'package:selfprivacy/logic/models/price.dart'; +import 'package:selfprivacy/logic/providers/providers_controller.dart'; + +part 'volumes_event.dart'; +part 'volumes_state.dart'; + +class VolumesBloc extends Bloc { + VolumesBloc() : super(VolumesInitial()) { + on( + _loadState, + transformer: droppable(), + ); + on( + _resetState, + transformer: droppable(), + ); + on( + _updateState, + transformer: droppable(), + ); + + final connectionRepository = getIt(); + + _apiStatusSubscription = connectionRepository.connectionStatusStream + .listen((final ConnectionStatus connectionStatus) { + switch (connectionStatus) { + case ConnectionStatus.nonexistent: + add(const VolumesServerReset()); + isLoaded = false; + break; + case ConnectionStatus.connected: + if (!isLoaded) { + add(const VolumesServerLoaded()); + isLoaded = true; + } + break; + default: + break; + } + }); + + _apiDataSubscription = connectionRepository.dataStream.listen( + (final ApiData apiData) { + if (apiData.volumes.data == null) { + add(const VolumesServerReset()); + } else { + add( + VolumesServerStateChanged( + apiData.volumes.data!, + ), + ); + } + }, + ); + } + + late StreamSubscription _apiStatusSubscription; + late StreamSubscription _apiDataSubscription; + bool isLoaded = false; + + Future getPricePerGb() async { + if (ProvidersController.currentServerProvider == null) { + return null; + } + Price? price; + final pricingResult = + await ProvidersController.currentServerProvider!.getAdditionalPricing(); + if (pricingResult.data == null || !pricingResult.success) { + getIt().showSnackBar('server.pricing_error'.tr()); + return price; + } + price = pricingResult.data!.perVolumeGb; + return price; + } + + Future _loadState( + final VolumesServerLoaded event, + final Emitter emit, + ) async { + if (ProvidersController.currentServerProvider == null) { + return; + } + + emit(VolumesLoading()); + + final volumesResult = + await ProvidersController.currentServerProvider!.getVolumes(); + + if (!volumesResult.success || volumesResult.data.isEmpty) { + emit(VolumesInitial()); + return; + } + + final serverVolumes = getIt().apiData.volumes.data; + + if (serverVolumes == null) { + emit(VolumesLoading(providerVolumes: volumesResult.data)); + return; + } else { + emit( + VolumesLoaded( + diskStatus: DiskStatus.fromVolumes( + serverVolumes, + volumesResult.data, + ), + providerVolumes: volumesResult.data, + serverVolumesHashCode: Object.hashAll(serverVolumes), + ), + ); + } + } + + Future _resetState( + final VolumesServerReset event, + final Emitter emit, + ) async { + emit(VolumesInitial()); + } + + @override + void onChange(final Change change) { + super.onChange(change); + } + + @override + Future close() async { + await _apiStatusSubscription.cancel(); + await _apiDataSubscription.cancel(); + await super.close(); + } + + Future invalidateCache() async { + getIt().apiData.volumes.invalidate(); + } + + Future _updateState( + final VolumesServerStateChanged event, + final Emitter emit, + ) async { + final serverVolumes = event.volumes; + final providerVolumes = state.providerVolumes; + emit( + VolumesLoaded( + diskStatus: DiskStatus.fromVolumes( + serverVolumes, + providerVolumes, + ), + providerVolumes: providerVolumes, + serverVolumesHashCode: Object.hashAll(serverVolumes), + ), + ); + } +} diff --git a/lib/logic/bloc/volumes/volumes_event.dart b/lib/logic/bloc/volumes/volumes_event.dart new file mode 100644 index 00000000..5e65b07d --- /dev/null +++ b/lib/logic/bloc/volumes/volumes_event.dart @@ -0,0 +1,30 @@ +part of 'volumes_bloc.dart'; + +abstract class VolumesEvent extends Equatable { + const VolumesEvent(); +} + +class VolumesServerLoaded extends VolumesEvent { + const VolumesServerLoaded(); + + @override + List get props => []; +} + +class VolumesServerReset extends VolumesEvent { + const VolumesServerReset(); + + @override + List get props => []; +} + +class VolumesServerStateChanged extends VolumesEvent { + const VolumesServerStateChanged( + this.volumes, + ); + + final List volumes; + + @override + List get props => [volumes]; +} diff --git a/lib/logic/bloc/volumes/volumes_state.dart b/lib/logic/bloc/volumes/volumes_state.dart new file mode 100644 index 00000000..a9ba2d06 --- /dev/null +++ b/lib/logic/bloc/volumes/volumes_state.dart @@ -0,0 +1,97 @@ +part of 'volumes_bloc.dart'; + +abstract class VolumesState extends Equatable { + const VolumesState({ + required this.diskStatus, + required final serverVolumesHashCode, + this.providerVolumes = const [], + }) : _serverVolumesHashCode = serverVolumesHashCode; + + final DiskStatus diskStatus; + final List providerVolumes; + List get volumes => diskStatus.diskVolumes; + final int? _serverVolumesHashCode; + + DiskVolume getVolume(final String volumeName) => volumes.firstWhere( + (final volume) => volume.name == volumeName, + orElse: () => DiskVolume(), + ); + + bool get isProviderVolumesLoaded => providerVolumes.isNotEmpty; + + VolumesState copyWith({ + required final int? serverVolumesHashCode, + final DiskStatus? diskStatus, + final List? providerVolumes, + }); +} + +class VolumesInitial extends VolumesState { + VolumesInitial() + : super( + diskStatus: DiskStatus(), + serverVolumesHashCode: null, + ); + + @override + List get props => [providerVolumes, _serverVolumesHashCode]; + + @override + VolumesInitial copyWith({ + required final int? serverVolumesHashCode, + final DiskStatus? diskStatus, + final List? providerVolumes, + }) => + VolumesInitial(); +} + +class VolumesLoading extends VolumesState { + VolumesLoading({ + super.serverVolumesHashCode, + final DiskStatus? diskStatus, + final List? providerVolumes, + }) : super( + diskStatus: diskStatus ?? DiskStatus(), + providerVolumes: providerVolumes ?? const [], + ); + + @override + List get props => [providerVolumes, _serverVolumesHashCode]; + + @override + VolumesLoading copyWith({ + required final int? serverVolumesHashCode, + final DiskStatus? diskStatus, + final List? providerVolumes, + }) => + VolumesLoading( + diskStatus: diskStatus ?? this.diskStatus, + providerVolumes: providerVolumes ?? this.providerVolumes, + serverVolumesHashCode: serverVolumesHashCode ?? _serverVolumesHashCode!, + ); +} + +class VolumesLoaded extends VolumesState { + const VolumesLoaded({ + required super.serverVolumesHashCode, + required super.diskStatus, + final List? providerVolumes, + }) : super( + providerVolumes: providerVolumes ?? const [], + ); + + @override + List get props => [providerVolumes, _serverVolumesHashCode]; + + @override + VolumesLoaded copyWith({ + final DiskStatus? diskStatus, + final List? providerVolumes, + final int? serverVolumesHashCode, + }) => + VolumesLoaded( + diskStatus: diskStatus ?? this.diskStatus, + providerVolumes: providerVolumes ?? this.providerVolumes, + serverVolumesHashCode: serverVolumesHashCode ?? _serverVolumesHashCode!, + ); +} diff --git a/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart b/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart index 951b57dd..3432fe7e 100644 --- a/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart +++ b/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart @@ -13,9 +13,9 @@ import 'package:selfprivacy/logic/providers/providers_controller.dart'; part 'provider_volume_state.dart'; -class ApiProviderVolumeCubit - extends ServerConnectionDependentCubit { - ApiProviderVolumeCubit() : super(const ApiProviderVolumeState.initial()); +class ProviderVolumeCubit + extends ServerConnectionDependentCubit { + ProviderVolumeCubit() : super(const ProviderVolumeState.initial()); final ServerApi serverApi = ServerApi(); @override @@ -36,24 +36,24 @@ class ApiProviderVolumeCubit } Future refresh() async { - emit(const ApiProviderVolumeState([], LoadingStatus.refreshing, false)); + emit(const ProviderVolumeState([], LoadingStatus.refreshing, false)); unawaited(_refetch()); } Future _refetch() async { if (ProvidersController.currentServerProvider == null) { - return emit(const ApiProviderVolumeState([], LoadingStatus.error, false)); + return emit(const ProviderVolumeState([], LoadingStatus.error, false)); } final volumesResult = await ProvidersController.currentServerProvider!.getVolumes(); if (!volumesResult.success || volumesResult.data.isEmpty) { - return emit(const ApiProviderVolumeState([], LoadingStatus.error, false)); + return emit(const ProviderVolumeState([], LoadingStatus.error, false)); } emit( - ApiProviderVolumeState( + ProviderVolumeState( volumesResult.data, LoadingStatus.success, false, @@ -61,18 +61,18 @@ class ApiProviderVolumeCubit ); } - Future attachVolume(final DiskVolume volume) async { - final ServerHostingDetails server = getIt().serverDetails!; - await ProvidersController.currentServerProvider! - .attachVolume(volume.providerVolume!, server.id); - unawaited(refresh()); - } - - Future detachVolume(final DiskVolume volume) async { - await ProvidersController.currentServerProvider! - .detachVolume(volume.providerVolume!); - unawaited(refresh()); - } + // Future attachVolume(final DiskVolume volume) async { + // final ServerHostingDetails server = getIt().serverDetails!; + // await ProvidersController.currentServerProvider! + // .attachVolume(volume.providerVolume!, server.id); + // unawaited(refresh()); + // } + // + // Future detachVolume(final DiskVolume volume) async { + // await ProvidersController.currentServerProvider! + // .detachVolume(volume.providerVolume!); + // unawaited(refresh()); + // } Future resizeVolume( final DiskVolume volume, @@ -119,29 +119,29 @@ class ApiProviderVolumeCubit return true; } - Future createVolume(final DiskSize size) async { - final ServerProviderVolume? volume = (await ProvidersController - .currentServerProvider! - .createVolume(size.gibibyte.toInt())) - .data; - - final diskVolume = DiskVolume(providerVolume: volume); - await attachVolume(diskVolume); - - await Future.delayed(const Duration(seconds: 10)); - - await ServerApi().mountVolume(volume!.name); - unawaited(refresh()); - } - - Future deleteVolume(final DiskVolume volume) async { - await ProvidersController.currentServerProvider! - .deleteVolume(volume.providerVolume!); - unawaited(refresh()); - } + // Future createVolume(final DiskSize size) async { + // final ServerProviderVolume? volume = (await ProvidersController + // .currentServerProvider! + // .createVolume(size.gibibyte.toInt())) + // .data; + // + // final diskVolume = DiskVolume(providerVolume: volume); + // await attachVolume(diskVolume); + // + // await Future.delayed(const Duration(seconds: 10)); + // + // await ServerApi().mountVolume(volume!.name); + // unawaited(refresh()); + // } + // + // Future deleteVolume(final DiskVolume volume) async { + // await ProvidersController.currentServerProvider! + // .deleteVolume(volume.providerVolume!); + // unawaited(refresh()); + // } @override void clear() { - emit(const ApiProviderVolumeState.initial()); + emit(const ProviderVolumeState.initial()); } } diff --git a/lib/logic/cubit/provider_volumes/provider_volume_state.dart b/lib/logic/cubit/provider_volumes/provider_volume_state.dart index 21faa52c..89603a5a 100644 --- a/lib/logic/cubit/provider_volumes/provider_volume_state.dart +++ b/lib/logic/cubit/provider_volumes/provider_volume_state.dart @@ -1,9 +1,9 @@ part of 'provider_volume_cubit.dart'; -class ApiProviderVolumeState extends ServerInstallationDependendState { - const ApiProviderVolumeState(this._volumes, this.status, this.isResizing); +class ProviderVolumeState extends ServerInstallationDependendState { + const ProviderVolumeState(this._volumes, this.status, this.isResizing); - const ApiProviderVolumeState.initial() + const ProviderVolumeState.initial() : this(const [], LoadingStatus.uninitialized, false); final List _volumes; final LoadingStatus status; @@ -11,12 +11,12 @@ class ApiProviderVolumeState extends ServerInstallationDependendState { List get volumes => _volumes; - ApiProviderVolumeState copyWith({ + ProviderVolumeState copyWith({ final List? volumes, final LoadingStatus? status, final bool? isResizing, }) => - ApiProviderVolumeState( + ProviderVolumeState( volumes ?? _volumes, status ?? this.status, isResizing ?? this.isResizing, diff --git a/lib/logic/cubit/server_volumes/server_volume_cubit.dart b/lib/logic/cubit/server_volumes/server_volume_cubit.dart deleted file mode 100644 index f3659d77..00000000 --- a/lib/logic/cubit/server_volumes/server_volume_cubit.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'dart:async'; - -import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart'; -import 'package:selfprivacy/logic/common_enum/common_enum.dart'; -import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart'; -import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart'; -import 'package:selfprivacy/logic/models/disk_status.dart'; -import 'package:selfprivacy/logic/models/json/server_disk_volume.dart'; - -part 'server_volume_state.dart'; - -class ApiServerVolumeCubit - extends ServerConnectionDependentCubit { - ApiServerVolumeCubit( - this.providerVolumeCubit, - ) : super(ApiServerVolumeState.initial()) { - // TODO: Remove this connection between cubits - _providerVolumeSubscription = - providerVolumeCubit.stream.listen(checkProviderVolumes); - } - - final ServerApi serverApi = ServerApi(); - - @override - Future load() async { - unawaited(reload()); - } - - late StreamSubscription _providerVolumeSubscription; - final ApiProviderVolumeCubit providerVolumeCubit; - - void checkProviderVolumes(final ApiProviderVolumeState state) { - emit( - ApiServerVolumeState( - this.state._volumes, - this.state.status, - DiskStatus.fromVolumes(this.state._volumes, state.volumes), - ), - ); - return; - } - - Future reload() async { - final volumes = await serverApi.getServerDiskVolumes(); - var status = LoadingStatus.error; - - if (volumes.isNotEmpty) { - status = LoadingStatus.success; - } - - emit( - ApiServerVolumeState( - volumes, - status, - DiskStatus.fromVolumes( - volumes, - providerVolumeCubit.state.volumes, - ), - ), - ); - } - - @override - void clear() { - emit(ApiServerVolumeState.initial()); - } - - @override - Future close() { - _providerVolumeSubscription.cancel(); - return super.close(); - } -} diff --git a/lib/logic/cubit/server_volumes/server_volume_state.dart b/lib/logic/cubit/server_volumes/server_volume_state.dart deleted file mode 100644 index 3ea7aaa5..00000000 --- a/lib/logic/cubit/server_volumes/server_volume_state.dart +++ /dev/null @@ -1,38 +0,0 @@ -part of 'server_volume_cubit.dart'; - -class ApiServerVolumeState extends ServerInstallationDependendState { - const ApiServerVolumeState( - this._volumes, - this.status, - this._diskStatus, - ); - - ApiServerVolumeState.initial() - : this(const [], LoadingStatus.uninitialized, DiskStatus()); - - final List _volumes; - final DiskStatus _diskStatus; - final LoadingStatus status; - - List get volumes => _diskStatus.diskVolumes; - DiskStatus get diskStatus => _diskStatus; - - DiskVolume getVolume(final String volumeName) => volumes.firstWhere( - (final volume) => volume.name == volumeName, - orElse: () => DiskVolume(), - ); - - ApiServerVolumeState copyWith({ - final List? volumes, - final LoadingStatus? status, - final DiskStatus? diskStatus, - }) => - ApiServerVolumeState( - volumes ?? _volumes, - status ?? this.status, - diskStatus ?? _diskStatus, - ); - - @override - List get props => [_volumes, status]; -} diff --git a/lib/logic/get_it/api_connection_repository.dart b/lib/logic/get_it/api_connection_repository.dart index 8a64b09d..6f0210ee 100644 --- a/lib/logic/get_it/api_connection_repository.dart +++ b/lib/logic/get_it/api_connection_repository.dart @@ -8,6 +8,7 @@ import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.da 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_disk_volume.dart'; import 'package:selfprivacy/logic/models/json/server_job.dart'; import 'package:selfprivacy/logic/models/service.dart'; @@ -95,10 +96,11 @@ class ApiConnectionRepository { _dataStream.add(_apiData); } - _apiData.serverJobs.data = await api.getServerJobs(); - _apiData.backupConfig.data = await api.getBackupsConfiguration(); - _apiData.backups.data = await api.getBackups(); - _apiData.services.data = await api.getAllServices(); + _apiData.serverJobs.data = await _apiData.serverJobs.fetchData(); + _apiData.backupConfig.data = await _apiData.backupConfig.fetchData(); + _apiData.backups.data = await _apiData.backups.fetchData(); + _apiData.services.data = await _apiData.services.fetchData(); + _apiData.volumes.data = await _apiData.volumes.fetchData(); _dataStream.add(_apiData); connectionStatus = ConnectionStatus.connected; @@ -136,6 +138,8 @@ class ApiConnectionRepository { .refetchData(version, () => _dataStream.add(_apiData)); await _apiData.services .refetchData(version, () => _dataStream.add(_apiData)); + await _apiData.volumes + .refetchData(version, () => _dataStream.add(_apiData)); } void emitData() { @@ -163,6 +167,9 @@ class ApiData { services = ApiDataElement>( fetchData: () async => api.getAllServices(), requiredApiVersion: '>=2.4.3', + ), + volumes = ApiDataElement>( + fetchData: () async => api.getServerDiskVolumes(), ); ApiDataElement> serverJobs; @@ -170,6 +177,7 @@ class ApiData { ApiDataElement backupConfig; ApiDataElement> backups; ApiDataElement> services; + ApiDataElement> volumes; } enum ConnectionStatus { diff --git a/lib/logic/models/disk_status.dart b/lib/logic/models/disk_status.dart index 1010f747..6708cf12 100644 --- a/lib/logic/models/disk_status.dart +++ b/lib/logic/models/disk_status.dart @@ -9,7 +9,6 @@ class DiskVolume { this.sizeUsed = const DiskSize(byte: 0), this.root = false, this.isResizable = false, - this.serverDiskVolume, this.providerVolume, }); @@ -27,7 +26,6 @@ class DiskVolume { ), root: volume.root, isResizable: providerVolume != null, - serverDiskVolume: volume, providerVolume: providerVolume, ); @@ -51,7 +49,6 @@ class DiskVolume { String name; bool root; bool isResizable; - ServerDiskVolume? serverDiskVolume; ServerProviderVolume? providerVolume; /// from 0.0 to 1.0 @@ -75,7 +72,6 @@ class DiskVolume { name: name ?? this.name, root: root ?? this.root, isResizable: isResizable ?? this.isResizable, - serverDiskVolume: serverDiskVolume ?? this.serverDiskVolume, providerVolume: providerVolume ?? this.providerVolume, ); } diff --git a/lib/logic/models/hive/server_details.dart b/lib/logic/models/hive/server_details.dart index e332be66..c19be012 100644 --- a/lib/logic/models/hive/server_details.dart +++ b/lib/logic/models/hive/server_details.dart @@ -27,6 +27,7 @@ class ServerHostingDetails { @HiveField(2) final DateTime? startTime; + // TODO: Check if it is still needed @HiveField(4) final ServerProviderVolume volume; diff --git a/lib/logic/models/json/server_disk_volume.dart b/lib/logic/models/json/server_disk_volume.dart index 873b5d97..d83c4000 100644 --- a/lib/logic/models/json/server_disk_volume.dart +++ b/lib/logic/models/json/server_disk_volume.dart @@ -1,12 +1,13 @@ +import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; part 'server_disk_volume.g.dart'; @JsonSerializable() -class ServerDiskVolume { +class ServerDiskVolume extends Equatable { factory ServerDiskVolume.fromJson(final Map json) => _$ServerDiskVolumeFromJson(json); - ServerDiskVolume({ + const ServerDiskVolume({ required this.freeSpace, required this.model, required this.name, @@ -25,4 +26,16 @@ class ServerDiskVolume { final String totalSpace; final String type; final String usedSpace; + + @override + List get props => [ + freeSpace, + model, + name, + root, + serial, + totalSpace, + type, + usedSpace, + ]; } diff --git a/lib/ui/pages/providers/providers.dart b/lib/ui/pages/providers/providers.dart index e65098d0..b03c5b55 100644 --- a/lib/ui/pages/providers/providers.dart +++ b/lib/ui/pages/providers/providers.dart @@ -3,9 +3,9 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart'; +import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart'; import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; -import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.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_icons/brand_icons.dart'; @@ -34,7 +34,7 @@ class _ProvidersPageState extends State { final DnsRecordsStatus dnsStatus = context.watch().state.dnsState; - final diskStatus = context.watch().state.diskStatus; + final diskStatus = context.watch().state.diskStatus; final ServerInstallationState appConfig = context.watch().state; diff --git a/lib/ui/pages/server_details/server_details_screen.dart b/lib/ui/pages/server_details/server_details_screen.dart index d1d5b8a4..1b66a21b 100644 --- a/lib/ui/pages/server_details/server_details_screen.dart +++ b/lib/ui/pages/server_details/server_details_screen.dart @@ -2,12 +2,12 @@ import 'package:auto_route/auto_route.dart'; import 'package:cubit_form/cubit_form.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/metrics/metrics_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; -import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart'; import 'package:selfprivacy/logic/models/job.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; @@ -81,7 +81,7 @@ class _ServerDetailsScreenState extends State heroSubtitle: 'server.description'.tr(), children: [ StorageCard( - diskStatus: context.watch().state.diskStatus, + diskStatus: context.watch().state.diskStatus, ), const SizedBox(height: 16), const _ServerSettings(), diff --git a/lib/ui/pages/server_storage/extending_volume.dart b/lib/ui/pages/server_storage/extending_volume.dart index 9c145061..60ac7379 100644 --- a/lib/ui/pages/server_storage/extending_volume.dart +++ b/lib/ui/pages/server_storage/extending_volume.dart @@ -2,8 +2,8 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart'; import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart'; -import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/disk_status.dart'; import 'package:selfprivacy/logic/models/price.dart'; @@ -59,7 +59,7 @@ class _ExtendingVolumePageState extends State { @override Widget build(final BuildContext context) => FutureBuilder( - future: context.read().getPricePerGb(), + future: context.read().getPricePerGb(), builder: ( final BuildContext context, final AsyncSnapshot snapshot, @@ -92,7 +92,7 @@ class _ExtendingVolumePageState extends State { } final isAlreadyResizing = - context.watch().state.isResizing; + context.watch().state.isResizing; return BrandHeroScreen( hasBackButton: true, @@ -163,12 +163,12 @@ class _ExtendingVolumePageState extends State { ), actionButtonTitle: 'basis.continue'.tr(), actionButtonOnPressed: () { - context.read().resizeVolume( + context.read().resizeVolume( widget.diskVolumeToResize, DiskSize.fromGibibyte( _currentSliderGbValue.truncate().toDouble(), ), - context.read().reload, + context.read().invalidateCache, ); context.router.popUntilRoot(); }, diff --git a/lib/ui/pages/services/service_page.dart b/lib/ui/pages/services/service_page.dart index a7c2be34..bb94356f 100644 --- a/lib/ui/pages/services/service_page.dart +++ b/lib/ui/pages/services/service_page.dart @@ -3,8 +3,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:selfprivacy/logic/bloc/services/services_bloc.dart'; +import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.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/models/job.dart'; import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/ui/components/cards/filled_card.dart'; @@ -113,8 +113,7 @@ class _ServicePageState extends State { onTap: () => context.pushRoute( ServicesMigrationRoute( services: [service], - diskStatus: - context.read().state.diskStatus, + diskStatus: context.read().state.diskStatus, ), ), leading: const Icon(Icons.drive_file_move_outlined), @@ -127,7 +126,7 @@ class _ServicePageState extends State { namedArgs: { 'usage': service.storageUsage.used.toString(), 'volume': context - .read() + .read() .state .getVolume(service.storageUsage.volume ?? '') .displayName,