From 55a13799b2b5a3c0259337bcf3452afbfe0fba39 Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Wed, 31 May 2023 17:56:08 +0800 Subject: [PATCH] new: tag `rename` --- lib/data/provider/server.dart | 13 +++++++ lib/data/res/default.dart | 29 +++++++++++++++ lib/data/res/misc.dart | 11 ------ lib/data/store/setting.dart | 21 ++++------- lib/view/page/ping.dart | 1 + lib/view/page/server/detail.dart | 2 +- lib/view/page/server/edit.dart | 2 + lib/view/page/server/tab.dart | 1 + lib/view/page/snippet/edit.dart | 1 + lib/view/page/snippet/list.dart | 3 +- lib/view/widget/tag.dart | 64 +++++++++++++++++++++++--------- 11 files changed, 103 insertions(+), 45 deletions(-) create mode 100644 lib/data/res/default.dart diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index c2ba7dfa..8483711f 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -77,6 +77,19 @@ class ServerProvider extends BusyProvider { notifyListeners(); } + void renameTag(String old, String new_) { + for (final s in _servers.values) { + if (s.spi.tags == null) continue; + for (var i = 0; i < s.spi.tags!.length; i++) { + if (s.spi.tags![i] == old) { + s.spi.tags![i] = new_; + } + } + _serverStore.update(s.spi, s.spi); + } + _updateTags(); + } + Server genServer(ServerPrivateInfo spi) { return Server(spi, initStatus, null, ServerState.disconnected); } diff --git a/lib/data/res/default.dart b/lib/data/res/default.dart new file mode 100644 index 00000000..9e4325ef --- /dev/null +++ b/lib/data/res/default.dart @@ -0,0 +1,29 @@ +import 'dart:ui'; + +// default server details page cards order +const defaultDetailCardOrder = [ + 'uptime', + 'cpu', + 'mem', + 'swap', + 'disk', + 'net', + 'temp' +]; + +const defaultDiskIgnorePath = [ + 'udev', + 'tmpfs', + 'devtmpfs', + 'overlay', + 'run', + 'none', +]; + +const defaultPrimaryColor = Color.fromARGB(255, 145, 58, 31); + +const defaultLaunchPageIdx = 0; + +const defaultUpdateInterval = 3; + +const defaultEditorTheme = 'monokai'; diff --git a/lib/data/res/misc.dart b/lib/data/res/misc.dart index 3b3d6940..2e6ec310 100644 --- a/lib/data/res/misc.dart +++ b/lib/data/res/misc.dart @@ -15,14 +15,3 @@ const maxDebugLogLines = 100; /// Method Channels const pkgName = 'tech.lolli.toolbox'; const bgRunChannel = MethodChannel('$pkgName/app_retain'); - -// default server details page cards order -const defaultDetailCardOrder = [ - 'uptime', - 'cpu', - 'mem', - 'swap', - 'disk', - 'net', - 'temp' -]; diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 5738682d..979ecf92 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -1,19 +1,19 @@ -import 'package:flutter/material.dart'; import 'package:toolbox/core/persistant_store.dart'; import 'package:toolbox/core/utils/platform.dart'; -import 'package:toolbox/data/res/misc.dart'; + +import '../res/default.dart'; class SettingStore extends PersistentStore { StoreProperty get primaryColor => property( 'primaryColor', - defaultValue: const Color.fromARGB(255, 145, 58, 31).value, + defaultValue: defaultPrimaryColor.value, ); StoreProperty get serverStatusUpdateInterval => - property('serverStatusUpdateInterval', defaultValue: 3); + property('serverStatusUpdateInterval', defaultValue: defaultUpdateInterval,); // Lanch page idx - StoreProperty get launchPage => property('launchPage', defaultValue: 0); + StoreProperty get launchPage => property('launchPage', defaultValue: defaultLaunchPageIdx,); // Version of store db StoreProperty get storeVersion => @@ -57,14 +57,7 @@ class SettingStore extends PersistentStore { // Server detail disk ignore path StoreProperty> get diskIgnorePath => - property('diskIgnorePath', defaultValue: [ - 'udev', - 'tmpfs', - 'devtmpfs', - 'overlay', - 'run', - 'none', - ]); + property('diskIgnorePath', defaultValue: defaultDiskIgnorePath); // Locale StoreProperty get locale => property('locale', defaultValue: null); @@ -75,5 +68,5 @@ class SettingStore extends PersistentStore { // Editor theme StoreProperty get editorTheme => - property('editorTheme', defaultValue: 'monokai'); + property('editorTheme', defaultValue: defaultEditorTheme); } diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index 280ca519..11091b65 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -76,6 +76,7 @@ class _PingPageState extends State ), ), floatingActionButton: FloatingActionButton( + heroTag: 'ping', onPressed: () { try { doPing(); diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 0d39f426..0431727d 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -7,7 +7,6 @@ import 'package:toolbox/data/model/server/disk.dart'; import 'package:toolbox/data/model/server/dist.dart'; import 'package:toolbox/data/model/server/memory.dart'; import 'package:toolbox/data/model/server/temp.dart'; -import 'package:toolbox/data/res/misc.dart'; import '../../../core/extension/numx.dart'; import '../../../data/model/server/net_speed.dart'; @@ -15,6 +14,7 @@ import '../../../data/model/server/server.dart'; import '../../../data/model/server/server_status.dart'; import '../../../data/provider/server.dart'; import '../../../data/res/color.dart'; +import '../../../data/res/default.dart'; import '../../../data/res/ui.dart'; import '../../../data/store/setting.dart'; import '../../../locator.dart'; diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index 497720f2..f38d80c1 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -153,6 +153,7 @@ class _ServerEditPageState extends State with AfterLayoutMixin { }), s: _s, tagSuggestions: [..._serverProvider.tags], + onRenameTag: _serverProvider.renameTag, ), width7, Row( @@ -225,6 +226,7 @@ class _ServerEditPageState extends State with AfterLayoutMixin { Widget _buildFAB() { return FloatingActionButton( + heroTag: 'server', child: const Icon(Icons.send), onPressed: () async { if (_ipController.text == '') { diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 03dfd51b..38446ade 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -74,6 +74,7 @@ class _ServerPageState extends State 'Add server info page', ).go(context), tooltip: _s.addAServer, + heroTag: 'server', child: const Icon(Icons.add), ), ); diff --git a/lib/view/page/snippet/edit.dart b/lib/view/page/snippet/edit.dart index e32f1ba7..93e90cca 100644 --- a/lib/view/page/snippet/edit.dart +++ b/lib/view/page/snippet/edit.dart @@ -65,6 +65,7 @@ class _SnippetEditPageState extends State Widget _buildFAB() { return FloatingActionButton( + heroTag: 'snippet', child: const Icon(Icons.send), onPressed: () { final name = _nameController.text; diff --git a/lib/view/page/snippet/list.dart b/lib/view/page/snippet/list.dart index 141db7c9..e843788d 100644 --- a/lib/view/page/snippet/list.dart +++ b/lib/view/page/snippet/list.dart @@ -28,9 +28,10 @@ class _SnippetListPageState extends State { return Scaffold( body: _buildBody(), floatingActionButton: FloatingActionButton( + heroTag: 'snippet', child: const Icon(Icons.add), onPressed: () => - AppRoute(const SnippetEditPage(), 'snippet edit page').go(context), + AppRoute(const SnippetEditPage(), 'snippet edit page',).go(context), ), ); } diff --git a/lib/view/widget/tag.dart b/lib/view/widget/tag.dart index 0546e921..bc8e58fd 100644 --- a/lib/view/widget/tag.dart +++ b/lib/view/widget/tag.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/view/widget/input_field.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -10,7 +11,7 @@ class TagEditor extends StatelessWidget { final List tags; final S s; final void Function(List)? onChanged; - final void Function(String)? onTapTag; + final void Function(String old, String new_)? onRenameTag; final List? tagSuggestions; const TagEditor({ @@ -18,7 +19,7 @@ class TagEditor extends StatelessWidget { required this.tags, required this.s, this.onChanged, - this.onTapTag, + this.onRenameTag, this.tagSuggestions, }); @@ -26,7 +27,7 @@ class TagEditor extends StatelessWidget { Widget build(BuildContext context) { return RoundRectCard(ListTile( leading: const Icon(Icons.tag), - title: _buildTags(tags), + title: _buildTags(context, tags), trailing: InkWell( child: const Icon(Icons.add), onTap: () { @@ -36,30 +37,34 @@ class TagEditor extends StatelessWidget { )); } - Widget _buildTags(List tags) { + Widget _buildTags(BuildContext context, List tags) { tagSuggestions?.removeWhere((element) => tags.contains(element)); final suggestionLen = tagSuggestions?.length ?? 0; final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1); if (counts == 0) return Text(s.tag); - return ConstrainedBox(constraints: BoxConstraints(maxHeight: 27), child: ListView.builder( - scrollDirection: Axis.horizontal, - itemBuilder: (context, index) { - if (index < tags.length) { - return _buildTagItem(tags[index], false); - } else if (index > tags.length) { - return _buildTagItem(tagSuggestions![index - tags.length - 1], true); - } - return const VerticalDivider(); - }, - itemCount: counts, - ),); + return ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 27), + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + if (index < tags.length) { + return _buildTagItem(context, tags[index], false); + } else if (index > tags.length) { + return _buildTagItem(context, + tagSuggestions![index - tags.length - 1], true,); + } + return const VerticalDivider(); + }, + itemCount: counts, + ), + ); } - Widget _buildTagItem(String tag, bool isAdd) { + Widget _buildTagItem(BuildContext context, String tag, bool isAdd) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 3), child: GestureDetector( - onTap: () => onTapTag?.call(tag), + onTap: () => _showRenameDialog(context, tag), child: Container( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(20.0)), @@ -122,4 +127,27 @@ class TagEditor extends StatelessWidget { ], ); } + + void _showRenameDialog(BuildContext context, String tag) { + final textEditingController = TextEditingController(text: tag); + showRoundDialog( + context: context, + title: Text(s.rename), + child: Input( + controller: textEditingController, + hint: s.tag, + ), + actions: [ + TextButton( + onPressed: () { + final newTag = textEditingController.text.trim(); + if (newTag.isEmpty) return; + onRenameTag?.call(tag, newTag); + context.pop(); + }, + child: Text(s.rename), + ), + ], + ); + } }