mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fix: sftp dl
This commit is contained in:
@@ -570,7 +570,7 @@ abstract class S {
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'request failed, status code: {code}'**
|
||||
String httpFailedWithCode(Object code, Object kode);
|
||||
String httpFailedWithCode(Object code);
|
||||
|
||||
/// No description provided for @image.
|
||||
///
|
||||
|
||||
@@ -255,7 +255,7 @@ class SDe extends S {
|
||||
String get host => 'Host';
|
||||
|
||||
@override
|
||||
String httpFailedWithCode(Object code, Object kode) {
|
||||
String httpFailedWithCode(Object code) {
|
||||
return 'Anfrage fehlgeschlagen, Statuscode: $code';
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ class SEn extends S {
|
||||
String get host => 'Host';
|
||||
|
||||
@override
|
||||
String httpFailedWithCode(Object code, Object kode) {
|
||||
String httpFailedWithCode(Object code) {
|
||||
return 'request failed, status code: $code';
|
||||
}
|
||||
|
||||
|
||||
@@ -255,8 +255,8 @@ class SId extends S {
|
||||
String get host => 'Host';
|
||||
|
||||
@override
|
||||
String httpFailedWithCode(Object code, Object kode) {
|
||||
return 'Permintaan gagal, kode status: $kode';
|
||||
String httpFailedWithCode(Object code) {
|
||||
return 'Permintaan gagal, kode status: $code';
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -255,7 +255,7 @@ class SZh extends S {
|
||||
String get host => '主机';
|
||||
|
||||
@override
|
||||
String httpFailedWithCode(Object code, Object kode) {
|
||||
String httpFailedWithCode(Object code) {
|
||||
return '请求失败, 状态码: $code';
|
||||
}
|
||||
|
||||
@@ -931,7 +931,7 @@ class SZhTw extends SZh {
|
||||
String get host => '主機';
|
||||
|
||||
@override
|
||||
String httpFailedWithCode(Object code, Object kode) {
|
||||
String httpFailedWithCode(Object code) {
|
||||
return '請求失敗, 狀態碼: $code';
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Especially thanks to <a href="https://github.com/TerminalStudio/dartssh2">dartss
|
||||
- [x] `Status` charts
|
||||
- [x] `Code editor`
|
||||
- [x] `Ping` and etc.
|
||||
- [x] Localization ( English, 简体中文, Deutsch, 繁體中文. [How to contribute?](#l10n-guide))
|
||||
- [x] Localization ( English, 简体中文, Deutsch, 繁體中文, Indonesian. [How to contribute?](#l10n-guide))
|
||||
- [x] Desktop support
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
- [x] 状态图表
|
||||
- [x] 代码编辑器
|
||||
- [x] `Ping` 和 更多
|
||||
- [x] 本地化 ( English, 简体中文, Deutsch, 繁體中文。 [如何贡献?](#l10n-guide))
|
||||
- [x] 本地化 ( English, 简体中文, Deutsch, 繁體中文, Indonesian。 [如何贡献?](#l10n-guide))
|
||||
- [x] 桌面端支持
|
||||
|
||||
|
||||
|
||||
@@ -470,7 +470,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -478,7 +478,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -602,7 +602,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -610,7 +610,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -628,7 +628,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -636,7 +636,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -657,7 +657,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -670,7 +670,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
@@ -696,7 +696,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -709,7 +709,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -732,7 +732,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -745,7 +745,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -12,7 +12,6 @@ class PersistentStore<E> {
|
||||
}
|
||||
|
||||
StoreProperty<T> property<T>(String key, {T? defaultValue}) {
|
||||
|
||||
return StoreProperty<T>(box, key, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,21 @@ enum GenSSHClientStatus {
|
||||
pwd,
|
||||
}
|
||||
|
||||
String getPrivateKey(String id) {
|
||||
final key = locator<PrivateKeyStore>().get(id);
|
||||
if (key == null) {
|
||||
throw SSHErr(
|
||||
type: SSHErrType.noPrivateKey,
|
||||
message: 'key [$id] not found',
|
||||
);
|
||||
}
|
||||
return key.privateKey;
|
||||
}
|
||||
|
||||
Future<SSHClient> genClient(
|
||||
ServerPrivateInfo spi, {
|
||||
void Function(GenSSHClientStatus)? onStatus,
|
||||
String? privateKey,
|
||||
}) async {
|
||||
onStatus?.call(GenSSHClientStatus.socket);
|
||||
late SSHSocket socket;
|
||||
@@ -66,17 +78,12 @@ Future<SSHClient> genClient(
|
||||
onPasswordRequest: () => spi.pwd,
|
||||
);
|
||||
}
|
||||
final key = locator<PrivateKeyStore>().get(spi.pubKeyId!);
|
||||
if (key == null) {
|
||||
throw SSHErr(
|
||||
type: SSHErrType.noPrivateKey,
|
||||
message: 'key [${spi.pubKeyId}] not found',
|
||||
);
|
||||
}
|
||||
privateKey ??= getPrivateKey(spi.pubKeyId!);
|
||||
|
||||
onStatus?.call(GenSSHClientStatus.key);
|
||||
return SSHClient(
|
||||
socket,
|
||||
username: spi.user,
|
||||
identities: await compute(loadIndentity, key.privateKey),
|
||||
identities: await compute(loadIndentity, privateKey),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
import 'dart:async';
|
||||
|
||||
import '../../../core/utils/server.dart';
|
||||
import '../server/server_private_info.dart';
|
||||
import 'worker.dart';
|
||||
|
||||
class SftpReqItem {
|
||||
class SftpReq {
|
||||
final ServerPrivateInfo spi;
|
||||
final String remotePath;
|
||||
final String localPath;
|
||||
final SftpReqType type;
|
||||
String? privateKey;
|
||||
|
||||
SftpReqItem(this.spi, this.remotePath, this.localPath);
|
||||
SftpReq(
|
||||
this.spi,
|
||||
this.remotePath,
|
||||
this.localPath,
|
||||
this.type,
|
||||
) {
|
||||
if (spi.pubKeyId != null) {
|
||||
privateKey = getPrivateKey(spi.pubKeyId!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum SftpReqType { download, upload }
|
||||
|
||||
class SftpReq {
|
||||
final SftpReqItem item;
|
||||
final String? privateKey;
|
||||
final SftpReqType type;
|
||||
|
||||
SftpReq({required this.item, this.privateKey, required this.type});
|
||||
}
|
||||
|
||||
class SftpReqStatus {
|
||||
final int id;
|
||||
final SftpReqItem item;
|
||||
final SftpReq req;
|
||||
final void Function() notifyListeners;
|
||||
late SftpWorker worker;
|
||||
final Completer? completer;
|
||||
|
||||
String get fileName => item.localPath.split('/').last;
|
||||
String get fileName => req.localPath.split('/').last;
|
||||
|
||||
// status of the download
|
||||
double? progress;
|
||||
@@ -38,17 +42,14 @@ class SftpReqStatus {
|
||||
Duration? spentTime;
|
||||
|
||||
SftpReqStatus({
|
||||
required this.item,
|
||||
required this.req,
|
||||
required this.notifyListeners,
|
||||
required SftpReqType type,
|
||||
this.completer,
|
||||
}) : id = DateTime.now().microsecondsSinceEpoch {
|
||||
worker = SftpWorker(
|
||||
onNotify: onNotify,
|
||||
item: item,
|
||||
type: type,
|
||||
);
|
||||
worker.init();
|
||||
req: req,
|
||||
)..init();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -79,6 +80,7 @@ class SftpReqStatus {
|
||||
spentTime = event;
|
||||
break;
|
||||
default:
|
||||
error = Exception('unknown event: $event');
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -6,20 +6,19 @@ import 'dart:typed_data';
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:easy_isolate/easy_isolate.dart';
|
||||
import 'package:toolbox/core/utils/misc.dart';
|
||||
import 'package:toolbox/core/utils/server.dart';
|
||||
|
||||
import 'req.dart';
|
||||
|
||||
class SftpWorker {
|
||||
final Function(Object event) onNotify;
|
||||
final SftpReqItem item;
|
||||
final SftpReqType type;
|
||||
final SftpReq req;
|
||||
|
||||
final worker = Worker();
|
||||
|
||||
SftpWorker({
|
||||
required this.onNotify,
|
||||
required this.item,
|
||||
required this.type,
|
||||
required this.req,
|
||||
});
|
||||
|
||||
void dispose() {
|
||||
@@ -35,7 +34,7 @@ class SftpWorker {
|
||||
isolateMessageHandler,
|
||||
errorHandler: print,
|
||||
);
|
||||
worker.sendMessage(SftpReq(item: item, type: type));
|
||||
worker.sendMessage(req);
|
||||
}
|
||||
|
||||
/// Handle the messages coming from the isolate
|
||||
@@ -69,29 +68,19 @@ Future<void> isolateMessageHandler(
|
||||
}
|
||||
|
||||
Future<void> _download(
|
||||
SftpReq data,
|
||||
SftpReq req,
|
||||
SendPort mainSendPort,
|
||||
SendErrorFunction sendError,
|
||||
) async {
|
||||
try {
|
||||
mainSendPort.send(SftpWorkerStatus.preparing);
|
||||
final watch = Stopwatch()..start();
|
||||
final item = data.item;
|
||||
final spi = item.spi;
|
||||
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
||||
SSHClient client;
|
||||
if (spi.pubKeyId == null) {
|
||||
client = SSHClient(socket,
|
||||
username: spi.user, onPasswordRequest: () => spi.pwd);
|
||||
} else {
|
||||
client = SSHClient(socket,
|
||||
username: spi.user, identities: SSHKeyPair.fromPem(data.privateKey!));
|
||||
}
|
||||
final client = await genClient(req.spi, privateKey: req.privateKey);
|
||||
mainSendPort.send(SftpWorkerStatus.sshConnectted);
|
||||
|
||||
final remotePath = item.remotePath;
|
||||
final localPath = item.localPath;
|
||||
await Directory(localPath.substring(0, item.localPath.lastIndexOf('/')))
|
||||
final remotePath = req.remotePath;
|
||||
final localPath = req.localPath;
|
||||
await Directory(localPath.substring(0, req.localPath.lastIndexOf('/')))
|
||||
.create(recursive: true);
|
||||
final local = File(localPath);
|
||||
if (await local.exists()) {
|
||||
@@ -104,7 +93,8 @@ Future<void> _download(
|
||||
mainSendPort.send(Exception('can not get file size'));
|
||||
return;
|
||||
}
|
||||
const defaultChunkSize = 1024 * 1024;
|
||||
// Read 10m each time
|
||||
const defaultChunkSize = 1024 * 1024 * 10;
|
||||
final chunkSize = size > defaultChunkSize ? defaultChunkSize : size;
|
||||
mainSendPort.send(size);
|
||||
mainSendPort.send(SftpWorkerStatus.downloading);
|
||||
@@ -125,29 +115,19 @@ Future<void> _download(
|
||||
}
|
||||
|
||||
Future<void> _upload(
|
||||
SftpReq data,
|
||||
SftpReq req,
|
||||
SendPort mainSendPort,
|
||||
SendErrorFunction sendError,
|
||||
) async {
|
||||
try {
|
||||
mainSendPort.send(SftpWorkerStatus.preparing);
|
||||
final watch = Stopwatch()..start();
|
||||
final item = data.item;
|
||||
final spi = item.spi;
|
||||
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
||||
SSHClient client;
|
||||
if (spi.pubKeyId == null) {
|
||||
client = SSHClient(socket,
|
||||
username: spi.user, onPasswordRequest: () => spi.pwd);
|
||||
} else {
|
||||
client = SSHClient(socket,
|
||||
username: spi.user, identities: SSHKeyPair.fromPem(data.privateKey!));
|
||||
}
|
||||
final client = await genClient(req.spi, privateKey: req.privateKey);
|
||||
mainSendPort.send(SftpWorkerStatus.sshConnectted);
|
||||
|
||||
final localPath = item.localPath;
|
||||
final localPath = req.localPath;
|
||||
final remotePath =
|
||||
item.remotePath + (getFileName(localPath) ?? 'srvbox_sftp_upload');
|
||||
req.remotePath + (getFileName(localPath) ?? 'srvbox_sftp_upload');
|
||||
final local = File(localPath);
|
||||
if (!await local.exists()) {
|
||||
mainSendPort.send(Exception('local file not exists'));
|
||||
|
||||
@@ -14,7 +14,7 @@ class SftpProvider extends ProviderBase {
|
||||
found = _status.where((e) => e.id == id);
|
||||
}
|
||||
if (fileName != null) {
|
||||
found = found.where((e) => e.item.localPath.split('/').last == fileName);
|
||||
found = found.where((e) => e.req.localPath.split('/').last == fileName);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -25,12 +25,11 @@ class SftpProvider extends ProviderBase {
|
||||
return found.first;
|
||||
}
|
||||
|
||||
void add(SftpReqItem item, SftpReqType type, {Completer? completer}) {
|
||||
void add(SftpReq req, {Completer? completer}) {
|
||||
_status.add(SftpReqStatus(
|
||||
item: item,
|
||||
notifyListeners: notifyListeners,
|
||||
type: type,
|
||||
completer: completer,
|
||||
req: req,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 389;
|
||||
static const int build = 395;
|
||||
static const String engine = "3.10.6";
|
||||
static const String buildAt = "2023-07-28 13:50:35.251988";
|
||||
static const int modifications = 17;
|
||||
static const String buildAt = "2023-07-28 17:28:52.039761";
|
||||
static const int modifications = 10;
|
||||
}
|
||||
|
||||
@@ -44,5 +44,3 @@ const centerSizedLoading = SizedBox(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
|
||||
const loadingIcon = IconButton(onPressed: null, icon: centerLoading);
|
||||
|
||||
@@ -5,6 +5,7 @@ const myGithub = 'https://github.com/lollipopkit';
|
||||
const appHelpUrl = '$myGithub/flutter_server_box#-help';
|
||||
|
||||
// Thanks
|
||||
// If you want to change the url, please open an issue.
|
||||
const thanksMap = {
|
||||
'its-tom': 'https://github.com/its-tom',
|
||||
'RainSunMe': 'https://github.com/RainSunMe',
|
||||
@@ -15,4 +16,5 @@ const thanksMap = {
|
||||
'Aeorq': 'https://github.com/Aeorq',
|
||||
'jaychoubaby': 'https://github.com/jaychoubaby',
|
||||
'allonmymind': 'https://github.com/allonmymind',
|
||||
'azkadev': 'https://github.com/azkadev'
|
||||
};
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"goto": "Pergi ke",
|
||||
"homeWidgetUrlConfig": "Konfigurasi URL Widget Rumah",
|
||||
"host": "Host",
|
||||
"httpFailedWithCode": "Permintaan gagal, kode status: {kode}",
|
||||
"httpFailedWithCode": "Permintaan gagal, kode status: {code}",
|
||||
"image": "Gambar",
|
||||
"imagesList": "Daftar gambar",
|
||||
"import": "Impor",
|
||||
|
||||
@@ -103,7 +103,9 @@ class _EditorPageState extends State<EditorPage> with AfterLayoutMixin {
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeTheme(
|
||||
data: CodeThemeData(styles: _codeTheme ?? (isDarkMode(context) ? monokaiTheme : a11yLightTheme)),
|
||||
data: CodeThemeData(
|
||||
styles: _codeTheme ??
|
||||
(isDarkMode(context) ? monokaiTheme : a11yLightTheme)),
|
||||
child: CodeField(
|
||||
focusNode: _focusNode,
|
||||
controller: _controller,
|
||||
|
||||
@@ -280,10 +280,12 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
locator<SftpProvider>().add(
|
||||
SftpReqItem(spi, remotePath, file.absolute.path),
|
||||
locator<SftpProvider>().add(SftpReq(
|
||||
spi,
|
||||
remotePath,
|
||||
file.absolute.path,
|
||||
SftpReqType.upload,
|
||||
);
|
||||
));
|
||||
showSnackBar(context, Text(_s.added2List));
|
||||
},
|
||||
),
|
||||
|
||||
@@ -79,7 +79,11 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
|
||||
Widget _buildItem(SftpReqStatus status) {
|
||||
if (status.error != null) {
|
||||
showSnackBar(context, Text(status.error.toString()));
|
||||
final err = status.error.toString();
|
||||
Future.delayed(
|
||||
const Duration(milliseconds: 377),
|
||||
() => showSnackBar(context, Text(err)),
|
||||
);
|
||||
status.error = null;
|
||||
}
|
||||
switch (status.status) {
|
||||
@@ -92,7 +96,7 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
status,
|
||||
str,
|
||||
trailing: IconButton(
|
||||
onPressed: () => shareFiles(context, [status.item.localPath]),
|
||||
onPressed: () => shareFiles(context, [status.req.localPath]),
|
||||
icon: const Icon(Icons.open_in_new),
|
||||
),
|
||||
);
|
||||
@@ -103,18 +107,35 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
return _wrapInCard(
|
||||
status,
|
||||
_s.downloadStatus(percentStr, size),
|
||||
trailing: CircularProgressIndicator(value: percent),
|
||||
trailing: SizedBox(
|
||||
height: 27,
|
||||
width: 27,
|
||||
child: CircularProgressIndicator(
|
||||
value: percent,
|
||||
),
|
||||
)
|
||||
);
|
||||
case SftpWorkerStatus.preparing:
|
||||
return _wrapInCard(status, _s.sftpDlPrepare, trailing: loadingIcon);
|
||||
return _wrapInCard(
|
||||
status,
|
||||
_s.sftpDlPrepare,
|
||||
trailing: _loading,
|
||||
);
|
||||
case SftpWorkerStatus.sshConnectted:
|
||||
return _wrapInCard(status, _s.sftpSSHConnected, trailing: loadingIcon);
|
||||
return _wrapInCard(
|
||||
status,
|
||||
_s.sftpSSHConnected,
|
||||
trailing: _loading,
|
||||
);
|
||||
default:
|
||||
return _wrapInCard(
|
||||
status,
|
||||
_s.unknown,
|
||||
trailing: const Icon(Icons.error, size: 40),
|
||||
trailing: const Icon(Icons.error),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const _loading =
|
||||
SizedBox(height: 27, width: 27, child: CircularProgressIndicator());
|
||||
|
||||
@@ -174,8 +174,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
return;
|
||||
}
|
||||
_sftp.add(
|
||||
SftpReqItem(widget.spi, remotePath, path),
|
||||
SftpReq(
|
||||
widget.spi,
|
||||
remotePath,
|
||||
path,
|
||||
SftpReqType.upload,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.upload_file));
|
||||
@@ -350,8 +354,13 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final remotePath = _getRemotePath(name);
|
||||
final localPath = await _getLocalPath(remotePath);
|
||||
final completer = Completer();
|
||||
final req = SftpReqItem(widget.spi, remotePath, localPath);
|
||||
_sftp.add(req, SftpReqType.download, completer: completer);
|
||||
final req = SftpReq(
|
||||
widget.spi,
|
||||
remotePath,
|
||||
localPath,
|
||||
SftpReqType.download,
|
||||
);
|
||||
_sftp.add(req, completer: completer);
|
||||
showRoundDialog(context: context, child: centerSizedLoading);
|
||||
await completer.future;
|
||||
context.pop();
|
||||
@@ -361,7 +370,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
'SFTP edit',
|
||||
).go<String>(context);
|
||||
if (result != null) {
|
||||
_sftp.add(req, SftpReqType.upload);
|
||||
_sftp.add(SftpReq(req.spi, remotePath, localPath, SftpReqType.upload));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,12 +390,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final remotePath = _getRemotePath(name);
|
||||
|
||||
_sftp.add(
|
||||
SftpReqItem(
|
||||
SftpReq(
|
||||
widget.spi,
|
||||
remotePath,
|
||||
await _getLocalPath(remotePath),
|
||||
),
|
||||
SftpReqType.download,
|
||||
),
|
||||
);
|
||||
|
||||
context.pop();
|
||||
|
||||
@@ -475,9 +475,9 @@
|
||||
baseConfigurationReference = C1C758C41C4E208965A68933 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -490,9 +490,9 @@
|
||||
baseConfigurationReference = 15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -505,9 +505,9 @@
|
||||
baseConfigurationReference = 7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 389;
|
||||
CURRENT_PROJECT_VERSION = 395;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.389;
|
||||
MARKETING_VERSION = 1.0.395;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
Reference in New Issue
Block a user