mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-07 00:24:18 +00:00
feat(backups): Add descriptions for backups
This commit is contained in:
parent
b3b7c83461
commit
62b7a0ee7e
|
@ -1,10 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'disk_volumes.graphql.dart';
|
||||
import 'package:gql/ast.dart';
|
||||
import 'package:graphql/client.dart' as graphql;
|
||||
import 'package:selfprivacy/utils/scalars.dart';
|
||||
import 'schema.graphql.dart';
|
||||
import 'server_api.graphql.dart';
|
||||
import 'services.graphql.dart';
|
||||
|
||||
class Fragment$genericBackupConfigReturn {
|
||||
Fragment$genericBackupConfigReturn({
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'package:gql/ast.dart';
|
|||
import 'package:graphql/client.dart' as graphql;
|
||||
import 'schema.graphql.dart';
|
||||
import 'server_api.graphql.dart';
|
||||
import 'services.graphql.dart';
|
||||
|
||||
class Fragment$basicMutationReturnFields {
|
||||
Fragment$basicMutationReturnFields({
|
||||
|
|
|
@ -255,6 +255,7 @@ type Service {
|
|||
isRequired: Boolean!
|
||||
isEnabled: Boolean!
|
||||
canBeBackedUp: Boolean!
|
||||
backupDescription: String!
|
||||
status: ServiceStatusEnum!
|
||||
url: String
|
||||
dnsRecords: [DnsRecord!]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import 'dart:async';
|
||||
import 'disk_volumes.graphql.dart';
|
||||
import 'package:gql/ast.dart';
|
||||
import 'package:graphql/client.dart' as graphql;
|
||||
import 'package:selfprivacy/utils/scalars.dart';
|
||||
import 'schema.graphql.dart';
|
||||
import 'services.graphql.dart';
|
||||
|
||||
class Fragment$basicMutationReturnFields {
|
||||
Fragment$basicMutationReturnFields({
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'disk_volumes.graphql.dart';
|
||||
import 'package:gql/ast.dart';
|
||||
import 'package:graphql/client.dart' as graphql;
|
||||
import 'schema.graphql.dart';
|
||||
import 'services.graphql.dart';
|
||||
|
||||
class Fragment$basicMutationReturnFields {
|
||||
Fragment$basicMutationReturnFields({
|
||||
|
|
|
@ -17,6 +17,7 @@ query AllServices {
|
|||
isMovable
|
||||
isRequired
|
||||
canBeBackedUp
|
||||
backupDescription
|
||||
status
|
||||
storageUsage {
|
||||
title
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'disk_volumes.graphql.dart';
|
||||
import 'package:gql/ast.dart';
|
||||
import 'package:graphql/client.dart' as graphql;
|
||||
import 'schema.graphql.dart';
|
||||
|
@ -2502,6 +2503,13 @@ const documentNodeQueryAllServices = DocumentNode(definitions: [
|
|||
directives: [],
|
||||
selectionSet: null,
|
||||
),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'backupDescription'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null,
|
||||
),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'status'),
|
||||
alias: null,
|
||||
|
@ -2884,6 +2892,7 @@ class Query$AllServices$services$allServices {
|
|||
required this.isMovable,
|
||||
required this.isRequired,
|
||||
required this.canBeBackedUp,
|
||||
required this.backupDescription,
|
||||
required this.status,
|
||||
required this.storageUsage,
|
||||
required this.svgIcon,
|
||||
|
@ -2901,6 +2910,7 @@ class Query$AllServices$services$allServices {
|
|||
final l$isMovable = json['isMovable'];
|
||||
final l$isRequired = json['isRequired'];
|
||||
final l$canBeBackedUp = json['canBeBackedUp'];
|
||||
final l$backupDescription = json['backupDescription'];
|
||||
final l$status = json['status'];
|
||||
final l$storageUsage = json['storageUsage'];
|
||||
final l$svgIcon = json['svgIcon'];
|
||||
|
@ -2918,6 +2928,7 @@ class Query$AllServices$services$allServices {
|
|||
isMovable: (l$isMovable as bool),
|
||||
isRequired: (l$isRequired as bool),
|
||||
canBeBackedUp: (l$canBeBackedUp as bool),
|
||||
backupDescription: (l$backupDescription as String),
|
||||
status: fromJson$Enum$ServiceStatusEnum((l$status as String)),
|
||||
storageUsage:
|
||||
Query$AllServices$services$allServices$storageUsage.fromJson(
|
||||
|
@ -2944,6 +2955,8 @@ class Query$AllServices$services$allServices {
|
|||
|
||||
final bool canBeBackedUp;
|
||||
|
||||
final String backupDescription;
|
||||
|
||||
final Enum$ServiceStatusEnum status;
|
||||
|
||||
final Query$AllServices$services$allServices$storageUsage storageUsage;
|
||||
|
@ -2972,6 +2985,8 @@ class Query$AllServices$services$allServices {
|
|||
_resultData['isRequired'] = l$isRequired;
|
||||
final l$canBeBackedUp = canBeBackedUp;
|
||||
_resultData['canBeBackedUp'] = l$canBeBackedUp;
|
||||
final l$backupDescription = backupDescription;
|
||||
_resultData['backupDescription'] = l$backupDescription;
|
||||
final l$status = status;
|
||||
_resultData['status'] = toJson$Enum$ServiceStatusEnum(l$status);
|
||||
final l$storageUsage = storageUsage;
|
||||
|
@ -2995,6 +3010,7 @@ class Query$AllServices$services$allServices {
|
|||
final l$isMovable = isMovable;
|
||||
final l$isRequired = isRequired;
|
||||
final l$canBeBackedUp = canBeBackedUp;
|
||||
final l$backupDescription = backupDescription;
|
||||
final l$status = status;
|
||||
final l$storageUsage = storageUsage;
|
||||
final l$svgIcon = svgIcon;
|
||||
|
@ -3009,6 +3025,7 @@ class Query$AllServices$services$allServices {
|
|||
l$isMovable,
|
||||
l$isRequired,
|
||||
l$canBeBackedUp,
|
||||
l$backupDescription,
|
||||
l$status,
|
||||
l$storageUsage,
|
||||
l$svgIcon,
|
||||
|
@ -3077,6 +3094,11 @@ class Query$AllServices$services$allServices {
|
|||
if (l$canBeBackedUp != lOther$canBeBackedUp) {
|
||||
return false;
|
||||
}
|
||||
final l$backupDescription = backupDescription;
|
||||
final lOther$backupDescription = other.backupDescription;
|
||||
if (l$backupDescription != lOther$backupDescription) {
|
||||
return false;
|
||||
}
|
||||
final l$status = status;
|
||||
final lOther$status = other.status;
|
||||
if (l$status != lOther$status) {
|
||||
|
@ -3134,6 +3156,7 @@ abstract class CopyWith$Query$AllServices$services$allServices<TRes> {
|
|||
bool? isMovable,
|
||||
bool? isRequired,
|
||||
bool? canBeBackedUp,
|
||||
String? backupDescription,
|
||||
Enum$ServiceStatusEnum? status,
|
||||
Query$AllServices$services$allServices$storageUsage? storageUsage,
|
||||
String? svgIcon,
|
||||
|
@ -3172,6 +3195,7 @@ class _CopyWithImpl$Query$AllServices$services$allServices<TRes>
|
|||
Object? isMovable = _undefined,
|
||||
Object? isRequired = _undefined,
|
||||
Object? canBeBackedUp = _undefined,
|
||||
Object? backupDescription = _undefined,
|
||||
Object? status = _undefined,
|
||||
Object? storageUsage = _undefined,
|
||||
Object? svgIcon = _undefined,
|
||||
|
@ -3201,6 +3225,10 @@ class _CopyWithImpl$Query$AllServices$services$allServices<TRes>
|
|||
canBeBackedUp: canBeBackedUp == _undefined || canBeBackedUp == null
|
||||
? _instance.canBeBackedUp
|
||||
: (canBeBackedUp as bool),
|
||||
backupDescription:
|
||||
backupDescription == _undefined || backupDescription == null
|
||||
? _instance.backupDescription
|
||||
: (backupDescription as String),
|
||||
status: status == _undefined || status == null
|
||||
? _instance.status
|
||||
: (status as Enum$ServiceStatusEnum),
|
||||
|
@ -3251,6 +3279,7 @@ class _CopyWithStubImpl$Query$AllServices$services$allServices<TRes>
|
|||
bool? isMovable,
|
||||
bool? isRequired,
|
||||
bool? canBeBackedUp,
|
||||
String? backupDescription,
|
||||
Enum$ServiceStatusEnum? status,
|
||||
Query$AllServices$services$allServices$storageUsage? storageUsage,
|
||||
String? svgIcon,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'disk_volumes.graphql.dart';
|
||||
import 'package:gql/ast.dart';
|
||||
import 'package:graphql/client.dart' as graphql;
|
||||
import 'schema.graphql.dart';
|
||||
import 'services.graphql.dart';
|
||||
|
||||
class Fragment$basicMutationReturnFields {
|
||||
Fragment$basicMutationReturnFields({
|
||||
|
|
|
@ -30,6 +30,7 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
|||
final BackupConfiguration? backupConfig =
|
||||
await api.getBackupsConfiguration();
|
||||
final List<Backup> backups = await api.getBackups();
|
||||
backups.sort((final a, final b) => b.time.compareTo(a.time));
|
||||
emit(
|
||||
state.copyWith(
|
||||
backblazeBucket: bucket,
|
||||
|
@ -144,6 +145,7 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
|||
Future<void> updateBackups({final bool useTimer = false}) async {
|
||||
emit(state.copyWith(refreshing: true));
|
||||
final backups = await api.getBackups();
|
||||
backups.sort((final a, final b) => b.time.compareTo(a.time));
|
||||
final backupConfig = await api.getBackupsConfiguration();
|
||||
|
||||
emit(
|
||||
|
|
|
@ -25,7 +25,7 @@ class BackupsState extends ServerInstallationDependendState {
|
|||
backups,
|
||||
preventActions,
|
||||
refreshTimer,
|
||||
refreshing
|
||||
refreshing,
|
||||
];
|
||||
|
||||
BackupsState copyWith({
|
||||
|
|
|
@ -18,6 +18,7 @@ class Service {
|
|||
isRequired: service.isRequired,
|
||||
isMovable: service.isMovable,
|
||||
canBeBackedUp: service.canBeBackedUp,
|
||||
backupDescription: service.backupDescription,
|
||||
status: ServiceStatus.fromGraphQL(service.status),
|
||||
storageUsage: ServiceStorageUsage(
|
||||
used: DiskSize(byte: int.parse(service.storageUsage.usedSpace)),
|
||||
|
@ -44,6 +45,7 @@ class Service {
|
|||
required this.isRequired,
|
||||
required this.isMovable,
|
||||
required this.canBeBackedUp,
|
||||
required this.backupDescription,
|
||||
required this.status,
|
||||
required this.storageUsage,
|
||||
required this.svgIcon,
|
||||
|
@ -78,6 +80,7 @@ class Service {
|
|||
isRequired: false,
|
||||
isMovable: false,
|
||||
canBeBackedUp: false,
|
||||
backupDescription: '',
|
||||
status: ServiceStatus.off,
|
||||
storageUsage: ServiceStorageUsage(
|
||||
used: const DiskSize(byte: 0),
|
||||
|
@ -95,6 +98,7 @@ class Service {
|
|||
final bool isRequired;
|
||||
final bool isMovable;
|
||||
final bool canBeBackedUp;
|
||||
final String backupDescription;
|
||||
final ServiceStatus status;
|
||||
final ServiceStorageUsage storageUsage;
|
||||
final String svgIcon;
|
||||
|
|
|
@ -147,7 +147,8 @@ class _HeroSliverAppBarState extends State<HeroSliverAppBar> {
|
|||
context: context,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
builder: (final BuildContext context) => DraggableScrollableSheet(
|
||||
builder: (final BuildContext context) =>
|
||||
DraggableScrollableSheet(
|
||||
expand: false,
|
||||
maxChildSize: 0.9,
|
||||
minChildSize: 0.4,
|
||||
|
|
|
@ -93,59 +93,88 @@ class _BackupDetailsPageState extends State<BackupDetailsPage>
|
|||
// Each list item has a date
|
||||
// When clicked, starts the restore action
|
||||
if (isBackupInitialized)
|
||||
OutlinedCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
'backups.latest_snapshots'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'backups.latest_snapshots_subtitle'.tr(),
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
),
|
||||
if (backups.isEmpty)
|
||||
ListTile(
|
||||
leading: const Icon(
|
||||
Icons.refresh,
|
||||
),
|
||||
title: Text(
|
||||
'backup.restore'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
Icons.error_outline,
|
||||
),
|
||||
title: Text('backup.no_backups'.tr()),
|
||||
),
|
||||
const Divider(
|
||||
height: 1.0,
|
||||
),
|
||||
if (backups.isEmpty)
|
||||
ListTile(
|
||||
leading: const Icon(
|
||||
Icons.error_outline,
|
||||
),
|
||||
title: Text('backup.no_backups'.tr()),
|
||||
),
|
||||
if (backups.isNotEmpty)
|
||||
Column(
|
||||
children: backups
|
||||
.map(
|
||||
(final Backup backup) => ListTile(
|
||||
onTap: preventActions
|
||||
? null
|
||||
: () {
|
||||
showPopUpAlert(
|
||||
alertTitle: 'backup.restoring'.tr(),
|
||||
description: 'backup.restore_alert'.tr(
|
||||
args: [backup.time.toString()],
|
||||
),
|
||||
actionButtonTitle: 'modals.yes'.tr(),
|
||||
actionButtonOnPressed: () => {
|
||||
context
|
||||
.read<BackupsCubit>()
|
||||
.restoreBackup(backup.id)
|
||||
},
|
||||
);
|
||||
if (backups.isNotEmpty)
|
||||
Column(
|
||||
children: backups.take(20).map(
|
||||
(final Backup backup) {
|
||||
final service = context
|
||||
.read<ServicesCubit>()
|
||||
.state
|
||||
.getServiceById(backup.serviceId);
|
||||
return ListTile(
|
||||
onTap: preventActions
|
||||
? null
|
||||
: () {
|
||||
showPopUpAlert(
|
||||
alertTitle: 'backup.restoring'.tr(),
|
||||
description: 'backup.restore_alert'.tr(
|
||||
args: [backup.time.toString()],
|
||||
),
|
||||
actionButtonTitle: 'modals.yes'.tr(),
|
||||
actionButtonOnPressed: () => {
|
||||
context
|
||||
.read<BackupsCubit>()
|
||||
.restoreBackup(backup.id)
|
||||
},
|
||||
title: Text(
|
||||
'${MaterialLocalizations.of(context).formatShortDate(backup.time)} ${TimeOfDay.fromDateTime(backup.time).format(context)}',
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
title: Text(
|
||||
'${MaterialLocalizations.of(context).formatShortDate(backup.time)} ${TimeOfDay.fromDateTime(backup.time).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.onBackground,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
: const Icon(
|
||||
Icons.question_mark_outlined,
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
if (backups.isNotEmpty && backups.length > 20)
|
||||
ListTile(
|
||||
title: Text(
|
||||
'backups.show_more'.tr(),
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
leading: const Icon(
|
||||
Icons.arrow_drop_down,
|
||||
),
|
||||
onTap: null,
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
OutlinedCard(
|
||||
|
@ -317,7 +346,7 @@ class _CreateBackupsModalState extends State<CreateBackupsModal> {
|
|||
service.displayName,
|
||||
),
|
||||
subtitle: Text(
|
||||
busy ? 'backup.service_busy'.tr() : service.description,
|
||||
busy ? 'backup.service_busy'.tr() : service.backupDescription,
|
||||
),
|
||||
secondary: SvgPicture.string(
|
||||
service.svgIcon,
|
||||
|
|
Loading…
Reference in a new issue