diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart index 62538a56..6d49f851 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart @@ -1196,6 +1196,12 @@ abstract class S { /// **'Are you sure to use no password?'** String get sureNoPwd; + /// No description provided for @sureStop. + /// + /// In en, this message translates to: + /// **'Sure to stop [{item}] ?'** + String sureStop(Object item); + /// No description provided for @sureToDeleteServer. /// /// In en, this message translates to: diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart index bf90f049..b76d18f4 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart @@ -585,6 +585,11 @@ class SDe extends S { @override String get sureNoPwd => 'Bist du sicher, dass du kein Passwort verwenden willst?'; + @override + String sureStop(Object item) { + return 'Sind Sie sicher, dass Sie [$item] stoppen möchten?'; + } + @override String sureToDeleteServer(Object server) { return 'Bist du sicher, dass du [$server] löschen willst?'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart index c2bb4d2b..411ecdb0 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart @@ -585,6 +585,11 @@ class SEn extends S { @override String get sureNoPwd => 'Are you sure to use no password?'; + @override + String sureStop(Object item) { + return 'Sure to stop [$item] ?'; + } + @override String sureToDeleteServer(Object server) { return 'Are you sure to delete server [$server]?'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart index b4dd49e8..d6926e31 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart @@ -585,6 +585,11 @@ class SId extends S { @override String get sureNoPwd => 'Apakah Anda pasti tidak menggunakan kata sandi?'; + @override + String sureStop(Object item) { + return 'Anda yakin ingin menghentikan [$item]?'; + } + @override String sureToDeleteServer(Object server) { return 'Apakah Anda pasti akan menghapus server [$server]?'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart index ae80281b..f95c1774 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart @@ -585,6 +585,11 @@ class SZh extends S { @override String get sureNoPwd => '确认使用无密码?'; + @override + String sureStop(Object item) { + return '确定要停止 [$item] 吗?'; + } + @override String sureToDeleteServer(Object server) { return '你确定要删除服务器 [$server] 吗?'; @@ -1276,6 +1281,11 @@ class SZhTw extends SZh { @override String get sureNoPwd => '確認使用無密碼?'; + @override + String sureStop(Object item) { + return '確定要停止 [$item] 嗎?'; + } + @override String sureToDeleteServer(Object server) { return '你確定要刪除服務器 [$server] 嗎?'; diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index e93c50d5..368c8f3d 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -12,7 +12,7 @@ on: branches: [ "main" ] jobs: - build: + check: runs-on: ubuntu-latest steps: diff --git a/lib/core/utils/platform.dart b/lib/core/utils/platform.dart index 0527f4a5..7f5a23f4 100644 --- a/lib/core/utils/platform.dart +++ b/lib/core/utils/platform.dart @@ -9,6 +9,7 @@ enum PlatformType { macos, windows, web, + fuchsia, unknown, } @@ -31,6 +32,9 @@ final _p = () { if (Platform.isWindows) { return PlatformType.windows; } + if (Platform.isFuchsia) { + return PlatformType.fuchsia; + } return PlatformType.unknown; }(); diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index abece32d..92930481 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -183,6 +183,7 @@ "sureDelete": "Soll [{name}] wirklich gelöscht werden?", "sureDirEmpty": "Stelle sicher, dass der Ordner leer ist.", "sureNoPwd": "Bist du sicher, dass du kein Passwort verwenden willst?", + "sureStop": "Sind Sie sicher, dass Sie [{item}] stoppen möchten?", "sureToDeleteServer": "Bist du sicher, dass du [{server}] löschen willst?", "system": "Systeme", "tag": "Tags", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 52fe82f3..f6a93ec3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -183,6 +183,7 @@ "sureDelete": "Are you sure to delete [{name}]?", "sureDirEmpty": "Make sure dir is empty.", "sureNoPwd": "Are you sure to use no password?", + "sureStop": "Sure to stop [{item}] ?", "sureToDeleteServer": "Are you sure to delete server [{server}]?", "system": "System", "tag": "Tags", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 0cc910c7..f8a0d146 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -183,6 +183,7 @@ "sureDelete": "Apakah Anda pasti akan menghapus [{name}]?", "sureDirEmpty": "Pastikan dir kosong.", "sureNoPwd": "Apakah Anda pasti tidak menggunakan kata sandi?", + "sureStop": "Anda yakin ingin menghentikan [{item}]?", "sureToDeleteServer": "Apakah Anda pasti akan menghapus server [{server}]?", "system": "Sistem", "tag": "Tag", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index d3c76c25..068cfdcc 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -183,6 +183,7 @@ "sureDelete": "确定删除 [{name}]?", "sureDirEmpty": "请确保文件夹为空", "sureNoPwd": "确认使用无密码?", + "sureStop": "确定要停止 [{item}] 吗?", "sureToDeleteServer": "你确定要删除服务器 [{server}] 吗?", "system": "系统", "tag": "标签", diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb index 7a66db3e..a285915f 100644 --- a/lib/l10n/app_zh_tw.arb +++ b/lib/l10n/app_zh_tw.arb @@ -183,6 +183,7 @@ "sureDelete": "確定刪除 [{name}]?", "sureDirEmpty": "請確保文件夾為空", "sureNoPwd": "確認使用無密碼?", + "sureStop": "確定要停止 [{item}] 嗎?", "sureToDeleteServer": "你確定要刪除服務器 [{server}] 嗎?", "system": "系統", "tag": "标签", diff --git a/lib/view/page/process.dart b/lib/view/page/process.dart index ead92097..07911a40 100644 --- a/lib/view/page/process.dart +++ b/lib/view/page/process.dart @@ -1,7 +1,9 @@ import 'dart:async'; +import 'package:dartssh2/dartssh2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/core/extension/stringx.dart'; import 'package:toolbox/core/extension/uint8list.dart'; import 'package:toolbox/core/utils/ui.dart'; @@ -25,6 +27,7 @@ class ProcessPage extends StatefulWidget { class _ProcessPageState extends State { late S _s; late Timer _timer; + SSHClient? _client; PsResult _result = PsResult(procs: []); int? _lastFocusId; @@ -35,24 +38,27 @@ class _ProcessPageState extends State { @override void initState() { super.initState(); - final client = _serverProvider.servers[widget.spi.id]?.client; - if (client == null) { + _client = _serverProvider.servers[widget.spi.id]?.client; + if (_client == null) { showSnackBar(context, Text(_s.noClient)); return; } - _timer = Timer.periodic(const Duration(seconds: 3), (_) async { - if (mounted) { - final result = await client.run('ps -aux'.withLangExport).string; - if (result.isEmpty) { - showSnackBar(context, Text(_s.noResult)); - return; - } - _result = PsResult.parse(result, sort: _procSortMode); - setState(() {}); - } else { - _timer.cancel(); + _timer = + Timer.periodic(const Duration(seconds: 3), (_) => _refresh()); + } + + Future _refresh() async { + if (mounted) { + final result = await _client?.run('ps -aux'.withLangExport).string; + if (result == null || result.isEmpty) { + showSnackBar(context, Text(_s.noResult)); + return; } - }); + _result = PsResult.parse(result, sort: _procSortMode); + setState(() {}); + } else { + _timer.cancel(); + } } @override @@ -140,6 +146,24 @@ class _ProcessPageState extends State { ], ), onTap: () => _lastFocusId = proc.pid, + onLongPress: () { + showRoundDialog( + context: context, + title: Text(_s.attention), + child: Text(_s.sureStop(proc.pid)), + actions: [ + TextButton( + onPressed: () async { + await _client?.run('kill ${proc.pid}'); + await _refresh(); + context.pop(); + }, + child: Text(_s.ok), + ), + ], + ); + }, + selected: _lastFocusId == proc.pid, autofocus: _lastFocusId == proc.pid, )); } diff --git a/test/widget_test.dart b/test/widget_test.dart deleted file mode 100644 index e38d965a..00000000 --- a/test/widget_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:toolbox/app.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -}