mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
#73 opt.: reorderable
This commit is contained in:
@@ -4,9 +4,6 @@ import 'package:nil/nil.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/order.dart';
|
import 'package:toolbox/core/extension/order.dart';
|
||||||
import 'package:toolbox/data/model/server/cpu.dart';
|
import 'package:toolbox/data/model/server/cpu.dart';
|
||||||
import 'package:toolbox/data/model/server/disk.dart';
|
|
||||||
import 'package:toolbox/data/model/server/memory.dart';
|
|
||||||
import 'package:toolbox/data/model/server/temp.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';
|
||||||
@@ -51,6 +48,18 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final map = Map.fromIterables(
|
||||||
|
defaultDetailCardOrder,
|
||||||
|
[
|
||||||
|
_buildUpTimeAndSys,
|
||||||
|
_buildCPUView,
|
||||||
|
_buildMemView,
|
||||||
|
_buildSwapView,
|
||||||
|
_buildDiskView,
|
||||||
|
_buildNetView,
|
||||||
|
_buildTemperature,
|
||||||
|
],
|
||||||
|
);
|
||||||
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||||
final s = provider.servers[widget.id];
|
final s = provider.servers[widget.id];
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
@@ -60,16 +69,19 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _buildMainPage(s);
|
return _buildMainPage(s, map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMainPage(Server si) {
|
Widget _buildMainPage(
|
||||||
|
Server si,
|
||||||
|
Map<String, Widget Function(ServerStatus)> map,
|
||||||
|
) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(si.spi.name, style: textSize18),
|
title: Text(si.spi.name, style: textSize18),
|
||||||
),
|
),
|
||||||
body: ReorderableListView(
|
body: ReorderableListView.builder(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: 13, right: 13, top: 13, bottom: _media.padding.bottom),
|
left: 13, right: 13, top: 13, bottom: _media.padding.bottom),
|
||||||
onReorder: (int oldIndex, int newIndex) {
|
onReorder: (int oldIndex, int newIndex) {
|
||||||
@@ -82,30 +94,18 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
footer: height13,
|
footer: height13,
|
||||||
children: _buildMainList(si.status),
|
itemCount: _cardsOrder.length,
|
||||||
|
buildDefaultDragHandles: false,
|
||||||
|
itemBuilder: (context, index) => ReorderableDelayedDragStartListener(
|
||||||
|
key: ValueKey(index),
|
||||||
|
index: index,
|
||||||
|
child: map[_cardsOrder[index]]?.call(si.status) ?? nil,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMainList(ServerStatus ss) {
|
Widget _buildCPUView(ServerStatus ss) {
|
||||||
final map = Map.fromIterables(
|
|
||||||
defaultDetailCardOrder,
|
|
||||||
[
|
|
||||||
_buildUpTimeAndSys(ss.sysVer, ss.uptime),
|
|
||||||
_buildCPUView(ss.cpu),
|
|
||||||
_buildMemView(ss.mem),
|
|
||||||
_buildSwapView(ss.swap),
|
|
||||||
_buildDiskView(ss.disk),
|
|
||||||
_buildNetView(ss.netSpeed),
|
|
||||||
_buildTemperature(ss.temps),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
return _cardsOrder
|
|
||||||
.map((e) => SizedBox(key: ValueKey(e), child: map[e]))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildCPUView(Cpus cs) {
|
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
Padding(
|
Padding(
|
||||||
padding: roundRectCardPadding,
|
padding: roundRectCardPadding,
|
||||||
@@ -114,25 +114,25 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${cs.usedPercent(coreIdx: 0).toInt()}%',
|
'${ss.cpu.usedPercent(coreIdx: 0).toInt()}%',
|
||||||
style: textSize27,
|
style: textSize27,
|
||||||
textScaleFactor: 1.0,
|
textScaleFactor: 1.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
_buildDetailPercent(cs.user, 'user'),
|
_buildDetailPercent(ss.cpu.user, 'user'),
|
||||||
width13,
|
width13,
|
||||||
_buildDetailPercent(cs.sys, 'sys'),
|
_buildDetailPercent(ss.cpu.sys, 'sys'),
|
||||||
width13,
|
width13,
|
||||||
_buildDetailPercent(cs.iowait, 'io'),
|
_buildDetailPercent(ss.cpu.iowait, 'io'),
|
||||||
width13,
|
width13,
|
||||||
_buildDetailPercent(cs.idle, 'idle')
|
_buildDetailPercent(ss.cpu.idle, 'idle')
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
height13,
|
height13,
|
||||||
_buildCPUProgress(cs)
|
_buildCPUProgress(ss.cpu)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -183,16 +183,16 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildUpTimeAndSys(String sysVer, String uptime) {
|
Widget _buildUpTimeAndSys(ServerStatus ss) {
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
Padding(
|
Padding(
|
||||||
padding: roundRectCardPadding,
|
padding: roundRectCardPadding,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(sysVer, style: textSize11, textScaleFactor: 1.0),
|
Text(ss.sysVer, style: textSize11, textScaleFactor: 1.0),
|
||||||
Text(
|
Text(
|
||||||
uptime,
|
ss.uptime,
|
||||||
style: textSize11,
|
style: textSize11,
|
||||||
textScaleFactor: 1.0,
|
textScaleFactor: 1.0,
|
||||||
),
|
),
|
||||||
@@ -202,10 +202,10 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMemView(Memory mem) {
|
Widget _buildMemView(ServerStatus ss) {
|
||||||
final free = mem.free / mem.total * 100;
|
final free = ss.mem.free / ss.mem.total * 100;
|
||||||
final avail = mem.availPercent * 100;
|
final avail = ss.mem.availPercent * 100;
|
||||||
final used = mem.usedPercent * 100;
|
final used = ss.mem.usedPercent * 100;
|
||||||
|
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
Padding(
|
Padding(
|
||||||
@@ -221,7 +221,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
children: [
|
children: [
|
||||||
Text('${used.toStringAsFixed(0)}%', style: textSize27),
|
Text('${used.toStringAsFixed(0)}%', style: textSize27),
|
||||||
width7,
|
width7,
|
||||||
Text('of ${(mem.total * 1024).convertBytes}',
|
Text('of ${(ss.mem.total * 1024).convertBytes}',
|
||||||
style: textSize13Grey)
|
style: textSize13Grey)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -242,10 +242,10 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSwapView(Swap swap) {
|
Widget _buildSwapView(ServerStatus ss) {
|
||||||
if (swap.total == 0) return nil;
|
if (ss.swap.total == 0) return nil;
|
||||||
final used = swap.usedPercent * 100;
|
final used = ss.swap.usedPercent * 100;
|
||||||
final cached = swap.cached / swap.total * 100;
|
final cached = ss.swap.cached / ss.swap.total * 100;
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
Padding(
|
Padding(
|
||||||
padding: roundRectCardPadding,
|
padding: roundRectCardPadding,
|
||||||
@@ -260,7 +260,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
children: [
|
children: [
|
||||||
Text('${used.toStringAsFixed(0)}%', style: textSize27),
|
Text('${used.toStringAsFixed(0)}%', style: textSize27),
|
||||||
width7,
|
width7,
|
||||||
Text('of ${(swap.total * 1024).convertBytes} ',
|
Text('of ${(ss.swap.total * 1024).convertBytes} ',
|
||||||
style: textSize13Grey)
|
style: textSize13Grey)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -275,7 +275,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDiskView(List<Disk> disk) {
|
Widget _buildDiskView(ServerStatus ss) {
|
||||||
|
final disk = ss.disk;
|
||||||
disk.removeWhere((e) {
|
disk.removeWhere((e) {
|
||||||
for (final ingorePath in _setting.diskIgnorePath.fetch()!) {
|
for (final ingorePath in _setting.diskIgnorePath.fetch()!) {
|
||||||
if (e.path.startsWith(ingorePath)) return true;
|
if (e.path.startsWith(ingorePath)) return true;
|
||||||
@@ -315,7 +316,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildNetView(NetSpeed ns) {
|
Widget _buildNetView(ServerStatus ss) {
|
||||||
|
final ns = ss.netSpeed;
|
||||||
final children = <Widget>[
|
final children = <Widget>[
|
||||||
_buildNetSpeedTop(),
|
_buildNetSpeedTop(),
|
||||||
const Divider(
|
const Divider(
|
||||||
@@ -397,7 +399,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTemperature(Temperatures temps) {
|
Widget _buildTemperature(ServerStatus ss) {
|
||||||
|
final temps = ss.temps;
|
||||||
if (temps.isEmpty) {
|
if (temps.isEmpty) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import 'package:toolbox/data/model/app/net_view.dart';
|
|||||||
import 'package:toolbox/data/model/server/snippet.dart';
|
import 'package:toolbox/data/model/server/snippet.dart';
|
||||||
import 'package:toolbox/data/provider/snippet.dart';
|
import 'package:toolbox/data/provider/snippet.dart';
|
||||||
import 'package:toolbox/view/page/process.dart';
|
import 'package:toolbox/view/page/process.dart';
|
||||||
import 'package:toolbox/view/widget/fade_in.dart';
|
|
||||||
import 'package:toolbox/view/widget/tag/picker.dart';
|
import 'package:toolbox/view/widget/tag/picker.dart';
|
||||||
import 'package:toolbox/view/widget/tag/switcher.dart';
|
import 'package:toolbox/view/widget/tag/switcher.dart';
|
||||||
|
|
||||||
@@ -126,8 +125,10 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
property: _settingStore.serverOrder,
|
property: _settingStore.serverOrder,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
itemBuilder: (_, index) => FadeIn(
|
buildDefaultDragHandles: false,
|
||||||
|
itemBuilder: (_, index) => ReorderableDelayedDragStartListener(
|
||||||
key: ValueKey('$_tag${filtered[index]}'),
|
key: ValueKey('$_tag${filtered[index]}'),
|
||||||
|
index: index,
|
||||||
child: _buildEachServerCard(pro.servers[filtered[index]]),
|
child: _buildEachServerCard(pro.servers[filtered[index]]),
|
||||||
),
|
),
|
||||||
itemCount: filtered.length,
|
itemCount: filtered.length,
|
||||||
|
|||||||
@@ -88,40 +88,13 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
all: _s.all,
|
all: _s.all,
|
||||||
width: _media.size.width,
|
width: _media.size.width,
|
||||||
),
|
),
|
||||||
|
buildDefaultDragHandles: false,
|
||||||
itemBuilder: (context, idx) {
|
itemBuilder: (context, idx) {
|
||||||
final snippet = filtered.elementAt(idx);
|
final snippet = filtered.elementAt(idx);
|
||||||
return RoundRectCard(
|
return ReorderableDelayedDragStartListener(
|
||||||
ListTile(
|
|
||||||
contentPadding: const EdgeInsets.only(left: 23, right: 17),
|
|
||||||
title: Text(
|
|
||||||
snippet.name,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
snippet.script,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
style: grey,
|
|
||||||
),
|
|
||||||
trailing: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => AppRoute(
|
|
||||||
SnippetEditPage(snippet: snippet),
|
|
||||||
'snippet edit page',
|
|
||||||
).go(context),
|
|
||||||
icon: const Icon(Icons.edit),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => _runSnippet(snippet),
|
|
||||||
icon: const Icon(Icons.play_arrow),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
key: ValueKey(snippet.name),
|
key: ValueKey(snippet.name),
|
||||||
|
index: idx,
|
||||||
|
child: _buildSnippetItem(snippet),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -129,6 +102,41 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildSnippetItem(Snippet snippet) {
|
||||||
|
return RoundRectCard(
|
||||||
|
ListTile(
|
||||||
|
contentPadding: const EdgeInsets.only(left: 23, right: 17),
|
||||||
|
title: Text(
|
||||||
|
snippet.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
snippet.script,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: grey,
|
||||||
|
),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => AppRoute(
|
||||||
|
SnippetEditPage(snippet: snippet),
|
||||||
|
'snippet edit page',
|
||||||
|
).go(context),
|
||||||
|
icon: const Icon(Icons.edit),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => _runSnippet(snippet),
|
||||||
|
icon: const Icon(Icons.play_arrow),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _runSnippet(Snippet snippet) async {
|
Future<void> _runSnippet(Snippet snippet) async {
|
||||||
final provider = locator<ServerProvider>();
|
final provider = locator<ServerProvider>();
|
||||||
final servers = await showDialog<List<Server>>(
|
final servers = await showDialog<List<Server>>(
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:nil/nil.dart';
|
||||||
import 'package:toolbox/core/extension/order.dart';
|
import 'package:toolbox/core/extension/order.dart';
|
||||||
|
import 'package:toolbox/core/utils/platform.dart';
|
||||||
import 'package:toolbox/core/utils/ui.dart';
|
import 'package:toolbox/core/utils/ui.dart';
|
||||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||||
import 'package:toolbox/data/store/setting.dart';
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
@@ -48,8 +50,10 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
|||||||
return ListTile(
|
return ListTile(
|
||||||
key: ValueKey(idx),
|
key: ValueKey(idx),
|
||||||
title: _buildTitle(key),
|
title: _buildTitle(key),
|
||||||
leading: const Icon(Icons.drag_handle, color: Colors.grey),
|
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
||||||
trailing: _buildCheckBox(keys, key, idx, idx < keys.length),
|
trailing: isDesktop
|
||||||
|
? nil
|
||||||
|
: const Icon(Icons.drag_handle, color: Colors.grey),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
itemCount: allKeys.length,
|
itemCount: allKeys.length,
|
||||||
|
|||||||
Reference in New Issue
Block a user