mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
#86 fix: docker loading forever
This commit is contained in:
@@ -9,6 +9,7 @@ import 'package:url_launcher/url_launcher.dart';
|
|||||||
|
|
||||||
import '../../data/model/server/snippet.dart';
|
import '../../data/model/server/snippet.dart';
|
||||||
import '../../data/provider/snippet.dart';
|
import '../../data/provider/snippet.dart';
|
||||||
|
import '../../data/res/ui.dart';
|
||||||
import '../../locator.dart';
|
import '../../locator.dart';
|
||||||
import '../../view/page/snippet/edit.dart';
|
import '../../view/page/snippet/edit.dart';
|
||||||
import '../../view/widget/picker.dart';
|
import '../../view/widget/picker.dart';
|
||||||
@@ -69,6 +70,14 @@ Future<T?> showRoundDialog<T>({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showLoadingDialog(BuildContext context, {bool barrierDismiss = false}) {
|
||||||
|
showRoundDialog(
|
||||||
|
context: context,
|
||||||
|
child: centerSizedLoading,
|
||||||
|
barrierDismiss: barrierDismiss,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildSwitch(
|
Widget buildSwitch(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
StoreProperty<bool> prop, {
|
StoreProperty<bool> prop, {
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import 'dart:async';
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:dartssh2/dartssh2.dart';
|
import 'package:dartssh2/dartssh2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||||
import 'package:toolbox/core/extension/stringx.dart';
|
import 'package:toolbox/core/extension/stringx.dart';
|
||||||
import 'package:toolbox/core/provider_base.dart';
|
|
||||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||||
import 'package:toolbox/data/model/docker/image.dart';
|
import 'package:toolbox/data/model/docker/image.dart';
|
||||||
import 'package:toolbox/data/model/docker/ps.dart';
|
import 'package:toolbox/data/model/docker/ps.dart';
|
||||||
@@ -22,7 +22,7 @@ final _dockerPrefixReg = RegExp(r'(sudo )?docker ');
|
|||||||
|
|
||||||
final _logger = Logger('DOCKER');
|
final _logger = Logger('DOCKER');
|
||||||
|
|
||||||
class DockerProvider extends BusyProvider {
|
class DockerProvider extends ChangeNotifier {
|
||||||
final _dockerStore = locator<DockerStore>();
|
final _dockerStore = locator<DockerStore>();
|
||||||
|
|
||||||
SSHClient? client;
|
SSHClient? client;
|
||||||
@@ -56,9 +56,6 @@ class DockerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
if (isBusy) return;
|
|
||||||
setBusyState();
|
|
||||||
|
|
||||||
var raw = '';
|
var raw = '';
|
||||||
await client!.exec(
|
await client!.exec(
|
||||||
AppShellFuncType.docker.exec,
|
AppShellFuncType.docker.exec,
|
||||||
@@ -68,7 +65,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
|
|
||||||
if (raw.contains(_dockerNotFound)) {
|
if (raw.contains(_dockerNotFound)) {
|
||||||
error = DockerErr(type: DockerErrType.notInstalled);
|
error = DockerErr(type: DockerErrType.notInstalled);
|
||||||
setBusyState(false);
|
notifyListeners();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +73,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
final segments = raw.split(seperator);
|
final segments = raw.split(seperator);
|
||||||
if (segments.length != dockerCmds.length) {
|
if (segments.length != dockerCmds.length) {
|
||||||
error = DockerErr(type: DockerErrType.segmentsNotMatch);
|
error = DockerErr(type: DockerErrType.segmentsNotMatch);
|
||||||
setBusyState(false);
|
notifyListeners();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,9 +95,8 @@ class DockerProvider extends BusyProvider {
|
|||||||
message: '$psRaw\n-\n$e',
|
message: '$psRaw\n-\n$e',
|
||||||
);
|
);
|
||||||
_logger.warning('parse docker ps: $psRaw', e);
|
_logger.warning('parse docker ps: $psRaw', e);
|
||||||
rethrow;
|
|
||||||
} finally {
|
} finally {
|
||||||
setBusyState(false);
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse docker images
|
// Parse docker images
|
||||||
@@ -116,9 +112,8 @@ class DockerProvider extends BusyProvider {
|
|||||||
message: '$imageRaw\n-\n$e',
|
message: '$imageRaw\n-\n$e',
|
||||||
);
|
);
|
||||||
_logger.warning('parse docker images: $imageRaw', e);
|
_logger.warning('parse docker images: $imageRaw', e);
|
||||||
rethrow;
|
|
||||||
} finally {
|
} finally {
|
||||||
setBusyState(false);
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse docker stats
|
// Parse docker stats
|
||||||
@@ -141,9 +136,8 @@ class DockerProvider extends BusyProvider {
|
|||||||
message: '$statsRaw\n-\n$e',
|
message: '$statsRaw\n-\n$e',
|
||||||
);
|
);
|
||||||
_logger.warning('parse docker stats: $statsRaw', e);
|
_logger.warning('parse docker stats: $statsRaw', e);
|
||||||
rethrow;
|
|
||||||
} finally {
|
} finally {
|
||||||
setBusyState(false);
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +169,6 @@ class DockerProvider extends BusyProvider {
|
|||||||
if (!cmd.startsWith(_dockerPrefixReg)) {
|
if (!cmd.startsWith(_dockerPrefixReg)) {
|
||||||
return DockerErr(type: DockerErrType.cmdNoPrefix);
|
return DockerErr(type: DockerErrType.cmdNoPrefix);
|
||||||
}
|
}
|
||||||
setBusyState();
|
|
||||||
|
|
||||||
runLog = '';
|
runLog = '';
|
||||||
final errs = <String>[];
|
final errs = <String>[];
|
||||||
@@ -191,16 +184,15 @@ class DockerProvider extends BusyProvider {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
runLog = null;
|
runLog = null;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
setBusyState(false);
|
|
||||||
return DockerErr(
|
return DockerErr(
|
||||||
type: DockerErrType.unknown,
|
type: DockerErrType.unknown,
|
||||||
message: errs.join('\n').trim(),
|
message: errs.join('\n').trim(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await refresh();
|
await refresh();
|
||||||
setBusyState(false);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,11 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
title: TwoLineText(up: 'Docker', down: widget.spi.name),
|
title: TwoLineText(up: 'Docker', down: widget.spi.name),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: _docker.refresh,
|
onPressed: () async {
|
||||||
|
showLoadingDialog(context);
|
||||||
|
await _docker.refresh();
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
icon: const Icon(Icons.refresh),
|
icon: const Icon(Icons.refresh),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -153,7 +157,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
context.pop();
|
context.pop();
|
||||||
|
showLoadingDialog(context);
|
||||||
final result = await _docker.run(cmd);
|
final result = await _docker.run(cmd);
|
||||||
|
context.pop();
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
showSnackBar(context, Text(result.message ?? _s.unknownError));
|
showSnackBar(context, Text(result.message ?? _s.unknownError));
|
||||||
}
|
}
|
||||||
@@ -331,7 +337,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLoading() {
|
Widget _buildLoading() {
|
||||||
if (!_docker.isBusy) return nil;
|
if (_docker.runLog == null) return nil;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(17),
|
padding: const EdgeInsets.all(17),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -409,11 +415,11 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
'${item.name} - ${item.status}',
|
'${item.name} - ${item.status}',
|
||||||
style: textSize13Grey,
|
style: textSize13Grey,
|
||||||
),
|
),
|
||||||
trailing: _buildMoreBtn(item, _docker.isBusy),
|
trailing: _buildMoreBtn(item),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMoreBtn(DockerPsItem dItem, bool busy) {
|
Widget _buildMoreBtn(DockerPsItem dItem) {
|
||||||
return PopupMenu(
|
return PopupMenu(
|
||||||
items: DockerMenuType.items(dItem.running)
|
items: DockerMenuType.items(dItem.running)
|
||||||
.map(
|
.map(
|
||||||
@@ -421,10 +427,6 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
onSelected: (DockerMenuType item) async {
|
onSelected: (DockerMenuType item) async {
|
||||||
if (busy) {
|
|
||||||
showSnackBar(context, Text(_s.isBusy));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (item) {
|
switch (item) {
|
||||||
case DockerMenuType.rm:
|
case DockerMenuType.rm:
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
@@ -433,9 +435,11 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
child: Text(_s.sureDelete(dItem.name)),
|
child: Text(_s.sureDelete(dItem.name)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
|
context.pop();
|
||||||
|
showLoadingDialog(context);
|
||||||
|
await _docker.delete(dItem.containerId);
|
||||||
context.pop();
|
context.pop();
|
||||||
_docker.delete(dItem.containerId);
|
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
)
|
)
|
||||||
@@ -443,13 +447,19 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case DockerMenuType.start:
|
case DockerMenuType.start:
|
||||||
_docker.start(dItem.containerId);
|
showLoadingDialog(context);
|
||||||
|
await _docker.start(dItem.containerId);
|
||||||
|
context.pop();
|
||||||
break;
|
break;
|
||||||
case DockerMenuType.stop:
|
case DockerMenuType.stop:
|
||||||
_docker.stop(dItem.containerId);
|
showLoadingDialog(context);
|
||||||
|
await _docker.stop(dItem.containerId);
|
||||||
|
context.pop();
|
||||||
break;
|
break;
|
||||||
case DockerMenuType.restart:
|
case DockerMenuType.restart:
|
||||||
_docker.restart(dItem.containerId);
|
showLoadingDialog(context);
|
||||||
|
await _docker.restart(dItem.containerId);
|
||||||
|
context.pop();
|
||||||
break;
|
break;
|
||||||
case DockerMenuType.logs:
|
case DockerMenuType.logs:
|
||||||
AppRoute(
|
AppRoute(
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ class _SftpPageState extends State<SftpPage> {
|
|||||||
SftpReqType.download,
|
SftpReqType.download,
|
||||||
);
|
);
|
||||||
_sftp.add(req, completer: completer);
|
_sftp.add(req, completer: completer);
|
||||||
showRoundDialog(context: context, child: centerSizedLoading);
|
showLoadingDialog(context);
|
||||||
await completer.future;
|
await completer.future;
|
||||||
context.pop();
|
context.pop();
|
||||||
|
|
||||||
@@ -458,10 +458,8 @@ class _SftpPageState extends State<SftpPage> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
context.pop();
|
context.pop();
|
||||||
showRoundDialog(
|
showLoadingDialog(
|
||||||
context: context,
|
context
|
||||||
child: centerSizedLoading,
|
|
||||||
barrierDismiss: false,
|
|
||||||
);
|
);
|
||||||
final remotePath = _getRemotePath(file);
|
final remotePath = _getRemotePath(file);
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user