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.
pull/467/head
Inex Code 2024-02-23 19:50:28 +03:00
parent 490e5f92f3
commit a9a7b04ad5
8 changed files with 103 additions and 60 deletions

View File

@ -60,17 +60,18 @@ mixin VolumeApi on GraphQLApiMap {
Future<GenericResult<String?>> migrateToBinds(
final Map<String, String> serviceToDisk,
final String fallbackDrive,
) async {
GenericResult<String?>? 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 =

View File

@ -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<ServerJobsEvent, ServerJobsState> {
await getIt<ApiConnectionRepository>().removeAllFinishedServerJobs();
}
Future<void> migrateToBinds(final Map<String, String> serviceToDisk) async {
final fallbackDrive = getIt<ApiConnectionRepository>()
.apiData
.volumes
.data
?.where((final drive) => drive.root)
.first
.name ??
'sda1';
final result = await getIt<ApiConnectionRepository>()
.api
.migrateToBinds(serviceToDisk, fallbackDrive);
if (result.data == null) {
getIt<NavigationService>()
.showSnackBar(result.message!, behavior: SnackBarBehavior.floating);
return;
}
}
@override
void onChange(final Change<ServerJobsState> change) {
super.onChange(change);

View File

@ -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,
),
),
);
}

View File

@ -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,

View File

@ -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<DeveloperSettingsPage> {
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<DeveloperSettingsPage> {
() => 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<DeveloperSettingsPage> {
.read<AppSettingsCubit>()
.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<AppSettingsCubit>().state.isOnboardingShowing,
onTap: () => context.pushRoute(
ServicesMigrationRoute(
diskStatus: context.read<VolumesBloc>().state.diskStatus,
services: context
.read<ServicesBloc>()
.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(

View File

@ -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<Service> services;
final bool isMigration;
@override
State<ServicesMigrationPage> createState() => _ServicesMigrationPageState();
@ -169,18 +171,24 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
),
),
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<ServicesBloc>().add(
ServiceMove(
service,
serviceToDisk[service.id]!,
),
);
if (widget.isMigration) {
context.read<ServerJobsBloc>().migrateToBinds(
serviceToDisk,
);
} else {
for (final service in widget.services) {
if (serviceToDisk[service.id] != null) {
context.read<ServicesBloc>().add(
ServiceMove(
service,
serviceToDisk[service.id]!,
),
);
}
}
}
context.router.popUntilRoot();

View File

@ -114,6 +114,7 @@ class _ServicePageState extends State<ServicePage> {
ServicesMigrationRoute(
services: [service],
diskStatus: context.read<VolumesBloc>().state.diskStatus,
isMigration: false,
),
),
leading: const Icon(Icons.drive_file_move_outlined),

View File

@ -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<ServicesMigrationRouteArgs> {
ServicesMigrationRoute({
required List<Service> services,
required DiskStatus diskStatus,
required bool isMigration,
Key? key,
List<PageRouteInfo>? children,
}) : super(
@ -582,6 +584,7 @@ class ServicesMigrationRoute extends PageRouteInfo<ServicesMigrationRouteArgs> {
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}';
}
}