mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-08 17:11:14 +00:00
Merge pull request 'fix: Return the binds migration interface' (#467) from inex/binds-migration into master
Reviewed-on: https://git.selfprivacy.org/SelfPrivacy/selfprivacy.org.app/pulls/467
This commit is contained in:
commit
212c60c613
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
|
21
lib/ui/components/list_tiles/section_title.dart
Normal file
21
lib/ui/components/list_tiles/section_title.dart
Normal 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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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}';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue