From a59286473fb73cc4952a3c744e8f966cc43c9457 Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Sun, 20 Aug 2023 18:30:08 +0800 Subject: [PATCH] opt. - move out btns from more vert btn (docker, sftp & etc.) - redesigned routes - confirmation before deleting private key --- lib/core/extension/media_queryx.dart | 2 +- lib/core/route.dart | 149 +++++++++++++ lib/core/update.dart | 3 +- lib/data/model/app/menu.dart | 30 +-- lib/data/res/build_data.dart | 6 +- lib/data/res/ui.dart | 2 + lib/view/page/docker.dart | 12 +- lib/view/page/full_screen.dart | 6 +- lib/view/page/pkg.dart | 11 +- lib/view/page/private_key/edit.dart | 31 ++- lib/view/page/server/detail.dart | 20 +- lib/view/page/server/edit.dart | 11 +- lib/view/page/server/tab.dart | 318 +++++++++++++-------------- lib/view/page/ssh/term.dart | 4 +- lib/view/page/storage/local.dart | 10 +- lib/view/page/storage/sftp.dart | 26 +-- 16 files changed, 380 insertions(+), 261 deletions(-) diff --git a/lib/core/extension/media_queryx.dart b/lib/core/extension/media_queryx.dart index a7361039..b02c815c 100644 --- a/lib/core/extension/media_queryx.dart +++ b/lib/core/extension/media_queryx.dart @@ -1,5 +1,5 @@ import 'package:flutter/widgets.dart'; extension MideaQueryX on MediaQueryData { - bool get isLarge => size.aspectRatio > 0.87 && size.width > 600; + bool get useDoubleColumn => size.width > 639; } diff --git a/lib/core/route.dart b/lib/core/route.dart index da325ee7..9c5f2904 100644 --- a/lib/core/route.dart +++ b/lib/core/route.dart @@ -1,9 +1,35 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:toolbox/core/analysis.dart'; +import 'package:toolbox/data/model/server/private_key_info.dart'; +import 'package:toolbox/data/model/server/server_private_info.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/locator.dart'; +import 'package:toolbox/view/page/backup.dart'; +import 'package:toolbox/view/page/docker.dart'; +import 'package:toolbox/view/page/home.dart'; +import 'package:toolbox/view/page/ping.dart'; +import 'package:toolbox/view/page/private_key/edit.dart'; +import 'package:toolbox/view/page/private_key/list.dart'; +import 'package:toolbox/view/page/server/detail.dart'; +import 'package:toolbox/view/page/ssh/term.dart'; +import 'package:toolbox/view/page/ssh/virt_key_setting.dart'; +import 'package:toolbox/view/page/storage/local.dart'; +import '../data/model/server/snippet.dart'; +import '../view/page/convert.dart'; +import '../view/page/debug.dart'; +import '../view/page/editor.dart'; +import '../view/page/full_screen.dart'; +import '../view/page/pkg.dart'; +import '../view/page/process.dart'; +import '../view/page/server/edit.dart'; +import '../view/page/server/tab.dart'; +import '../view/page/setting.dart'; +import '../view/page/snippet/edit.dart'; +import '../view/page/snippet/list.dart'; +import '../view/page/storage/sftp.dart'; +import '../view/page/storage/sftp_mission.dart'; import 'utils/ui.dart'; class AppRoute { @@ -32,4 +58,127 @@ class AppRoute { } return go(context); } + + static AppRoute serverDetail({Key? key, required ServerPrivateInfo spi}) { + return AppRoute(ServerDetailPage(key: key, spi: spi), 'server_detail'); + } + + static AppRoute serverTab({Key? key}) { + return AppRoute(ServerPage(key: key), 'server_tab'); + } + + static AppRoute serverEdit({Key? key, ServerPrivateInfo? spi}) { + return AppRoute( + ServerEditPage(spi: spi), + 'server_${spi == null ? 'add' : 'edit'}', + ); + } + + static AppRoute keyEdit({Key? key, PrivateKeyInfo? pki}) { + return AppRoute( + PrivateKeyEditPage(pki: pki), + 'key_${pki == null ? 'add' : 'edit'}', + ); + } + + static AppRoute keyList({Key? key}) { + return AppRoute(PrivateKeysListPage(key: key), 'key_detail'); + } + + static AppRoute snippetEdit({Key? key, Snippet? snippet}) { + return AppRoute( + SnippetEditPage(snippet: snippet), + 'snippet_${snippet == null ? 'add' : 'edit'}', + ); + } + + static AppRoute snippetList({Key? key}) { + return AppRoute(SnippetListPage(key: key), 'snippet_detail'); + } + + static AppRoute ssh({ + Key? key, + required ServerPrivateInfo spi, + String? initCmd, + }) { + return AppRoute( + SSHPage( + key: key, + spi: spi, + initCmd: initCmd, + ), + 'ssh_term', + ); + } + + static AppRoute sshVirtKeySetting({Key? key}) { + return AppRoute(SSHVirtKeySettingPage(key: key), 'ssh_virt_key_setting'); + } + + static AppRoute localStorage({Key? key}) { + return AppRoute(LocalStoragePage(key: key), 'local_storage'); + } + + static AppRoute sftpMission({Key? key}) { + return AppRoute(SftpMissionPage(key: key), 'sftp_mission'); + } + + static AppRoute sftp( + {Key? key, + required ServerPrivateInfo spi, + String? initPath, + bool isSelect = false}) { + return AppRoute( + SftpPage( + key: key, + spi: spi, + initPath: initPath, + selectPath: isSelect, + ), + 'sftp'); + } + + static AppRoute backup({Key? key}) { + return AppRoute(BackupPage(key: key), 'backup'); + } + + static AppRoute convert({Key? key}) { + return AppRoute(ConvertPage(key: key), 'convert'); + } + + static AppRoute debug({Key? key}) { + return AppRoute(DebugPage(key: key), 'debug'); + } + + static AppRoute docker({Key? key, required ServerPrivateInfo spi}) { + return AppRoute(DockerManagePage(key: key, spi: spi), 'docker'); + } + + static AppRoute editor({Key? key, required String path}) { + return AppRoute(EditorPage(key: key, path: path), 'editor'); + } + + static AppRoute fullscreen({Key? key}) { + return AppRoute(FullScreenPage(key: key), 'fullscreen'); + } + + static AppRoute home({Key? key}) { + return AppRoute(HomePage(key: key), 'home'); + } + + static AppRoute ping({Key? key}) { + return AppRoute(PingPage(key: key), 'ping'); + } + + static AppRoute pkg({Key? key, required ServerPrivateInfo spi}) { + return AppRoute(PkgPage(key: key, spi: spi), 'pkg'); + } + + static AppRoute process({Key? key, required ServerPrivateInfo spi}) { + return AppRoute(ProcessPage(key: key, spi: spi), 'process'); + } + + static AppRoute setting({Key? key}) { + return AppRoute(SettingPage(key: key), 'setting'); + } } diff --git a/lib/core/update.dart b/lib/core/update.dart index 549b77ea..af2b0766 100644 --- a/lib/core/update.dart +++ b/lib/core/update.dart @@ -9,6 +9,7 @@ import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/core/utils/misc.dart' hide pathJoin; import 'package:toolbox/data/model/app/update.dart'; import 'package:toolbox/data/res/path.dart'; +import 'package:toolbox/data/res/ui.dart'; import '../data/provider/app.dart'; import '../data/res/build_data.dart'; @@ -125,7 +126,7 @@ Future _doUpdate(AppUpdate update, BuildContext context, S s) async { ), TextButton( onPressed: () => context.pop(true), - child: Text(s.ok, style: const TextStyle(color: Colors.red)), + child: Text(s.ok, style: textRed), ), ], ); diff --git a/lib/data/model/app/menu.dart b/lib/data/model/app/menu.dart index 8431c2e9..72287ff1 100644 --- a/lib/data/model/app/menu.dart +++ b/lib/data/model/app/menu.dart @@ -2,12 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; enum ServerTabMenuType { + terminal, sftp, - snippet, - pkg, docker, process, - edit; + pkg, + snippet, + ; IconData get icon { switch (this) { @@ -19,31 +20,12 @@ enum ServerTabMenuType { return Icons.system_security_update; case ServerTabMenuType.docker: return Icons.view_agenda; - case ServerTabMenuType.edit: - return Icons.edit; case ServerTabMenuType.process: return Icons.list_alt_outlined; + case ServerTabMenuType.terminal: + return Icons.terminal; } } - - String text(S s) { - switch (this) { - case ServerTabMenuType.sftp: - return 'SFTP'; - case ServerTabMenuType.snippet: - return s.snippet; - case ServerTabMenuType.pkg: - return s.pkg; - case ServerTabMenuType.docker: - return 'Docker'; - case ServerTabMenuType.edit: - return s.edit; - case ServerTabMenuType.process: - return s.process; - } - } - - PopupMenuItem build(S s) => _build(this, icon, text(s)); } enum DockerMenuType { diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 356f28eb..ffd67395 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,8 +2,8 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 477; + static const int build = 480; static const String engine = "3.10.6"; - static const String buildAt = "2023-08-17 21:39:55.328086"; - static const int modifications = 14; + static const String buildAt = "2023-08-19 23:10:30.475495"; + static const int modifications = 10; } diff --git a/lib/data/res/ui.dart b/lib/data/res/ui.dart index dda846b9..86ba8910 100644 --- a/lib/data/res/ui.dart +++ b/lib/data/res/ui.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; /// Font style +const textSize9Grey = TextStyle(color: Colors.grey, fontSize: 9); const textSize11 = TextStyle(fontSize: 11); const textSize12Grey = TextStyle(color: Colors.grey, fontSize: 11); const textSize13 = TextStyle(fontSize: 13); @@ -12,6 +13,7 @@ const textSize18 = TextStyle(fontSize: 18); const textSize27 = TextStyle(fontSize: 27); const grey = TextStyle(color: Colors.grey); +const textRed = TextStyle(color: Colors.red); /// Icon diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index c5d8b9af..d6c7ffaf 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -26,7 +26,7 @@ import '../widget/url_text.dart'; class DockerManagePage extends StatefulWidget { final ServerPrivateInfo spi; - const DockerManagePage(this.spi, {Key? key}) : super(key: key); + const DockerManagePage({required this.spi, Key? key}) : super(key: key); @override State createState() => _DockerManagePageState(); @@ -223,10 +223,7 @@ class _DockerManagePageState extends State { ), TextButton( onPressed: onSubmitted, - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.ok, style: textRed), ), ], ); @@ -327,10 +324,7 @@ class _DockerManagePageState extends State { ); } }, - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.ok, style: textRed), ), ], ); diff --git a/lib/view/page/full_screen.dart b/lib/view/page/full_screen.dart index 62afdb35..b928ad20 100644 --- a/lib/view/page/full_screen.dart +++ b/lib/view/page/full_screen.dart @@ -22,7 +22,6 @@ import '../../data/model/server/server.dart'; import '../../data/model/server/server_private_info.dart'; import '../../data/model/server/server_status.dart'; import '../../data/res/color.dart'; -import 'server/detail.dart'; import 'server/edit.dart'; import 'setting.dart'; @@ -163,10 +162,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { final rootDisk = findRootDisk(ss.disk); return InkWell( - onTap: () => AppRoute( - ServerDetailPage(spi.id), - 'server detail page', - ).go(context), + onTap: () => AppRoute.serverDetail(spi: spi).go(context), child: Stack( children: [ Positioned( diff --git a/lib/view/page/pkg.dart b/lib/view/page/pkg.dart index 2e79b75d..02221fff 100644 --- a/lib/view/page/pkg.dart +++ b/lib/view/page/pkg.dart @@ -16,8 +16,8 @@ import '../widget/custom_appbar.dart'; import '../widget/round_rect_card.dart'; import '../widget/two_line_text.dart'; -class PkgManagePage extends StatefulWidget { - const PkgManagePage(this.spi, {Key? key}) : super(key: key); +class PkgPage extends StatefulWidget { + const PkgPage({Key? key, required this.spi}) : super(key: key); final ServerPrivateInfo spi; @@ -25,7 +25,7 @@ class PkgManagePage extends StatefulWidget { _PkgManagePageState createState() => _PkgManagePageState(); } -class _PkgManagePageState extends State +class _PkgManagePageState extends State with SingleTickerProviderStateMixin { late MediaQueryData _media; final _scrollController = ScrollController(); @@ -122,10 +122,7 @@ class _PkgManagePageState extends State child: Text(_s.cancel)), TextButton( onPressed: () => onSubmitted(), - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.ok, style: textRed), ), ], ); diff --git a/lib/view/page/private_key/edit.dart b/lib/view/page/private_key/edit.dart index 09d83d12..0a512c05 100644 --- a/lib/view/page/private_key/edit.dart +++ b/lib/view/page/private_key/edit.dart @@ -79,20 +79,35 @@ class _PrivateKeyEditPageState extends State } PreferredSizeWidget _buildAppBar() { - final actions = widget.pki == null - ? null - : [ - IconButton( - tooltip: _s.delete, + final actions = [ + IconButton( + tooltip: _s.delete, + onPressed: () { + showRoundDialog( + context: context, + title: Text(_s.attention), + child: Text(_s.sureDelete(widget.pki!.id)), + actions: [ + TextButton( onPressed: () { _provider.delete(widget.pki!); context.pop(); + context.pop(); }, - icon: const Icon(Icons.delete)) - ]; + child: Text( + _s.ok, + style: textRed, + ), + ), + ], + ); + }, + icon: const Icon(Icons.delete), + ) + ]; return CustomAppBar( title: Text(_s.edit, style: textSize18), - actions: actions, + actions: widget.pki == null ? null : actions, ); } diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 75023589..3fe7a4ba 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -1,10 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:provider/provider.dart'; +import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/core/extension/order.dart'; import 'package:toolbox/data/model/server/cpu.dart'; +import 'package:toolbox/data/model/server/server_private_info.dart'; import '../../../core/extension/numx.dart'; +import '../../../core/route.dart'; import '../../../data/model/server/net_speed.dart'; import '../../../data/model/server/server.dart'; import '../../../data/model/server/server_status.dart'; @@ -18,9 +21,9 @@ import '../../widget/custom_appbar.dart'; import '../../widget/round_rect_card.dart'; class ServerDetailPage extends StatefulWidget { - const ServerDetailPage(this.id, {Key? key}) : super(key: key); + const ServerDetailPage({Key? key, required this.spi}) : super(key: key); - final String id; + final ServerPrivateInfo spi; @override _ServerDetailPageState createState() => _ServerDetailPageState(); @@ -62,7 +65,7 @@ class _ServerDetailPageState extends State @override Widget build(BuildContext context) { return Consumer(builder: (_, provider, __) { - final s = provider.servers[widget.id]; + final s = provider.servers[widget.spi.id]; if (s == null) { return Scaffold( body: Center( @@ -78,6 +81,17 @@ class _ServerDetailPageState extends State return Scaffold( appBar: CustomAppBar( title: Text(si.spi.name, style: textSize18), + actions: [ + IconButton( + icon: const Icon(Icons.edit), + onPressed: () async { + final delete = await AppRoute.serverEdit(spi: si.spi).go(context); + if (delete == true) { + context.pop(); + } + }, + ) + ], ), body: ReorderableListView.builder( padding: EdgeInsets.only( diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index cff2a43a..9d516e0f 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -100,17 +100,10 @@ class _ServerEditPageState extends State with AfterLayoutMixin { onPressed: () { _serverProvider.delServer(widget.spi!.id); context.pop(); - context.pop(); + context.pop(true); }, - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.ok, style: textRed), ), - TextButton( - onPressed: () => context.pop(), - child: Text(_s.cancel), - ) ], ); }, diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index de7921f2..05e37773 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -30,13 +30,8 @@ import '../../../data/model/app/menu.dart'; import '../../../data/res/ui.dart'; import '../../../data/store/setting.dart'; import '../../../locator.dart'; -import '../../widget/popup_menu.dart'; import '../../widget/round_rect_card.dart'; -import '../docker.dart'; -import '../pkg.dart'; -import '../storage/sftp.dart'; import '../ssh/term.dart'; -import 'detail.dart'; import 'edit.dart'; class ServerPage extends StatefulWidget { @@ -49,13 +44,12 @@ class ServerPage extends StatefulWidget { class _ServerPageState extends State with AutomaticKeepAliveClientMixin, AfterLayoutMixin { late MediaQueryData _media; - late ThemeData _theme; late ServerProvider _serverProvider; late SettingStore _settingStore; late S _s; String? _tag; - bool _buildGrid = false; + bool _useDoubleColumn = false; @override void initState() { @@ -68,8 +62,7 @@ class _ServerPageState extends State void didChangeDependencies() { super.didChangeDependencies(); _media = MediaQuery.of(context); - _buildGrid = _media.isLarge; - _theme = Theme.of(context); + _useDoubleColumn = _media.useDoubleColumn; _s = S.of(context)!; } @@ -106,10 +99,10 @@ class _ServerPageState extends State } final filtered = _filterServers(pro); - if (_buildGrid) { + if (_useDoubleColumn) { return _buildBodyMedium(pro); } - return _buildBodySmall(pro, filtered); + return _buildBodySmall(provider: pro, filtered: filtered); }, ); if (isDesktop) { @@ -128,10 +121,13 @@ class _ServerPageState extends State _tag == null || (pro.servers[e]?.spi.tags?.contains(_tag) ?? false)) .toList(); - Widget _buildBodySmall(ServerProvider pro, List filtered) { + Widget _buildBodySmall( + {required ServerProvider provider, + required List filtered, + EdgeInsets? padding = const EdgeInsets.fromLTRB(7, 10, 7, 7)}) { return ReorderableListView.builder( header: TagSwitcher( - tags: pro.tags, + tags: provider.tags, width: _media.size.width, onTagChanged: (p0) => setState(() { _tag = p0; @@ -140,9 +136,9 @@ class _ServerPageState extends State all: _s.all, ), footer: const SizedBox(height: 77), - padding: const EdgeInsets.fromLTRB(7, 10, 7, 7), + padding: padding, onReorder: (oldIndex, newIndex) => setState(() { - pro.serverOrder.moveByItem( + provider.serverOrder.moveByItem( filtered, oldIndex, newIndex, @@ -153,7 +149,7 @@ class _ServerPageState extends State itemBuilder: (_, index) => ReorderableDelayedDragStartListener( key: ValueKey('$_tag${filtered[index]}'), index: index, - child: _buildEachServerCard(pro.servers[filtered[index]]), + child: _buildEachServerCard(provider.servers[filtered[index]]), ), itemCount: filtered.length, ); @@ -166,10 +162,18 @@ class _ServerPageState extends State return Row( children: [ Expanded( - child: _buildBodySmall(pro, left), + child: _buildBodySmall( + provider: pro, + filtered: left, + padding: const EdgeInsets.fromLTRB(7, 10, 0, 7), + ), ), Expanded( - child: _buildBodySmall(pro, right), + child: _buildBodySmall( + provider: pro, + filtered: right, + padding: const EdgeInsets.fromLTRB(0, 10, 7, 7), + ), ), ], ); @@ -184,10 +188,7 @@ class _ServerPageState extends State key: Key(si.spi.id + (_tag ?? '')), onTap: () { if (si.state.canViewDetails) { - AppRoute( - ServerDetailPage(si.spi.id), - 'server detail page', - ).go(context); + AppRoute.serverDetail(spi: si.spi).go(context); } else if (si.status.failedInfo != null) { _showFailReason(si.status); } @@ -208,26 +209,36 @@ class _ServerPageState extends State ) { final rootDisk = findRootDisk(ss.disk); late final List children; - var height = 23.0; + double? height; if (cs != ServerState.finished) { + height = 23.0; children = [ _buildServerCardTitle(ss, cs, spi), ]; } else { - height = 137; children = [ _buildServerCardTitle(ss, cs, spi), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _buildPercentCircle(ss.cpu.usedPercent()), - _buildPercentCircle(ss.mem.usedPercent * 100), - _buildNet(ss), - _buildIOData( - 'Total:\n${rootDisk?.size}', 'Used:\n${rootDisk?.usedPercent}%') - ], + height13, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 13), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildPercentCircle(ss.cpu.usedPercent()), + _buildPercentCircle(ss.mem.usedPercent * 100), + _buildNet(ss), + _buildIOData( + 'Total:\n${rootDisk?.size}', + 'Used:\n${rootDisk?.usedPercent}%', + ), + ], + ), + ), + height13, + SizedBox( + height: 29, + child: _buildMoreBtn(spi), ), - const SizedBox(height: 3), ]; } @@ -237,7 +248,8 @@ class _ServerPageState extends State height: height, child: Column( mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: children, ), ); @@ -267,14 +279,7 @@ class _ServerPageState extends State ) ], ), - Row( - children: [ - _buildTopRightText(ss, cs), - width13, - _buildSSHBtn(spi), - _buildMoreBtn(spi), - ], - ) + _buildTopRightText(ss, cs), ], ), ); @@ -320,81 +325,81 @@ class _ServerPageState extends State ); } - Widget _buildSSHBtn(ServerPrivateInfo spi) { - return GestureDetector( - child: const Icon(Icons.terminal, size: 21), - onTap: () => gotoSSH(spi), - ); + void _onTapMoreBtns(ServerTabMenuType value, ServerPrivateInfo spi) async { + switch (value) { + case ServerTabMenuType.pkg: + AppRoute.pkg(spi: spi).checkClientAndGo( + context: context, + s: _s, + id: spi.id, + ); + break; + case ServerTabMenuType.sftp: + AppRoute.sftp(spi: spi).checkClientAndGo( + context: context, + s: _s, + id: spi.id, + ); + break; + case ServerTabMenuType.snippet: + final provider = locator(); + final snippets = await showDialog>( + context: context, + builder: (_) => TagPicker( + items: provider.snippets, + containsTag: (t, tag) => t.tags?.contains(tag) ?? false, + tags: provider.tags.toSet(), + name: (t) => t.name, + ), + ); + if (snippets == null) { + return; + } + final result = await _serverProvider.runSnippets(spi.id, snippets); + if (result != null && result.isNotEmpty) { + showRoundDialog( + context: context, + title: Text(_s.result), + child: Text(result), + actions: [ + TextButton( + onPressed: () => copy2Clipboard(result), + child: Text(_s.copy), + ) + ], + ); + } + break; + case ServerTabMenuType.docker: + AppRoute.docker(spi: spi).checkClientAndGo( + context: context, + s: _s, + id: spi.id, + ); + break; + case ServerTabMenuType.process: + AppRoute(ProcessPage(spi: spi), 'process page').checkClientAndGo( + context: context, + s: _s, + id: spi.id, + ); + break; + case ServerTabMenuType.terminal: + gotoSSH(spi); + break; + } } Widget _buildMoreBtn(ServerPrivateInfo spi) { - return PopupMenu( - items: ServerTabMenuType.values.map((e) => e.build(_s)).toList(), - padding: const EdgeInsets.symmetric(horizontal: 10), - onSelected: (ServerTabMenuType value) async { - switch (value) { - case ServerTabMenuType.pkg: - AppRoute(PkgManagePage(spi), 'pkg manage').checkClientAndGo( - context: context, - s: _s, - id: spi.id, - ); - break; - case ServerTabMenuType.sftp: - AppRoute(SftpPage(spi), 'SFTP').checkClientAndGo( - context: context, - s: _s, - id: spi.id, - ); - break; - case ServerTabMenuType.snippet: - final provider = locator(); - final snippets = await showDialog>( - context: context, - builder: (_) => TagPicker( - items: provider.snippets, - containsTag: (t, tag) => t.tags?.contains(tag) ?? false, - tags: provider.tags.toSet(), - name: (t) => t.name, - ), - ); - if (snippets == null) { - return; - } - final result = await _serverProvider.runSnippets(spi.id, snippets); - if (result != null && result.isNotEmpty) { - showRoundDialog( - context: context, - title: Text(_s.result), - child: Text(result), - actions: [ - TextButton( - onPressed: () => copy2Clipboard(result), - child: Text(_s.copy), - ) - ], - ); - } - break; - case ServerTabMenuType.edit: - AppRoute(ServerEditPage(spi: spi), 'Edit server info').go(context); - break; - case ServerTabMenuType.docker: - AppRoute(DockerManagePage(spi), 'Docker manage').checkClientAndGo( - context: context, - s: _s, - id: spi.id, - ); - break; - case ServerTabMenuType.process: - AppRoute(ProcessPage(spi: spi), 'process page').checkClientAndGo( - context: context, - s: _s, - id: spi.id, - ); - break; - } - }, + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: ServerTabMenuType.values + .map((e) => IconButton( + onPressed: () => _onTapMoreBtns(e, spi), + padding: EdgeInsets.zero, + icon: Icon(e.icon, size: 15), + )) + .toList(), ); } @@ -411,15 +416,6 @@ class _ServerPageState extends State ); } - Widget _buildExplainText(String text) { - return Text( - text, - style: const TextStyle(fontSize: 12), - textAlign: TextAlign.center, - textScaleFactor: 1.0, - ); - } - String _getTopRightStr( ServerState cs, double? temp, @@ -453,53 +449,51 @@ class _ServerPageState extends State } Widget _buildIOData(String up, String down) { - final statusTextStyle = TextStyle( - fontSize: 9, color: _theme.textTheme.bodyLarge!.color!.withAlpha(177)); return Column( - children: [ - const SizedBox(height: 5), - Text( - up, - style: statusTextStyle, - textAlign: TextAlign.center, - textScaleFactor: 1.0, - ), - const SizedBox(height: 3), - Text( - down, - style: statusTextStyle, - textAlign: TextAlign.center, - textScaleFactor: 1.0, - ) - ], - ); + children: [ + const SizedBox(height: 5), + Text( + up, + style: textSize9Grey, + textAlign: TextAlign.center, + textScaleFactor: 1.0, + ), + const SizedBox(height: 3), + Text( + down, + style: textSize9Grey, + textAlign: TextAlign.center, + textScaleFactor: 1.0, + ) + ], + ); } Widget _buildPercentCircle(double percent) { if (percent <= 0) percent = 0.01; if (percent >= 100) percent = 99.9; return Stack( - children: [ - Center( - child: CircleChart( - progressColor: primaryColor, - progressNumber: percent, - maxNumber: 100, - width: 53, - height: 53, + children: [ + Center( + child: CircleChart( + progressColor: primaryColor, + progressNumber: percent, + maxNumber: 100, + width: 53, + height: 53, + ), + ), + Positioned.fill( + child: Center( + child: Text( + '${percent.toStringAsFixed(1)}%', + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 11), + textScaleFactor: 1.0, ), ), - Positioned.fill( - child: Center( - child: Text( - '${percent.toStringAsFixed(1)}%', - textAlign: TextAlign.center, - style: const TextStyle(fontSize: 11), - textScaleFactor: 1.0, - ), - ), - ), - ], + ), + ], ); } diff --git a/lib/view/page/ssh/term.dart b/lib/view/page/ssh/term.dart index a91d93a4..12a7f2aa 100644 --- a/lib/view/page/ssh/term.dart +++ b/lib/view/page/ssh/term.dart @@ -22,7 +22,6 @@ import '../../../data/res/color.dart'; import '../../../data/res/terminal.dart'; import '../../../data/store/setting.dart'; import '../../../locator.dart'; -import '../storage/sftp.dart'; const echoPWD = 'echo \$PWD'; @@ -275,8 +274,7 @@ class _SSHPageState extends State { ); return; } - final page = SftpPage(widget.spi, initPath: initPath); - AppRoute(page, 'SSH SFTP').go(context); + AppRoute.sftp(spi: widget.spi, initPath: initPath).go(context); } } diff --git a/lib/view/page/storage/local.dart b/lib/view/page/storage/local.dart index bb72c9aa..c3ce34e0 100644 --- a/lib/view/page/storage/local.dart +++ b/lib/view/page/storage/local.dart @@ -9,7 +9,6 @@ import 'package:toolbox/data/provider/sftp.dart'; import 'package:toolbox/data/res/misc.dart'; import 'package:toolbox/locator.dart'; import 'package:toolbox/view/page/editor.dart'; -import 'package:toolbox/view/page/storage/sftp.dart'; import 'package:toolbox/view/widget/input_field.dart'; import 'package:toolbox/view/widget/picker.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; @@ -312,12 +311,9 @@ class _LocalStoragePageState extends State { if (spi == null) { return; } - final remotePath = await AppRoute( - SftpPage( - spi, - selectPath: true, - ), - 'SFTP page (select)', + final remotePath = await AppRoute.sftp( + spi: spi, + isSelect: true, ).go(context); if (remotePath == null) { return; diff --git a/lib/view/page/storage/sftp.dart b/lib/view/page/storage/sftp.dart index 560682bb..9d2c177a 100644 --- a/lib/view/page/storage/sftp.dart +++ b/lib/view/page/storage/sftp.dart @@ -37,11 +37,11 @@ class SftpPage extends StatefulWidget { final String? initPath; final bool selectPath; - const SftpPage( - this.spi, { + const SftpPage({ Key? key, + required this.spi, + required this.selectPath, this.initPath, - this.selectPath = false, }) : super(key: key); @override @@ -479,10 +479,7 @@ class _SftpPageState extends State { } _listDir(); }, - child: Text( - _s.delete, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.delete, style: textRed), ), ], ); @@ -523,10 +520,7 @@ class _SftpPageState extends State { context.pop(); _listDir(); }, - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.ok, style: textRed), ), ], ); @@ -569,10 +563,7 @@ class _SftpPageState extends State { context.pop(); _listDir(); }, - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.ok, style: textRed), ), ], ); @@ -610,10 +601,7 @@ class _SftpPageState extends State { context.pop(); _listDir(); }, - child: Text( - _s.rename, - style: const TextStyle(color: Colors.red), - ), + child: Text(_s.rename, style: textRed), ), ], );