feat: Implement backups wizard confirmation step

This commit is contained in:
NaiJi 2023-10-04 05:23:33 -03:00
parent d6871e448e
commit 757bf27dc8
9 changed files with 90 additions and 30 deletions

View File

@ -27,12 +27,15 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
Future<void> load() async {
if (serverInstallationCubit.state is ServerInstallationFinished) {
final BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
final BackupsCredential? backupsCredential =
getIt<ApiConfigModel>().backblazeCredential;
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(
backupsCredential: backupsCredential,
backblazeBucket: bucket,
isInitialized: backupConfig?.isInitialized,
autobackupPeriod: backupConfig?.autobackupPeriod ?? Duration.zero,

View File

@ -1,7 +1,10 @@
import 'dart:async';
import 'package:cubit_form/cubit_form.dart';
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/api_maps/rest_maps/backblaze.dart';
import 'package:selfprivacy/logic/models/backup.dart';
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
@ -10,13 +13,14 @@ part 'backups_wizard_state.dart';
class BackupsWizardCubit extends Cubit<BackupsWizardState> {
BackupsWizardCubit() : super(const BackupsWizardState());
BackupConfiguration? serverBackupConfig;
Future<void> load() async {
final BackupConfiguration? backupConfig =
await ServerApi().getBackupsConfiguration();
serverBackupConfig = await ServerApi().getBackupsConfiguration();
/// If config already exists, then user only lacks credentials,
/// we don't need full re-initialization
if (backupConfig != null) {
if (serverBackupConfig != null) {
emit(state.copyWith(currentStep: BackupsWizardStep.hostingRecovery));
}
}
@ -26,7 +30,7 @@ class BackupsWizardCubit extends Cubit<BackupsWizardState> {
state.copyWith(
backupsCredential: backupsCredential,
currentStep: state.currentStep == BackupsWizardStep.hostingRecovery
? BackupsWizardStep.finished
? BackupsWizardStep.confirmRecovery
: BackupsWizardStep.settingsInitialization,
),
);
@ -55,4 +59,24 @@ class BackupsWizardCubit extends Cubit<BackupsWizardState> {
),
);
}
void recoverBackupsInformation() async {
try {
await getIt<ApiConfigModel>()
.storeBackblazeCredential(state.backupsCredential!);
final bucket = await BackblazeApi()
.fetchBucket(state.backupsCredential!, serverBackupConfig!);
await getIt<ApiConfigModel>().storeBackblazeBucket(bucket!);
} catch (e) {
print(e);
getIt<NavigationService>().showSnackBar('jobs.generic_error'.tr());
return;
}
emit(
state.copyWith(
currentStep: BackupsWizardStep.finished,
),
);
}
}

View File

@ -6,7 +6,7 @@ import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
import 'package:easy_localization/easy_localization.dart';
class BackblazeFormCubit extends FormCubit {
BackblazeFormCubit(this.onSubmitCallback) {
BackblazeFormCubit({required this.onSubmitCallback}) {
keyId = FieldCubit(
initalValue: '',
validations: [

View File

@ -33,6 +33,8 @@ class BackupDetailsPage extends StatelessWidget {
is ServerInstallationFinished;
final BackupsState backupsState = context.watch<BackupsCubit>().state;
final bool isBackupInitialized = backupsState.isInitialized;
final bool isBackupWizard =
!isBackupInitialized || backupsState.backupsCredential == null;
final StateType providerState = isReady && isBackupInitialized
? StateType.stable
: StateType.uninitialized;
@ -58,7 +60,7 @@ class BackupDetailsPage extends StatelessWidget {
);
}
if (!isBackupInitialized) {
if (isBackupWizard) {
return BrandHeroScreen(
heroIcon: BrandIcons.save,
heroTitle: 'backup.card_title'.tr(),
@ -75,7 +77,8 @@ class BackupDetailsPage extends StatelessWidget {
BrandButton.rised(
onPressed: preventActions
? null
: () => context.pushRoute(const BackupsInitializingRoute()),
: () =>
context.replaceRoute(const BackupsInitializingRoute()),
text: 'backup.initialize'.tr(),
),
],

View File

@ -1,12 +1,13 @@
import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
import 'package:selfprivacy/logic/cubit/backups_wizard/backups_wizard_cubit.dart';
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart';
class BackupProviderPicker extends StatelessWidget {
const BackupProviderPicker({
class BackupConfirmationPage extends StatelessWidget {
const BackupConfirmationPage({
super.key,
});
@ -16,7 +17,7 @@ class BackupProviderPicker extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${'initializing.connect_to_server_provider'.tr()}Backblaze',
'Confirm and connect TEST',
style: Theme.of(context).textTheme.headlineSmall,
),
],
@ -26,7 +27,9 @@ class BackupProviderPicker extends StatelessWidget {
children: [
const SizedBox(height: 32),
BrandButton.rised(
onPressed: () => context.read<BackblazeFormCubit>().trySubmit(),
onPressed: () => context
.read<BackupsWizardCubit>()
.recoverBackupsInformation(),
text: 'basis.connect'.tr(),
),
const SizedBox(height: 10),

View File

@ -2,13 +2,17 @@ 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/cubit/backups/backups_cubit.dart';
import 'package:selfprivacy/logic/cubit/backups_wizard/backups_wizard_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
import 'package:selfprivacy/ui/components/drawers/progress_drawer.dart';
import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart';
import 'package:selfprivacy/ui/components/drawers/support_drawer.dart';
import 'package:selfprivacy/ui/pages/backups/setup/backup_confirmation.dart';
import 'package:selfprivacy/ui/pages/backups/setup/backup_provider_picker.dart';
import 'package:selfprivacy/ui/pages/backups/setup/backup_settings_page.dart';
import 'package:selfprivacy/ui/router/router.dart';
@ -22,28 +26,55 @@ class BackupsInitializingPage extends StatelessWidget {
Widget build(final BuildContext context) {
final Widget actualInitializingPage;
final cubit = context.watch<BackupsWizardCubit>();
int progressDrawerStep = 0;
final currentStep = cubit.state.currentStep;
switch (currentStep) {
case BackupsWizardStep.confirmInitialization:
actualInitializingPage = const BackupConfirmationPage();
progressDrawerStep = 2;
break;
case BackupsWizardStep.confirmRecovery:
actualInitializingPage = const BackupConfirmationPage();
progressDrawerStep = 2;
break;
case BackupsWizardStep.settingsInitialization:
actualInitializingPage = const BackupSettingsPage();
progressDrawerStep = 1;
break;
case BackupsWizardStep.hostingRecovery:
case BackupsWizardStep.hostingInitialization:
default:
actualInitializingPage = const BackupProviderPicker();
progressDrawerStep = 0;
actualInitializingPage = BlocProvider(
create: (final context) => BackblazeFormCubit(
onSubmitCallback:
(final String keyId, final String applicationKey) =>
cubit.setBackupsCredential(
BackupsCredential(
applicationKey: applicationKey,
keyId: keyId,
provider: BackupsProviderType.backblaze,
),
),
),
child: Builder(
builder: (final context) => const BackupProviderPicker(),
),
);
break;
}
final List<String> titles = [
'backup.steps.hosting',
'backup.steps.period',
'backup.steps.rotation',
'backup.wizard.steps.hosting',
'backup.wizard.steps.settings',
'backup.wizard.steps.confirmation',
];
return BlocListener<BackupsWizardCubit, BackupsWizardState>(
listener: (final context, final state) {
if (cubit.state.currentStep == BackupsWizardStep.finished) {
context.router.pop();
context.read<BackupsCubit>().load();
context.router.popUntilRoot();
}
},
child: Scaffold(
@ -52,15 +83,8 @@ class BackupsInitializingPage extends StatelessWidget {
appBar: Breakpoints.large.isActive(context)
? null
: AppBar(
actions: [
if (cubit.state.currentStep == BackupsWizardStep.finished)
IconButton(
icon: const Icon(Icons.check),
onPressed: () {
context.router.pop();
},
),
const SizedBox.shrink(),
actions: const [
SizedBox.shrink(),
],
title: Text(
'more_page.configuration_wizard'.tr(),
@ -86,7 +110,7 @@ class BackupsInitializingPage extends StatelessWidget {
if (Breakpoints.large.isActive(context))
ProgressDrawer(
steps: titles,
currentStep: currentStep.index,
currentStep: progressDrawerStep,
title: 'more_page.configuration_wizard'.tr(),
constraints: constraints,
trailing: Column(
@ -109,7 +133,7 @@ class BackupsInitializingPage extends StatelessWidget {
'basis.later'.tr(),
),
onPressed: () {
context.router.pop();
context.router.popUntilRoot();
},
),
],

View File

@ -22,7 +22,7 @@ class BackupSettingsPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'backup.settings.initialize_settings_title'.tr(),
'backup.wizard.initialize_settings_title'.tr(),
style: Theme.of(context).textTheme.headlineSmall,
),
],

View File

@ -30,7 +30,8 @@ class _ProvidersPageState extends State<ProvidersPage> {
final bool isReady = context.watch<ServerInstallationCubit>().state
is ServerInstallationFinished;
final bool isBackupInitialized =
context.watch<BackupsCubit>().state.isInitialized;
context.watch<BackupsCubit>().state.isInitialized &&
context.watch<BackupsCubit>().state.backupsCredential != null;
final DnsRecordsStatus dnsStatus =
context.watch<DnsRecordsCubit>().state.dnsState;

View File

@ -2,6 +2,7 @@ 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/cubit/backups/backups_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/forms/factories/field_cubit_factory.dart';
@ -80,6 +81,7 @@ class InitializingPage extends StatelessWidget {
IconButton(
icon: const Icon(Icons.check),
onPressed: () {
context.read<BackupsCubit>().load();
context.router.popUntilRoot();
},
),