From a9a7b04ad5e3cdd848d3ce24ca7632e70e8053dd Mon Sep 17 00:00:00 2001 From: Inex Code Date: Fri, 23 Feb 2024 19:50:28 +0300 Subject: [PATCH] fix: Return the binds migration interface Turns out, there are still servers that didn't perform the binds migration. The can't perform it anymore because email changed the id. I'm getting back the option to perform the binds migration, with some fallback defaults. --- .../graphql_maps/server_api/volume_api.dart | 11 ++-- .../bloc/server_jobs/server_jobs_bloc.dart | 20 +++++++ .../components/list_tiles/section_title.dart | 21 +++++++ lib/ui/pages/more/about_application.dart | 21 +------ .../more/app_settings/developer_settings.dart | 55 ++++++++++--------- .../binds_migration/services_migration.dart | 26 ++++++--- lib/ui/pages/services/service_page.dart | 1 + lib/ui/router/router.gr.dart | 8 ++- 8 files changed, 103 insertions(+), 60 deletions(-) create mode 100644 lib/ui/components/list_tiles/section_title.dart 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 713544eb..c111baa4 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 @@ -60,17 +60,18 @@ mixin VolumeApi on GraphQLApiMap { Future> migrateToBinds( final Map serviceToDisk, + final String fallbackDrive, ) async { GenericResult? mutation; try { final GraphQLClient client = await getClient(); final input = Input$MigrateToBindsInput( - bitwardenBlockDevice: serviceToDisk['bitwarden']!, - emailBlockDevice: serviceToDisk['mailserver']!, - giteaBlockDevice: serviceToDisk['gitea']!, - nextcloudBlockDevice: serviceToDisk['nextcloud']!, - pleromaBlockDevice: serviceToDisk['pleroma']!, + bitwardenBlockDevice: serviceToDisk['bitwarden'] ?? fallbackDrive, + emailBlockDevice: serviceToDisk['email'] ?? fallbackDrive, + giteaBlockDevice: serviceToDisk['gitea'] ?? fallbackDrive, + nextcloudBlockDevice: serviceToDisk['nextcloud'] ?? fallbackDrive, + pleromaBlockDevice: serviceToDisk['pleroma'] ?? fallbackDrive, ); final variables = Variables$Mutation$MigrateToBinds(input: input); final migrateMutation = diff --git a/lib/logic/bloc/server_jobs/server_jobs_bloc.dart b/lib/logic/bloc/server_jobs/server_jobs_bloc.dart index 43b415e6..3ae45aa9 100644 --- a/lib/logic/bloc/server_jobs/server_jobs_bloc.dart +++ b/lib/logic/bloc/server_jobs/server_jobs_bloc.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/models/json/server_job.dart'; @@ -68,6 +69,25 @@ class ServerJobsBloc extends Bloc { await getIt().removeAllFinishedServerJobs(); } + Future migrateToBinds(final Map serviceToDisk) async { + final fallbackDrive = getIt() + .apiData + .volumes + .data + ?.where((final drive) => drive.root) + .first + .name ?? + 'sda1'; + final result = await getIt() + .api + .migrateToBinds(serviceToDisk, fallbackDrive); + if (result.data == null) { + getIt() + .showSnackBar(result.message!, behavior: SnackBarBehavior.floating); + return; + } + } + @override void onChange(final Change change) { super.onChange(change); diff --git a/lib/ui/components/list_tiles/section_title.dart b/lib/ui/components/list_tiles/section_title.dart new file mode 100644 index 00000000..f37fb09d --- /dev/null +++ b/lib/ui/components/list_tiles/section_title.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class SectionTitle extends StatelessWidget { + const SectionTitle({ + required this.title, + super.key, + }); + + final String title; + + @override + Widget build(final BuildContext context) => Padding( + padding: const EdgeInsets.all(16), + child: Text( + title, + style: Theme.of(context).textTheme.labelLarge!.copyWith( + color: Theme.of(context).colorScheme.secondary, + ), + ), + ); +} diff --git a/lib/ui/pages/more/about_application.dart b/lib/ui/pages/more/about_application.dart index b652b8af..9e6cae65 100644 --- a/lib/ui/pages/more/about_application.dart +++ b/lib/ui/pages/more/about_application.dart @@ -5,6 +5,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:package_info/package_info.dart'; import 'package:selfprivacy/config/get_it_config.dart'; +import 'package:selfprivacy/ui/components/list_tiles/section_title.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; import 'package:selfprivacy/utils/breakpoints.dart'; import 'package:selfprivacy/utils/platform_adapter.dart'; @@ -220,26 +221,6 @@ class AboutApplicationPage extends StatelessWidget { } } -class SectionTitle extends StatelessWidget { - const SectionTitle({ - required this.title, - super.key, - }); - - final String title; - - @override - Widget build(final BuildContext context) => Padding( - padding: const EdgeInsets.all(16), - child: Text( - title, - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), - ), - ); -} - class LinkListTile extends StatelessWidget { const LinkListTile({ required this.title, diff --git a/lib/ui/pages/more/app_settings/developer_settings.dart b/lib/ui/pages/more/app_settings/developer_settings.dart index 8acf16a4..cd1c6811 100644 --- a/lib/ui/pages/more/app_settings/developer_settings.dart +++ b/lib/ui/pages/more/app_settings/developer_settings.dart @@ -3,8 +3,12 @@ import 'package:easy_localization/easy_localization.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/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/ui/components/list_tiles/section_title.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; +import 'package:selfprivacy/ui/router/router.dart'; @RoutePage() class DeveloperSettingsPage extends StatefulWidget { @@ -23,15 +27,7 @@ class _DeveloperSettingsPageState extends State { heroTitle: 'developer_settings.title'.tr(), heroSubtitle: 'developer_settings.subtitle'.tr(), children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text( - 'developer_settings.server_setup'.tr(), - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), - ), - ), + SectionTitle(title: 'developer_settings.server_setup'.tr()), SwitchListTile( title: Text('developer_settings.use_staging_acme'.tr()), subtitle: @@ -59,15 +55,7 @@ class _DeveloperSettingsPageState extends State { () => TlsOptions.allowCustomSshKeyDuringSetup = value, ), ), - Padding( - padding: const EdgeInsets.all(16), - child: Text( - 'developer_settings.routing'.tr(), - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), - ), - ), + SectionTitle(title: 'developer_settings.routing'.tr()), ListTile( title: Text('developer_settings.reset_onboarding'.tr()), subtitle: @@ -78,15 +66,32 @@ class _DeveloperSettingsPageState extends State { .read() .turnOffOnboarding(isOnboardingShowing: true), ), - Padding( - padding: const EdgeInsets.all(16), - child: Text( - 'developer_settings.cubit_statuses'.tr(), - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), + ListTile( + title: Text('storage.start_migration_button'.tr()), + subtitle: Text('storage.data_migration_notice'.tr()), + enabled: + !context.watch().state.isOnboardingShowing, + onTap: () => context.pushRoute( + ServicesMigrationRoute( + diskStatus: context.read().state.diskStatus, + services: context + .read() + .state + .services + .where( + (final service) => + service.id == 'bitwarden' || + service.id == 'gitea' || + service.id == 'pleroma' || + service.id == 'email' || + service.id == 'nextcloud', + ) + .toList(), + isMigration: true, + ), ), ), + SectionTitle(title: 'developer_settings.cubit_statuses'.tr()), ListTile( title: const Text('ApiConnectionRepository status'), subtitle: Text( diff --git a/lib/ui/pages/server_storage/binds_migration/services_migration.dart b/lib/ui/pages/server_storage/binds_migration/services_migration.dart index 53e72d91..695b8de4 100644 --- a/lib/ui/pages/server_storage/binds_migration/services_migration.dart +++ b/lib/ui/pages/server_storage/binds_migration/services_migration.dart @@ -18,11 +18,13 @@ class ServicesMigrationPage extends StatefulWidget { const ServicesMigrationPage({ required this.services, required this.diskStatus, + required this.isMigration, super.key, }); final DiskStatus diskStatus; final List services; + final bool isMigration; @override State createState() => _ServicesMigrationPageState(); @@ -169,18 +171,24 @@ class _ServicesMigrationPageState extends State { ), ), const SizedBox(height: 16), - if (isVolumePicked) + if (widget.isMigration || (!widget.isMigration && isVolumePicked)) BrandButton.filled( child: Text('storage.start_migration_button'.tr()), onPressed: () { - for (final service in widget.services) { - if (serviceToDisk[service.id] != null) { - context.read().add( - ServiceMove( - service, - serviceToDisk[service.id]!, - ), - ); + if (widget.isMigration) { + context.read().migrateToBinds( + serviceToDisk, + ); + } else { + for (final service in widget.services) { + if (serviceToDisk[service.id] != null) { + context.read().add( + ServiceMove( + service, + serviceToDisk[service.id]!, + ), + ); + } } } context.router.popUntilRoot(); diff --git a/lib/ui/pages/services/service_page.dart b/lib/ui/pages/services/service_page.dart index 41e7f7ef..c0064eef 100644 --- a/lib/ui/pages/services/service_page.dart +++ b/lib/ui/pages/services/service_page.dart @@ -114,6 +114,7 @@ class _ServicePageState extends State { ServicesMigrationRoute( services: [service], diskStatus: context.read().state.diskStatus, + isMigration: false, ), ), leading: const Icon(Icons.drive_file_move_outlined), diff --git a/lib/ui/router/router.gr.dart b/lib/ui/router/router.gr.dart index 1ff6d09c..98f4453a 100644 --- a/lib/ui/router/router.gr.dart +++ b/lib/ui/router/router.gr.dart @@ -159,6 +159,7 @@ abstract class _$RootRouter extends RootStackRouter { child: ServicesMigrationPage( services: args.services, diskStatus: args.diskStatus, + isMigration: args.isMigration, key: args.key, ), ); @@ -575,6 +576,7 @@ class ServicesMigrationRoute extends PageRouteInfo { ServicesMigrationRoute({ required List services, required DiskStatus diskStatus, + required bool isMigration, Key? key, List? children, }) : super( @@ -582,6 +584,7 @@ class ServicesMigrationRoute extends PageRouteInfo { args: ServicesMigrationRouteArgs( services: services, diskStatus: diskStatus, + isMigration: isMigration, key: key, ), initialChildren: children, @@ -597,6 +600,7 @@ class ServicesMigrationRouteArgs { const ServicesMigrationRouteArgs({ required this.services, required this.diskStatus, + required this.isMigration, this.key, }); @@ -604,11 +608,13 @@ class ServicesMigrationRouteArgs { final DiskStatus diskStatus; + final bool isMigration; + final Key? key; @override String toString() { - return 'ServicesMigrationRouteArgs{services: $services, diskStatus: $diskStatus, key: $key}'; + return 'ServicesMigrationRouteArgs{services: $services, diskStatus: $diskStatus, isMigration: $isMigration, key: $key}'; } }