feat: backup and restaure
This commit is contained in:
parent
96aa836e85
commit
e530cc655d
12 changed files with 292 additions and 105 deletions
|
|
@ -236,5 +236,27 @@
|
|||
"log_out_from":"Log out from {tracker}?",
|
||||
"log_out":"Log out",
|
||||
"update_pending":"Update pending",
|
||||
"update_all":"Update all"
|
||||
"update_all":"Update all",
|
||||
"backup_and_restore":"Backup and restore",
|
||||
"create_backup":"Create backup",
|
||||
"create_backup_dialog_title":"What do you want to backup?",
|
||||
"create_backup_subtitle":"Can be used to restore current library",
|
||||
"restore_backup":"Restore backup",
|
||||
"restore_backup_subtitle":"Restore library from backup file",
|
||||
"automatic_backups":"Automatic backups",
|
||||
"backup_frequency":"Backup frequency",
|
||||
"backup_location":"Backup location",
|
||||
"backup_options":"Backup options",
|
||||
"backup_options_dialog_title":"What do you want to backup?",
|
||||
"backup_options_subtile":"What information to include in the backup file",
|
||||
"backup_and_restore_warning_info":"You should keep copies of backups in other places as well",
|
||||
"library_entries":"Library entries",
|
||||
"categories":"Categories",
|
||||
"chapters_and_episode":"Chapters and episode",
|
||||
"every_6_hours":"Every 6 hours",
|
||||
"every_12_hours":"Every 12 hours",
|
||||
"daily":"Daily",
|
||||
"every_2_days":"Every 2 days",
|
||||
"weekly":"Weekly",
|
||||
"restore_backup_warning_title":"Restoring a backup will overwrite all existing data.\n\nContinue restoring?"
|
||||
}
|
||||
|
|
@ -236,5 +236,27 @@
|
|||
"log_out_from":"Se déconnecter de {tracker} ?",
|
||||
"log_out":"Se déconnecter",
|
||||
"update_pending":"Mises à jour en attente",
|
||||
"update_all":"Tout mettre à jour"
|
||||
"update_all":"Tout mettre à jour",
|
||||
"backup_and_restore":"Sauvegarder et restaurer",
|
||||
"create_backup":"Créer une sauvegarde",
|
||||
"create_backup_dialog_title":"Que voulez-vous sauvegarder ?",
|
||||
"create_backup_subtitle":"Peut être utilisé pour restaurer la bibliothèque actuelle",
|
||||
"restore_backup":"Restaurer une sauvegarde",
|
||||
"restore_backup_subtitle":"Restaurer la bibliothèque à partir d'un fichier de sauvegarde",
|
||||
"automatic_backups":"Sauvegarders automatiques",
|
||||
"backup_frequency":"Fréquence de sauvegarde",
|
||||
"backup_location":"Dossier de sauvegarde",
|
||||
"backup_options":"Options de sauvegarde",
|
||||
"backup_options_dialog_title":"Que voulez-vous sauvegarder ?",
|
||||
"backup_options_subtile":"Quelle information inclure dans le fichier de sauvegarde",
|
||||
"backup_and_restore_warning_info":"Vous devez égalemement conserver des copies des sauvegardes à d'atures endroits",
|
||||
"library_entries":"Entrées de la bibliothèque",
|
||||
"categories":"Catégories",
|
||||
"chapters_and_episode":"Chapitres et épisodes",
|
||||
"every_6_hours":"Toutes les 6 heures",
|
||||
"every_12_hours":"Toutes les 12 heures",
|
||||
"daily":"Tous les jours",
|
||||
"every_2_days":"Tous les 2 jours",
|
||||
"weekly":"Chaque semaine",
|
||||
"restore_backup_warning_title":"La restauration d'une sauvegarde écrasera toutes les données existantes.\n\nContinuer la restauration ?"
|
||||
}
|
||||
|
|
@ -306,6 +306,10 @@ class Settings {
|
|||
: null;
|
||||
themeIsDark = json['themeIsDark'];
|
||||
userAgent = json['userAgent'];
|
||||
backupFrequency = json['backupFrequency'];
|
||||
backupFrequencyOptions = json['backupFrequencyOptions']?.cast<int>();
|
||||
autoBackupLocation = json['autoBackupLocation'];
|
||||
startDatebackup = json['startDatebackup'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
@ -399,6 +403,10 @@ class Settings {
|
|||
}
|
||||
data['themeIsDark'] = themeIsDark;
|
||||
data['userAgent'] = userAgent;
|
||||
data['backupFrequency'] = backupFrequency;
|
||||
data['backupFrequencyOptions'] = backupFrequencyOptions;
|
||||
data['autoBackupLocation'] = autoBackupLocation;
|
||||
data['startDatebackup'] = startDatebackup;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:mangayomi/models/source.dart';
|
|||
import 'package:mangayomi/modules/browse/extension/providers/fetch_manga_sources.dart';
|
||||
import 'package:mangayomi/modules/main_view/providers/migration.dart';
|
||||
import 'package:mangayomi/modules/more/about/providers/check_for_update.dart';
|
||||
import 'package:mangayomi/modules/more/backup_and_restore/providers/auto_backup.dart';
|
||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||
import 'package:mangayomi/modules/widgets/error_text.dart';
|
||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||
|
|
@ -29,6 +30,7 @@ class MainScreen extends ConsumerWidget {
|
|||
final l10n = l10nLocalizations(context)!;
|
||||
final route = GoRouter.of(context);
|
||||
ref.watch(checkForUpdateProvider(context: context));
|
||||
ref.read(checkAndBackupProvider);
|
||||
return ref.watch(migrationProvider).when(data: (_) {
|
||||
return Consumer(builder: (context, ref, chuld) {
|
||||
final location = ref.watch(
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
final l10n = l10nLocalizations(context)!;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Backup and restore"),
|
||||
title: Text(l10n.backup_and_restore),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
final list = _getList();
|
||||
final list = _getList(context);
|
||||
List<int> indexList = [];
|
||||
indexList.addAll(backupFrequencyOptions);
|
||||
showDialog(
|
||||
|
|
@ -38,8 +38,8 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"What do you want to backup?",
|
||||
title: Text(
|
||||
l10n.create_backup_dialog_title,
|
||||
),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
|
|
@ -101,27 +101,80 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
);
|
||||
});
|
||||
},
|
||||
title: const Text("Create backup"),
|
||||
title: Text(l10n.create_backup),
|
||||
subtitle: Text(
|
||||
"Can be used to restore current library",
|
||||
l10n.create_backup_subtitle,
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
allowMultiple: false,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['backup']);
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(l10n.restore_backup),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.info_outline_rounded,
|
||||
color: secondaryColor(context)),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 5),
|
||||
child: Text(l10n.restore_backup_warning_title),
|
||||
),
|
||||
],
|
||||
)),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style:
|
||||
TextStyle(color: primaryColor(context)),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
FilePickerResult? result =
|
||||
await FilePicker.platform.pickFiles(
|
||||
allowMultiple: false,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['backup']);
|
||||
|
||||
if (result != null && context.mounted) {
|
||||
ref.watch(doRestoreProvider(
|
||||
path: result.files.first.path!, context: context));
|
||||
}
|
||||
if (result != null && context.mounted) {
|
||||
ref.watch(doRestoreProvider(
|
||||
path: result.files.first.path!,
|
||||
context: context));
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
l10n.ok,
|
||||
style:
|
||||
TextStyle(color: primaryColor(context)),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
title: const Text("Restore backup"),
|
||||
title: Text(l10n.restore_backup),
|
||||
subtitle: Text(
|
||||
"Restore library from backup file",
|
||||
l10n.restore_backup_subtitle,
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
|
|
@ -129,7 +182,7 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text('Automatic backups',
|
||||
Text(l10n.automatic_backups,
|
||||
style:
|
||||
TextStyle(fontSize: 13, color: primaryColor(context))),
|
||||
],
|
||||
|
|
@ -140,9 +193,9 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
final list = _getBackupFrequencyList();
|
||||
final list = _getBackupFrequencyList(context);
|
||||
return AlertDialog(
|
||||
title: const Text("Backup frequency"),
|
||||
title: Text(l10n.backup_frequency),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: ListView.builder(
|
||||
|
|
@ -186,9 +239,9 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
);
|
||||
});
|
||||
},
|
||||
title: const Text("Backup frequency"),
|
||||
title: Text(l10n.backup_frequency),
|
||||
subtitle: Text(
|
||||
_getBackupFrequencyList()[backupFrequency],
|
||||
_getBackupFrequencyList(context)[backupFrequency],
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
|
|
@ -200,7 +253,7 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
ref.read(autoBackupLocationStateProvider.notifier).set(result);
|
||||
}
|
||||
},
|
||||
title: const Text('Backup location'),
|
||||
title: Text(l10n.backup_location),
|
||||
subtitle: Text(
|
||||
autoBackupLocation.$2.isEmpty
|
||||
? autoBackupLocation.$1
|
||||
|
|
@ -210,7 +263,7 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
final list = _getList();
|
||||
final list = _getList(context);
|
||||
List<int> indexList = [];
|
||||
indexList.addAll(backupFrequencyOptions);
|
||||
showDialog(
|
||||
|
|
@ -219,8 +272,8 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"What do you want to backup?",
|
||||
title: Text(
|
||||
l10n.backup_options_subtile,
|
||||
),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
|
|
@ -279,9 +332,9 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
);
|
||||
});
|
||||
},
|
||||
title: const Text("Backup options"),
|
||||
title: Text(l10n.backup_options),
|
||||
subtitle: Text(
|
||||
"What information to include in the backup file",
|
||||
l10n.backup_options_subtile,
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
|
|
@ -297,8 +350,7 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
"You should keep copies of backups in other places as well",
|
||||
subtitle: Text(l10n.backup_and_restore_warning_info,
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context))),
|
||||
)
|
||||
],
|
||||
|
|
@ -307,25 +359,27 @@ class BackupAndRestore extends ConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
List<String> _getList() {
|
||||
List<String> _getList(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return [
|
||||
"Library entries",
|
||||
"Categories",
|
||||
"Chapters and episode",
|
||||
"Tracking",
|
||||
"History",
|
||||
"Settings",
|
||||
"Extensions"
|
||||
l10n.library_entries,
|
||||
l10n.categories,
|
||||
l10n.chapters_and_episode,
|
||||
l10n.tracking,
|
||||
l10n.history,
|
||||
l10n.settings,
|
||||
l10n.extensions
|
||||
];
|
||||
}
|
||||
|
||||
List<String> _getBackupFrequencyList() {
|
||||
List<String> _getBackupFrequencyList(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return [
|
||||
"Off",
|
||||
"Every 6 hours",
|
||||
"Every 12 hours",
|
||||
"Daily",
|
||||
"Every 2 days",
|
||||
"Weekly"
|
||||
l10n.off,
|
||||
l10n.every_6_hours,
|
||||
l10n.every_12_hours,
|
||||
l10n.daily,
|
||||
l10n.every_2_days,
|
||||
l10n.weekly
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:io';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/modules/more/backup_and_restore/providers/backup.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'auto_backup.g.dart';
|
||||
|
|
@ -13,10 +14,8 @@ class BackupFrequencyState extends _$BackupFrequencyState {
|
|||
}
|
||||
|
||||
void set(int value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..backupFrequency = value));
|
||||
_setBackupFrequency(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +23,7 @@ class BackupFrequencyState extends _$BackupFrequencyState {
|
|||
class BackupFrequencyOptionsState extends _$BackupFrequencyOptionsState {
|
||||
@override
|
||||
List<int> build() {
|
||||
return isar.settings.getSync(227)!.backupFrequencyOptions ?? [];
|
||||
return isar.settings.getSync(227)!.backupFrequencyOptions ?? [0, 1, 2, 3];
|
||||
}
|
||||
|
||||
void set(List<int> values) {
|
||||
|
|
@ -54,13 +53,61 @@ class AutoBackupLocationState extends _$AutoBackupLocationState {
|
|||
Future refresh() async {
|
||||
_storageProvider = await StorageProvider().getDefaultDirectory();
|
||||
final settings = isar.settings.getSync(227);
|
||||
state =
|
||||
("${_storageProvider!.path}backup", settings!.autoBackupLocation ?? "");
|
||||
state = (
|
||||
"${_storageProvider!.path}backup/",
|
||||
settings!.autoBackupLocation ?? ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// this.personalPageModeList,
|
||||
// this.backupFrequency,
|
||||
// this.backupFrequencyOptions,
|
||||
// this.autoBackupLocation,
|
||||
// this.startDatebackup
|
||||
@riverpod
|
||||
Future<void> checkAndBackup(CheckAndBackupRef ref) async {
|
||||
final settings = isar.settings.getSync(227);
|
||||
if (settings!.backupFrequency != null) {
|
||||
final backupFrequency = _duration(settings.backupFrequency);
|
||||
if (backupFrequency != null) {
|
||||
if (settings.startDatebackup != null) {
|
||||
final startDatebackup =
|
||||
DateTime.fromMillisecondsSinceEpoch(settings.startDatebackup!);
|
||||
if (DateTime.now().isAfter(startDatebackup)) {
|
||||
_setBackupFrequency(settings.backupFrequency!);
|
||||
final storageProvider = StorageProvider();
|
||||
await storageProvider.requestPermission();
|
||||
final defaulteDirectory = await storageProvider.getDefaultDirectory();
|
||||
final backupLocation = ref.watch(autoBackupLocationStateProvider).$2;
|
||||
final backupDirectory = Directory(backupLocation.isEmpty
|
||||
? "${defaulteDirectory!.path}backup/"
|
||||
: backupLocation);
|
||||
if (!(await backupDirectory.exists())) {
|
||||
backupDirectory.create();
|
||||
}
|
||||
ref.watch(doBackUpProvider(
|
||||
list: ref.watch(backupFrequencyOptionsStateProvider),
|
||||
path: backupDirectory.path,
|
||||
context: null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Duration? _duration(int? backupFrequency) {
|
||||
return switch (backupFrequency) {
|
||||
1 => const Duration(hours: 6),
|
||||
2 => const Duration(hours: 12),
|
||||
3 => const Duration(days: 1),
|
||||
4 => const Duration(days: 2),
|
||||
5 => const Duration(days: 7),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
void _setBackupFrequency(int value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
final duration = _duration(value);
|
||||
final now = DateTime.now();
|
||||
final startDate = duration != null ? now.add(duration) : null;
|
||||
isar.writeTxnSync(() => isar.settings.putSync(settings!
|
||||
..backupFrequency = value
|
||||
..startDatebackup = startDate?.millisecondsSinceEpoch));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,23 @@ part of 'auto_backup.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$checkAndBackupHash() => r'039aea77df04d1925a25ad8839177cf9ee96aa65';
|
||||
|
||||
/// See also [checkAndBackup].
|
||||
@ProviderFor(checkAndBackup)
|
||||
final checkAndBackupProvider = AutoDisposeProvider<void>.internal(
|
||||
checkAndBackup,
|
||||
name: r'checkAndBackupProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$checkAndBackupHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef CheckAndBackupRef = AutoDisposeProviderRef<void>;
|
||||
String _$backupFrequencyStateHash() =>
|
||||
r'234368840b43f1f1bb3f4825f39c86bfa189a8ac';
|
||||
r'2e73e3fe54456978ff92f49cdc67e84f2af6de7c';
|
||||
|
||||
/// See also [BackupFrequencyState].
|
||||
@ProviderFor(BackupFrequencyState)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:isar/isar.dart';
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/category.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
|
|
@ -22,7 +23,7 @@ part 'backup.g.dart';
|
|||
void doBackUp(DoBackUpRef ref,
|
||||
{required List<int> list,
|
||||
required String path,
|
||||
required BuildContext context}) {
|
||||
required BuildContext? context}) {
|
||||
Map<String, dynamic> datas = {};
|
||||
datas.addAll({"version": "1"});
|
||||
if (list.contains(0)) {
|
||||
|
|
@ -53,6 +54,13 @@ void doBackUp(DoBackUpRef ref,
|
|||
.map((e) => e.toJson())
|
||||
.toList();
|
||||
datas.addAll({"chapters": res});
|
||||
final res_ = isar.downloads
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.findAllSync()
|
||||
.map((e) => e.toJson())
|
||||
.toList();
|
||||
datas.addAll({"downloads": res_});
|
||||
}
|
||||
if (list.contains(3)) {
|
||||
final res = isar.tracks
|
||||
|
|
@ -108,28 +116,30 @@ void doBackUp(DoBackUpRef ref,
|
|||
encoder.addFile(File(backupFilePath));
|
||||
encoder.close();
|
||||
Directory(backupFilePath).deleteSync(recursive: true);
|
||||
Navigator.pop(context);
|
||||
BotToast.showNotification(
|
||||
animationDuration: const Duration(milliseconds: 200),
|
||||
animationReverseDuration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(seconds: 5),
|
||||
backButtonBehavior: BackButtonBehavior.none,
|
||||
leading: (cancel) =>
|
||||
Image.asset('assets/app_icons/icon-red.png', height: 40),
|
||||
title: (_) => const Text(
|
||||
"Backup created!",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
trailing: (_) => UnconstrainedBox(
|
||||
alignment: Alignment.topLeft,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Share.shareXFiles([XFile('$path/$name.backup')],
|
||||
text: '$name.backup');
|
||||
},
|
||||
child: const Text('Share')),
|
||||
),
|
||||
enableSlideOff: true,
|
||||
onlyOne: true,
|
||||
crossPage: true);
|
||||
if (context != null) {
|
||||
Navigator.pop(context);
|
||||
BotToast.showNotification(
|
||||
animationDuration: const Duration(milliseconds: 200),
|
||||
animationReverseDuration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(seconds: 5),
|
||||
backButtonBehavior: BackButtonBehavior.none,
|
||||
leading: (cancel) =>
|
||||
Image.asset('assets/app_icons/icon-red.png', height: 40),
|
||||
title: (_) => const Text(
|
||||
"Backup created!",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
trailing: (_) => UnconstrainedBox(
|
||||
alignment: Alignment.topLeft,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Share.shareXFiles([XFile('$path/$name.backup')],
|
||||
text: '$name.backup');
|
||||
},
|
||||
child: const Text('Share')),
|
||||
),
|
||||
enableSlideOff: true,
|
||||
onlyOne: true,
|
||||
crossPage: true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'backup.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$doBackUpHash() => r'e94ed6a96237dd5efc68bf26f26b276ffd777472';
|
||||
String _$doBackUpHash() => r'4418d6aa9ea87ffa30195af59f9e93f95f7915f6';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -42,7 +42,7 @@ class DoBackUpFamily extends Family<void> {
|
|||
DoBackUpProvider call({
|
||||
required List<int> list,
|
||||
required String path,
|
||||
required BuildContext context,
|
||||
required BuildContext? context,
|
||||
}) {
|
||||
return DoBackUpProvider(
|
||||
list: list,
|
||||
|
|
@ -83,7 +83,7 @@ class DoBackUpProvider extends AutoDisposeProvider<void> {
|
|||
DoBackUpProvider({
|
||||
required List<int> list,
|
||||
required String path,
|
||||
required BuildContext context,
|
||||
required BuildContext? context,
|
||||
}) : this._internal(
|
||||
(ref) => doBackUp(
|
||||
ref as DoBackUpRef,
|
||||
|
|
@ -118,7 +118,7 @@ class DoBackUpProvider extends AutoDisposeProvider<void> {
|
|||
|
||||
final List<int> list;
|
||||
final String path;
|
||||
final BuildContext context;
|
||||
final BuildContext? context;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
|
|
@ -172,7 +172,7 @@ mixin DoBackUpRef on AutoDisposeProviderRef<void> {
|
|||
String get path;
|
||||
|
||||
/// The parameter `context` of this provider.
|
||||
BuildContext get context;
|
||||
BuildContext? get context;
|
||||
}
|
||||
|
||||
class _DoBackUpProviderElement extends AutoDisposeProviderElement<void>
|
||||
|
|
@ -184,7 +184,7 @@ class _DoBackUpProviderElement extends AutoDisposeProviderElement<void>
|
|||
@override
|
||||
String get path => (origin as DoBackUpProvider).path;
|
||||
@override
|
||||
BuildContext get context => (origin as DoBackUpProvider).context;
|
||||
BuildContext? get context => (origin as DoBackUpProvider).context;
|
||||
}
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:mangayomi/eval/model/m_bridge.dart';
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/category.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
|
|
@ -45,6 +46,9 @@ void doRestore(DoRestoreRef ref,
|
|||
final history = (backup["history"] as List?)
|
||||
?.map((e) => History.fromJson(e))
|
||||
.toList();
|
||||
final downloads = (backup["downloads"] as List?)
|
||||
?.map((e) => Download.fromJson(e))
|
||||
.toList();
|
||||
final settings = (backup["settings"] as List?)
|
||||
?.map((e) => Settings.fromJson(e))
|
||||
.toList();
|
||||
|
|
@ -66,6 +70,17 @@ void doRestore(DoRestoreRef ref,
|
|||
}
|
||||
}
|
||||
|
||||
isar.downloads.clearSync();
|
||||
if (downloads != null) {
|
||||
for (var download in downloads) {
|
||||
final chapter = isar.chapters.getSync(download.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.downloads.putSync(download..chapter.value = chapter);
|
||||
download.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.historys.clearSync();
|
||||
if (history != null) {
|
||||
for (var element in history) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'restore.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$doRestoreHash() => r'99dffa1f733b1d8ca19be263e70380915bf70590';
|
||||
String _$doRestoreHash() => r'3faca290a7217c27da2cdf21a559cec077a0201e';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -56,20 +56,12 @@ class MoreScreen extends StatelessWidget {
|
|||
icon: Icons.label_outline_rounded,
|
||||
title: l10n.categories,
|
||||
),
|
||||
|
||||
// ListTileWidget(
|
||||
// onTap: () {
|
||||
// context.push('/history');
|
||||
// },
|
||||
// icon: Icons.history_outlined,
|
||||
// title: l10n.history,
|
||||
// ),
|
||||
ListTileWidget(
|
||||
onTap: () {
|
||||
context.push('/backupAndRestore');
|
||||
},
|
||||
icon: Icons.settings_backup_restore_sharp,
|
||||
title: 'Backup and restore',
|
||||
title: l10n.backup_and_restore,
|
||||
),
|
||||
const Divider(),
|
||||
|
||||
|
|
@ -86,11 +78,11 @@ class MoreScreen extends StatelessWidget {
|
|||
},
|
||||
icon: Icons.info_outline,
|
||||
title: l10n.about),
|
||||
ListTileWidget(
|
||||
onTap: () {},
|
||||
icon: Icons.help_outline,
|
||||
title: l10n.help,
|
||||
),
|
||||
// ListTileWidget(
|
||||
// onTap: () {},
|
||||
// icon: Icons.help_outline,
|
||||
// title: l10n.help,
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue