selfprivacy.org.app/lib/ui/pages/services/service_page.dart
Inex Code a9a7b04ad5 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.
2024-02-23 19:50:28 +03:00

220 lines
6.9 KiB
Dart

import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart';
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
import 'package:selfprivacy/ui/router/router.dart';
import 'package:selfprivacy/utils/launch_url.dart';
@RoutePage()
class ServicePage extends StatefulWidget {
const ServicePage({required this.serviceId, super.key});
final String serviceId;
@override
State<ServicePage> createState() => _ServicePageState();
}
class _ServicePageState extends State<ServicePage> {
@override
Widget build(final BuildContext context) {
final Service? service =
context.watch<ServicesBloc>().state.getServiceById(widget.serviceId);
if (service == null) {
return const BrandHeroScreen(
hasBackButton: true,
children: [
Center(
child: CircularProgressIndicator(),
),
],
);
}
final bool serviceDisabled = service.status == ServiceStatus.inactive ||
service.status == ServiceStatus.off;
final bool serviceLocked =
context.watch<ServicesBloc>().state.isServiceLocked(service.id);
return BrandHeroScreen(
hasBackButton: true,
hasFlashButton: true,
heroIconWidget: SvgPicture.string(
service.svgIcon,
width: 48.0,
height: 48.0,
colorFilter: ColorFilter.mode(
Theme.of(context).colorScheme.onBackground,
BlendMode.srcIn,
),
),
heroTitle: service.displayName,
children: [
ServiceStatusCard(status: service.status),
const SizedBox(height: 16),
if (service.url != null)
ListTile(
iconColor: Theme.of(context).colorScheme.onBackground,
onTap: () => launchURL(service.url),
leading: const Icon(Icons.open_in_browser),
title: Text(
'service_page.open_in_browser'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
subtitle: Text(
service.url!.replaceAll('https://', ''),
style: Theme.of(context).textTheme.bodyMedium,
),
),
const SizedBox(height: 8),
const Divider(),
const SizedBox(height: 8),
ListTile(
iconColor: Theme.of(context).colorScheme.onBackground,
onTap: () =>
context.read<ServicesBloc>().add(ServiceRestart(service)),
leading: const Icon(Icons.restart_alt_outlined),
title: Text(
'service_page.restart'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
enabled: !serviceDisabled && !serviceLocked,
),
ListTile(
iconColor: Theme.of(context).colorScheme.onBackground,
onTap: () => context.read<JobsCubit>().addJob(
ServiceToggleJob(
service: service,
needToTurnOn: serviceDisabled,
),
),
leading: const Icon(Icons.power_settings_new),
title: Text(
serviceDisabled
? 'service_page.enable'.tr()
: 'service_page.disable'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
enabled: !serviceLocked,
),
if (service.isMovable)
ListTile(
iconColor: Theme.of(context).colorScheme.onBackground,
// Open page ServicesMigrationPage
onTap: () => context.pushRoute(
ServicesMigrationRoute(
services: [service],
diskStatus: context.read<VolumesBloc>().state.diskStatus,
isMigration: false,
),
),
leading: const Icon(Icons.drive_file_move_outlined),
title: Text(
'service_page.move'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
subtitle: Text(
'service_page.uses'.tr(
namedArgs: {
'usage': service.storageUsage.used.toString(),
'volume': context
.read<VolumesBloc>()
.state
.getVolume(service.storageUsage.volume ?? '')
.displayName,
},
),
style: Theme.of(context).textTheme.bodyMedium,
),
enabled: !serviceDisabled &&
!serviceLocked &&
service.storageUsage.volume != null,
),
if (service.canBeBackedUp)
ListTile(
iconColor: Theme.of(context).colorScheme.onBackground,
// Open page ServicesMigrationPage
onTap: () => context.pushRoute(
BackupsListRoute(service: service),
),
leading: const Icon(Icons.settings_backup_restore_outlined),
title: Text(
'service_page.snapshots'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
),
],
);
}
}
class ServiceStatusCard extends StatelessWidget {
const ServiceStatusCard({
required this.status,
super.key,
});
final ServiceStatus status;
@override
Widget build(final BuildContext context) {
late IconData icon;
late String buttonTitle;
switch (status) {
case ServiceStatus.active:
icon = Icons.check_circle_outline;
buttonTitle = 'service_page.status.active';
break;
case ServiceStatus.inactive:
icon = Icons.stop_circle_outlined;
buttonTitle = 'service_page.status.inactive';
break;
case ServiceStatus.failed:
icon = Icons.error_outline;
buttonTitle = 'service_page.status.failed';
break;
case ServiceStatus.off:
icon = Icons.power_settings_new;
buttonTitle = 'service_page.status.off';
break;
case ServiceStatus.activating:
icon = Icons.restart_alt_outlined;
buttonTitle = 'service_page.status.activating';
break;
case ServiceStatus.deactivating:
icon = Icons.restart_alt_outlined;
buttonTitle = 'service_page.status.deactivating';
break;
case ServiceStatus.reloading:
icon = Icons.restart_alt_outlined;
buttonTitle = 'service_page.status.reloading';
}
return FilledCard(
tertiary: true,
child: ListTile(
leading: Icon(
icon,
size: 24,
),
title: Text(buttonTitle.tr()),
),
);
}
}