mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2026-01-31 13:25:10 +01:00
opt. for docker & apt
This commit is contained in:
@@ -58,61 +58,60 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore: prefer_function_declarations_over_variables
|
||||
Function onSubmitted = () {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
};
|
||||
|
||||
// ignore: prefer_function_declarations_over_variables
|
||||
PwdRequestFunc onPwdRequest = (triedTimes, user) async {
|
||||
if (!mounted) return '';
|
||||
await showRoundDialog(
|
||||
context,
|
||||
triedTimes == 3 ? s.lastTry : (user ?? s.unknown),
|
||||
TextField(
|
||||
controller: textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
onSubmitted: (_) => onSubmitted(),
|
||||
decoration: InputDecoration(
|
||||
labelText: s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () => onSubmitted(),
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
return textController.text.trim();
|
||||
};
|
||||
|
||||
_aptProvider.init(
|
||||
si.client!,
|
||||
si.status.sysVer.dist,
|
||||
() =>
|
||||
scrollController.jumpTo(scrollController.position.maxScrollExtent),
|
||||
() => scrollControllerUpdate
|
||||
.jumpTo(scrollControllerUpdate.positions.last.maxScrollExtent),
|
||||
onPwdRequest);
|
||||
.jumpTo(scrollController.position.maxScrollExtent),
|
||||
onPwdRequest,
|
||||
widget.spi.user);
|
||||
_aptProvider.refreshInstalled();
|
||||
}
|
||||
|
||||
void onSubmitted() {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
Future<String> onPwdRequest() async {
|
||||
if (!mounted) return '';
|
||||
await showRoundDialog(
|
||||
context,
|
||||
widget.spi.user,
|
||||
TextField(
|
||||
controller: textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
onSubmitted: (_) => onSubmitted(),
|
||||
decoration: InputDecoration(
|
||||
labelText: s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () => onSubmitted(),
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
return textController.text.trim();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
||||
@@ -6,7 +6,9 @@ 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/data/res/error.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:toolbox/data/store/docker.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/center_loading.dart';
|
||||
@@ -25,6 +27,7 @@ class DockerManagePage extends StatefulWidget {
|
||||
class _DockerManagePageState extends State<DockerManagePage> {
|
||||
final _docker = locator<DockerProvider>();
|
||||
final greyTextStyle = const TextStyle(color: Colors.grey);
|
||||
final textController = TextEditingController();
|
||||
late S s;
|
||||
|
||||
@override
|
||||
@@ -51,69 +54,233 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Navigator.of(context).pop();
|
||||
return;
|
||||
}
|
||||
_docker.init(client, widget.spi.user);
|
||||
_docker.init(client, widget.spi.user, onPwdRequest, widget.spi.id);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: 'Docker', down: widget.spi.name),
|
||||
),
|
||||
body: _buildMain(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMain() {
|
||||
return Consumer<DockerProvider>(builder: (_, docker, __) {
|
||||
final running = docker.items;
|
||||
if (docker.error != null && running == null) {
|
||||
return SizedBox.expand(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.error,
|
||||
size: 37,
|
||||
),
|
||||
const SizedBox(height: 27),
|
||||
Text(docker.error!),
|
||||
const SizedBox(height: 27),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: _buildSolution(docker.error!),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
if (running == null) {
|
||||
_docker.refresh();
|
||||
return centerLoading;
|
||||
}
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(7),
|
||||
children: [
|
||||
_buildVersion(
|
||||
docker.edition ?? s.unknown, docker.version ?? s.unknown),
|
||||
_buildPsItems(running, docker)
|
||||
].map((e) => RoundRectCard(e)).toList(),
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: 'Docker', down: widget.spi.name),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => docker.refresh(),
|
||||
icon: const Icon(Icons.refresh))
|
||||
],
|
||||
),
|
||||
body: _buildMain(docker),
|
||||
floatingActionButton: _buildFAB(docker),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildSolution(String err) {
|
||||
switch (err) {
|
||||
case 'docker not found':
|
||||
Widget _buildFAB(DockerProvider docker) {
|
||||
final c = TextEditingController();
|
||||
return FloatingActionButton(
|
||||
onPressed: () {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.cmd,
|
||||
TextField(
|
||||
keyboardType: TextInputType.multiline,
|
||||
maxLines: 7,
|
||||
controller: c,
|
||||
autocorrect: false,
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
final result = await docker.run(c.text.trim());
|
||||
if (result != null) {
|
||||
showSnackBar(
|
||||
context, Text(getErrMsg(result) ?? s.unknownError));
|
||||
}
|
||||
},
|
||||
child: Text(s.run),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
child: const Icon(Icons.code),
|
||||
);
|
||||
}
|
||||
|
||||
String? getErrMsg(DockerErr err) {
|
||||
switch (err.type) {
|
||||
case DockerErrType.cmdNoPrefix:
|
||||
return s.dockerCmdPrefixErr;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void onSubmitted() {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
Future<String> onPwdRequest() async {
|
||||
if (!mounted) return '';
|
||||
await showRoundDialog(
|
||||
context,
|
||||
widget.spi.user,
|
||||
TextField(
|
||||
controller: textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
onSubmitted: (_) => onSubmitted(),
|
||||
decoration: InputDecoration(
|
||||
labelText: s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () => onSubmitted(),
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
return textController.text.trim();
|
||||
}
|
||||
|
||||
Widget _buildMain(DockerProvider docker) {
|
||||
final running = docker.items;
|
||||
if (docker.error != null && running == null) {
|
||||
return SizedBox.expand(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.error,
|
||||
size: 37,
|
||||
),
|
||||
const SizedBox(height: 27),
|
||||
_buildErr(docker.error!),
|
||||
const SizedBox(height: 27),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: _buildSolution(docker.error!),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
if (running == null) {
|
||||
_docker.refresh();
|
||||
return centerLoading;
|
||||
}
|
||||
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(7),
|
||||
children: [
|
||||
_buildVersion(docker.edition ?? s.unknown, docker.version ?? s.unknown),
|
||||
_buildPsItems(running, docker),
|
||||
_buildEditHost(running, docker),
|
||||
_buildRunLog(docker),
|
||||
].map((e) => RoundRectCard(e)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRunLog(DockerProvider docker) {
|
||||
if (docker.runLog == null) return const SizedBox();
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: Text(docker.runLog!, maxLines: 1,),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEditHost(List<DockerPsItem> running, DockerProvider docker) {
|
||||
if (running.isEmpty) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(17, 17, 17, 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
s.dockerEmptyRunningItems,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => _showEditHostDialog(docker),
|
||||
child: Text(s.dockerEditHost))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
Future<void> _showEditHostDialog(DockerProvider docker) async {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.dockerEditHost,
|
||||
TextField(
|
||||
maxLines: 1,
|
||||
autocorrect: false,
|
||||
controller:
|
||||
TextEditingController(text: 'unix:///run/user/1000/docker.sock'),
|
||||
onSubmitted: (value) {
|
||||
locator<DockerStore>().setDockerHost(widget.spi.id, value.trim());
|
||||
docker.refresh();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildErr(DockerErr err) {
|
||||
var errStr = '';
|
||||
switch (err.type) {
|
||||
case DockerErrType.noClient:
|
||||
errStr = s.noClient;
|
||||
break;
|
||||
case DockerErrType.notInstalled:
|
||||
errStr = s.dockerNotInstalled;
|
||||
break;
|
||||
case DockerErrType.invalidVersion:
|
||||
errStr = s.invalidVersion;
|
||||
break;
|
||||
default:
|
||||
errStr = err.message ?? s.unknown;
|
||||
}
|
||||
return Text(errStr);
|
||||
}
|
||||
|
||||
Widget _buildSolution(DockerErr err) {
|
||||
switch (err.type) {
|
||||
case DockerErrType.notInstalled:
|
||||
return UrlText(
|
||||
text: s.installDockerWithUrl,
|
||||
replace: s.install,
|
||||
);
|
||||
case 'no client':
|
||||
case DockerErrType.noClient:
|
||||
return Text(s.waitConnection);
|
||||
case 'invalid version':
|
||||
case DockerErrType.invalidVersion:
|
||||
return UrlText(
|
||||
text: s.invalidVersionHelp(issueUrl),
|
||||
replace: 'Github',
|
||||
|
||||
@@ -51,7 +51,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
SizedBox(height: _media.size.height * 0.03),
|
||||
SizedBox(height: _media.size.height * 0.01),
|
||||
_buildLinuxIcon(si.status.sysVer),
|
||||
SizedBox(height: _media.size.height * 0.03),
|
||||
_buildUpTimeAndSys(si.status),
|
||||
|
||||
Reference in New Issue
Block a user