Remove SFTP download

This commit is contained in:
Junyuan Feng
2022-04-06 13:23:54 +08:00
parent f8201f9542
commit 00cfd0f88d
8 changed files with 144 additions and 136 deletions

View File

@@ -43,9 +43,9 @@ SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
flutter_icmp_ping: 07e508847df7fa9262d050bb0b203de074bbe517 flutter_icmp_ping: 07e508847df7fa9262d050bb0b203de074bbe517
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5 path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114 r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114
url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

View File

@@ -0,0 +1,15 @@
extension NumX on num {
String get convertBytes {
const suffix = ['B', 'KB', 'MB', 'GB', 'TB'];
double value = toDouble();
int squareTimes = 0;
for (; value / 1024 > 1 && squareTimes < suffix.length - 1; squareTimes++) {
value /= 1024;
}
var finalValue = value.toStringAsFixed(1);
if (finalValue.endsWith('.0')) {
finalValue = finalValue.replaceFirst('.0', '');
}
return '$finalValue ${suffix[squareTimes]}';
}
}

12
lib/core/path.dart Normal file
View File

@@ -0,0 +1,12 @@
import 'dart:io';
import 'package:path_provider/path_provider.dart';
Future<Directory> get sftpDownloadDir async {
final docDir = await getApplicationDocumentsDirectory();
final dir = Directory('${docDir.path}/sftp');
if (!dir.existsSync()) {
dir.createSync();
}
return dir;
}

View File

@@ -1,4 +1,4 @@
import 'dart:math'; import 'package:toolbox/core/extension/numx.dart';
class NetSpeedPart { class NetSpeedPart {
String device; String device;
@@ -27,45 +27,31 @@ class NetSpeed {
String speedIn({String? device}) { String speedIn({String? device}) {
if (old[0].device == '' || now[0].device == '') return '0kb/s'; if (old[0].device == '' || now[0].device == '') return '0kb/s';
int idx = 0; final idx = deviceIdx(device);
if (device != null) {
for (var item in now) {
if (item.device == device) {
idx = now.indexOf(item);
break;
}
}
}
final speedInBytesPerSecond = final speedInBytesPerSecond =
(now[idx].bytesIn - old[idx].bytesIn) / timeDiff; (now[idx].bytesIn - old[idx].bytesIn) / timeDiff;
int squareTimes = 0; return buildStandardOutput(speedInBytesPerSecond);
for (; speedInBytesPerSecond / pow(1024, squareTimes) > 1024;) {
if (squareTimes >= suffixs.length - 1) break;
squareTimes++;
}
return '${(speedInBytesPerSecond / pow(1024, squareTimes)).toStringAsFixed(1)} ${suffixs[squareTimes]}';
} }
String speedOut({String? device}) { String speedOut({String? device}) {
if (old[0].device == '' || now[0].device == '') return '0kb/s'; if (old[0].device == '' || now[0].device == '') return '0kb/s';
int idx = 0; final idx = deviceIdx(device);
final speedInBytesPerSecond =
(now[idx].bytesOut - old[idx].bytesOut) / timeDiff;
return buildStandardOutput(speedInBytesPerSecond);
}
int deviceIdx(String? device) {
if (device != null) { if (device != null) {
for (var item in now) { for (var item in now) {
if (item.device == device) { if (item.device == device) {
idx = now.indexOf(item); return now.indexOf(item);
break;
} }
} }
} }
final speedInBytesPerSecond = return 0;
(now[idx].bytesOut - old[idx].bytesOut) / timeDiff;
int squareTimes = 0;
for (; speedInBytesPerSecond / pow(1024, squareTimes) > 1024;) {
if (squareTimes >= suffixs.length - 1) break;
squareTimes++;
} }
return '${(speedInBytesPerSecond / pow(1024, squareTimes)).toStringAsFixed(1)} ${suffixs[squareTimes]}';
}
}
const suffixs = ['b/s', 'kb/s', 'mb/s', 'gb/s']; String buildStandardOutput(double speed) =>
'${speed.convertBytes.toLowerCase()}/s';
}

View File

@@ -2,9 +2,9 @@
class BuildData { class BuildData {
static const String name = "ServerBox"; static const String name = "ServerBox";
static const int build = 108; static const int build = 109;
static const String engine = static const String engine =
"Flutter 2.10.3 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 7e9793dee1 (8 days ago) • 2022-03-02 11:23:12 -0600\nEngine • revision bd539267b4\nTools • Dart 2.16.1 • DevTools 2.9.2\n"; "Flutter 2.10.4 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision c860cba910 (12 days ago) • 2022-03-25 00:23:12 -0500\nEngine • revision 57d3bac3dd\nTools • Dart 2.16.2 • DevTools 2.9.2\n";
static const String buildAt = "2022-03-10 15:25:32.032568"; static const String buildAt = "2022-04-06 13:00:26.954649";
static const int modifications = 0; static const int modifications = 7;
} }

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/numx.dart';
import 'package:toolbox/data/model/server/net_speed.dart'; import 'package:toolbox/data/model/server/net_speed.dart';
import 'package:toolbox/data/model/server/server.dart'; import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/model/server/server_status.dart'; import 'package:toolbox/data/model/server/server_status.dart';
@@ -177,24 +178,11 @@ class _ServerDetailPageState extends State<ServerDetailPage>
)); ));
} }
String convertMB(int mb) {
const suffix = ['MB', 'GB', 'TB'];
double value = mb.toDouble();
int squareTimes = 0;
for (; value / 1024 > 1 && squareTimes < 3; squareTimes++) {
value /= 1024;
}
var finalValue = value.toStringAsFixed(1);
if (finalValue.endsWith('.0')) {
finalValue = finalValue.replaceFirst('.0', '');
}
return '$finalValue ${suffix[squareTimes]}';
}
Widget _buildMemView(ServerStatus ss) { Widget _buildMemView(ServerStatus ss) {
final pColor = primaryColor; final pColor = primaryColor;
final used = ss.memory.used / ss.memory.total; final used = ss.memory.used / ss.memory.total;
final width = _media.size.width - 17 * 2 - 17 * 2; final width = _media.size.width - 17 * 2 - 17 * 2;
const mb = 1024 * 1024;
return RoundRectCard(Padding( return RoundRectCard(Padding(
padding: roundRectCardPadding, padding: roundRectCardPadding,
child: SizedBox( child: SizedBox(
@@ -206,10 +194,12 @@ class _ServerDetailPageState extends State<ServerDetailPage>
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
_buildMemExplain(convertMB(ss.memory.used), pColor),
_buildMemExplain( _buildMemExplain(
convertMB(ss.memory.cache), pColor.withAlpha(77)), (ss.memory.used * mb).convertBytes, pColor),
_buildMemExplain(convertMB(ss.memory.total - ss.memory.used), _buildMemExplain((ss.memory.cache * mb).convertBytes,
pColor.withAlpha(77)),
_buildMemExplain(
((ss.memory.total - ss.memory.used) * mb).convertBytes,
progressColor.resolve(context)) progressColor.resolve(context))
], ],
), ),

View File

@@ -1,8 +1,6 @@
import 'dart:io';
import 'package:dartssh2/dartssh2.dart'; import 'package:dartssh2/dartssh2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'; import 'package:toolbox/core/extension/numx.dart';
import 'package:toolbox/core/utils.dart'; import 'package:toolbox/core/utils.dart';
import 'package:toolbox/data/model/server/server_connection_state.dart'; import 'package:toolbox/data/model/server/server_connection_state.dart';
import 'package:toolbox/data/model/server/server_private_info.dart'; import 'package:toolbox/data/model/server/server_private_info.dart';
@@ -10,7 +8,6 @@ import 'package:toolbox/data/model/sftp/absolute_path.dart';
import 'package:toolbox/data/model/sftp/sftp_side_status.dart'; import 'package:toolbox/data/model/sftp/sftp_side_status.dart';
import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/data/provider/server.dart';
import 'package:toolbox/locator.dart'; import 'package:toolbox/locator.dart';
import 'package:toolbox/view/widget/center_loading.dart';
import 'package:toolbox/view/widget/fade_in.dart'; import 'package:toolbox/view/widget/fade_in.dart';
import 'package:toolbox/view/widget/two_line_text.dart'; import 'package:toolbox/view/widget/two_line_text.dart';
@@ -96,7 +93,7 @@ class _SFTPPageState extends State<SFTPPage> {
return _buildDestSelector(); return _buildDestSelector();
} }
final file = _status.files![index - 1]; final file = _status.files![index - 1];
final isDir = file.attr.mode?.isDirectory ?? true; final isDir = file.attr.isDirectory;
return ListTile( return ListTile(
leading: Icon(isDir ? Icons.folder : Icons.insert_drive_file), leading: Icon(isDir ? Icons.folder : Icons.insert_drive_file),
title: Text(file.filename), title: Text(file.filename),
@@ -108,7 +105,7 @@ class _SFTPPageState extends State<SFTPPage> {
style: const TextStyle(color: Colors.grey), style: const TextStyle(color: Colors.grey),
), ),
subtitle: subtitle:
isDir ? null : Text(convertBytes(file.attr.size ?? 0)), isDir ? null : Text((file.attr.size ?? 0).convertBytes),
onTap: () { onTap: () {
if (isDir) { if (isDir) {
_status.path?.update(file.filename); _status.path?.update(file.filename);
@@ -148,11 +145,11 @@ class _SFTPPageState extends State<SFTPPage> {
title: const Text('Rename'), title: const Text('Rename'),
onTap: () => rename(context, file), onTap: () => rename(context, file),
), ),
ListTile( // ListTile(
leading: const Icon(Icons.download), // leading: const Icon(Icons.download),
title: const Text('Download'), // title: const Text('Download'),
onTap: () => download(context, file), // onTap: () => download(context, file),
) // )
], ],
), ),
[ [
@@ -162,41 +159,63 @@ class _SFTPPageState extends State<SFTPPage> {
]); ]);
} }
void download(BuildContext context, SftpName name) { // void download(BuildContext context, SftpName name) {
showRoundDialog( // showRoundDialog(
context, 'Download', Text('Download ${name.filename} to local?'), [ // context, 'Download', Text('Download ${name.filename} to local?'), [
TextButton( // TextButton(
onPressed: () => Navigator.of(context).pop(), // onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel')), // child: const Text('Cancel')),
TextButton( // TextButton(
onPressed: () async { // onPressed: () async {
var result = ''; // var result = '';
try { // try {
Navigator.of(context).pop(); // Navigator.of(context).pop();
showRoundDialog(context, name.filename, centerSizedLoading, [], // showRoundDialog(
barrierDismiss: false); // context,
final path = await getApplicationDocumentsDirectory(); // name.filename,
final localFile = File('${path.path}/${name.filename}'); // const Text('Downloading...\nKepp this app in the foreground.',
final remotePath = _status.path!.path + '/' + name.filename; // textAlign: TextAlign.center),
final file = await _status.client?.open(remotePath); // [],
localFile.writeAsBytes(await file!.readBytes()); // barrierDismiss: false);
Navigator.of(context).pop(); // final path = await sftpDownloadDir;
} catch (e) { // final local = File('${path.path}/${name.filename}');
result = e.toString(); // if (await local.exists()) {
} finally { // await local.delete();
if (result.isEmpty) { // }
result = 'Donwloaded successfully.';
} // final localFile =
showRoundDialog(context, 'Result', Text(result), [ // await local.open(mode: FileMode.writeOnlyAppend);
TextButton( // final remotePath = _status.path!.path + '/' + name.filename;
onPressed: () => Navigator.of(context).pop(), // final file = await _status.client!.open(remotePath);
child: const Text('OK')) // final size = (await file.stat()).size;
]); // if (size == null) {
} // throw Exception('can not get file size');
}, // }
child: const Text('Download'))
]); // const chunkSize = 1024 * 128;
} // for (var i = 0; i < size; i += chunkSize) {
// final data = file.read(length: chunkSize);
// await for (var item in data) {
// localFile.writeFrom(item);
// }
// }
// } catch (e) {
// result = e.toString();
// } finally {
// Navigator.of(context).pop();
// if (result.isEmpty) {
// result = 'Donwloaded successfully.';
// }
// showRoundDialog(context, 'Result', Text(result), [
// TextButton(
// onPressed: () => Navigator.of(context).pop(),
// child: const Text('OK'))
// ]);
// }
// },
// child: const Text('Download'))
// ]);
// }
void delete(BuildContext context, SftpName file) { void delete(BuildContext context, SftpName file) {
Navigator.of(context).pop(); Navigator.of(context).pop();
@@ -296,20 +315,6 @@ class _SFTPPageState extends State<SFTPPage> {
]); ]);
} }
String convertBytes(int bytes) {
const suffix = ['B', 'KB', 'MB', 'GB', 'TB'];
double value = bytes.toDouble();
int squareTimes = 0;
for (; value / 1024 > 1 && squareTimes < 3; squareTimes++) {
value /= 1024;
}
var finalValue = value.toStringAsFixed(1);
if (finalValue.endsWith('.0')) {
finalValue = finalValue.replaceFirst('.0', '');
}
return '$finalValue ${suffix[squareTimes]}';
}
Future<void> listDir({String? path, SSHClient? client}) async { Future<void> listDir({String? path, SSHClient? client}) async {
if (_status.isBusy) { if (_status.isBusy) {
return; return;

View File

@@ -14,7 +14,7 @@ packages:
name: archive name: archive
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.11" version: "3.3.0"
args: args:
dependency: transitive dependency: transitive
description: description:
@@ -99,7 +99,7 @@ packages:
description: description:
path: "." path: "."
ref: master ref: master
resolved-ref: dcb1f6084242a7b4b8e4edd4b180a42ad7f595ca resolved-ref: fb568d2e50714f65f85b822c343bb53f129b9f6f
url: "https://github.com/Countly/countly-sdk-flutter-bridge.git" url: "https://github.com/Countly/countly-sdk-flutter-bridge.git"
source: git source: git
version: "20.11.4" version: "20.11.4"
@@ -123,7 +123,7 @@ packages:
name: dart_ping name: dart_ping
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.1" version: "6.1.2"
dart_ping_ios: dart_ping_ios:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -137,21 +137,21 @@ packages:
name: dartssh2 name: dartssh2
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.4" version: "2.6.0"
dio: dio:
dependency: "direct main" dependency: "direct main"
description: description:
name: dio name: dio
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.4" version: "4.0.6"
dropdown_button2: dropdown_button2:
dependency: "direct main" dependency: "direct main"
description: description:
name: dropdown_button2 name: dropdown_button2
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.1" version: "1.2.5"
extended_image: extended_image:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -165,7 +165,7 @@ packages:
name: extended_image_library name: extended_image_library
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.2" version: "3.1.4"
fading_edge_scrollview: fading_edge_scrollview:
dependency: transitive dependency: transitive
description: description:
@@ -205,7 +205,7 @@ packages:
name: flutter_advanced_drawer name: flutter_advanced_drawer
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.2"
flutter_icmp_ping: flutter_icmp_ping:
dependency: transitive dependency: transitive
description: description:
@@ -264,7 +264,7 @@ packages:
name: hive name: hive
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" version: "2.1.0"
hive_flutter: hive_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -299,7 +299,7 @@ packages:
name: image name: image
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.1" version: "3.1.3"
js: js:
dependency: transitive dependency: transitive
description: description:
@@ -327,7 +327,7 @@ packages:
name: marquee name: marquee
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.0" version: "2.2.1"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -383,14 +383,14 @@ packages:
name: path_provider_android name: path_provider_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.11" version: "2.0.12"
path_provider_ios: path_provider_ios:
dependency: transitive dependency: transitive
description: description:
name: path_provider_ios name: path_provider_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.7" version: "2.0.8"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@@ -460,7 +460,7 @@ packages:
name: pointycastle name: pointycastle
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.5.0" version: "3.5.2"
process: process:
dependency: transitive dependency: transitive
description: description:
@@ -488,7 +488,7 @@ packages:
name: r_upgrade name: r_upgrade
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.7+2" version: "0.3.7+3"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@@ -556,35 +556,35 @@ packages:
name: url_launcher name: url_launcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.18" version: "6.0.20"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.14" version: "6.0.15"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.14" version: "6.0.15"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.3" version: "3.0.0"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.3" version: "3.0.0"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -598,14 +598,14 @@ packages:
name: url_launcher_web name: url_launcher_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.6" version: "2.0.9"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "3.0.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@@ -619,7 +619,7 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.11" version: "2.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@@ -643,4 +643,4 @@ packages:
version: "3.1.0" version: "3.1.0"
sdks: sdks:
dart: ">=2.15.1 <3.0.0" dart: ">=2.15.1 <3.0.0"
flutter: ">=2.5.0" flutter: ">=2.10.0"