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();
}
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);
}

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

View File

@@ -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<int> get primaryColor => property(
'primaryColor',
defaultValue: const Color.fromARGB(255, 145, 58, 31).value,
defaultValue: defaultPrimaryColor.value,
);
StoreProperty<int> get serverStatusUpdateInterval =>
property('serverStatusUpdateInterval', defaultValue: 3);
property('serverStatusUpdateInterval', defaultValue: defaultUpdateInterval,);
// Lanch page idx
StoreProperty<int> get launchPage => property('launchPage', defaultValue: 0);
StoreProperty<int> get launchPage => property('launchPage', defaultValue: defaultLaunchPageIdx,);
// Version of store db
StoreProperty<int> get storeVersion =>
@@ -57,14 +57,7 @@ class SettingStore extends PersistentStore {
// Server detail disk ignore path
StoreProperty<List<String>> get diskIgnorePath =>
property('diskIgnorePath', defaultValue: [
'udev',
'tmpfs',
'devtmpfs',
'overlay',
'run',
'none',
]);
property('diskIgnorePath', defaultValue: defaultDiskIgnorePath);
// Locale
StoreProperty<String> get locale => property('locale', defaultValue: null);
@@ -75,5 +68,5 @@ class SettingStore extends PersistentStore {
// Editor theme
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(
heroTag: 'ping',
onPressed: () {
try {
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/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';

View File

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

View File

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

View File

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

View File

@@ -28,9 +28,10 @@ class _SnippetListPageState extends State<SnippetListPage> {
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),
),
);
}

View File

@@ -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<String> tags;
final S s;
final void Function(List<String>)? onChanged;
final void Function(String)? onTapTag;
final void Function(String old, String new_)? onRenameTag;
final List<String>? 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<String> tags) {
Widget _buildTags(BuildContext context, List<String> 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),
),
],
);
}
}