Support Docker start/stop/remove

This commit is contained in:
Junyuan Feng
2022-03-08 17:40:32 +08:00
parent 34e6b99297
commit 241002c3ea
8 changed files with 190 additions and 56 deletions

View File

@@ -1,13 +1,17 @@
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/utils.dart';
import 'package:toolbox/data/model/app/menu_item.dart';
import 'package:toolbox/data/model/docker/ps.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/provider/docker.dart';
import 'package:toolbox/data/provider/server.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/view/widget/center_loading.dart';
import 'package:toolbox/view/widget/two_line_text.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
import 'package:toolbox/view/widget/url_text.dart';
class DockerManagePage extends StatefulWidget {
final ServerPrivateInfo spi;
@@ -20,6 +24,7 @@ class DockerManagePage extends StatefulWidget {
class _DockerManagePageState extends State<DockerManagePage> {
final _docker = locator<DockerProvider>();
final greyTextStyle = const TextStyle(color: Colors.grey);
late MediaQueryData _media;
@override
void dispose() {
@@ -27,6 +32,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
_docker.clear();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_media = MediaQuery.of(context);
}
@override
void initState() {
super.initState();
@@ -46,7 +57,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Docker'),
title: TwoLineText(up: 'Docker', down: widget.spi.ip),
),
body: _buildMain(),
);
@@ -57,8 +68,15 @@ class _DockerManagePageState extends State<DockerManagePage> {
final running = docker.running;
if (docker.error != null && running == null) {
return Center(
child: Text(docker.error!),
);
child: Column(
children: [
SizedBox(
height: _media.size.height * 0.43,
),
Text(docker.error!),
_buildSolution(docker.error!)
],
));
}
if (running == null) {
_docker.refresh();
@@ -66,23 +84,40 @@ class _DockerManagePageState extends State<DockerManagePage> {
}
return ListView(
padding: const EdgeInsets.all(7),
children:
[_buildVersion(docker.edition ?? 'Unknown', docker.version ?? 'Unknown'), _buildPsItems(running)].map((e) => RoundRectCard(e)).toList(),
children: [
_buildVersion(
docker.edition ?? 'Unknown', docker.version ?? 'Unknown'),
_buildPsItems(running, docker)
].map((e) => RoundRectCard(e)).toList(),
);
});
}
Widget _buildVersion(String edition, String version) {
return Padding(padding: EdgeInsets.all(13), child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(edition),
Text(version)
],
),);
Widget _buildSolution(String err) {
switch (err) {
case 'docker not found':
return const UrlText(
text: 'Please https://docs.docker.com/engine/install docker first.',
replace: 'install',
);
case 'no client':
return const Text('Plz wait for the connection to be established.');
default:
return const Text('Unknown error');
}
}
Widget _buildPsItems(List<DockerPsItem> running) {
Widget _buildVersion(String edition, String version) {
return Padding(
padding: const EdgeInsets.all(13),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Text(edition), Text(version)],
),
);
}
Widget _buildPsItems(List<DockerPsItem> running, DockerProvider docker) {
return ExpansionTile(
title: const Text('Container Status'),
subtitle: Text(_buildSubtitle(running), style: greyTextStyle),
@@ -90,14 +125,60 @@ class _DockerManagePageState extends State<DockerManagePage> {
return ListTile(
title: Text(item.image),
subtitle: Text(item.status),
trailing: IconButton(
onPressed: () {},
icon: Icon(item.running ? Icons.stop : Icons.play_arrow)),
trailing: docker.isBusy ? const CircularProgressIndicator() : _buildMoreBtn(item.running, item.containerId),
);
}).toList(),
);
}
Widget _buildMoreBtn(bool running, String containerId) {
final item = running ? DockerMenuItems.stop : DockerMenuItems.start;
return DropdownButtonHideUnderline(
child: DropdownButton2(
customButton: const Padding(
padding: EdgeInsets.only(left: 7),
child: Icon(
Icons.more_vert,
size: 17,
),
),
customItemsHeight: 8,
items: [
DropdownMenuItem<MenuItem>(
value: item,
child: item.build,
),
DropdownMenuItem<MenuItem>(
value: DockerMenuItems.rm,
child: DockerMenuItems.rm.build,
),
],
onChanged: (value) {
final item = value as MenuItem;
switch (item) {
case DockerMenuItems.rm:
_docker.delete(containerId);
break;
case DockerMenuItems.start:
_docker.start(containerId);
break;
case DockerMenuItems.stop:
_docker.stop(containerId);
break;
}
},
itemHeight: 37,
itemPadding: const EdgeInsets.only(left: 17, right: 17),
dropdownWidth: 160,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(7),
),
dropdownElevation: 8,
offset: const Offset(0, 8),
),
);
}
String _buildSubtitle(List<DockerPsItem> running) {
final runningCount = running.where((element) => element.running).length;
final stoped = running.length - runningCount;