diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 807e913e..544e17e1 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -354,7 +354,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 134; + CURRENT_PROJECT_VERSION = 135; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -362,7 +362,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.134; + MARKETING_VERSION = 1.0.135; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -484,7 +484,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 134; + CURRENT_PROJECT_VERSION = 135; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -492,7 +492,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.134; + MARKETING_VERSION = 1.0.135; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -508,7 +508,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 134; + CURRENT_PROJECT_VERSION = 135; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -516,7 +516,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.134; + MARKETING_VERSION = 1.0.135; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/core/analysis.dart b/lib/core/analysis.dart index 5f6c7927..f7a2d521 100644 --- a/lib/core/analysis.dart +++ b/lib/core/analysis.dart @@ -22,7 +22,7 @@ class Analysis { await Countly.giveAllConsent(); } else { Logger('COUNTLY') - .info('Unsupported platform ${Platform.operatingSystem}'); + .info('Unsupported platform ${Platform.operatingSystem}'); } } diff --git a/lib/core/update.dart b/lib/core/update.dart index b0859463..b8e29f95 100644 --- a/lib/core/update.dart +++ b/lib/core/update.dart @@ -1,9 +1,8 @@ -// ignore_for_file: avoid_print - import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; import 'package:r_upgrade/r_upgrade.dart'; import 'package:toolbox/core/utils.dart'; import 'package:toolbox/data/provider/app.dart'; @@ -12,12 +11,14 @@ import 'package:toolbox/data/service/app.dart'; import 'package:toolbox/generated/l10n.dart'; import 'package:toolbox/locator.dart'; +final logger = Logger('UPDATE'); + Future isFileAvailable(String url) async { try { final resp = await Dio().head(url); return resp.statusCode == 200; } catch (e) { - print('update file not available: $e'); + logger.warning('update file not available: $e'); return false; } } @@ -39,11 +40,11 @@ Future doUpdate(BuildContext context, {bool force = false}) async { }(); if (!force && newest <= BuildData.build) { - print('Update ignored due to current: ${BuildData.build}, ' + logger.info('Update ignored due to current: ${BuildData.build}, ' 'update: $newest'); return; } - print('Update available: $newest'); + logger.info('Update available: $newest'); if (Platform.isAndroid && !await isFileAvailable(update.android)) { return; diff --git a/lib/data/provider/apt.dart b/lib/data/provider/apt.dart index 548bffbc..da9d8676 100644 --- a/lib/data/provider/apt.dart +++ b/lib/data/provider/apt.dart @@ -10,7 +10,8 @@ import 'package:toolbox/core/provider_base.dart'; import 'package:toolbox/data/model/apt/upgrade_pkg_info.dart'; import 'package:toolbox/data/model/distribution.dart'; -typedef PwdRequestFunc = Future Function(String? userName); +typedef PwdRequestFunc = Future Function( + bool lastTimes, String? userName); final pwdRequestWithUserReg = RegExp(r'\[sudo\] password for (.+):'); class AptProvider extends BusyProvider { @@ -27,7 +28,8 @@ class AptProvider extends BusyProvider { String? error; String? upgradeLog; String? updateLog; - String? savedPwd; + String lastLog = ''; + int triedTimes = 0; AptProvider(); @@ -49,10 +51,10 @@ class AptProvider extends BusyProvider { error = null; upgradeLog = null; updateLog = whoami = null; - savedPwd = null; onUpgrade = null; onUpdate = null; onPasswordRequest = null; + triedTimes = 0; } Future refreshInstalled() async { @@ -128,7 +130,10 @@ class AptProvider extends BusyProvider { session.stderr.listen((e) => _onPwd(e, session.stdin)); session.stdout.listen((data) async { - upgradeLog = (upgradeLog ?? '') + data.string; + final log = data.string; + if (lastLog == log.trim()) return; + upgradeLog = (upgradeLog ?? '') + log; + lastLog = log.trim(); notifyListeners(); onUpgrade!(); }); @@ -143,16 +148,12 @@ class AptProvider extends BusyProvider { if (event.contains('[sudo] password for ')) { final user = pwdRequestWithUserReg.firstMatch(event)?.group(1); logger.info('sudo password request for $user'); - final pwd = await () async { - if (savedPwd != null) return savedPwd!; - final inputPwd = await (onPasswordRequest ?? (_) async => '')(user); - if (inputPwd.isNotEmpty) { - savedPwd = inputPwd; - } - return inputPwd; - }(); + triedTimes++; + final pwd = + await (onPasswordRequest ?? (_) async => '')(triedTimes == 3, user); if (pwd.isEmpty) { logger.info('sudo password request cancelled'); + return; } stdin.add(Uint8List.fromList(utf8.encode('$pwd\n'))); } diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 929edb7c..540b0e75 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,9 +2,9 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 134; + static const int build = 135; static const String engine = - "Flutter 3.0.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision ee4e09cce0 (2 days ago) • 2022-05-09 16:45:18 -0700\nEngine • revision d1b9a6938a\nTools • Dart 2.17.0 • DevTools 2.12.2\n"; - static const String buildAt = "2022-05-12 14:31:57.568409"; - static const int modifications = 37; + "Flutter 3.0.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision ee4e09cce0 (3 days ago) • 2022-05-09 16:45:18 -0700\nEngine • revision d1b9a6938a\nTools • Dart 2.17.0 • DevTools 2.12.2\n"; + static const String buildAt = "2022-05-13 09:32:15.654170"; + static const int modifications = 15; } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 589b9fab..c59de071 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -41,21 +41,19 @@ class MessageLookup extends MessageLookupByLibrary { static String m8(myGithub) => "\nMade with ❤️ by ${myGithub}"; - static String m9(user) => "Password for ${user}"; + static String m9(url) => "Please report bugs on ${url}"; - static String m10(url) => "Please report bugs on ${url}"; + static String m10(time) => "Spent time: ${time}"; - static String m11(time) => "Spent time: ${time}"; + static String m11(name) => "Are you sure to delete [${name}]?"; - static String m12(name) => "Are you sure to delete [${name}]?"; + static String m12(server) => "Are you sure to delete server [${server}]?"; - static String m13(server) => "Are you sure to delete server [${server}]?"; + static String m13(build) => "Found: v1.0.${build}, click to update"; - static String m14(build) => "Found: v1.0.${build}, click to update"; + static String m14(build) => "Current: v1.0.${build}"; - static String m15(build) => "Current: v1.0.${build}"; - - static String m16(build) => "Current: v1.0.${build}, is up to date"; + static String m15(build) => "Current: v1.0.${build}, is up to date"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -122,6 +120,7 @@ class MessageLookup extends MessageLookupByLibrary { "keepForeground": MessageLookupByLibrary.simpleMessage("Keep app foreground!"), "keyAuth": MessageLookupByLibrary.simpleMessage("Key Auth"), + "lastTry": MessageLookupByLibrary.simpleMessage("Last try!"), "launchPage": MessageLookupByLibrary.simpleMessage("Launch page"), "license": MessageLookupByLibrary.simpleMessage("License"), "loadingFiles": @@ -160,9 +159,8 @@ class MessageLookup extends MessageLookupByLibrary { "port": MessageLookupByLibrary.simpleMessage("Port"), "privateKey": MessageLookupByLibrary.simpleMessage("Private Key"), "pwd": MessageLookupByLibrary.simpleMessage("Password"), - "pwdForUser": m9, "rename": MessageLookupByLibrary.simpleMessage("Rename"), - "reportBugsOnGithubIssue": m10, + "reportBugsOnGithubIssue": m9, "result": MessageLookupByLibrary.simpleMessage("Result"), "run": MessageLookupByLibrary.simpleMessage("Run"), "save": MessageLookupByLibrary.simpleMessage("Save"), @@ -186,11 +184,11 @@ class MessageLookup extends MessageLookupByLibrary { "sftpSSHConnected": MessageLookupByLibrary.simpleMessage("SFTP Connected"), "snippet": MessageLookupByLibrary.simpleMessage("Snippet"), - "spentTime": m11, + "spentTime": m10, "start": MessageLookupByLibrary.simpleMessage("Start"), "stop": MessageLookupByLibrary.simpleMessage("Stop"), - "sureDelete": m12, - "sureToDeleteServer": m13, + "sureDelete": m11, + "sureToDeleteServer": m12, "ttl": MessageLookupByLibrary.simpleMessage("TTL"), "unknown": MessageLookupByLibrary.simpleMessage("unknown"), "unknownError": MessageLookupByLibrary.simpleMessage("Unknown error"), @@ -204,9 +202,9 @@ class MessageLookup extends MessageLookupByLibrary { "upsideDown": MessageLookupByLibrary.simpleMessage("Upside Down"), "urlOrJson": MessageLookupByLibrary.simpleMessage("URL or JSON"), "user": MessageLookupByLibrary.simpleMessage("User"), - "versionHaveUpdate": m14, - "versionUnknownUpdate": m15, - "versionUpdated": m16, + "versionHaveUpdate": m13, + "versionUnknownUpdate": m14, + "versionUpdated": m15, "waitConnection": MessageLookupByLibrary.simpleMessage( "Please wait for the connection to be established."), "willTakEeffectImmediately": diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index a07bcac2..0c27e4b2 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -41,21 +41,19 @@ class MessageLookup extends MessageLookupByLibrary { static String m8(myGithub) => "\n用❤️制作 by ${myGithub}"; - static String m9(user) => "${user}的密码"; + static String m9(url) => "请到 ${url} 提交问题"; - static String m10(url) => "请到 ${url} 提交问题"; + static String m10(time) => "耗时: ${time}"; - static String m11(time) => "耗时: ${time}"; + static String m11(name) => "确定删除[${name}]?"; - static String m12(name) => "确定删除[${name}]?"; + static String m12(server) => "你确定要删除服务器 [${server}] 吗?"; - static String m13(server) => "你确定要删除服务器 [${server}] 吗?"; + static String m13(build) => "找到新版本:v1.0.${build}, 点击更新"; - static String m14(build) => "找到新版本:v1.0.${build}, 点击更新"; + static String m14(build) => "当前:v1.0.${build}"; - static String m15(build) => "当前:v1.0.${build}"; - - static String m16(build) => "当前:v1.0.${build}, 已是最新版本"; + static String m15(build) => "当前:v1.0.${build}, 已是最新版本"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -110,6 +108,7 @@ class MessageLookup extends MessageLookupByLibrary { "invalidVersionHelp": m7, "keepForeground": MessageLookupByLibrary.simpleMessage("请保持应用处于前台!"), "keyAuth": MessageLookupByLibrary.simpleMessage("公钥认证"), + "lastTry": MessageLookupByLibrary.simpleMessage("最后尝试"), "launchPage": MessageLookupByLibrary.simpleMessage("启动页"), "license": MessageLookupByLibrary.simpleMessage("开源证书"), "loadingFiles": MessageLookupByLibrary.simpleMessage("正在加载目录。。。"), @@ -139,9 +138,8 @@ class MessageLookup extends MessageLookupByLibrary { "port": MessageLookupByLibrary.simpleMessage("端口"), "privateKey": MessageLookupByLibrary.simpleMessage("私钥"), "pwd": MessageLookupByLibrary.simpleMessage("密码"), - "pwdForUser": m9, "rename": MessageLookupByLibrary.simpleMessage("重命名"), - "reportBugsOnGithubIssue": m10, + "reportBugsOnGithubIssue": m9, "result": MessageLookupByLibrary.simpleMessage("结果"), "run": MessageLookupByLibrary.simpleMessage("运行"), "save": MessageLookupByLibrary.simpleMessage("保存"), @@ -160,11 +158,11 @@ class MessageLookup extends MessageLookupByLibrary { "sftpSSHConnected": MessageLookupByLibrary.simpleMessage("SFTP 已连接,即将开始下载..."), "snippet": MessageLookupByLibrary.simpleMessage("代码片段"), - "spentTime": m11, + "spentTime": m10, "start": MessageLookupByLibrary.simpleMessage("开始"), "stop": MessageLookupByLibrary.simpleMessage("停止"), - "sureDelete": m12, - "sureToDeleteServer": m13, + "sureDelete": m11, + "sureToDeleteServer": m12, "ttl": MessageLookupByLibrary.simpleMessage("缓存时间"), "unknown": MessageLookupByLibrary.simpleMessage("未知"), "unknownError": MessageLookupByLibrary.simpleMessage("未知错误"), @@ -177,9 +175,9 @@ class MessageLookup extends MessageLookupByLibrary { "upsideDown": MessageLookupByLibrary.simpleMessage("上下交换"), "urlOrJson": MessageLookupByLibrary.simpleMessage("链接或JSON"), "user": MessageLookupByLibrary.simpleMessage("用户"), - "versionHaveUpdate": m14, - "versionUnknownUpdate": m15, - "versionUpdated": m16, + "versionHaveUpdate": m13, + "versionUnknownUpdate": m14, + "versionUpdated": m15, "waitConnection": MessageLookupByLibrary.simpleMessage("请等待连接建立"), "willTakEeffectImmediately": MessageLookupByLibrary.simpleMessage("更改将会立即生效") diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index ba85c229..498cdd3a 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -1181,16 +1181,6 @@ class S { ); } - /// `Password for {user}` - String pwdForUser(Object user) { - return Intl.message( - 'Password for $user', - name: 'pwdForUser', - desc: '', - args: [user], - ); - } - /// `Current platform does not support in app update.\nPlease build from source and install it.` String get platformNotSupportUpdate { return Intl.message( @@ -1220,6 +1210,16 @@ class S { args: [], ); } + + /// `Last try!` + String get lastTry { + return Intl.message( + 'Last try!', + name: 'lastTry', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 3bcaccac..175b55ec 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -112,8 +112,8 @@ "noUpdateAvailable": "No update available", "foundNUpdate": "Found {count} update", "updateAll": "Update all", - "pwdForUser": "Password for {user}", "platformNotSupportUpdate": "Current platform does not support in app update.\nPlease build from source and install it.", "invalidVersionHelp": "Please make sure that docker is installed correctly, or that you are using a non-self-compiled version. If you don't have the above issues, please submit an issue on {url}.", - "noInterface": "No interface" + "noInterface": "No interface", + "lastTry": "Last try!" } \ No newline at end of file diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index ae9dfce1..f0f5159f 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -112,8 +112,8 @@ "noUpdateAvailable": "没有可用更新", "foundNUpdate": "找到 {count} 个更新", "updateAll": "更新全部", - "pwdForUser": "{user}的密码", "platformNotSupportUpdate": "当前平台不支持更新,请编译最新源码后手动安装", "invalidVersionHelp": "请确保正确安装了docker,或者使用的非自编译版本。如果没有以上问题,请在 {url} 提交问题。", - "noInterface": "没有可用的接口" + "noInterface": "没有可用的接口", + "lastTry": "最后尝试" } \ No newline at end of file diff --git a/lib/view/page/apt.dart b/lib/view/page/apt.dart index dc05126f..a7bc8cb8 100644 --- a/lib/view/page/apt.dart +++ b/lib/view/page/apt.dart @@ -59,16 +59,17 @@ class _AptManagePageState extends State } // ignore: prefer_function_declarations_over_variables - PwdRequestFunc onPwdRequest = (user) async { + PwdRequestFunc onPwdRequest = (lastTime, user) async { if (!mounted) return ''; final textController = TextEditingController(); await showRoundDialog( context, - s.pwdForUser(user ?? s.unknown), + lastTime ? s.lastTry : (user ?? s.unknown), TextField( controller: textController, keyboardType: TextInputType.visiblePassword, obscureText: true, + onSubmitted: (_) => textController.text.trim(), decoration: InputDecoration( labelText: s.pwd, ), diff --git a/lib/view/page/convert.dart b/lib/view/page/convert.dart index e73e83ad..ce5e5ca1 100644 --- a/lib/view/page/convert.dart +++ b/lib/view/page/convert.dart @@ -89,7 +89,8 @@ class _ConvertPageState extends State Widget _buildInputTop() { return SizedBox( height: _media.size.height * 0.33, - child: buildInput(context, _textEditingController), + child: buildInput(context, _textEditingController, + onSubmitted: (_) => _textEditingControllerResult.text = doConvert()), ); } diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index 53df7eda..b6c80dba 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -48,7 +48,8 @@ class _PingPageState extends State padding: const EdgeInsets.symmetric(horizontal: 7), child: Column(children: [ const SizedBox(height: 13), - buildInput(context, _textEditingController, maxLines: 1), + buildInput(context, _textEditingController, + maxLines: 1, onSubmitted: (_) => doPing()), _buildControl(), SizedBox( width: double.infinity, diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index c677af4b..18198a4f 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -209,7 +209,8 @@ class _ServerPageState extends State _buildExplainText('Net'), _buildExplainText('Disk'), ], - ) + ), + const SizedBox(height: 3), ], ); } @@ -218,7 +219,7 @@ class _ServerPageState extends State return DropdownButtonHideUnderline( child: DropdownButton2( customButton: const Padding( - padding: EdgeInsets.only(left: 7), + padding: EdgeInsets.symmetric(horizontal: 5, vertical: 1.7), child: Icon( Icons.more_vert, size: 17, diff --git a/lib/view/widget/input_field.dart b/lib/view/widget/input_field.dart index 2eaf3da2..279ec932 100644 --- a/lib/view/widget/input_field.dart +++ b/lib/view/widget/input_field.dart @@ -2,16 +2,21 @@ import 'package:flutter/material.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; Widget buildInput(BuildContext context, TextEditingController controller, - {int maxLines = 20, String? hint}) { + {int maxLines = 20, + String? hint, + Function(String)? onSubmitted, + bool? obscureText}) { return RoundRectCard( TextField( maxLines: maxLines, + onSubmitted: onSubmitted, decoration: InputDecoration( fillColor: Theme.of(context).cardColor, hintText: hint, filled: true, border: InputBorder.none), controller: controller, + obscureText: obscureText ?? false, ), ); }