mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-23 09:16:54 +00:00
refactor: Rewire cubit from depending on server_installation_cubit to the new connection manager
This commit is contained in:
parent
332e31b655
commit
b1be3f24d6
|
@ -9,7 +9,7 @@ import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
|||
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/client_jobs/client_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||
|
@ -36,7 +36,8 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
final apiVolumesCubit = ApiProviderVolumeCubit(serverInstallationCubit);
|
||||
final apiServerVolumesCubit =
|
||||
ApiServerVolumeCubit(serverInstallationCubit, apiVolumesCubit);
|
||||
final serverJobsCubit = ServerJobsCubit(serverInstallationCubit);
|
||||
final serverJobsBloc = ServerJobsBloc();
|
||||
final connectionStatusBloc = ConnectionStatusBloc();
|
||||
final serverDetailsCubit = ServerDetailsCubit(serverInstallationCubit);
|
||||
|
||||
return MultiProvider(
|
||||
|
@ -64,11 +65,11 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
lazy: false,
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => backupsCubit..load(),
|
||||
create: (final _) => backupsCubit,
|
||||
lazy: false,
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => dnsRecordsCubit..load(),
|
||||
create: (final _) => dnsRecordsCubit,
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => recoveryKeyCubit..load(),
|
||||
|
@ -83,8 +84,9 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
create: (final _) => apiServerVolumesCubit..load(),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => serverJobsCubit..load(),
|
||||
create: (final _) => serverJobsBloc,
|
||||
),
|
||||
BlocProvider(create: (final _) => connectionStatusBloc),
|
||||
BlocProvider(
|
||||
create: (final _) => serverDetailsCubit..load(),
|
||||
),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:get_it/get_it.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_config.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/get_it/console.dart';
|
||||
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||
|
||||
|
@ -15,5 +16,9 @@ Future<void> getItSetup() async {
|
|||
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
||||
getIt.registerSingleton<ApiConfigModel>(ApiConfigModel()..init());
|
||||
|
||||
getIt.registerSingleton<ApiConnectionRepository>(
|
||||
ApiConnectionRepository()..init(),
|
||||
);
|
||||
|
||||
await getIt.allReady();
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
|
||||
export 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
|
||||
part 'authentication_dependend_state.dart';
|
||||
|
||||
abstract class ServerInstallationDependendCubit<
|
||||
T extends ServerInstallationDependendState> extends Cubit<T> {
|
||||
ServerInstallationDependendCubit(
|
||||
this.serverInstallationCubit,
|
||||
final T initState,
|
||||
) : super(initState) {
|
||||
authCubitSubscription =
|
||||
serverInstallationCubit.stream.listen(checkAuthStatus);
|
||||
checkAuthStatus(serverInstallationCubit.state);
|
||||
}
|
||||
|
||||
void checkAuthStatus(final ServerInstallationState state) {
|
||||
if (state is ServerInstallationFinished) {
|
||||
load();
|
||||
} else if (state is ServerInstallationEmpty) {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
late StreamSubscription authCubitSubscription;
|
||||
final ServerInstallationCubit serverInstallationCubit;
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
authCubitSubscription.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
|
@ -4,7 +4,8 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
|
@ -13,10 +14,9 @@ import 'package:selfprivacy/logic/models/service.dart';
|
|||
|
||||
part 'backups_state.dart';
|
||||
|
||||
class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
||||
class BackupsCubit extends ServerConnectionDependentCubit<BackupsState> {
|
||||
BackupsCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(
|
||||
serverInstallationCubit,
|
||||
const BackupsState(preventActions: true),
|
||||
);
|
||||
|
||||
|
@ -25,24 +25,22 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
|||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
final BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
|
||||
final BackupConfiguration? backupConfig =
|
||||
await api.getBackupsConfiguration();
|
||||
final List<Backup> backups = await api.getBackups();
|
||||
backups.sort((final a, final b) => b.time.compareTo(a.time));
|
||||
emit(
|
||||
state.copyWith(
|
||||
backblazeBucket: bucket,
|
||||
isInitialized: backupConfig?.isInitialized,
|
||||
autobackupPeriod: backupConfig?.autobackupPeriod ?? Duration.zero,
|
||||
autobackupQuotas: backupConfig?.autobackupQuotas,
|
||||
backups: backups,
|
||||
preventActions: false,
|
||||
refreshing: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
final BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
|
||||
final BackupConfiguration? backupConfig =
|
||||
await api.getBackupsConfiguration();
|
||||
final List<Backup> backups = await api.getBackups();
|
||||
backups.sort((final a, final b) => b.time.compareTo(a.time));
|
||||
emit(
|
||||
state.copyWith(
|
||||
backblazeBucket: bucket,
|
||||
isInitialized: backupConfig?.isInitialized,
|
||||
autobackupPeriod: backupConfig?.autobackupPeriod ?? Duration.zero,
|
||||
autobackupQuotas: backupConfig?.autobackupQuotas,
|
||||
backups: backups,
|
||||
preventActions: false,
|
||||
refreshing: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> initializeBackups() async {
|
||||
|
@ -59,10 +57,11 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
|||
final BackblazeBucket bucket;
|
||||
|
||||
if (state.backblazeBucket == null) {
|
||||
final String domain = serverInstallationCubit
|
||||
.state.serverDomain!.domainName
|
||||
final String domain = getIt<ApiConnectionRepository>()
|
||||
.serverDomain!
|
||||
.domainName
|
||||
.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
|
||||
final int serverId = serverInstallationCubit.state.serverDetails!.id;
|
||||
final int serverId = getIt<ApiConnectionRepository>().serverDetails!.id;
|
||||
String bucketName =
|
||||
'${DateTime.now().millisecondsSinceEpoch}-$serverId-$domain';
|
||||
if (bucketName.length > 49) {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
|
||||
part 'connection_status_event.dart';
|
||||
part 'connection_status_state.dart';
|
||||
|
||||
class ConnectionStatusBloc
|
||||
extends Bloc<ConnectionStatusEvent, ConnectionStatusState> {
|
||||
ConnectionStatusBloc()
|
||||
: super(
|
||||
const ConnectionStatusState(
|
||||
connectionStatus: ConnectionStatus.nonexistent,
|
||||
),
|
||||
) {
|
||||
final apiConnectionRepository = getIt<ApiConnectionRepository>();
|
||||
apiConnectionRepository.connectionStatusStream.listen(
|
||||
(final ConnectionStatus connectionStatus) {
|
||||
add(
|
||||
ConnectionStatusChanged(connectionStatus),
|
||||
);
|
||||
},
|
||||
);
|
||||
on<ConnectionStatusChanged>((final event, final emit) {
|
||||
emit(ConnectionStatusState(connectionStatus: event.connectionStatus));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
part of 'connection_status_bloc.dart';
|
||||
|
||||
sealed class ConnectionStatusEvent extends Equatable {
|
||||
const ConnectionStatusEvent();
|
||||
}
|
||||
|
||||
class ConnectionStatusChanged extends ConnectionStatusEvent {
|
||||
const ConnectionStatusChanged(this.connectionStatus);
|
||||
|
||||
final ConnectionStatus connectionStatus;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [connectionStatus];
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
part of 'connection_status_bloc.dart';
|
||||
|
||||
class ConnectionStatusState extends Equatable {
|
||||
const ConnectionStatusState({
|
||||
required this.connectionStatus,
|
||||
});
|
||||
|
||||
final ConnectionStatus connectionStatus;
|
||||
|
||||
@override
|
||||
List<Object> get props => [connectionStatus];
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
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/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/api_token.dart';
|
||||
|
||||
part 'devices_state.dart';
|
||||
|
||||
class ApiDevicesCubit
|
||||
extends ServerInstallationDependendCubit<ApiDevicesState> {
|
||||
class ApiDevicesCubit extends ServerConnectionDependentCubit<ApiDevicesState> {
|
||||
ApiDevicesCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiDevicesState.initial());
|
||||
: super(const ApiDevicesState.initial());
|
||||
|
||||
final ServerApi api = ServerApi();
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||
|
||||
|
@ -10,11 +12,9 @@ import 'package:selfprivacy/utils/network_utils.dart';
|
|||
|
||||
part 'dns_records_state.dart';
|
||||
|
||||
class DnsRecordsCubit
|
||||
extends ServerInstallationDependendCubit<DnsRecordsState> {
|
||||
class DnsRecordsCubit extends ServerConnectionDependentCubit<DnsRecordsState> {
|
||||
DnsRecordsCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(
|
||||
serverInstallationCubit,
|
||||
const DnsRecordsState(dnsState: DnsRecordsStatus.refreshing),
|
||||
);
|
||||
|
||||
|
@ -29,38 +29,36 @@ class DnsRecordsCubit
|
|||
),
|
||||
);
|
||||
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||
final String? ipAddress =
|
||||
serverInstallationCubit.state.serverDetails?.ip4;
|
||||
final ServerDomain? domain = getIt<ApiConnectionRepository>().serverDomain;
|
||||
final String? ipAddress =
|
||||
getIt<ApiConnectionRepository>().serverDetails?.ip4;
|
||||
|
||||
if (domain == null || ipAddress == null) {
|
||||
emit(const DnsRecordsState());
|
||||
return;
|
||||
}
|
||||
|
||||
final List<DnsRecord> allDnsRecords = await api.getDnsRecords();
|
||||
allDnsRecords.removeWhere((final record) => record.type == 'AAAA');
|
||||
final foundRecords = await validateDnsRecords(
|
||||
domain,
|
||||
extractDkimRecord(allDnsRecords)?.content ?? '',
|
||||
allDnsRecords,
|
||||
);
|
||||
|
||||
if (!foundRecords.success || foundRecords.data.isEmpty) {
|
||||
emit(const DnsRecordsState());
|
||||
return;
|
||||
}
|
||||
|
||||
emit(
|
||||
DnsRecordsState(
|
||||
dnsRecords: foundRecords.data,
|
||||
dnsState: foundRecords.data.any((final r) => r.isSatisfied == false)
|
||||
? DnsRecordsStatus.error
|
||||
: DnsRecordsStatus.good,
|
||||
),
|
||||
);
|
||||
if (domain == null || ipAddress == null) {
|
||||
emit(const DnsRecordsState());
|
||||
return;
|
||||
}
|
||||
|
||||
final List<DnsRecord> allDnsRecords = await api.getDnsRecords();
|
||||
allDnsRecords.removeWhere((final record) => record.type == 'AAAA');
|
||||
final foundRecords = await validateDnsRecords(
|
||||
domain,
|
||||
extractDkimRecord(allDnsRecords)?.content ?? '',
|
||||
allDnsRecords,
|
||||
);
|
||||
|
||||
if (!foundRecords.success || foundRecords.data.isEmpty) {
|
||||
emit(const DnsRecordsState());
|
||||
return;
|
||||
}
|
||||
|
||||
emit(
|
||||
DnsRecordsState(
|
||||
dnsRecords: foundRecords.data,
|
||||
dnsState: foundRecords.data.any((final r) => r.isSatisfied == false)
|
||||
? DnsRecordsStatus.error
|
||||
: DnsRecordsStatus.good,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Tries to check whether all known DNS records on the domain by ip4
|
||||
|
@ -171,7 +169,7 @@ class DnsRecordsCubit
|
|||
final List<DnsRecord> records = await api.getDnsRecords();
|
||||
|
||||
/// TODO: Error handling?
|
||||
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||
final ServerDomain? domain = getIt<ApiConnectionRepository>().serverDomain;
|
||||
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
||||
records: records,
|
||||
domain: domain!,
|
||||
|
|
|
@ -4,7 +4,7 @@ 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/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
|
@ -14,16 +14,14 @@ import 'package:selfprivacy/logic/providers/providers_controller.dart';
|
|||
part 'provider_volume_state.dart';
|
||||
|
||||
class ApiProviderVolumeCubit
|
||||
extends ServerInstallationDependendCubit<ApiProviderVolumeState> {
|
||||
extends ServerConnectionDependentCubit<ApiProviderVolumeState> {
|
||||
ApiProviderVolumeCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiProviderVolumeState.initial());
|
||||
: super(const ApiProviderVolumeState.initial());
|
||||
final ServerApi serverApi = ServerApi();
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
unawaited(_refetch());
|
||||
}
|
||||
unawaited(_refetch());
|
||||
}
|
||||
|
||||
Future<Price?> getPricePerGb() async {
|
||||
|
|
|
@ -2,15 +2,15 @@ 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/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/recovery_token_status.dart';
|
||||
|
||||
part 'recovery_key_state.dart';
|
||||
|
||||
class RecoveryKeyCubit
|
||||
extends ServerInstallationDependendCubit<RecoveryKeyState> {
|
||||
extends ServerConnectionDependentCubit<RecoveryKeyState> {
|
||||
RecoveryKeyCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const RecoveryKeyState.initial());
|
||||
: super(const RecoveryKeyState.initial());
|
||||
|
||||
final ServerApi api = ServerApi();
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
|
||||
export 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
|
||||
part 'server_connection_dependent_state.dart';
|
||||
|
||||
abstract class ServerConnectionDependentCubit<
|
||||
T extends ServerInstallationDependendState> extends Cubit<T> {
|
||||
ServerConnectionDependentCubit(
|
||||
super.initState,
|
||||
) {
|
||||
final connectionRepository = getIt<ApiConnectionRepository>();
|
||||
|
||||
apiStatusSubscription =
|
||||
connectionRepository.connectionStatusStream.listen(checkAuthStatus);
|
||||
checkAuthStatus(connectionRepository.connectionStatus);
|
||||
}
|
||||
|
||||
void checkAuthStatus(final ConnectionStatus state) {
|
||||
switch (state) {
|
||||
case ConnectionStatus.nonexistent:
|
||||
clear();
|
||||
isLoaded = false;
|
||||
break;
|
||||
case ConnectionStatus.connected:
|
||||
if (!isLoaded) {
|
||||
load();
|
||||
isLoaded = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
late StreamSubscription apiStatusSubscription;
|
||||
bool isLoaded = false;
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
apiStatusSubscription.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
part of 'authentication_dependend_cubit.dart';
|
||||
part of 'server_connection_dependent_cubit.dart';
|
||||
|
||||
abstract class ServerInstallationDependendState extends Equatable {
|
||||
const ServerInstallationDependendState();
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
|
@ -8,9 +8,9 @@ import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
|||
part 'server_detailed_info_state.dart';
|
||||
|
||||
class ServerDetailsCubit
|
||||
extends ServerInstallationDependendCubit<ServerDetailsState> {
|
||||
extends ServerConnectionDependentCubit<ServerDetailsState> {
|
||||
ServerDetailsCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, ServerDetailsInitial());
|
||||
: super(ServerDetailsInitial());
|
||||
|
||||
ServerDetailsRepository repository = ServerDetailsRepository();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ 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/rest_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/tls_options.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
|
@ -484,6 +485,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
if (dkimCreated) {
|
||||
await repository.saveHasFinalChecked(true);
|
||||
emit(dataState.finish());
|
||||
getIt<ApiConnectionRepository>().init();
|
||||
} else {
|
||||
runDelayed(
|
||||
finishCheckIfServerIsOkay,
|
||||
|
|
87
lib/logic/cubit/server_jobs/server_jobs_bloc.dart
Normal file
87
lib/logic/cubit/server_jobs/server_jobs_bloc.dart
Normal file
|
@ -0,0 +1,87 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
||||
export 'package:provider/provider.dart';
|
||||
|
||||
part 'server_jobs_state.dart';
|
||||
part 'server_jobs_event.dart';
|
||||
|
||||
class ServerJobsBloc extends Bloc<ServerJobsEvent, ServerJobsState> {
|
||||
ServerJobsBloc()
|
||||
: super(
|
||||
ServerJobsInitialState(),
|
||||
) {
|
||||
final apiConnectionRepository = getIt<ApiConnectionRepository>();
|
||||
_apiDataSubscription = apiConnectionRepository.dataStream.listen(
|
||||
(final ApiData apiData) {
|
||||
add(
|
||||
ServerJobsListChanged([...apiData.serverJobs.data ?? []]),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
on<ServerJobsListChanged>(
|
||||
_mapServerJobsListChangedToState,
|
||||
);
|
||||
on<RemoveServerJob>(
|
||||
_mapRemoveServerJobToState,
|
||||
);
|
||||
on<RemoveAllFinishedJobs>(
|
||||
_mapRemoveAllFinishedJobsToState,
|
||||
);
|
||||
}
|
||||
|
||||
StreamSubscription? _apiDataSubscription;
|
||||
|
||||
Future<void> _mapServerJobsListChangedToState(
|
||||
final ServerJobsListChanged event,
|
||||
final Emitter<ServerJobsState> emit,
|
||||
) async {
|
||||
if (event.serverJobList.isEmpty) {
|
||||
emit(ServerJobsListEmptyState());
|
||||
return;
|
||||
}
|
||||
final newState =
|
||||
ServerJobsListWithJobsState(serverJobList: event.serverJobList);
|
||||
emit(newState);
|
||||
}
|
||||
|
||||
Future<void> _mapRemoveServerJobToState(
|
||||
final RemoveServerJob event,
|
||||
final Emitter<ServerJobsState> emit,
|
||||
) async {
|
||||
await getIt<ApiConnectionRepository>().removeServerJob(event.uid);
|
||||
}
|
||||
|
||||
Future<void> _mapRemoveAllFinishedJobsToState(
|
||||
final RemoveAllFinishedJobs event,
|
||||
final Emitter<ServerJobsState> emit,
|
||||
) async {
|
||||
final List<ServerJob> finishedJobs = state.serverJobList
|
||||
.where(
|
||||
(final ServerJob job) =>
|
||||
job.status == JobStatusEnum.finished ||
|
||||
job.status == JobStatusEnum.error,
|
||||
)
|
||||
.toList();
|
||||
for (final ServerJob job in finishedJobs) {
|
||||
await getIt<ApiConnectionRepository>().removeServerJob(job.uid);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onChange(final Change<ServerJobsState> change) {
|
||||
super.onChange(change);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
_apiDataSubscription?.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
|
@ -1,123 +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/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
||||
export 'package:provider/provider.dart';
|
||||
|
||||
part 'server_jobs_state.dart';
|
||||
|
||||
class ServerJobsCubit
|
||||
extends ServerInstallationDependendCubit<ServerJobsState> {
|
||||
ServerJobsCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(
|
||||
serverInstallationCubit,
|
||||
ServerJobsState(),
|
||||
);
|
||||
|
||||
Timer? timer;
|
||||
final ServerApi api = ServerApi();
|
||||
|
||||
@override
|
||||
void clear() async {
|
||||
emit(
|
||||
ServerJobsState(),
|
||||
);
|
||||
if (timer != null && timer!.isActive) {
|
||||
timer!.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
final List<ServerJob> jobs = await api.getServerJobs();
|
||||
emit(
|
||||
ServerJobsState(
|
||||
serverJobList: jobs,
|
||||
),
|
||||
);
|
||||
timer = Timer(const Duration(seconds: 5), () => reload(useTimer: true));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> migrateToBinds(final Map<String, String> serviceToDisk) async {
|
||||
final result = await api.migrateToBinds(serviceToDisk);
|
||||
if (result.data == null) {
|
||||
getIt<NavigationService>().showSnackBar(result.message!);
|
||||
return;
|
||||
}
|
||||
|
||||
emit(
|
||||
ServerJobsState(
|
||||
migrationJobUid: result.data,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ServerJob? getServerJobByUid(final String uid) {
|
||||
ServerJob? job;
|
||||
|
||||
try {
|
||||
job = state.serverJobList.firstWhere(
|
||||
(final ServerJob job) => job.uid == uid,
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
Future<void> removeServerJob(final String uid) async {
|
||||
final result = await api.removeApiJob(uid);
|
||||
if (!result.success) {
|
||||
getIt<NavigationService>().showSnackBar('jobs.generic_error'.tr());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.data) {
|
||||
getIt<NavigationService>()
|
||||
.showSnackBar(result.message ?? 'jobs.generic_error'.tr());
|
||||
return;
|
||||
}
|
||||
|
||||
emit(
|
||||
ServerJobsState(
|
||||
serverJobList: [
|
||||
for (final ServerJob job in state.serverJobList)
|
||||
if (job.uid != uid) job,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeAllFinishedJobs() async {
|
||||
final List<ServerJob> finishedJobs = state.serverJobList
|
||||
.where(
|
||||
(final ServerJob job) =>
|
||||
job.status == JobStatusEnum.finished ||
|
||||
job.status == JobStatusEnum.error,
|
||||
)
|
||||
.toList();
|
||||
for (final ServerJob job in finishedJobs) {
|
||||
await removeServerJob(job.uid);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> reload({final bool useTimer = false}) async {
|
||||
final List<ServerJob> jobs = await api.getServerJobs();
|
||||
emit(
|
||||
ServerJobsState(
|
||||
serverJobList: jobs,
|
||||
),
|
||||
);
|
||||
if (useTimer) {
|
||||
timer = Timer(const Duration(seconds: 5), () => reload(useTimer: true));
|
||||
}
|
||||
}
|
||||
}
|
28
lib/logic/cubit/server_jobs/server_jobs_event.dart
Normal file
28
lib/logic/cubit/server_jobs/server_jobs_event.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
part of 'server_jobs_bloc.dart';
|
||||
|
||||
sealed class ServerJobsEvent extends Equatable {
|
||||
const ServerJobsEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class ServerJobsListChanged extends ServerJobsEvent {
|
||||
const ServerJobsListChanged(this.serverJobList);
|
||||
|
||||
final List<ServerJob> serverJobList;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [serverJobList];
|
||||
}
|
||||
|
||||
class RemoveServerJob extends ServerJobsEvent {
|
||||
const RemoveServerJob(this.uid);
|
||||
|
||||
final String uid;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [uid];
|
||||
}
|
||||
|
||||
class RemoveAllFinishedJobs extends ServerJobsEvent {}
|
|
@ -1,15 +1,16 @@
|
|||
part of 'server_jobs_cubit.dart';
|
||||
part of 'server_jobs_bloc.dart';
|
||||
|
||||
class ServerJobsState extends ServerInstallationDependendState {
|
||||
sealed class ServerJobsState extends Equatable {
|
||||
ServerJobsState({
|
||||
final serverJobList = const <ServerJob>[],
|
||||
this.migrationJobUid,
|
||||
}) {
|
||||
_serverJobList = serverJobList;
|
||||
}
|
||||
final int? hashCode,
|
||||
}) : _hashCode = hashCode ?? Object.hashAll([]);
|
||||
|
||||
late final List<ServerJob> _serverJobList;
|
||||
final String? migrationJobUid;
|
||||
final int? _hashCode;
|
||||
|
||||
final apiConnectionRepository = getIt<ApiConnectionRepository>();
|
||||
|
||||
List<ServerJob> get _serverJobList =>
|
||||
apiConnectionRepository.apiData.serverJobs.data ?? [];
|
||||
|
||||
List<ServerJob> get serverJobList {
|
||||
try {
|
||||
|
@ -36,14 +37,19 @@ class ServerJobsState extends ServerInstallationDependendState {
|
|||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [migrationJobUid, _serverJobList];
|
||||
|
||||
ServerJobsState copyWith({
|
||||
final List<ServerJob>? serverJobList,
|
||||
final String? migrationJobUid,
|
||||
}) =>
|
||||
ServerJobsState(
|
||||
serverJobList: serverJobList ?? _serverJobList,
|
||||
migrationJobUid: migrationJobUid ?? this.migrationJobUid,
|
||||
);
|
||||
List<Object?> get props => [_hashCode];
|
||||
}
|
||||
|
||||
class ServerJobsInitialState extends ServerJobsState {
|
||||
ServerJobsInitialState() : super(hashCode: Object.hashAll([]));
|
||||
}
|
||||
|
||||
class ServerJobsListEmptyState extends ServerJobsState {
|
||||
ServerJobsListEmptyState() : super(hashCode: Object.hashAll([]));
|
||||
}
|
||||
|
||||
class ServerJobsListWithJobsState extends ServerJobsState {
|
||||
ServerJobsListWithJobsState({
|
||||
required final List<ServerJob> serverJobList,
|
||||
}) : super(hashCode: Object.hashAll([...serverJobList]));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ 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/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
|
@ -10,11 +10,12 @@ import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
|||
part 'server_volume_state.dart';
|
||||
|
||||
class ApiServerVolumeCubit
|
||||
extends ServerInstallationDependendCubit<ApiServerVolumeState> {
|
||||
extends ServerConnectionDependentCubit<ApiServerVolumeState> {
|
||||
ApiServerVolumeCubit(
|
||||
final ServerInstallationCubit serverInstallationCubit,
|
||||
this.providerVolumeCubit,
|
||||
) : super(serverInstallationCubit, ApiServerVolumeState.initial()) {
|
||||
) : super(ApiServerVolumeState.initial()) {
|
||||
// TODO: Remove this connection between cubits
|
||||
_providerVolumeSubscription =
|
||||
providerVolumeCubit.stream.listen(checkProviderVolumes);
|
||||
}
|
||||
|
@ -23,9 +24,7 @@ class ApiServerVolumeCubit
|
|||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
unawaited(reload());
|
||||
}
|
||||
unawaited(reload());
|
||||
}
|
||||
|
||||
late StreamSubscription<ApiProviderVolumeState> _providerVolumeSubscription;
|
||||
|
|
|
@ -3,28 +3,26 @@ 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/app_config_dependent/authentication_dependend_cubit.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 ServerInstallationDependendCubit<ServicesState> {
|
||||
class ServicesCubit extends ServerConnectionDependentCubit<ServicesState> {
|
||||
ServicesCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ServicesState.empty());
|
||||
: super(const ServicesState.empty());
|
||||
final ServerApi api = ServerApi();
|
||||
Timer? timer;
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
final List<Service> services = await api.getAllServices();
|
||||
emit(
|
||||
ServicesState(
|
||||
services: services,
|
||||
lockedServices: const [],
|
||||
),
|
||||
);
|
||||
timer = Timer(const Duration(seconds: 10), () => reload(useTimer: true));
|
||||
}
|
||||
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 {
|
||||
|
|
|
@ -5,17 +5,17 @@ import 'package:hive/hive.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
|
||||
export 'package:provider/provider.dart';
|
||||
|
||||
part 'users_state.dart';
|
||||
|
||||
class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||
class UsersCubit extends ServerConnectionDependentCubit<UsersState> {
|
||||
UsersCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(
|
||||
serverInstallationCubit,
|
||||
const UsersState(
|
||||
<User>[],
|
||||
false,
|
||||
|
@ -28,9 +28,6 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is! ServerInstallationFinished) {
|
||||
return;
|
||||
}
|
||||
final List<User> loadedUsers = box.values.toList();
|
||||
if (loadedUsers.isNotEmpty) {
|
||||
emit(
|
||||
|
@ -45,7 +42,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
if (serverInstallationCubit.state is! ServerInstallationFinished) {
|
||||
if (getIt<ApiConnectionRepository>().connectionStatus !=
|
||||
ConnectionStatus.nonexistent) {
|
||||
return;
|
||||
}
|
||||
emit(state.copyWith(isLoading: true));
|
||||
|
|
164
lib/logic/get_it/api_connection_repository.dart
Normal file
164
lib/logic/get_it/api_connection_repository.dart
Normal file
|
@ -0,0 +1,164 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
||||
/// Repository for all API calls
|
||||
/// Stores the current state of all data from API and exposes it to Blocs.
|
||||
class ApiConnectionRepository {
|
||||
Box box = Hive.box(BNames.serverInstallationBox);
|
||||
final ServerApi api = ServerApi();
|
||||
|
||||
final ApiData _apiData = ApiData();
|
||||
|
||||
ApiData get apiData => _apiData;
|
||||
|
||||
ConnectionStatus connectionStatus = ConnectionStatus.nonexistent;
|
||||
|
||||
final _dataStream = StreamController<ApiData>.broadcast();
|
||||
final _connectionStatusStream =
|
||||
StreamController<ConnectionStatus>.broadcast();
|
||||
|
||||
Stream<ApiData> get dataStream => _dataStream.stream;
|
||||
Stream<ConnectionStatus> get connectionStatusStream =>
|
||||
_connectionStatusStream.stream;
|
||||
|
||||
ConnectionStatus get currentConnectionStatus => connectionStatus;
|
||||
|
||||
Timer? _timer;
|
||||
|
||||
Future<void> removeServerJob(final String uid) async {
|
||||
await api.removeApiJob(uid);
|
||||
_apiData.serverJobs.data
|
||||
?.removeWhere((final ServerJob element) => element.uid == uid);
|
||||
_dataStream.add(_apiData);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_dataStream.close();
|
||||
_connectionStatusStream.close();
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
ServerHostingDetails? get serverDetails =>
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
ServerDomain? get serverDomain => getIt<ApiConfigModel>().serverDomain;
|
||||
|
||||
void init() async {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
final hasFinalChecked =
|
||||
box.get(BNames.hasFinalChecked, defaultValue: false);
|
||||
if (serverDetails == null || !hasFinalChecked) {
|
||||
return;
|
||||
}
|
||||
connectionStatus = ConnectionStatus.reconnecting;
|
||||
_connectionStatusStream.add(connectionStatus);
|
||||
|
||||
final String? apiVersion = await api.getApiVersion();
|
||||
if (apiVersion == null) {
|
||||
connectionStatus = ConnectionStatus.offline;
|
||||
_connectionStatusStream.add(connectionStatus);
|
||||
return;
|
||||
} else {
|
||||
connectionStatus = ConnectionStatus.connected;
|
||||
_connectionStatusStream.add(connectionStatus);
|
||||
_apiData.apiVersion.data = apiVersion;
|
||||
_dataStream.add(_apiData);
|
||||
}
|
||||
|
||||
_apiData.serverJobs.data = await api.getServerJobs();
|
||||
_dataStream.add(_apiData);
|
||||
|
||||
// Use timer to periodically check for new jobs
|
||||
_timer = Timer.periodic(
|
||||
const Duration(seconds: 10),
|
||||
reload,
|
||||
);
|
||||
}
|
||||
|
||||
void reload(final Timer timer) async {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
if (serverDetails == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String? apiVersion = await api.getApiVersion();
|
||||
if (apiVersion == null) {
|
||||
connectionStatus = ConnectionStatus.offline;
|
||||
_connectionStatusStream.add(connectionStatus);
|
||||
return;
|
||||
} else {
|
||||
connectionStatus = ConnectionStatus.connected;
|
||||
_connectionStatusStream.add(connectionStatus);
|
||||
_apiData.apiVersion.data = apiVersion;
|
||||
}
|
||||
|
||||
if (VersionConstraint.parse(_apiData.apiVersion.requiredApiVersion)
|
||||
.allows(Version.parse(apiVersion))) {
|
||||
final jobs = await api.getServerJobs();
|
||||
if (Object.hashAll(_apiData.serverJobs.data ?? []) !=
|
||||
Object.hashAll(jobs)) {
|
||||
_apiData.serverJobs.data = [...jobs];
|
||||
_dataStream.add(_apiData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ApiData {
|
||||
ApiData()
|
||||
: serverJobs = ApiDataElement<List<ServerJob>>(null),
|
||||
apiVersion = ApiDataElement<String>(null);
|
||||
|
||||
ApiDataElement<List<ServerJob>> serverJobs;
|
||||
ApiDataElement<String> apiVersion;
|
||||
}
|
||||
|
||||
enum ConnectionStatus {
|
||||
nonexistent,
|
||||
connected,
|
||||
reconnecting,
|
||||
offline,
|
||||
unauthorized,
|
||||
}
|
||||
|
||||
class ApiDataElement<T> {
|
||||
ApiDataElement(
|
||||
final T? data, {
|
||||
this.requiredApiVersion = '>=2.3.0',
|
||||
this.ttl = 60,
|
||||
}) : _data = data,
|
||||
_lastUpdated = DateTime.now();
|
||||
|
||||
T? _data;
|
||||
final String requiredApiVersion;
|
||||
|
||||
/// TTL of the data in seconds
|
||||
final int ttl;
|
||||
|
||||
/// Timestamp of when the data was last updated
|
||||
DateTime _lastUpdated;
|
||||
|
||||
bool get isExpired {
|
||||
final now = DateTime.now();
|
||||
final difference = now.difference(_lastUpdated);
|
||||
return difference.inSeconds > ttl;
|
||||
}
|
||||
|
||||
T? get data => _data;
|
||||
|
||||
/// Sets the data and updates the lastUpdated timestamp
|
||||
set data(final T? data) {
|
||||
_data = data;
|
||||
_lastUpdated = DateTime.now();
|
||||
}
|
||||
|
||||
/// Returns the last time the data was updated
|
||||
DateTime get lastUpdated => _lastUpdated;
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_api.graphql.dart';
|
||||
|
||||
part 'server_job.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class ServerJob {
|
||||
class ServerJob extends Equatable {
|
||||
factory ServerJob.fromJson(final Map<String, dynamic> json) =>
|
||||
_$ServerJobFromJson(json);
|
||||
ServerJob({
|
||||
const ServerJob({
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.status,
|
||||
|
@ -50,6 +51,22 @@ class ServerJob {
|
|||
final String? result;
|
||||
final String? statusText;
|
||||
final DateTime? finishedAt;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
uid,
|
||||
typeId,
|
||||
updatedAt,
|
||||
createdAt,
|
||||
error,
|
||||
progress,
|
||||
result,
|
||||
statusText,
|
||||
finishedAt,
|
||||
];
|
||||
}
|
||||
|
||||
enum JobStatusEnum {
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';
|
||||
|
@ -22,10 +22,10 @@ class JobsContent extends StatelessWidget {
|
|||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final List<ServerJob> serverJobs =
|
||||
context.watch<ServerJobsCubit>().state.serverJobList;
|
||||
context.watch<ServerJobsBloc>().state.serverJobList;
|
||||
|
||||
final bool hasRemovableJobs =
|
||||
context.watch<ServerJobsCubit>().state.hasRemovableJobs;
|
||||
context.watch<ServerJobsBloc>().state.hasRemovableJobs;
|
||||
|
||||
return BlocBuilder<JobsCubit, JobsState>(
|
||||
builder: (final context, final state) {
|
||||
|
@ -152,8 +152,8 @@ class JobsContent extends StatelessWidget {
|
|||
IconButton(
|
||||
onPressed: hasRemovableJobs
|
||||
? () => context
|
||||
.read<ServerJobsCubit>()
|
||||
.removeAllFinishedJobs()
|
||||
.read<ServerJobsBloc>()
|
||||
.add(RemoveAllFinishedJobs())
|
||||
: null,
|
||||
icon: const Icon(Icons.clear_all),
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
|
@ -172,7 +172,9 @@ class JobsContent extends StatelessWidget {
|
|||
serverJob: job,
|
||||
),
|
||||
onDismissed: (final direction) {
|
||||
context.read<ServerJobsCubit>().removeServerJob(job.uid);
|
||||
context.read<ServerJobsBloc>().add(
|
||||
RemoveServerJob(job.uid),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
@ -43,7 +43,7 @@ class BackupDetailsPage extends StatelessWidget {
|
|||
context.watch<ServicesCubit>().state.servicesThatCanBeBackedUp;
|
||||
final Duration? autobackupPeriod = backupsState.autobackupPeriod;
|
||||
final List<ServerJob> backupJobs = context
|
||||
.watch<ServerJobsCubit>()
|
||||
.watch<ServerJobsBloc>()
|
||||
.state
|
||||
.backupJobList
|
||||
.where((final job) => job.status != JobStatusEnum.finished)
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/utils/extensions/duration.dart';
|
||||
|
||||
class ChangeAutobackupsPeriodModal extends StatefulWidget {
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
|
||||
class ChangeRotationQuotasModal extends StatefulWidget {
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||
import 'package:selfprivacy/utils/platform_adapter.dart';
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
|
||||
|
@ -29,7 +29,7 @@ class _CreateBackupsModalState extends State<CreateBackupsModal> {
|
|||
void initState() {
|
||||
super.initState();
|
||||
final List<String> busyServices = context
|
||||
.read<ServerJobsCubit>()
|
||||
.read<ServerJobsBloc>()
|
||||
.state
|
||||
.backupJobList
|
||||
.where(
|
||||
|
@ -48,7 +48,7 @@ class _CreateBackupsModalState extends State<CreateBackupsModal> {
|
|||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final List<String> busyServices = context
|
||||
.watch<ServerJobsCubit>()
|
||||
.watch<ServerJobsBloc>()
|
||||
.state
|
||||
.backupJobList
|
||||
.where(
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
@ -34,7 +34,7 @@ class _SnapshotModalState extends State<SnapshotModal> {
|
|||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final List<String> busyServices = context
|
||||
.watch<ServerJobsCubit>()
|
||||
.watch<ServerJobsBloc>()
|
||||
.state
|
||||
.backupJobList
|
||||
.where(
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/tls_options.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_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/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
|
@ -100,6 +102,14 @@ class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
|
|||
context.watch<RecoveryKeyCubit>().state.loadingStatus.toString(),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('ApiConnectionRepository status'),
|
||||
subtitle: Text(
|
||||
getIt<ApiConnectionRepository>()
|
||||
.currentConnectionStatus
|
||||
.toString(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/service.dart';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
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:flutter_bloc/flutter_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';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
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/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
||||
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'package:cubit_form/cubit_form.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'package:cubit_form/cubit_form.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/server_provider_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/illustrations/stray_deer.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/price.dart';
|
||||
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||
|
|
Loading…
Reference in a new issue