backup add docker

This commit is contained in:
lollipopkit
2023-03-27 15:09:19 +08:00
parent 2747df64dd
commit 2ea061d324
14 changed files with 49 additions and 56 deletions

View File

@@ -159,10 +159,16 @@ abstract class S {
/// **'Backup'** /// **'Backup'**
String get backup; String get backup;
/// No description provided for @backupAndRestore.
///
/// In en, this message translates to:
/// **'Backup and Restore'**
String get backupAndRestore;
/// No description provided for @backupTip. /// No description provided for @backupTip.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'The exported data is simply encrypted. \nPlease keep it safe.\nRestoring will not overwrite existing data (except setting).'** /// **'The exported data is simply encrypted. \nPlease keep it safe.\nRestoring will not overwrite existing data.'**
String get backupTip; String get backupTip;
/// No description provided for @backupVersionNotMatch. /// No description provided for @backupVersionNotMatch.
@@ -507,12 +513,6 @@ abstract class S {
/// **'Import'** /// **'Import'**
String get import; String get import;
/// No description provided for @importAndExport.
///
/// In en, this message translates to:
/// **'Import and Export'**
String get importAndExport;
/// No description provided for @inputDomainHere. /// No description provided for @inputDomainHere.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View File

@@ -38,7 +38,10 @@ class SEn extends S {
String get backup => 'Backup'; String get backup => 'Backup';
@override @override
String get backupTip => 'The exported data is simply encrypted. \nPlease keep it safe.\nRestoring will not overwrite existing data (except setting).'; String get backupAndRestore => 'Backup and Restore';
@override
String get backupTip => 'The exported data is simply encrypted. \nPlease keep it safe.\nRestoring will not overwrite existing data.';
@override @override
String get backupVersionNotMatch => 'Backup version is not match.'; String get backupVersionNotMatch => 'Backup version is not match.';
@@ -229,9 +232,6 @@ class SEn extends S {
@override @override
String get import => 'Import'; String get import => 'Import';
@override
String get importAndExport => 'Import and Export';
@override @override
String get inputDomainHere => 'Input Domain here'; String get inputDomainHere => 'Input Domain here';

View File

@@ -38,7 +38,10 @@ class SZh extends S {
String get backup => '备份'; String get backup => '备份';
@override @override
String get backupTip => '导出的数据仅进行了简单加密,请妥善保管。\n除了设置项,恢复的数据不会覆盖现有数据。'; String get backupAndRestore => '备份和恢复';
@override
String get backupTip => '导出的数据仅进行了简单加密,请妥善保管。\n恢复的数据不会覆盖现有数据。';
@override @override
String get backupVersionNotMatch => '备份版本不匹配,无法恢复'; String get backupVersionNotMatch => '备份版本不匹配,无法恢复';
@@ -229,9 +232,6 @@ class SZh extends S {
@override @override
String get import => '导入'; String get import => '导入';
@override
String get importAndExport => '导入或导出';
@override @override
String get inputDomainHere => '在这里输入域名'; String get inputDomainHere => '在这里输入域名';

View File

@@ -359,7 +359,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 244; CURRENT_PROJECT_VERSION = 245;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -367,7 +367,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.244; MARKETING_VERSION = 1.0.245;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -490,7 +490,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 244; CURRENT_PROJECT_VERSION = 245;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -498,7 +498,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.244; MARKETING_VERSION = 1.0.245;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -515,7 +515,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 244; CURRENT_PROJECT_VERSION = 245;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -523,7 +523,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.244; MARKETING_VERSION = 1.0.245;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View File

@@ -9,9 +9,7 @@ class Backup {
final List<ServerPrivateInfo> spis; final List<ServerPrivateInfo> spis;
final List<Snippet> snippets; final List<Snippet> snippets;
final List<PrivateKeyInfo> keys; final List<PrivateKeyInfo> keys;
final int primaryColor; final Map<String, String> dockerHosts;
final int serverStatusUpdateInterval;
final int launchPage;
Backup( Backup(
this.version, this.version,
@@ -19,9 +17,7 @@ class Backup {
this.spis, this.spis,
this.snippets, this.snippets,
this.keys, this.keys,
this.primaryColor, this.dockerHosts,
this.serverStatusUpdateInterval,
this.launchPage,
); );
Backup.fromJson(Map<String, dynamic> json) Backup.fromJson(Map<String, dynamic> json)
@@ -35,9 +31,7 @@ class Backup {
keys = (json['keys'] as List) keys = (json['keys'] as List)
.map((e) => PrivateKeyInfo.fromJson(e)) .map((e) => PrivateKeyInfo.fromJson(e))
.toList(), .toList(),
primaryColor = json['primaryColor'], dockerHosts = json['dockerHosts'];
serverStatusUpdateInterval = json['serverStatusUpdateInterval'],
launchPage = json['launchPage'];
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'version': version, 'version': version,
@@ -45,8 +39,5 @@ class Backup {
'spis': spis, 'spis': spis,
'snippets': snippets, 'snippets': snippets,
'keys': keys, 'keys': keys,
'primaryColor': primaryColor,
'serverStatusUpdateInterval': serverStatusUpdateInterval,
'launchPage': launchPage,
}; };
} }

View File

@@ -2,8 +2,8 @@
class BuildData { class BuildData {
static const String name = "ServerBox"; static const String name = "ServerBox";
static const int build = 244; static const int build = 245;
static const String engine = "Flutter 3.7.7 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 2ad6cd72c0 (13 days ago) • 2023-03-08 09:41:59 -0800\nEngine • revision 1837b5be5f\nTools • Dart 2.19.4 • DevTools 2.20.1\n"; static const String engine = "Flutter 3.7.7 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 2ad6cd72c0 (3 weeks ago) • 2023-03-08 09:41:59 -0800\nEngine • revision 1837b5be5f\nTools • Dart 2.19.4 • DevTools 2.20.1\n";
static const String buildAt = "2023-03-21 15:36:44.082988"; static const String buildAt = "2023-03-27 13:57:46.119777";
static const int modifications = 2; static const int modifications = 2;
} }

View File

@@ -7,14 +7,14 @@ Future<Directory> get docDir async {
if (isAndroid) { if (isAndroid) {
final dir = await getExternalStorageDirectory(); final dir = await getExternalStorageDirectory();
if (dir != null) { if (dir != null) {
return Directory('${dir.path}/server_box'); return dir;
} }
// fallthrough to getApplicationDocumentsDirectory // fallthrough to getApplicationDocumentsDirectory
} }
return await getApplicationDocumentsDirectory(); return await getApplicationDocumentsDirectory();
} }
Future<Directory> get sftpDownloadDir async { Future<Directory> get sftpDir async {
final dir = Directory('${(await docDir).path}/sftp'); final dir = Directory('${(await docDir).path}/sftp');
return dir.create(recursive: true); return dir.create(recursive: true);
} }

View File

@@ -8,4 +8,8 @@ class DockerStore extends PersistentStore {
void setDockerHost(String id, String host) { void setDockerHost(String id, String host) {
box.put(id, host); box.put(id, host);
} }
Map<String, String> fetch() {
return box.toMap().cast<String, String>();
}
} }

View File

@@ -10,7 +10,8 @@
"auto": "Auto", "auto": "Auto",
"backDir": "Back", "backDir": "Back",
"backup": "Backup", "backup": "Backup",
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.\nRestoring will not overwrite existing data (except setting).", "backupAndRestore": "Backup and Restore",
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.\nRestoring will not overwrite existing data.",
"backupVersionNotMatch": "Backup version is not match.", "backupVersionNotMatch": "Backup version is not match.",
"cancel": "Cancel", "cancel": "Cancel",
"choose": "Choose", "choose": "Choose",
@@ -68,7 +69,6 @@
"httpFailedWithCode": "request failed, status code: {code}", "httpFailedWithCode": "request failed, status code: {code}",
"imagesList": "Images list", "imagesList": "Images list",
"import": "Import", "import": "Import",
"importAndExport": "Import and Export",
"inputDomainHere": "Input Domain here", "inputDomainHere": "Input Domain here",
"install": "install", "install": "install",
"installDockerWithUrl": "Please https://docs.docker.com/engine/install docker first.", "installDockerWithUrl": "Please https://docs.docker.com/engine/install docker first.",

View File

@@ -10,7 +10,8 @@
"auto": "自动", "auto": "自动",
"backDir": "返回上一级", "backDir": "返回上一级",
"backup": "备份", "backup": "备份",
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。\n除了设置项恢复的数据不会覆盖现有数据。", "backupAndRestore": "备份和恢复",
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。\n恢复的数据不会覆盖现有数据。",
"backupVersionNotMatch": "备份版本不匹配,无法恢复", "backupVersionNotMatch": "备份版本不匹配,无法恢复",
"cancel": "取消", "cancel": "取消",
"choose": "选择", "choose": "选择",
@@ -68,7 +69,6 @@
"httpFailedWithCode": "请求失败, 状态码: {code}", "httpFailedWithCode": "请求失败, 状态码: {code}",
"imagesList": "镜像列表", "imagesList": "镜像列表",
"import": "导入", "import": "导入",
"importAndExport": "导入或导出",
"inputDomainHere": "在这里输入域名", "inputDomainHere": "在这里输入域名",
"install": "安装", "install": "安装",
"installDockerWithUrl": "请先 https://docs.docker.com/engine/install docker", "installDockerWithUrl": "请先 https://docs.docker.com/engine/install docker",

View File

@@ -11,9 +11,9 @@ import '../../core/extension/colorx.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/ui.dart'; import '../../data/res/ui.dart';
import '../../data/store/docker.dart';
import '../../data/store/private_key.dart'; import '../../data/store/private_key.dart';
import '../../data/store/server.dart'; import '../../data/store/server.dart';
import '../../data/store/setting.dart';
import '../../data/store/snippet.dart'; import '../../data/store/snippet.dart';
import '../../locator.dart'; import '../../locator.dart';
@@ -22,10 +22,10 @@ const backupFormatVersion = 1;
class BackupPage extends StatelessWidget { class BackupPage extends StatelessWidget {
BackupPage({Key? key}) : super(key: key); BackupPage({Key? key}) : super(key: key);
final _setting = locator<SettingStore>();
final _server = locator<ServerStore>(); final _server = locator<ServerStore>();
final _snippet = locator<SnippetStore>(); final _snippet = locator<SnippetStore>();
final _privateKey = locator<PrivateKeyStore>(); final _privateKey = locator<PrivateKeyStore>();
final _dockerHosts = locator<DockerStore>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -33,7 +33,7 @@ class BackupPage extends StatelessWidget {
final s = S.of(context)!; final s = S.of(context)!;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(s.importAndExport, style: textSize18), title: Text(s.backupAndRestore, style: textSize18),
), ),
body: Center( body: Center(
child: Column( child: Column(
@@ -103,9 +103,7 @@ class BackupPage extends StatelessWidget {
_server.fetch(), _server.fetch(),
_snippet.fetch(), _snippet.fetch(),
_privateKey.fetch(), _privateKey.fetch(),
_setting.primaryColor.fetch() ?? Colors.pinkAccent.value, _dockerHosts.fetch(),
_setting.serverStatusUpdateInterval.fetch() ?? 2,
_setting.launchPage.fetch() ?? 0,
), ),
), ),
); );
@@ -194,10 +192,9 @@ class BackupPage extends StatelessWidget {
for (final s in backup.keys) { for (final s in backup.keys) {
_privateKey.put(s); _privateKey.put(s);
} }
_setting.primaryColor.put(backup.primaryColor); for (final k in backup.dockerHosts.keys) {
_setting.serverStatusUpdateInterval _dockerHosts.setDockerHost(k, backup.dockerHosts[k]!);
.put(backup.serverStatusUpdateInterval); }
_setting.launchPage.put(backup.launchPage);
Navigator.of(context).pop(); Navigator.of(context).pop();
showSnackBar(context, Text(s.restoreSuccess)); showSnackBar(context, Text(s.restoreSuccess));
}, },

View File

@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart'; import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/data/res/path.dart';
import '../../core/utils/misc.dart'; import '../../core/utils/misc.dart';
import '../../core/utils/platform.dart'; import '../../core/utils/platform.dart';
@@ -15,6 +14,7 @@ import '../../data/provider/app.dart';
import '../../data/provider/server.dart'; import '../../data/provider/server.dart';
import '../../data/res/build_data.dart'; import '../../data/res/build_data.dart';
import '../../data/res/color.dart'; import '../../data/res/color.dart';
import '../../data/res/path.dart';
import '../../data/res/tab.dart'; import '../../data/res/tab.dart';
import '../../data/res/ui.dart'; import '../../data/res/ui.dart';
import '../../data/store/setting.dart'; import '../../data/store/setting.dart';
@@ -61,6 +61,7 @@ class _SettingPageState extends State<SettingPage> {
_nightMode = _setting.themeMode.fetch()!; _nightMode = _setting.themeMode.fetch()!;
_updateInterval = _setting.serverStatusUpdateInterval.fetch()!.toDouble(); _updateInterval = _setting.serverStatusUpdateInterval.fetch()!.toDouble();
_maxRetryCount = _setting.maxRetryCount.fetch()!.toDouble(); _maxRetryCount = _setting.maxRetryCount.fetch()!.toDouble();
_selectedColorValue = _setting.primaryColor.fetch()!;
} }
@override @override
@@ -101,8 +102,8 @@ class _SettingPageState extends State<SettingPage> {
_buildThemeMode(), _buildThemeMode(),
_buildAppColorPreview(), _buildAppColorPreview(),
_buildLaunchPage(), _buildLaunchPage(),
_buildCheckUpdate(),
_buildFont(), _buildFont(),
_buildCheckUpdate(),
]; ];
if (isIOS) { if (isIOS) {
children.add(_buildPushToken()); children.add(_buildPushToken());

View File

@@ -29,7 +29,7 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
sftpDownloadDir.then((dir) { sftpDir.then((dir) {
_path = PathWithPrefix(dir.path); _path = PathWithPrefix(dir.path);
_prefixPath = '${dir.path}/'; _prefixPath = '${dir.path}/';
setState(() {}); setState(() {});

View File

@@ -302,7 +302,7 @@ class _SFTPPageState extends State<SFTPPage> {
final prePath = _status.path!.path; final prePath = _status.path!.path;
final remotePath = final remotePath =
prePath + (prePath.endsWith('/') ? '' : '/') + name.filename; prePath + (prePath.endsWith('/') ? '' : '/') + name.filename;
final local = '${(await sftpDownloadDir).path}$remotePath'; final local = '${(await sftpDir).path}$remotePath';
final pubKeyId = widget.spi.pubKeyId; final pubKeyId = widget.spi.pubKeyId;
locator<SftpProvider>().add( locator<SftpProvider>().add(