mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
#144 new: sftp decompress
This commit is contained in:
@@ -332,6 +332,12 @@ abstract class S {
|
||||
/// **'Decode'**
|
||||
String get decode;
|
||||
|
||||
/// No description provided for @decompress.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Decompress'**
|
||||
String get decompress;
|
||||
|
||||
/// No description provided for @delete.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -121,6 +121,9 @@ class SDe extends S {
|
||||
@override
|
||||
String get decode => 'Decode';
|
||||
|
||||
@override
|
||||
String get decompress => 'Dekomprimieren';
|
||||
|
||||
@override
|
||||
String get delete => 'Löschen';
|
||||
|
||||
|
||||
@@ -121,6 +121,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get decode => 'Decode';
|
||||
|
||||
@override
|
||||
String get decompress => 'Decompress';
|
||||
|
||||
@override
|
||||
String get delete => 'Delete';
|
||||
|
||||
|
||||
@@ -121,6 +121,9 @@ class SId extends S {
|
||||
@override
|
||||
String get decode => 'Membaca sandi';
|
||||
|
||||
@override
|
||||
String get decompress => 'Dekompresi';
|
||||
|
||||
@override
|
||||
String get delete => 'Menghapus';
|
||||
|
||||
|
||||
@@ -121,6 +121,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get decode => '解码';
|
||||
|
||||
@override
|
||||
String get decompress => '解压缩';
|
||||
|
||||
@override
|
||||
String get delete => '删除';
|
||||
|
||||
@@ -835,6 +838,9 @@ class SZhTw extends SZh {
|
||||
@override
|
||||
String get decode => '解碼';
|
||||
|
||||
@override
|
||||
String get decompress => '解壓縮';
|
||||
|
||||
@override
|
||||
String get delete => '刪除';
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ class SftpBrowserStatus {
|
||||
List<SftpName>? files;
|
||||
AbsolutePath? path;
|
||||
SftpClient? client;
|
||||
bool isBusy = false;
|
||||
|
||||
SftpBrowserStatus();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 498;
|
||||
static const int build = 499;
|
||||
static const String engine = "3.13.0";
|
||||
static const String buildAt = "2023-08-23 21:54:10.937955";
|
||||
static const int modifications = 2;
|
||||
static const String buildAt = "2023-08-25 18:04:51.443337";
|
||||
static const int modifications = 4;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"dark": "Dunkel",
|
||||
"debug": "Debug",
|
||||
"decode": "Decode",
|
||||
"decompress": "Dekomprimieren",
|
||||
"delete": "Löschen",
|
||||
"deleteServers": "Batch-Löschung von Servern",
|
||||
"disabled": "Behinderte",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"dark": "Dark",
|
||||
"debug": "Debug",
|
||||
"decode": "Decode",
|
||||
"decompress": "Decompress",
|
||||
"delete": "Delete",
|
||||
"deleteServers": "Batch delete servers",
|
||||
"disabled": "Disabled",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"dark": "Gelap",
|
||||
"debug": "Debug",
|
||||
"decode": "Membaca sandi",
|
||||
"decompress": "Dekompresi",
|
||||
"delete": "Menghapus",
|
||||
"deleteServers": "Penghapusan server secara batch",
|
||||
"disabled": "Dengan disabilitas",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"dark": "暗",
|
||||
"debug": "调试",
|
||||
"decode": "解码",
|
||||
"decompress": "解压缩",
|
||||
"delete": "删除",
|
||||
"deleteServers": "批量删除服务器",
|
||||
"disabled": "已禁用",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"dark": "暗",
|
||||
"debug": "調試",
|
||||
"decode": "解碼",
|
||||
"decompress": "解壓縮",
|
||||
"delete": "刪除",
|
||||
"deleteServers": "批量刪除服務器",
|
||||
"disabled": "已禁用",
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../../core/extension/numx.dart';
|
||||
import '../../../core/extension/stringx.dart';
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/misc.dart';
|
||||
import '../../../core/utils/platform.dart' hide pathJoin;
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/server/server_private_info.dart';
|
||||
import '../../../data/model/sftp/absolute_path.dart';
|
||||
@@ -130,6 +131,7 @@ class _SftpPageState extends State<SftpPage> {
|
||||
_buildGotoBtn(),
|
||||
_buildUploadBtn(),
|
||||
];
|
||||
if (isDesktop) children.add(_buildRefreshBtn());
|
||||
return SafeArea(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.fromLTRB(11, 7, 11, 11),
|
||||
@@ -256,11 +258,14 @@ class _SftpPageState extends State<SftpPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFileView() {
|
||||
if (_status.isBusy) {
|
||||
return centerLoading;
|
||||
Widget _buildRefreshBtn() {
|
||||
return IconButton(
|
||||
onPressed: () => _listDir(),
|
||||
icon: const Icon(Icons.refresh),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFileView() {
|
||||
if (_status.files == null) {
|
||||
final p_ = widget.initPath ?? '/';
|
||||
_status.path = AbsolutePath(p_);
|
||||
@@ -341,6 +346,11 @@ class _SftpPageState extends State<SftpPage> {
|
||||
title: Text(_s.download),
|
||||
onTap: () => _download(context, file),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.folder_zip),
|
||||
title: Text(_s.decompress),
|
||||
onTap: () => _decompress(context, file),
|
||||
),
|
||||
]);
|
||||
}
|
||||
showRoundDialog(
|
||||
@@ -596,6 +606,30 @@ class _SftpPageState extends State<SftpPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _decompress(BuildContext context, SftpName name) async {
|
||||
context.pop();
|
||||
final absPath = _getRemotePath(name);
|
||||
final cmd = _getDecompressCmd(absPath);
|
||||
if (cmd == null) {
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.error),
|
||||
child: Text('Unsupport file: ${name.filename}'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
return;
|
||||
}
|
||||
showLoadingDialog(context);
|
||||
await _client?.run(cmd);
|
||||
context.pop();
|
||||
_listDir();
|
||||
}
|
||||
|
||||
String _getRemotePath(SftpName name) {
|
||||
final prePath = _status.path!.path;
|
||||
return pathJoin(prePath, name.filename);
|
||||
@@ -607,10 +641,7 @@ class _SftpPageState extends State<SftpPage> {
|
||||
|
||||
/// Only return true if the path is changed
|
||||
Future<bool> _listDir({String? path, SSHClient? client}) async {
|
||||
if (_status.isBusy) {
|
||||
return false;
|
||||
}
|
||||
_status.isBusy = true;
|
||||
showLoadingDialog(context);
|
||||
if (client != null) {
|
||||
final sftpc = await client.sftp();
|
||||
_status.client = sftpc;
|
||||
@@ -637,12 +668,13 @@ class _SftpPageState extends State<SftpPage> {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_status.files = fs;
|
||||
_status.isBusy = false;
|
||||
});
|
||||
context.pop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (e, trace) {
|
||||
context.pop();
|
||||
_logger.warning('list dir failed', e, trace);
|
||||
await _backward();
|
||||
Future.delayed(
|
||||
@@ -669,3 +701,60 @@ class _SftpPageState extends State<SftpPage> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String? _getDecompressCmd(String filename) {
|
||||
for (final ext in _extCmdMap.keys) {
|
||||
if (filename.endsWith('.$ext')) {
|
||||
return _extCmdMap[ext]?.replaceAll('FILE', '"$filename"');
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Translate from
|
||||
/// https://github.com/ohmyzsh/ohmyzsh/blob/03a0d5bbaedc732436b5c67b166cde954817cc2f/plugins/extract/extract.plugin.zsh
|
||||
const _extCmdMap = {
|
||||
'tar.gz': 'tar zxvf FILE',
|
||||
'tgz': 'tar zxvf FILE',
|
||||
'tar.bz2': 'tar jxvf FILE',
|
||||
'tbz2': 'tar jxvf FILE',
|
||||
'tar.xz': 'tar --xz -xvf FILE',
|
||||
'txz': 'tar --xz -xvf FILE',
|
||||
'tar.lzma': 'tar --lzma -xvf FILE',
|
||||
'tlz': 'tar --lzma -xvf FILE',
|
||||
'tar.zst': 'tar --zstd -xvf FILE',
|
||||
'tzst': 'tar --zstd -xvf FILE',
|
||||
'tar': 'tar xvf FILE',
|
||||
'tar.lz': 'tar xvf FILE',
|
||||
'tar.lz4': 'lz4 -c -d FILE | tar xvf - ',
|
||||
'gz': 'gunzip FILE',
|
||||
'bz2': 'bunzip2 FILE',
|
||||
'xz': 'unxz FILE',
|
||||
'lzma': 'unlzma FILE',
|
||||
'z': 'uncompress FILE',
|
||||
'zip': 'unzip FILE',
|
||||
'war': 'unzip FILE',
|
||||
'jar': 'unzip FILE',
|
||||
'ear': 'unzip FILE',
|
||||
'sublime-package': 'unzip FILE',
|
||||
'ipa': 'unzip FILE',
|
||||
'ipsw': 'unzip FILE',
|
||||
'apk': 'unzip FILE',
|
||||
'xpi': 'unzip FILE',
|
||||
'aar': 'unzip FILE',
|
||||
'whl': 'unzip FILE',
|
||||
'rar': 'unrar x -ad FILE',
|
||||
'rpm': 'rpm2cpio FILE | cpio --quiet -id',
|
||||
'7z': '7za x FILE',
|
||||
'deb': 'mkdir -p "control" "data"'
|
||||
'ar vx FILE > /dev/null'
|
||||
'cd control; extract ../control.tar.*'
|
||||
'cd ../data; extract ../data.tar.*'
|
||||
'cd ..; rm *.tar.* debian-binary',
|
||||
'zst': 'unzstd FILE',
|
||||
'cab': 'cabextract FILE',
|
||||
'exe': 'cabextract FILE',
|
||||
'cpio': 'cpio -idmvF FILE',
|
||||
'obscpio': 'cpio -idmvF FILE',
|
||||
'zpaq': 'zpaq x FILE',
|
||||
};
|
||||
|
||||
@@ -474,9 +474,9 @@
|
||||
baseConfigurationReference = C1C758C41C4E208965A68933 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
CURRENT_PROJECT_VERSION = 499;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
MARKETING_VERSION = 1.0.499;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -489,9 +489,9 @@
|
||||
baseConfigurationReference = 15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
CURRENT_PROJECT_VERSION = 499;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
MARKETING_VERSION = 1.0.499;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -504,9 +504,9 @@
|
||||
baseConfigurationReference = 7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
CURRENT_PROJECT_VERSION = 499;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
MARKETING_VERSION = 1.0.499;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
Reference in New Issue
Block a user