From 195ddd2bccca78be40b6e2a23b32e06e57ebc2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?lollipopkit=F0=9F=8F=B3=EF=B8=8F=E2=80=8D=E2=9A=A7?= =?UTF-8?q?=EF=B8=8F?= <10864310+lollipopkit@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:27:22 +0800 Subject: [PATCH] refactor: `SSHClientX.exec` --- ios/Runner.xcodeproj/project.pbxproj | 36 ++-- lib/core/extension/ssh_client.dart | 165 ++++++------------ lib/core/utils/server.dart | 4 +- .../model/server/server_private_info.dart | 23 +-- .../model/server/server_private_info.g.dart | 2 +- lib/data/provider/server.dart | 36 ++-- lib/data/provider/systemd.dart | 39 ++--- lib/data/res/build_data.dart | 7 +- lib/view/page/backup.dart | 5 +- lib/view/page/private_key/edit.dart | 2 +- lib/view/page/server/edit.dart | 2 +- lib/view/page/storage/sftp.dart | 20 +-- lib/view/page/systemd.dart | 9 +- macos/Runner.xcodeproj/project.pbxproj | 12 +- pubspec.lock | 8 +- pubspec.yaml | 6 +- 16 files changed, 155 insertions(+), 221 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 88a5a11e..6afead88 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -690,7 +690,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -700,7 +700,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -826,7 +826,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -836,7 +836,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -854,7 +854,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -864,7 +864,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -885,7 +885,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -898,7 +898,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; @@ -924,7 +924,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -937,7 +937,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -960,7 +960,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -973,7 +973,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -996,7 +996,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_PREVIEWS = YES; @@ -1008,7 +1008,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; @@ -1037,7 +1037,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_PREVIEWS = YES; @@ -1049,7 +1049,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_NAME = ServerBox; @@ -1075,7 +1075,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_PREVIEWS = YES; @@ -1087,7 +1087,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_NAME = ServerBox; diff --git a/lib/core/extension/ssh_client.dart b/lib/core/extension/ssh_client.dart index eef9c48e..e3ad656f 100644 --- a/lib/core/extension/ssh_client.dart +++ b/lib/core/extension/ssh_client.dart @@ -13,65 +13,66 @@ typedef OnStdin = void Function(SSHSession session); typedef PwdRequestFunc = Future Function(String? user); extension SSHClientX on SSHClient { - /// TODO: delete [exec] - Future exec( - String cmd, { - OnStdout? onStderr, + Future<(SSHSession, String)> exec( + OnStdin onStdin, { + String? entry, + SSHPtyConfig? pty, OnStdout? onStdout, - OnStdin? stdin, - bool redirectToBash = false, // not working yet. do not use + OnStdout? onStderr, + bool stdout = true, + bool stderr = true, + Map? env, }) async { - final session = await execute(redirectToBash ? 'head -1 | bash' : cmd); - - if (redirectToBash) { - session.stdin.add('$cmd\n'.uint8List); - } + final session = await execute( + entry ?? 'cat | sh', + pty: pty, + environment: env, + ); + final result = BytesBuilder(copy: false); final stdoutDone = Completer(); final stderrDone = Completer(); - if (onStdout != null) { - session.stdout.listen( - (e) => onStdout(e.string, session), - onDone: stdoutDone.complete, - ); - } else { - stdoutDone.complete(); - } + session.stdout.listen( + (e) { + onStdout?.call(e.string, session); + if (stdout) result.add(e); + }, + onDone: stdoutDone.complete, + onError: stderrDone.completeError, + ); - if (onStderr != null) { - session.stderr.listen( - (e) => onStderr(e.string, session), - onDone: stderrDone.complete, - ); - } else { - stderrDone.complete(); - } + session.stderr.listen( + (e) { + onStderr?.call(e.string, session); + if (stderr) result.add(e); + }, + onDone: stderrDone.complete, + onError: stderrDone.completeError, + ); - if (stdin != null) { - stdin(session); - } + onStdin(session); await stdoutDone.future; await stderrDone.future; - session.close(); - return session; + return (session, result.takeBytes().string); } Future execWithPwd( - String cmd, { + String script, { + String? entry, BuildContext? context, OnStdout? onStdout, OnStdout? onStderr, - OnStdin? stdin, - bool redirectToBash = false, // not working yet. do not use required String id, }) async { var isRequestingPwd = false; - final session = await exec( - cmd, - redirectToBash: redirectToBash, + final (session, _) = await exec( + (sess) { + sess.stdin.add('$script\n'.uint8List); + sess.stdin.close(); + }, onStderr: (data, session) async { onStderr?.call(data, session); if (isRequestingPwd) return; @@ -84,88 +85,38 @@ extension SSHClientX on SSHClient { ? await context.showPwdDialog(title: user, id: id) : null; if (pwd == null || pwd.isEmpty) { - session.kill(SSHSignal.TERM); + session.stdin.close(); } else { session.stdin.add('$pwd\n'.uint8List); } isRequestingPwd = false; } }, - onStdout: (data, sink) async { - onStdout?.call(data, sink); - }, - stdin: stdin, + onStdout: onStdout, + entry: entry, ); return session.exitCode; } - Future runForOutput( - String command, { - bool runInPty = false, + Future execForOutput( + String script, { + SSHPtyConfig? pty, bool stdout = true, bool stderr = true, - Map? environment, - Future Function(SSHSession)? action, + String? entry, + Map? env, }) async { - final session = await execute( - command, - pty: runInPty ? const SSHPtyConfig() : null, - environment: environment, + final ret = await exec( + (session) { + session.stdin.add('$script\n'.uint8List); + session.stdin.close(); + }, + pty: pty, + env: env, + stdout: stdout, + stderr: stderr, + entry: entry, ); - - final result = BytesBuilder(copy: false); - final stdoutDone = Completer(); - final stderrDone = Completer(); - - session.stdout.listen( - stdout ? result.add : (_) {}, - onDone: stdoutDone.complete, - onError: stderrDone.completeError, - ); - - session.stderr.listen( - stderr ? result.add : (_) {}, - onDone: stderrDone.complete, - onError: stderrDone.completeError, - ); - - if (action != null) await action(session); - - await stdoutDone.future; - await stderrDone.future; - - return result.takeBytes(); - } - - Future runScriptIn( - String cmd, { - String shell = '/bin/sh', - bool stdout = true, - bool stderr = true, - }) async { - final session = await execute('cat | $shell'); - - final result = BytesBuilder(copy: false); - final stdoutDone = Completer(); - final stderrDone = Completer(); - - session.stdout.listen( - stdout ? result.add : (_) {}, - onDone: stdoutDone.complete, - onError: stderrDone.completeError, - ); - session.stderr.listen( - stderr ? result.add : (_) {}, - onDone: stderrDone.complete, - onError: stderrDone.completeError, - ); - - session.stdin.add('$cmd\n'.uint8List); - session.stdin.close(); - - await stdoutDone.future; - await stderrDone.future; - - return result.takeBytes().string; + return ret.$2; } } diff --git a/lib/core/utils/server.dart b/lib/core/utils/server.dart index 99062a0e..0e7b4330 100644 --- a/lib/core/utils/server.dart +++ b/lib/core/utils/server.dart @@ -95,8 +95,8 @@ Future genClient( try { final ipPort = spi.fromStringUrl(); return await SSHSocket.connect( - ipPort.ip, - ipPort.port, + ipPort.$1, + ipPort.$2, timeout: timeout, ); } catch (e) { diff --git a/lib/data/model/server/server_private_info.dart b/lib/data/model/server/server_private_info.dart index b42bf0e1..aa69d20e 100644 --- a/lib/data/model/server/server_private_info.dart +++ b/lib/data/model/server/server_private_info.dart @@ -31,8 +31,8 @@ class ServerPrivateInfo { final List? tags; @HiveField(7) final String? alterUrl; - @HiveField(8) - final bool? autoConnect; + @HiveField(8, defaultValue: true) + final bool autoConnect; /// [id] of the jump server @HiveField(9) @@ -59,7 +59,7 @@ class ServerPrivateInfo { this.keyId, this.tags, this.alterUrl, - this.autoConnect, + this.autoConnect = true, this.jumpId, this.custom, this.wolCfg, @@ -75,7 +75,7 @@ class ServerPrivateInfo { final keyId = json['pubKeyId'] as String?; final tags = (json['tags'] as List?)?.cast(); final alterUrl = json['alterUrl'] as String?; - final autoConnect = json['autoConnect'] as bool?; + final autoConnect = json['autoConnect'] as bool? ?? true; final jumpId = json['jumpId'] as String?; final custom = json['customCmd'] == null ? null @@ -128,9 +128,7 @@ class ServerPrivateInfo { if (alterUrl != null) { data['alterUrl'] = alterUrl; } - if (autoConnect != null) { - data['autoConnect'] = autoConnect; - } + data['autoConnect'] = autoConnect; if (jumpId != null) { data['jumpId'] = jumpId; } @@ -160,7 +158,7 @@ class ServerPrivateInfo { custom?.cmds != old.custom?.cmds; } - IpPort fromStringUrl() { + (String, int) fromStringUrl() { if (alterUrl == null) { throw SSHErr(type: SSHErrType.connect, message: 'alterUrl is null'); } @@ -177,7 +175,7 @@ class ServerPrivateInfo { if (port <= 0 || port > 65535) { throw SSHErr(type: SSHErrType.connect, message: 'alterUrl port error'); } - return IpPort(ip_, port_); + return (ip_, port_); } @override @@ -206,11 +204,6 @@ class ServerPrivateInfo { logoUrl: 'https://example.com/logo.png', ), ); -} -class IpPort { - final String ip; - final int port; - - IpPort(this.ip, this.port); + bool get isRoot => user == 'root'; } diff --git a/lib/data/model/server/server_private_info.g.dart b/lib/data/model/server/server_private_info.g.dart index c79d1529..0ca3d1aa 100644 --- a/lib/data/model/server/server_private_info.g.dart +++ b/lib/data/model/server/server_private_info.g.dart @@ -25,7 +25,7 @@ class ServerPrivateInfoAdapter extends TypeAdapter { keyId: fields[5] as String?, tags: (fields[6] as List?)?.cast(), alterUrl: fields[7] as String?, - autoConnect: fields[8] as bool?, + autoConnect: fields[8] == null ? true : fields[8] as bool, jumpId: fields[9] as String?, custom: fields[10] as ServerCustom?, wolCfg: fields[11] as WakeOnLanCfg?, diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 4be71c2d..328daf2c 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -34,7 +34,7 @@ class ServerProvider extends ChangeNotifier { final _manualDisconnectedIds = {}; Future load() async { - // Issue #147 + // #147 // Clear all servers because of restarting app will cause duplicate servers final oldServers = Map.from(_servers); _servers.clear(); @@ -46,7 +46,7 @@ class ServerProvider extends ChangeNotifier { final originServer = oldServers[spi.id]; final newServer = genServer(spi); - /// Issues #258 + /// #258 /// If not [shouldReconnect], then keep the old state. if (originServer != null && !originServer.spi.shouldReconnect(spi)) { newServer.conn = originServer.conn; @@ -112,20 +112,20 @@ class ServerProvider extends ChangeNotifier { return; } - await Future.wait(_servers.values.map((s) => _connectFn(s, onlyFailed))); - } + await Future.wait(_servers.values.map((s) async { + if (onlyFailed) { + if (s.conn != ServerConn.failed) return; + TryLimiter.reset(s.spi.id); + } - Future _connectFn(Server s, bool onlyFailed) async { - if (onlyFailed) { - if (s.conn != ServerConn.failed) return; - TryLimiter.reset(s.spi.id); - } + if (_manualDisconnectedIds.contains(s.spi.id)) return; - if (!(s.spi.autoConnect ?? true) && s.conn == ServerConn.disconnected || - _manualDisconnectedIds.contains(s.spi.id)) { - return; - } - return await _getData(s.spi); + if (s.conn == ServerConn.disconnected && !s.spi.autoConnect) { + return; + } + + return await _getData(s.spi); + })); } Future startAutoRefresh() async { @@ -301,16 +301,16 @@ class ServerProvider extends ChangeNotifier { final scriptRaw = ShellFunc.allScript(spi.custom?.cmds).uint8List; try { - final writeScriptResult = await s.client!.runForOutput( - ShellFunc.getInstallShellCmd(spi.id), - action: (session) async { + final (_, writeScriptResult) = await s.client!.exec( + (session) async { session.stdin.add(scriptRaw); session.stdin.close(); }, + entry: ShellFunc.getInstallShellCmd(spi.id), ); if (writeScriptResult.isNotEmpty) { ShellFunc.switchScriptDir(spi.id); - throw String.fromCharCodes(writeScriptResult); + throw writeScriptResult; } } on SSHAuthAbortError catch (e) { TryLimiter.inc(sid); diff --git a/lib/data/provider/systemd.dart b/lib/data/provider/systemd.dart index 22d8db2a..817c6653 100644 --- a/lib/data/provider/systemd.dart +++ b/lib/data/provider/systemd.dart @@ -8,28 +8,27 @@ import 'package:server_box/data/res/provider.dart'; final class SystemdProvider { late final SSHClient _client; + late final bool isRoot; SystemdProvider.init(ServerPrivateInfo spi) { + isRoot = spi.isRoot; _client = Pros.server.pick(spi: spi)!.client!; getUnits(); } final isBusy = false.vn; - final isRoot = false.vn; final units = [].vn; Future getUnits() async { isBusy.value = true; try { - final result = await _client.runScriptIn(_getUnitsCmd); + final result = await _client.execForOutput(_getUnitsCmd); final units = result.split('\n'); - final isRootRaw = units.firstOrNull; - isRoot.value = isRootRaw == '0'; final userUnits = []; final systemUnits = []; - for (final unit in units.skip(1)) { + for (final unit in units) { if (unit.startsWith('/etc/systemd/system')) { systemUnits.add(unit); } else if (unit.startsWith('~/.config/systemd/user')) { @@ -64,7 +63,7 @@ for unit in ${unitNames_.join(' ')}; do echo -n "${ShellFunc.seperator}\n\$state" done '''; - final result = await _client.runScriptIn(script); + final result = await _client.execForOutput(script); final units = result.split(ShellFunc.seperator); final parsedUnits = []; @@ -124,17 +123,8 @@ done }); return parsedUnits; } -} - -String _getIniVal(String line) { - return line.split('=').last; -} - -const _getUnitsCmd = ''' -# If root, get system & user units, otherwise get user units -uid=\$(id -u) -echo \$uid + late final _getUnitsCmd = ''' get_files() { unit_type=\$1 base_dir=\$2 @@ -149,14 +139,12 @@ get_files() { get_type_files() { unit_type=\$1 - base_dir="" - if [ "\$uid" -eq 0 ]; then - get_files \$unit_type /etc/systemd/system - get_files \$unit_type ~/.config/systemd/user - else - get_files \$unit_type ~/.config/systemd/user - fi + +${isRoot ? """ +get_files \$unit_type /etc/systemd/system +get_files \$unit_type ~/.config/systemd/user""" : """ +get_files \$unit_type ~/.config/systemd/user"""} } types="service socket mount timer" @@ -165,3 +153,8 @@ for type in \$types; do get_type_files \$type done '''; +} + +String _getIniVal(String line) { + return line.split('=').last; +} diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 36c2d3fb..e1aa84a9 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -1,7 +1,8 @@ // This file is generated by fl_build. Do not edit. +// ignore_for_file: prefer_single_quotes class BuildData { - static const String name = 'ServerBox'; - static const int build = 1058; - static const int script = 56; + static const String name = "ServerBox"; + static const int build = 1060; + static const int script = 57; } diff --git a/lib/view/page/backup.dart b/lib/view/page/backup.dart index eee3d78a..20245f9a 100644 --- a/lib/view/page/backup.dart +++ b/lib/view/page/backup.dart @@ -156,9 +156,8 @@ class BackupPage extends StatelessWidget { trailing: ListenableBuilder( listenable: webdavLoading, builder: (_, __) { - if (webdavLoading.value) { - return UIs.centerSizedLoadingSmall; - } + if (webdavLoading.value) return SizedLoading.centerSmall; + return Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/view/page/private_key/edit.dart b/lib/view/page/private_key/edit.dart index 33585324..30cfc0d6 100644 --- a/lib/view/page/private_key/edit.dart +++ b/lib/view/page/private_key/edit.dart @@ -199,7 +199,7 @@ class _PrivateKeyEditPageState extends State { return; } FocusScope.of(context).unfocus(); - _loading.value = UIs.centerSizedLoading; + _loading.value = SizedLoading.centerMedium; try { final decrypted = await Computer.shared.start(decyptPem, [key, pwd]); final pki = PrivateKeyInfo(id: name, key: decrypted); diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index 20d29818..9fa06397 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -606,7 +606,7 @@ class _ServerEditPageState extends State with AfterLayoutMixin { _tags.value = spi.tags?.toSet() ?? {}; _altUrlController.text = spi.alterUrl ?? ''; - _autoConnect.value = spi.autoConnect ?? true; + _autoConnect.value = spi.autoConnect; _jumpServer.value = spi.jumpId; final custom = spi.custom; diff --git a/lib/view/page/storage/sftp.dart b/lib/view/page/storage/sftp.dart index 3684d08b..fc1bc6dd 100644 --- a/lib/view/page/storage/sftp.dart +++ b/lib/view/page/storage/sftp.dart @@ -64,24 +64,22 @@ class _SftpPageState extends State with AfterLayoutMixin { } Widget _buildSortMenu() { + final options = [ + (_SortType.name, libL10n.name), + (_SortType.size, l10n.size), + (_SortType.time, l10n.time), + ]; return ValBuilder( listenable: _sortOption, builder: (value) { return PopupMenuButton<_SortType>( icon: const Icon(Icons.sort), itemBuilder: (context) { - final currentSelectedOption = _sortOption.value; - final options = [ - (_SortType.name, libL10n.name), - (_SortType.size, l10n.size), - (_SortType.time, l10n.time), - ]; return options.map((r) { final (type, name) = r; - final selected = type == currentSelectedOption.sortBy; - final title = selected - ? "$name (${currentSelectedOption.reversed ? '-' : '+'})" - : name; + final selected = type == value.sortBy; + final title = + selected ? "$name (${value.reversed ? '-' : '+'})" : name; return PopupMenuItem( value: type, child: Text( @@ -607,7 +605,7 @@ class _SftpPageState extends State with AfterLayoutMixin { /// Issue #97 /// In order to compatible with the Synology NAS /// which not has '.' and '..' in listdir - if (fs.isNotEmpty && fs.firstOrNull?.filename == '.') { + if (fs.firstOrNull?.filename == '.') { fs.removeAt(0); } diff --git a/lib/view/page/systemd.dart b/lib/view/page/systemd.dart index 7b5bd301..9c7457d7 100644 --- a/lib/view/page/systemd.dart +++ b/lib/view/page/systemd.dart @@ -54,9 +54,9 @@ final class _SystemdPageState extends State { (isBusy) => AnimatedContainer( duration: Durations.medium1, curve: Curves.fastEaseInToSlowEaseOut, - height: isBusy ? 50 : 0, + height: isBusy ? 30 : 0, child: isBusy - ? UIs.centerSizedLoadingSmall.paddingOnly(bottom: 7) + ? SizedLoading.centerSmall.paddingOnly(bottom: 7) : const SizedBox.shrink(), ), ), @@ -71,8 +71,7 @@ final class _SystemdPageState extends State { (units) { if (units.isEmpty) { return SliverToBoxAdapter( - child: ListTile(title: Text(libL10n.empty)) - .cardx + child: CenterGreyTitle(libL10n.empty) .paddingSymmetric(horizontal: 13), ); } @@ -103,7 +102,7 @@ final class _SystemdPageState extends State { return PopupMenu( items: unit.availableFuncs.map(_buildUnitFuncBtn).toList(), onSelected: (val) async { - final cmd = unit.getCmd(func: val, isRoot: _pro.isRoot.value); + final cmd = unit.getCmd(func: val, isRoot: _pro.isRoot); final sure = await context.showRoundDialog( title: libL10n.attention, child: SimpleMarkdown(data: '```shell\n$cmd\n```'), diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index e5ac8461..6cd6b526 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -471,7 +471,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Server Box"; @@ -481,7 +481,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "Server Box"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -608,7 +608,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = BA88US33G6; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Server Box"; @@ -618,7 +618,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "Server Box"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -638,7 +638,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1058; + CURRENT_PROJECT_VERSION = 1060; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6; INFOPLIST_FILE = Runner/Info.plist; @@ -649,7 +649,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.1058; + MARKETING_VERSION = 1.0.1060; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "Server Box"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/pubspec.lock b/pubspec.lock index 49d2c4df..29751bd1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -373,8 +373,8 @@ packages: dependency: "direct dev" description: path: "." - ref: "v1.0.41" - resolved-ref: "6f1f4e8c9fecb3a43725e19e6747d4e2a727ea89" + ref: "v1.0.42" + resolved-ref: "2cae3388a66581169638c3b3f5fc73dd7b5b4bfd" url: "https://github.com/lppcg/fl_build.git" source: git version: "1.0.0" @@ -390,8 +390,8 @@ packages: dependency: "direct main" description: path: "." - ref: "v1.0.132" - resolved-ref: f68453c64cfa3b363bcd6b5e7d76cad7fa7724c6 + ref: "v1.0.134" + resolved-ref: "24b9778e8fb482ee233b70bcc4a38587aa7f76b1" url: "https://github.com/lppcg/fl_lib" source: git version: "0.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index ee8c6413..ed939fa6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: server_box description: server status & toolbox app. publish_to: 'none' -version: 1.0.1058+1058 +version: 1.0.1060+1060 environment: sdk: ">=3.0.0" @@ -60,7 +60,7 @@ dependencies: fl_lib: git: url: https://github.com/lppcg/fl_lib - ref: v1.0.132 + ref: v1.0.134 dependency_overrides: # dartssh2: @@ -82,7 +82,7 @@ dev_dependencies: fl_build: git: url: https://github.com/lppcg/fl_build.git - ref: v1.0.41 + ref: v1.0.42 flutter: generate: true