mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
new: tag rename
This commit is contained in:
@@ -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
29
lib/data/res/default.dart
Normal 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';
|
||||||
@@ -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'
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class _PingPageState extends State<PingPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
|
heroTag: 'ping',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
try {
|
try {
|
||||||
doPing();
|
doPing();
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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 == '') {
|
||||||
|
|||||||
@@ -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),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
scrollDirection: Axis.horizontal,
|
constraints: const BoxConstraints(maxHeight: 27),
|
||||||
itemBuilder: (context, index) {
|
child: ListView.builder(
|
||||||
if (index < tags.length) {
|
scrollDirection: Axis.horizontal,
|
||||||
return _buildTagItem(tags[index], false);
|
itemBuilder: (context, index) {
|
||||||
} else if (index > tags.length) {
|
if (index < tags.length) {
|
||||||
return _buildTagItem(tagSuggestions![index - tags.length - 1], true);
|
return _buildTagItem(context, tags[index], false);
|
||||||
}
|
} else if (index > tags.length) {
|
||||||
return const VerticalDivider();
|
return _buildTagItem(context,
|
||||||
},
|
tagSuggestions![index - tags.length - 1], true,);
|
||||||
itemCount: counts,
|
}
|
||||||
),);
|
return const VerticalDivider();
|
||||||
|
},
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user