opt. for backup

This commit is contained in:
lollipopkit
2023-04-19 10:51:10 +08:00
parent 216d64e3eb
commit 552e2738cd
4 changed files with 44 additions and 72 deletions

View File

@@ -24,11 +24,16 @@ Future<bool> shareFiles(BuildContext context, List<String> filePaths) async {
} else { } else {
text = '${filePaths.length} ${S.of(context)!.files}'; text = '${filePaths.length} ${S.of(context)!.files}';
} }
final xfiles = filePaths.map((e) => XFile(e)).toList(); // ignore: deprecated_member_use
await Share.shareXFiles(xfiles, text: 'ServerBox -> $text'); await Share.shareFiles(filePaths, text: 'ServerBox -> $text');
return filePaths.isNotEmpty; return filePaths.isNotEmpty;
} }
Future<bool> shareText(String text) async {
final result = await Share.shareWithResult(text, subject: 'ServerBox backup');
return result.status == ShareResultStatus.success;
}
void copy(String text) { void copy(String text) {
Clipboard.setData(ClipboardData(text: text)); Clipboard.setData(ClipboardData(text: text));
} }

View File

@@ -1,13 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/core/utils/misc.dart'; import 'package:toolbox/data/res/path.dart';
import '../../core/extension/colorx.dart'; import '../../core/extension/colorx.dart';
import '../../core/utils/misc.dart';
import '../../core/utils/ui.dart'; import '../../core/utils/ui.dart';
import '../../data/model/app/backup.dart'; import '../../data/model/app/backup.dart';
import '../../data/res/color.dart'; import '../../data/res/color.dart';
@@ -51,8 +52,20 @@ class BackupPage extends StatelessWidget {
const SizedBox( const SizedBox(
height: 107, height: 107,
), ),
_buildCard(s.restore, Icons.download, media, _buildCard(s.restore, Icons.download, media, () async {
() => _showImportDialog(context, s)), final path = await pickOneFile();
if (path == null) {
showSnackBar(context, Text(s.notSelected));
return;
}
final file = File(path);
if (!file.existsSync()) {
showSnackBar(context, Text(s.fileNotExist(path)));
return;
}
final text = await file.readAsString();
_import(text, context, s);
}),
const SizedBox(height: 7), const SizedBox(height: 7),
const Divider(), const Divider(),
const SizedBox(height: 7), const SizedBox(height: 7),
@@ -60,7 +73,23 @@ class BackupPage extends StatelessWidget {
s.backup, s.backup,
Icons.file_upload, Icons.file_upload,
media, media,
() => _showExportDialog(context, s), () async {
final result = _diyEncrtpt(
json.encode(
Backup(
backupFormatVersion,
DateTime.now().toString().split('.').first,
_server.fetch(),
_snippet.fetch(),
_privateKey.fetch(),
_dockerHosts.fetch(),
),
),
);
final path = '${(await docDir).path}/srvbox_bak.json';
await File(path).writeAsString(result);
await shareFiles(context, [path]);
},
) )
], ],
)), )),
@@ -94,68 +123,6 @@ class BackupPage extends StatelessWidget {
); );
} }
Future<void> _showExportDialog(BuildContext context, S s) async {
final exportFieldController = TextEditingController()
..text = _diyEncrtpt(
json.encode(
Backup(
backupFormatVersion,
DateTime.now().toString().split('.').first,
_server.fetch(),
_snippet.fetch(),
_privateKey.fetch(),
_dockerHosts.fetch(),
),
),
);
await showRoundDialog(
context,
s.export,
TextField(
decoration: const InputDecoration(
labelText: 'JSON',
),
maxLines: 7,
controller: exportFieldController,
),
[
TextButton(
child: Text(s.copy),
onPressed: () {
Clipboard.setData(ClipboardData(text: exportFieldController.text));
Navigator.pop(context);
},
),
],
);
}
Future<void> _showImportDialog(BuildContext context, S s) async {
final importFieldController = TextEditingController();
await showRoundDialog(
context,
s.import,
TextField(
decoration: const InputDecoration(
labelText: 'JSON',
),
maxLines: 3,
controller: importFieldController,
),
[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(s.cancel),
),
TextButton(
onPressed: () async =>
await _import(importFieldController.text.trim(), context, s),
child: const Text('GO'),
)
],
);
}
Future<void> _import(String text, BuildContext context, S s) async { Future<void> _import(String text, BuildContext context, S s) async {
if (text.isEmpty) { if (text.isEmpty) {
showSnackBar(context, Text(s.fieldMustNotEmpty)); showSnackBar(context, Text(s.fieldMustNotEmpty));

View File

@@ -746,10 +746,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: "8c6892037b1824e2d7e8f59d54b3105932899008642e6372e5079c6939b4b625" sha256: "692261968a494e47323dcc8bc66d8d52e81bc27cb4b808e4e8d7e8079d4cc01a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.1" version: "6.3.2"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:

View File

@@ -52,7 +52,7 @@ dependencies:
r_upgrade: 0.3.8+2 r_upgrade: 0.3.8+2
path_provider: ^2.0.9 path_provider: ^2.0.9
easy_isolate: ^1.3.0 easy_isolate: ^1.3.0
share_plus: ^6.3.1 share_plus: ^6.3.2
intl: ^0.17.0 intl: ^0.17.0
share_plus_web: ^3.1.0 share_plus_web: ^3.1.0
# xterm: ^3.4.1 # xterm: ^3.4.1