Add backup and restore functionality for rental data in settings
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:rental_income_tracker/state/rent_controller.dart';
|
||||
@@ -12,6 +13,32 @@ class SettingsScreen extends StatefulWidget {
|
||||
class _SettingsScreenState extends State<SettingsScreen> {
|
||||
final TextEditingController _rentController = TextEditingController();
|
||||
|
||||
Future<bool> _confirmImport() async {
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Import backup file?'),
|
||||
content: const Text(
|
||||
'This will overwrite current local settings and logged entries with the contents of the selected backup file.',
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: const Text('Import'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return result ?? false;
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
@@ -103,16 +130,71 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
const SizedBox(height: 12),
|
||||
FilledButton.icon(
|
||||
onPressed: () async {
|
||||
final path = await controller.exportJson();
|
||||
final directoryPath = await FilePicker.platform
|
||||
.getDirectoryPath(dialogTitle: 'Choose backup folder');
|
||||
if (directoryPath == null || !context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final path = await controller.exportBackupToDirectory(
|
||||
directoryPath,
|
||||
);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Exported to $path')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Backup saved to $path')),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.download),
|
||||
label: const Text('Export JSON'),
|
||||
label: const Text('Create backup'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
FilledButton.icon(
|
||||
onPressed: () async {
|
||||
final shouldImport = await _confirmImport();
|
||||
if (!shouldImport || !context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await FilePicker.platform.pickFiles(
|
||||
dialogTitle: 'Choose backup file',
|
||||
type: FileType.custom,
|
||||
allowedExtensions: <String>['json'],
|
||||
withData: false,
|
||||
);
|
||||
final filePath = result?.files.single.path;
|
||||
if (filePath == null || !context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final path = await controller.importBackupFromFile(
|
||||
filePath,
|
||||
);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
_rentController.text = controller.settings.rentUsd
|
||||
.toStringAsFixed(2);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Imported backup from $path')),
|
||||
);
|
||||
} catch (_) {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
controller.errorMessage ?? 'Restore failed.',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.restore),
|
||||
label: const Text('Import backup file'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
|
||||
Reference in New Issue
Block a user