new: tag rename

This commit is contained in:
lollipopkit
2023-05-31 17:56:08 +08:00
parent d24fe5ff5d
commit 55a13799b2
11 changed files with 103 additions and 45 deletions

View File

@@ -77,6 +77,19 @@ class ServerProvider extends BusyProvider {
notifyListeners(); 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) { Server genServer(ServerPrivateInfo spi) {
return Server(spi, initStatus, null, ServerState.disconnected); return Server(spi, initStatus, null, ServerState.disconnected);
} }

29
lib/data/res/default.dart Normal file
View File

@@ -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';

View File

@@ -15,14 +15,3 @@ const maxDebugLogLines = 100;
/// Method Channels /// Method Channels
const pkgName = 'tech.lolli.toolbox'; const pkgName = 'tech.lolli.toolbox';
const bgRunChannel = MethodChannel('$pkgName/app_retain'); const bgRunChannel = MethodChannel('$pkgName/app_retain');
// default server details page cards order
const defaultDetailCardOrder = [
'uptime',
'cpu',
'mem',
'swap',
'disk',
'net',
'temp'
];

View File

@@ -1,19 +1,19 @@
import 'package:flutter/material.dart';
import 'package:toolbox/core/persistant_store.dart'; import 'package:toolbox/core/persistant_store.dart';
import 'package:toolbox/core/utils/platform.dart'; import 'package:toolbox/core/utils/platform.dart';
import 'package:toolbox/data/res/misc.dart';
import '../res/default.dart';
class SettingStore extends PersistentStore { class SettingStore extends PersistentStore {
StoreProperty<int> get primaryColor => property( StoreProperty<int> get primaryColor => property(
'primaryColor', 'primaryColor',
defaultValue: const Color.fromARGB(255, 145, 58, 31).value, defaultValue: defaultPrimaryColor.value,
); );
StoreProperty<int> get serverStatusUpdateInterval => StoreProperty<int> get serverStatusUpdateInterval =>
property('serverStatusUpdateInterval', defaultValue: 3); property('serverStatusUpdateInterval', defaultValue: defaultUpdateInterval,);
// Lanch page idx // Lanch page idx
StoreProperty<int> get launchPage => property('launchPage', defaultValue: 0); StoreProperty<int> get launchPage => property('launchPage', defaultValue: defaultLaunchPageIdx,);
// Version of store db // Version of store db
StoreProperty<int> get storeVersion => StoreProperty<int> get storeVersion =>
@@ -57,14 +57,7 @@ class SettingStore extends PersistentStore {
// Server detail disk ignore path // Server detail disk ignore path
StoreProperty<List<String>> get diskIgnorePath => StoreProperty<List<String>> get diskIgnorePath =>
property('diskIgnorePath', defaultValue: [ property('diskIgnorePath', defaultValue: defaultDiskIgnorePath);
'udev',
'tmpfs',
'devtmpfs',
'overlay',
'run',
'none',
]);
// Locale // Locale
StoreProperty<String> get locale => property('locale', defaultValue: null); StoreProperty<String> get locale => property('locale', defaultValue: null);
@@ -75,5 +68,5 @@ class SettingStore extends PersistentStore {
// Editor theme // Editor theme
StoreProperty<String> get editorTheme => StoreProperty<String> get editorTheme =>
property('editorTheme', defaultValue: 'monokai'); property('editorTheme', defaultValue: defaultEditorTheme);
} }

View File

@@ -76,6 +76,7 @@ class _PingPageState extends State<PingPage>
), ),
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
heroTag: 'ping',
onPressed: () { onPressed: () {
try { try {
doPing(); doPing();

View File

@@ -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/dist.dart';
import 'package:toolbox/data/model/server/memory.dart'; import 'package:toolbox/data/model/server/memory.dart';
import 'package:toolbox/data/model/server/temp.dart'; import 'package:toolbox/data/model/server/temp.dart';
import 'package:toolbox/data/res/misc.dart';
import '../../../core/extension/numx.dart'; import '../../../core/extension/numx.dart';
import '../../../data/model/server/net_speed.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/model/server/server_status.dart';
import '../../../data/provider/server.dart'; import '../../../data/provider/server.dart';
import '../../../data/res/color.dart'; import '../../../data/res/color.dart';
import '../../../data/res/default.dart';
import '../../../data/res/ui.dart'; import '../../../data/res/ui.dart';
import '../../../data/store/setting.dart'; import '../../../data/store/setting.dart';
import '../../../locator.dart'; import '../../../locator.dart';

View File

@@ -153,6 +153,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
}), }),
s: _s, s: _s,
tagSuggestions: [..._serverProvider.tags], tagSuggestions: [..._serverProvider.tags],
onRenameTag: _serverProvider.renameTag,
), ),
width7, width7,
Row( Row(
@@ -225,6 +226,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
Widget _buildFAB() { Widget _buildFAB() {
return FloatingActionButton( return FloatingActionButton(
heroTag: 'server',
child: const Icon(Icons.send), child: const Icon(Icons.send),
onPressed: () async { onPressed: () async {
if (_ipController.text == '') { if (_ipController.text == '') {

View File

@@ -74,6 +74,7 @@ class _ServerPageState extends State<ServerPage>
'Add server info page', 'Add server info page',
).go(context), ).go(context),
tooltip: _s.addAServer, tooltip: _s.addAServer,
heroTag: 'server',
child: const Icon(Icons.add), child: const Icon(Icons.add),
), ),
); );

View File

@@ -65,6 +65,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
Widget _buildFAB() { Widget _buildFAB() {
return FloatingActionButton( return FloatingActionButton(
heroTag: 'snippet',
child: const Icon(Icons.send), child: const Icon(Icons.send),
onPressed: () { onPressed: () {
final name = _nameController.text; final name = _nameController.text;

View File

@@ -28,9 +28,10 @@ class _SnippetListPageState extends State<SnippetListPage> {
return Scaffold( return Scaffold(
body: _buildBody(), body: _buildBody(),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
heroTag: 'snippet',
child: const Icon(Icons.add), child: const Icon(Icons.add),
onPressed: () => onPressed: () =>
AppRoute(const SnippetEditPage(), 'snippet edit page').go(context), AppRoute(const SnippetEditPage(), 'snippet edit page',).go(context),
), ),
); );
} }

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; 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/input_field.dart';
import 'package:toolbox/view/widget/round_rect_card.dart'; import 'package:toolbox/view/widget/round_rect_card.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
@@ -10,7 +11,7 @@ class TagEditor extends StatelessWidget {
final List<String> tags; final List<String> tags;
final S s; final S s;
final void Function(List<String>)? onChanged; final void Function(List<String>)? onChanged;
final void Function(String)? onTapTag; final void Function(String old, String new_)? onRenameTag;
final List<String>? tagSuggestions; final List<String>? tagSuggestions;
const TagEditor({ const TagEditor({
@@ -18,7 +19,7 @@ class TagEditor extends StatelessWidget {
required this.tags, required this.tags,
required this.s, required this.s,
this.onChanged, this.onChanged,
this.onTapTag, this.onRenameTag,
this.tagSuggestions, this.tagSuggestions,
}); });
@@ -26,7 +27,7 @@ class TagEditor extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RoundRectCard(ListTile( return RoundRectCard(ListTile(
leading: const Icon(Icons.tag), leading: const Icon(Icons.tag),
title: _buildTags(tags), title: _buildTags(context, tags),
trailing: InkWell( trailing: InkWell(
child: const Icon(Icons.add), child: const Icon(Icons.add),
onTap: () { onTap: () {
@@ -36,30 +37,34 @@ class TagEditor extends StatelessWidget {
)); ));
} }
Widget _buildTags(List<String> tags) { Widget _buildTags(BuildContext context, List<String> tags) {
tagSuggestions?.removeWhere((element) => tags.contains(element)); tagSuggestions?.removeWhere((element) => tags.contains(element));
final suggestionLen = tagSuggestions?.length ?? 0; final suggestionLen = tagSuggestions?.length ?? 0;
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1); final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
if (counts == 0) return Text(s.tag); if (counts == 0) return Text(s.tag);
return ConstrainedBox(constraints: BoxConstraints(maxHeight: 27), child: ListView.builder( return ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 27),
child: ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index < tags.length) { if (index < tags.length) {
return _buildTagItem(tags[index], false); return _buildTagItem(context, tags[index], false);
} else if (index > tags.length) { } else if (index > tags.length) {
return _buildTagItem(tagSuggestions![index - tags.length - 1], true); return _buildTagItem(context,
tagSuggestions![index - tags.length - 1], true,);
} }
return const VerticalDivider(); return const VerticalDivider();
}, },
itemCount: counts, itemCount: counts,
),); ),
);
} }
Widget _buildTagItem(String tag, bool isAdd) { Widget _buildTagItem(BuildContext context, String tag, bool isAdd) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 3), padding: const EdgeInsets.symmetric(horizontal: 3),
child: GestureDetector( child: GestureDetector(
onTap: () => onTapTag?.call(tag), onTap: () => _showRenameDialog(context, tag),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(20.0)), 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),
),
],
);
}
} }