mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-09 17:39:42 +00:00
refactor(ui): Refactor backup snapshot lists to not repeat code
This commit is contained in:
parent
8dd3d1c70b
commit
1168b2219f
27
lib/ui/atoms/list_tiles/section_headline.dart
Normal file
27
lib/ui/atoms/list_tiles/section_headline.dart
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SectionHeadline extends StatelessWidget {
|
||||||
|
const SectionHeadline({
|
||||||
|
required this.title,
|
||||||
|
required this.subtitle,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
subtitle,
|
||||||
|
style: Theme.of(context).textTheme.labelMedium,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
96
lib/ui/molecules/list_items/snapshot_item.dart
Normal file
96
lib/ui/molecules/list_items/snapshot_item.dart
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||||
|
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
||||||
|
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
|
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||||
|
import 'package:selfprivacy/ui/organisms/modals/backups/snapshot_modal.dart';
|
||||||
|
|
||||||
|
class SnapshotItem extends StatelessWidget {
|
||||||
|
const SnapshotItem({
|
||||||
|
required this.backup,
|
||||||
|
required this.preventActions,
|
||||||
|
this.overrideColor,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Backup backup;
|
||||||
|
final bool preventActions;
|
||||||
|
final Color? overrideColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final service =
|
||||||
|
context.read<ServicesBloc>().state.getServiceById(backup.serviceId);
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
onTap: preventActions
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
useRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (final BuildContext context) =>
|
||||||
|
DraggableScrollableSheet(
|
||||||
|
expand: false,
|
||||||
|
maxChildSize: 0.9,
|
||||||
|
minChildSize: 0.5,
|
||||||
|
initialChildSize: 0.7,
|
||||||
|
builder: (
|
||||||
|
final context,
|
||||||
|
final scrollController,
|
||||||
|
) =>
|
||||||
|
SnapshotModal(
|
||||||
|
snapshot: backup,
|
||||||
|
scrollController: scrollController,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onLongPress: preventActions
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showPopUpAlert(
|
||||||
|
alertTitle: 'backup.forget_snapshot'.tr(),
|
||||||
|
description: 'backup.forget_snapshot_alert'.tr(),
|
||||||
|
actionButtonTitle: 'backup.forget_snapshot'.tr(),
|
||||||
|
actionButtonOnPressed: () => context.read<BackupsBloc>().add(
|
||||||
|
ForgetSnapshot(
|
||||||
|
backup.id,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
title: Text(
|
||||||
|
style: TextStyle(
|
||||||
|
color: overrideColor,
|
||||||
|
),
|
||||||
|
'${MaterialLocalizations.of(context).formatShortDate(backup.time.toLocal())} ${TimeOfDay.fromDateTime(backup.time.toLocal()).format(context)}',
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
style: TextStyle(
|
||||||
|
color: overrideColor,
|
||||||
|
),
|
||||||
|
service?.displayName ?? backup.fallbackServiceName,
|
||||||
|
),
|
||||||
|
leading: service != null
|
||||||
|
? SvgPicture.string(
|
||||||
|
service.svgIcon,
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
colorFilter: ColorFilter.mode(
|
||||||
|
overrideColor ?? Theme.of(context).colorScheme.onSurface,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
Icons.question_mark_outlined,
|
||||||
|
color: overrideColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
||||||
|
@ -13,14 +12,14 @@ import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||||
import 'package:selfprivacy/ui/atoms/buttons/brand_button.dart';
|
import 'package:selfprivacy/ui/atoms/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/atoms/icons/brand_icons.dart';
|
import 'package:selfprivacy/ui/atoms/icons/brand_icons.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
import 'package:selfprivacy/ui/atoms/list_tiles/section_headline.dart';
|
||||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/molecules/cards/server_job_card.dart';
|
import 'package:selfprivacy/ui/molecules/cards/server_job_card.dart';
|
||||||
|
import 'package:selfprivacy/ui/molecules/list_items/snapshot_item.dart';
|
||||||
import 'package:selfprivacy/ui/organisms/modals/backups/change_period_modal.dart';
|
import 'package:selfprivacy/ui/organisms/modals/backups/change_period_modal.dart';
|
||||||
import 'package:selfprivacy/ui/organisms/modals/backups/change_rotation_quotas_modal.dart';
|
import 'package:selfprivacy/ui/organisms/modals/backups/change_rotation_quotas_modal.dart';
|
||||||
import 'package:selfprivacy/ui/organisms/modals/backups/copy_encryption_key_modal.dart';
|
import 'package:selfprivacy/ui/organisms/modals/backups/copy_encryption_key_modal.dart';
|
||||||
import 'package:selfprivacy/ui/organisms/modals/backups/create_backups_modal.dart';
|
import 'package:selfprivacy/ui/organisms/modals/backups/create_backups_modal.dart';
|
||||||
import 'package:selfprivacy/ui/organisms/modals/backups/snapshot_modal.dart';
|
|
||||||
import 'package:selfprivacy/ui/router/router.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:selfprivacy/utils/extensions/duration.dart';
|
import 'package:selfprivacy/utils/extensions/duration.dart';
|
||||||
|
|
||||||
|
@ -279,17 +278,9 @@ class BackupDetailsPage extends StatelessWidget {
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
SectionHeadline(
|
||||||
title: Text(
|
title: 'backup.latest_snapshots'.tr(),
|
||||||
'backup.latest_snapshots'.tr(),
|
subtitle: 'backup.latest_snapshots_subtitle'.tr(),
|
||||||
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
|
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
'backup.latest_snapshots_subtitle'.tr(),
|
|
||||||
style: Theme.of(context).textTheme.labelMedium,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (backups.isEmpty)
|
if (backups.isEmpty)
|
||||||
ListTile(
|
ListTile(
|
||||||
|
@ -306,84 +297,16 @@ class BackupDetailsPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
if (backups.isNotEmpty)
|
if (backups.isNotEmpty)
|
||||||
Column(
|
Column(
|
||||||
children: backups.take(15).map(
|
children: backups
|
||||||
(final Backup backup) {
|
.take(15)
|
||||||
final service = context
|
.map(
|
||||||
.read<ServicesBloc>()
|
(final Backup backup) => SnapshotItem(
|
||||||
.state
|
backup: backup,
|
||||||
.getServiceById(backup.serviceId);
|
preventActions: preventActions,
|
||||||
return ListTile(
|
overrideColor: overrideColor,
|
||||||
onTap: preventActions
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
useRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (final BuildContext context) =>
|
|
||||||
DraggableScrollableSheet(
|
|
||||||
expand: false,
|
|
||||||
maxChildSize: 0.9,
|
|
||||||
minChildSize: 0.5,
|
|
||||||
initialChildSize: 0.7,
|
|
||||||
builder: (
|
|
||||||
final context,
|
|
||||||
final scrollController,
|
|
||||||
) =>
|
|
||||||
SnapshotModal(
|
|
||||||
snapshot: backup,
|
|
||||||
scrollController: scrollController,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onLongPress: preventActions
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
showPopUpAlert(
|
|
||||||
alertTitle: 'backup.forget_snapshot'.tr(),
|
|
||||||
description:
|
|
||||||
'backup.forget_snapshot_alert'.tr(),
|
|
||||||
actionButtonTitle:
|
|
||||||
'backup.forget_snapshot'.tr(),
|
|
||||||
actionButtonOnPressed: () =>
|
|
||||||
context.read<BackupsBloc>().add(
|
|
||||||
ForgetSnapshot(
|
|
||||||
backup.id,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
title: Text(
|
|
||||||
style: TextStyle(
|
|
||||||
color: overrideColor,
|
|
||||||
),
|
|
||||||
'${MaterialLocalizations.of(context).formatShortDate(backup.time.toLocal())} ${TimeOfDay.fromDateTime(backup.time.toLocal()).format(context)}',
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
style: TextStyle(
|
|
||||||
color: overrideColor,
|
|
||||||
),
|
|
||||||
service?.displayName ?? backup.fallbackServiceName,
|
|
||||||
),
|
|
||||||
leading: service != null
|
|
||||||
? SvgPicture.string(
|
|
||||||
service.svgIcon,
|
|
||||||
height: 24,
|
|
||||||
width: 24,
|
|
||||||
colorFilter: ColorFilter.mode(
|
|
||||||
overrideColor ??
|
|
||||||
Theme.of(context).colorScheme.onSurface,
|
|
||||||
BlendMode.srcIn,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Icon(
|
.toList(),
|
||||||
Icons.question_mark_outlined,
|
|
||||||
color: overrideColor,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).toList(),
|
|
||||||
),
|
),
|
||||||
if (backups.isNotEmpty && backups.length > 15)
|
if (backups.isNotEmpty && backups.length > 15)
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
|
@ -2,14 +2,11 @@ import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
|
||||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/services/services_bloc.dart';
|
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
|
||||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/organisms/modals/backups/snapshot_modal.dart';
|
import 'package:selfprivacy/ui/molecules/list_items/snapshot_item.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class BackupsListPage extends StatelessWidget {
|
class BackupsListPage extends StatelessWidget {
|
||||||
|
@ -41,67 +38,11 @@ class BackupsListPage extends StatelessWidget {
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
...backups.map(
|
...backups.map(
|
||||||
(final Backup backup) {
|
(final Backup backup) => SnapshotItem(
|
||||||
final service = context
|
backup: backup,
|
||||||
.read<ServicesBloc>()
|
preventActions: preventActions,
|
||||||
.state
|
|
||||||
.getServiceById(backup.serviceId);
|
|
||||||
return ListTile(
|
|
||||||
onTap: preventActions
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
useRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (final BuildContext context) =>
|
|
||||||
DraggableScrollableSheet(
|
|
||||||
expand: false,
|
|
||||||
maxChildSize: 0.9,
|
|
||||||
minChildSize: 0.5,
|
|
||||||
initialChildSize: 0.7,
|
|
||||||
builder: (final context, final scrollController) =>
|
|
||||||
SnapshotModal(
|
|
||||||
snapshot: backup,
|
|
||||||
scrollController: scrollController,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
onLongPress: preventActions
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
showPopUpAlert(
|
|
||||||
alertTitle: 'backup.forget_snapshot'.tr(),
|
|
||||||
description: 'backup.forget_snapshot_alert'.tr(),
|
|
||||||
actionButtonTitle: 'backup.forget_snapshot'.tr(),
|
|
||||||
actionButtonOnPressed: () => context
|
|
||||||
.read<BackupsBloc>()
|
|
||||||
.add(ForgetSnapshot(backup.id)),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
title: Text(
|
|
||||||
'${MaterialLocalizations.of(context).formatShortDate(backup.time.toLocal())} ${TimeOfDay.fromDateTime(backup.time.toLocal()).format(context)}',
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
service?.displayName ?? backup.fallbackServiceName,
|
|
||||||
),
|
|
||||||
leading: service != null
|
|
||||||
? SvgPicture.string(
|
|
||||||
service.svgIcon,
|
|
||||||
height: 24,
|
|
||||||
width: 24,
|
|
||||||
colorFilter: ColorFilter.mode(
|
|
||||||
Theme.of(context).colorScheme.onSurface,
|
|
||||||
BlendMode.srcIn,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const Icon(
|
|
||||||
Icons.question_mark_outlined,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue