mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-02-02 14:16:58 +00:00
Implement ServerJob cubit
This commit is contained in:
parent
7bbdaf2ebe
commit
37d5ee9913
|
@ -10,7 +10,7 @@ import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
|||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/volumes/volumes_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
|
||||
class BlocAndProviderConfig extends StatelessWidget {
|
||||
const BlocAndProviderConfig({final super.key, this.child});
|
||||
|
@ -27,7 +27,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
final dnsRecordsCubit = DnsRecordsCubit(serverInstallationCubit);
|
||||
final recoveryKeyCubit = RecoveryKeyCubit(serverInstallationCubit);
|
||||
final apiDevicesCubit = ApiDevicesCubit(serverInstallationCubit);
|
||||
final apiVolumesCubit = ApiVolumesCubit(serverInstallationCubit);
|
||||
final apiVolumesCubit = ApiProviderVolumeCubit(serverInstallationCubit);
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
|
|
108
lib/logic/cubit/provider_volumes/provider_volume_cubit.dart
Normal file
108
lib/logic/cubit/provider_volumes/provider_volume_cubit.dart
Normal file
|
@ -0,0 +1,108 @@
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
|
||||
part 'provider_volume_state.dart';
|
||||
|
||||
class ApiProviderVolumeCubit
|
||||
extends ServerInstallationDependendCubit<ApiProviderVolumeState> {
|
||||
ApiProviderVolumeCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiProviderVolumeState.initial()) {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
providerApi = serverDetails == null
|
||||
? null
|
||||
: VolumeApiFactoryCreator.createVolumeProviderApiFactory(
|
||||
getIt<ApiConfigModel>().serverDetails!.provider,
|
||||
);
|
||||
}
|
||||
|
||||
VolumeProviderApiFactory? providerApi;
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
_refetch();
|
||||
}
|
||||
}
|
||||
|
||||
Future<double?> getPricePerGb() async =>
|
||||
providerApi!.getVolumeProvider().getPricePerGb();
|
||||
|
||||
Future<void> refresh() async {
|
||||
emit(const ApiProviderVolumeState([], LoadingStatus.refreshing));
|
||||
_refetch();
|
||||
}
|
||||
|
||||
Future<void> _refetch() async {
|
||||
if (providerApi == null) {
|
||||
return emit(const ApiProviderVolumeState([], LoadingStatus.error));
|
||||
}
|
||||
|
||||
final List<ServerVolume> volumes =
|
||||
await providerApi!.getVolumeProvider().getVolumes();
|
||||
|
||||
if (volumes.isEmpty) {
|
||||
return emit(const ApiProviderVolumeState([], LoadingStatus.error));
|
||||
}
|
||||
|
||||
emit(ApiProviderVolumeState(volumes, LoadingStatus.success));
|
||||
}
|
||||
|
||||
Future<void> attachVolume(final ServerVolume volume) async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
await providerApi!.getVolumeProvider().attachVolume(volume.id, server.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> detachVolume(final ServerVolume volume) async {
|
||||
await providerApi!.getVolumeProvider().detachVolume(volume.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<bool> resizeVolume(
|
||||
final DiskVolume volume,
|
||||
final int newSizeGb,
|
||||
) async {
|
||||
final bool resized = await providerApi!.getVolumeProvider().resizeVolume(
|
||||
volume.providerVolume!.id,
|
||||
newSizeGb,
|
||||
);
|
||||
|
||||
if (!resized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await ServerApi().resizeVolume(volume.name);
|
||||
refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> createVolume() async {
|
||||
final ServerVolume? volume =
|
||||
await providerApi!.getVolumeProvider().createVolume();
|
||||
await attachVolume(volume!);
|
||||
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
|
||||
await ServerApi().mountVolume(volume.name);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> deleteVolume(final DiskVolume volume) async {
|
||||
await providerApi!
|
||||
.getVolumeProvider()
|
||||
.deleteVolume(volume.providerVolume!.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
emit(const ApiProviderVolumeState.initial());
|
||||
}
|
||||
}
|
24
lib/logic/cubit/provider_volumes/provider_volume_state.dart
Normal file
24
lib/logic/cubit/provider_volumes/provider_volume_state.dart
Normal file
|
@ -0,0 +1,24 @@
|
|||
part of 'provider_volume_cubit.dart';
|
||||
|
||||
class ApiProviderVolumeState extends ServerInstallationDependendState {
|
||||
const ApiProviderVolumeState(this._volumes, this.status);
|
||||
|
||||
const ApiProviderVolumeState.initial()
|
||||
: this(const [], LoadingStatus.uninitialized);
|
||||
final List<ServerVolume> _volumes;
|
||||
final LoadingStatus status;
|
||||
|
||||
List<ServerVolume> get volumes => _volumes;
|
||||
|
||||
ApiProviderVolumeState copyWith({
|
||||
final List<ServerVolume>? volumes,
|
||||
final LoadingStatus? status,
|
||||
}) =>
|
||||
ApiProviderVolumeState(
|
||||
volumes ?? _volumes,
|
||||
status ?? this.status,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_volumes];
|
||||
}
|
|
@ -554,9 +554,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
);
|
||||
}
|
||||
|
||||
Future<List<ServerDiskVolume>> getServerDiskVolumes() async =>
|
||||
ServerApi().getServerDiskVolumes();
|
||||
|
||||
Future<void> setAndValidateCloudflareToken(final String token) async {
|
||||
final ServerInstallationRecovery dataState =
|
||||
state as ServerInstallationRecovery;
|
||||
|
|
36
lib/logic/cubit/server_volumes/server_volume_cubit.dart
Normal file
36
lib/logic/cubit/server_volumes/server_volume_cubit.dart
Normal file
|
@ -0,0 +1,36 @@
|
|||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
|
||||
part 'server_volume_state.dart';
|
||||
|
||||
class ApiServerVolumeCubit
|
||||
extends ServerInstallationDependendCubit<ApiServerVolumeState> {
|
||||
ApiServerVolumeCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiServerVolumeState.initial());
|
||||
|
||||
final ServerApi serverApi = ServerApi();
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
_refetch();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refetch() async {
|
||||
final List<ServerDiskVolume> volumes =
|
||||
await serverApi.getServerDiskVolumes();
|
||||
if (volumes.isNotEmpty) {
|
||||
emit(ApiServerVolumeState(volumes, LoadingStatus.success));
|
||||
} else {
|
||||
emit(const ApiServerVolumeState([], LoadingStatus.error));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
emit(const ApiServerVolumeState.initial());
|
||||
}
|
||||
}
|
24
lib/logic/cubit/server_volumes/server_volume_state.dart
Normal file
24
lib/logic/cubit/server_volumes/server_volume_state.dart
Normal file
|
@ -0,0 +1,24 @@
|
|||
part of 'server_volume_cubit.dart';
|
||||
|
||||
class ApiServerVolumeState extends ServerInstallationDependendState {
|
||||
const ApiServerVolumeState(this._volumes, this.status);
|
||||
|
||||
const ApiServerVolumeState.initial()
|
||||
: this(const [], LoadingStatus.uninitialized);
|
||||
final List<ServerDiskVolume> _volumes;
|
||||
final LoadingStatus status;
|
||||
|
||||
List<ServerDiskVolume> get volumes => _volumes;
|
||||
|
||||
ApiServerVolumeState copyWith({
|
||||
final List<ServerDiskVolume>? volumes,
|
||||
final LoadingStatus? status,
|
||||
}) =>
|
||||
ApiServerVolumeState(
|
||||
volumes ?? _volumes,
|
||||
status ?? this.status,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_volumes];
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
|
||||
part 'volumes_state.dart';
|
||||
|
||||
class ApiVolumesCubit
|
||||
extends ServerInstallationDependendCubit<ApiVolumesState> {
|
||||
ApiVolumesCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiVolumesState.initial()) {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
providerApi = serverDetails == null
|
||||
? null
|
||||
: VolumeApiFactoryCreator.createVolumeProviderApiFactory(
|
||||
getIt<ApiConfigModel>().serverDetails!.provider,
|
||||
);
|
||||
}
|
||||
|
||||
VolumeProviderApiFactory? providerApi;
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
_refetch();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<ServerVolume>> getVolumes() async {
|
||||
if (providerApi == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return providerApi!.getVolumeProvider().getVolumes();
|
||||
}
|
||||
|
||||
Future<double?> getPricePerGb() async =>
|
||||
providerApi!.getVolumeProvider().getPricePerGb();
|
||||
|
||||
Future<void> refresh() async {
|
||||
emit(const ApiVolumesState([], LoadingStatus.refreshing));
|
||||
_refetch();
|
||||
}
|
||||
|
||||
Future<void> _refetch() async {
|
||||
final List<ServerVolume> volumes = await getVolumes();
|
||||
if (volumes.isNotEmpty) {
|
||||
emit(ApiVolumesState(volumes, LoadingStatus.success));
|
||||
} else {
|
||||
emit(const ApiVolumesState([], LoadingStatus.error));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> attachVolume(final ServerVolume volume) async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
await providerApi!.getVolumeProvider().attachVolume(volume.id, server.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> detachVolume(final ServerVolume volume) async {
|
||||
await providerApi!.getVolumeProvider().detachVolume(volume.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<bool> resizeVolume(
|
||||
final ServerDiskVolume volume,
|
||||
final int newSizeGb,
|
||||
) async {
|
||||
final ServerVolume? providerVolume = await fetchProdiverVolume(volume);
|
||||
final bool resized = await providerApi!.getVolumeProvider().resizeVolume(
|
||||
providerVolume!.id,
|
||||
newSizeGb,
|
||||
);
|
||||
|
||||
if (!resized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await ServerApi().resizeVolume(volume.name);
|
||||
refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> createVolume() async {
|
||||
final ServerVolume? volume =
|
||||
await providerApi!.getVolumeProvider().createVolume();
|
||||
await attachVolume(volume!);
|
||||
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
|
||||
final ServerDiskVolume? diskVolume = await fetchServerDiskVolume(volume);
|
||||
await ServerApi().mountVolume(diskVolume!.name);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> deleteVolume(final ServerDiskVolume volume) async {
|
||||
final ServerVolume? providerVolume = await fetchProdiverVolume(volume);
|
||||
await providerApi!.getVolumeProvider().deleteVolume(providerVolume!.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
emit(const ApiVolumesState.initial());
|
||||
}
|
||||
|
||||
Future<ServerVolume?> fetchProdiverVolume(
|
||||
final ServerDiskVolume volume,
|
||||
) async {
|
||||
ServerVolume? fetchedVolume;
|
||||
final List<ServerVolume> volumes =
|
||||
await providerApi!.getVolumeProvider().getVolumes();
|
||||
|
||||
for (final ServerVolume providerVolume in volumes) {
|
||||
if (providerVolume.linuxDevice == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String deviceId = providerVolume.linuxDevice!.split('/').last;
|
||||
if (deviceId.contains(volume.model!) &&
|
||||
deviceId.contains(volume.serial!)) {
|
||||
fetchedVolume = providerVolume;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fetchedVolume;
|
||||
}
|
||||
|
||||
Future<ServerDiskVolume?> fetchServerDiskVolume(
|
||||
final ServerVolume volume,
|
||||
) async {
|
||||
ServerDiskVolume? fetchedVolume;
|
||||
if (volume.linuxDevice == null) {
|
||||
return fetchedVolume;
|
||||
}
|
||||
|
||||
final List<ServerDiskVolume> volumes =
|
||||
await ServerApi().getServerDiskVolumes();
|
||||
|
||||
for (final ServerDiskVolume serverDiskVolumes in volumes) {
|
||||
if (serverDiskVolumes.model == null || serverDiskVolumes.serial == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String deviceId = volume.linuxDevice!.split('/').last;
|
||||
if (deviceId.contains(serverDiskVolumes.model!) &&
|
||||
deviceId.contains(serverDiskVolumes.serial!)) {
|
||||
fetchedVolume = serverDiskVolumes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fetchedVolume;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
part of 'volumes_cubit.dart';
|
||||
|
||||
class ApiVolumesState extends ServerInstallationDependendState {
|
||||
const ApiVolumesState(this._volumes, this.status);
|
||||
|
||||
const ApiVolumesState.initial() : this(const [], LoadingStatus.uninitialized);
|
||||
final List<ServerVolume> _volumes;
|
||||
final LoadingStatus status;
|
||||
|
||||
List<ServerVolume> get volumes => _volumes;
|
||||
|
||||
ApiVolumesState copyWith({
|
||||
final List<ServerVolume>? volumes,
|
||||
final LoadingStatus? status,
|
||||
}) =>
|
||||
ApiVolumesState(
|
||||
volumes ?? _volumes,
|
||||
status ?? this.status,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_volumes];
|
||||
}
|
|
@ -5,7 +5,8 @@ import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
|||
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/volumes/volumes_cubit.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/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
|
@ -76,22 +77,10 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
|||
cards.add(
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: FutureBuilder(
|
||||
future: Future.wait([
|
||||
context.read<ServerInstallationCubit>().getServerDiskVolumes(),
|
||||
context.read<ApiVolumesCubit>().getVolumes(),
|
||||
]),
|
||||
builder: (
|
||||
final BuildContext context,
|
||||
final AsyncSnapshot<List<dynamic>> snapshot,
|
||||
) =>
|
||||
StorageCard(
|
||||
diskStatus: snapshot.hasData
|
||||
? toDiskStatus(
|
||||
snapshot.data![0] as List<ServerDiskVolume>,
|
||||
snapshot.data![1] as List<ServerVolume>,
|
||||
)
|
||||
: DiskStatus(),
|
||||
child: StorageCard(
|
||||
diskStatus: toDiskStatus(
|
||||
context.read<ApiServerVolumeCubit>().state.volumes,
|
||||
context.read<ApiProviderVolumeCubit>().state.volumes,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/volumes/volumes_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||
|
@ -39,7 +39,7 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
|
|||
|
||||
@override
|
||||
Widget build(final BuildContext context) => FutureBuilder(
|
||||
future: context.read<ApiVolumesCubit>().getPricePerGb(),
|
||||
future: context.read<ApiProviderVolumeCubit>().getPricePerGb(),
|
||||
builder: (
|
||||
final BuildContext context,
|
||||
final AsyncSnapshot<void> snapshot,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
|
||||
|
||||
class ServiceStorageConsumptionListItem extends StatelessWidget {
|
||||
const ServiceStorageConsumptionListItem({
|
||||
required this.title,
|
||||
required this.percentage,
|
||||
required this.storageConsumptionText,
|
||||
required this.color,
|
||||
required this.icon,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final double percentage;
|
||||
final String storageConsumptionText;
|
||||
final Color color;
|
||||
final IconData icon;
|
||||
@override
|
||||
Widget build(final BuildContext context) => Row(
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
storageConsumptionText,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
BrandLinearIndicator(
|
||||
value: percentage,
|
||||
color: color,
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
height: 7.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue