mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-09 17:39:42 +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(
|
Future<GenericResult<String?>> migrateToBinds(
|
||||||
final Map<String, String> serviceToDisk,
|
final Map<String, String> serviceToDisk,
|
||||||
|
final String fallbackDrive,
|
||||||
) async {
|
) async {
|
||||||
GenericResult<String?>? mutation;
|
GenericResult<String?>? mutation;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final GraphQLClient client = await getClient();
|
final GraphQLClient client = await getClient();
|
||||||
final input = Input$MigrateToBindsInput(
|
final input = Input$MigrateToBindsInput(
|
||||||
bitwardenBlockDevice: serviceToDisk['bitwarden']!,
|
bitwardenBlockDevice: serviceToDisk['bitwarden'] ?? fallbackDrive,
|
||||||
emailBlockDevice: serviceToDisk['mailserver']!,
|
emailBlockDevice: serviceToDisk['email'] ?? fallbackDrive,
|
||||||
giteaBlockDevice: serviceToDisk['gitea']!,
|
giteaBlockDevice: serviceToDisk['gitea'] ?? fallbackDrive,
|
||||||
nextcloudBlockDevice: serviceToDisk['nextcloud']!,
|
nextcloudBlockDevice: serviceToDisk['nextcloud'] ?? fallbackDrive,
|
||||||
pleromaBlockDevice: serviceToDisk['pleroma']!,
|
pleromaBlockDevice: serviceToDisk['pleroma'] ?? fallbackDrive,
|
||||||
);
|
);
|
||||||
final variables = Variables$Mutation$MigrateToBinds(input: input);
|
final variables = Variables$Mutation$MigrateToBinds(input: input);
|
||||||
final migrateMutation =
|
final migrateMutation =
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:bloc_concurrency/bloc_concurrency.dart';
|
import 'package:bloc_concurrency/bloc_concurrency.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||||
|
@ -68,6 +69,25 @@ class ServerJobsBloc extends Bloc<ServerJobsEvent, ServerJobsState> {
|
||||||
await getIt<ApiConnectionRepository>().removeAllFinishedServerJobs();
|
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
|
@override
|
||||||
void onChange(final Change<ServerJobsState> change) {
|
void onChange(final Change<ServerJobsState> change) {
|
||||||
super.onChange(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:flutter/material.dart';
|
||||||
import 'package:package_info/package_info.dart';
|
import 'package:package_info/package_info.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.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/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/utils/breakpoints.dart';
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
import 'package:selfprivacy/utils/platform_adapter.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 {
|
class LinkListTile extends StatelessWidget {
|
||||||
const LinkListTile({
|
const LinkListTile({
|
||||||
required this.title,
|
required this.title,
|
||||||
|
|
|
@ -3,8 +3,12 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/tls_options.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/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/layouts/brand_hero_screen.dart';
|
||||||
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class DeveloperSettingsPage extends StatefulWidget {
|
class DeveloperSettingsPage extends StatefulWidget {
|
||||||
|
@ -23,15 +27,7 @@ class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
|
||||||
heroTitle: 'developer_settings.title'.tr(),
|
heroTitle: 'developer_settings.title'.tr(),
|
||||||
heroSubtitle: 'developer_settings.subtitle'.tr(),
|
heroSubtitle: 'developer_settings.subtitle'.tr(),
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
SectionTitle(title: 'developer_settings.server_setup'.tr()),
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: Text('developer_settings.use_staging_acme'.tr()),
|
title: Text('developer_settings.use_staging_acme'.tr()),
|
||||||
subtitle:
|
subtitle:
|
||||||
|
@ -59,15 +55,7 @@ class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
|
||||||
() => TlsOptions.allowCustomSshKeyDuringSetup = value,
|
() => TlsOptions.allowCustomSshKeyDuringSetup = value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
SectionTitle(title: 'developer_settings.routing'.tr()),
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Text(
|
|
||||||
'developer_settings.routing'.tr(),
|
|
||||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text('developer_settings.reset_onboarding'.tr()),
|
title: Text('developer_settings.reset_onboarding'.tr()),
|
||||||
subtitle:
|
subtitle:
|
||||||
|
@ -78,15 +66,32 @@ class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
|
||||||
.read<AppSettingsCubit>()
|
.read<AppSettingsCubit>()
|
||||||
.turnOffOnboarding(isOnboardingShowing: true),
|
.turnOffOnboarding(isOnboardingShowing: true),
|
||||||
),
|
),
|
||||||
Padding(
|
ListTile(
|
||||||
padding: const EdgeInsets.all(16),
|
title: Text('storage.start_migration_button'.tr()),
|
||||||
child: Text(
|
subtitle: Text('storage.data_migration_notice'.tr()),
|
||||||
'developer_settings.cubit_statuses'.tr(),
|
enabled:
|
||||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
!context.watch<AppSettingsCubit>().state.isOnboardingShowing,
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
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(
|
ListTile(
|
||||||
title: const Text('ApiConnectionRepository status'),
|
title: const Text('ApiConnectionRepository status'),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
|
|
|
@ -18,11 +18,13 @@ class ServicesMigrationPage extends StatefulWidget {
|
||||||
const ServicesMigrationPage({
|
const ServicesMigrationPage({
|
||||||
required this.services,
|
required this.services,
|
||||||
required this.diskStatus,
|
required this.diskStatus,
|
||||||
|
required this.isMigration,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
final DiskStatus diskStatus;
|
final DiskStatus diskStatus;
|
||||||
final List<Service> services;
|
final List<Service> services;
|
||||||
|
final bool isMigration;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ServicesMigrationPage> createState() => _ServicesMigrationPageState();
|
State<ServicesMigrationPage> createState() => _ServicesMigrationPageState();
|
||||||
|
@ -169,18 +171,24 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
if (isVolumePicked)
|
if (widget.isMigration || (!widget.isMigration && isVolumePicked))
|
||||||
BrandButton.filled(
|
BrandButton.filled(
|
||||||
child: Text('storage.start_migration_button'.tr()),
|
child: Text('storage.start_migration_button'.tr()),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
for (final service in widget.services) {
|
if (widget.isMigration) {
|
||||||
if (serviceToDisk[service.id] != null) {
|
context.read<ServerJobsBloc>().migrateToBinds(
|
||||||
context.read<ServicesBloc>().add(
|
serviceToDisk,
|
||||||
ServiceMove(
|
);
|
||||||
service,
|
} else {
|
||||||
serviceToDisk[service.id]!,
|
for (final service in widget.services) {
|
||||||
),
|
if (serviceToDisk[service.id] != null) {
|
||||||
);
|
context.read<ServicesBloc>().add(
|
||||||
|
ServiceMove(
|
||||||
|
service,
|
||||||
|
serviceToDisk[service.id]!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.router.popUntilRoot();
|
context.router.popUntilRoot();
|
||||||
|
|
|
@ -114,6 +114,7 @@ class _ServicePageState extends State<ServicePage> {
|
||||||
ServicesMigrationRoute(
|
ServicesMigrationRoute(
|
||||||
services: [service],
|
services: [service],
|
||||||
diskStatus: context.read<VolumesBloc>().state.diskStatus,
|
diskStatus: context.read<VolumesBloc>().state.diskStatus,
|
||||||
|
isMigration: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
leading: const Icon(Icons.drive_file_move_outlined),
|
leading: const Icon(Icons.drive_file_move_outlined),
|
||||||
|
|
|
@ -159,6 +159,7 @@ abstract class _$RootRouter extends RootStackRouter {
|
||||||
child: ServicesMigrationPage(
|
child: ServicesMigrationPage(
|
||||||
services: args.services,
|
services: args.services,
|
||||||
diskStatus: args.diskStatus,
|
diskStatus: args.diskStatus,
|
||||||
|
isMigration: args.isMigration,
|
||||||
key: args.key,
|
key: args.key,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -575,6 +576,7 @@ class ServicesMigrationRoute extends PageRouteInfo<ServicesMigrationRouteArgs> {
|
||||||
ServicesMigrationRoute({
|
ServicesMigrationRoute({
|
||||||
required List<Service> services,
|
required List<Service> services,
|
||||||
required DiskStatus diskStatus,
|
required DiskStatus diskStatus,
|
||||||
|
required bool isMigration,
|
||||||
Key? key,
|
Key? key,
|
||||||
List<PageRouteInfo>? children,
|
List<PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
|
@ -582,6 +584,7 @@ class ServicesMigrationRoute extends PageRouteInfo<ServicesMigrationRouteArgs> {
|
||||||
args: ServicesMigrationRouteArgs(
|
args: ServicesMigrationRouteArgs(
|
||||||
services: services,
|
services: services,
|
||||||
diskStatus: diskStatus,
|
diskStatus: diskStatus,
|
||||||
|
isMigration: isMigration,
|
||||||
key: key,
|
key: key,
|
||||||
),
|
),
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
|
@ -597,6 +600,7 @@ class ServicesMigrationRouteArgs {
|
||||||
const ServicesMigrationRouteArgs({
|
const ServicesMigrationRouteArgs({
|
||||||
required this.services,
|
required this.services,
|
||||||
required this.diskStatus,
|
required this.diskStatus,
|
||||||
|
required this.isMigration,
|
||||||
this.key,
|
this.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -604,11 +608,13 @@ class ServicesMigrationRouteArgs {
|
||||||
|
|
||||||
final DiskStatus diskStatus;
|
final DiskStatus diskStatus;
|
||||||
|
|
||||||
|
final bool isMigration;
|
||||||
|
|
||||||
final Key? key;
|
final Key? key;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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