Files
flutter_server_box/lib/view/page/container/actions.dart
lollipopkit🏳️‍⚧️ 53a7c0d8ff migrate: riverpod + freezed (#870)
2025-08-31 00:55:54 +08:00

241 lines
7.6 KiB
Dart

part of 'container.dart';
extension on _ContainerPageState {
/// The notifier for the container state.
ContainerNotifier get _containerNotifier => ref.read(_provider.notifier);
/// Watch the current state of the container.
ContainerState get _containerState => ref.watch(_provider);
Future<void> _showAddFAB() async {
final imageCtrl = TextEditingController();
final nameCtrl = TextEditingController();
final argsCtrl = TextEditingController();
await context.showRoundDialog(
title: l10n.newContainer,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Input(
autoFocus: true,
type: TextInputType.text,
label: l10n.image,
hint: 'xxx:1.1',
controller: imageCtrl,
suggestion: false,
),
Input(
type: TextInputType.text,
controller: nameCtrl,
label: libL10n.name,
hint: 'xxx',
suggestion: false,
),
Input(
type: TextInputType.text,
controller: argsCtrl,
label: l10n.extraArgs,
hint: '-p 2222:22 -v ~/.xxx/:/xxx',
suggestion: false,
),
],
),
actions: Btn.ok(
onTap: () async {
context.pop();
await _showAddCmdPreview(
_buildAddCmd(imageCtrl.text.trim(), nameCtrl.text.trim(), argsCtrl.text.trim()),
);
},
).toList,
);
}
Future<void> _showPruneDialog({
required String title,
String? message,
required Future<ContainerErr?> Function() onConfirm,
}) async {
await context.showRoundDialog(
title: title,
child: Text(message ?? libL10n.askContinue('${l10n.prune} $title')),
actions: Btn.ok(
onTap: () async {
context.pop();
final (result, err) = await context.showLoadingDialog(fn: onConfirm);
if (err != null || result != null) {
final e = result?.message ?? err?.toString();
context.showRoundDialog(title: libL10n.error, child: Text(e.toString()));
} else {
context.showSnackBar(libL10n.success);
}
},
red: true,
).toList,
);
}
Future<void> _showAddCmdPreview(String cmd) async {
await context.showRoundDialog(
title: l10n.preview,
child: Text(cmd),
actions: [
TextButton(onPressed: () => context.pop(), child: Text(libL10n.cancel)),
TextButton(
onPressed: () async {
context.pop();
final (result, err) = await context.showLoadingDialog(fn: () => _containerNotifier.run(cmd));
if (err != null || result != null) {
final e = result?.message ?? err?.toString();
context.showRoundDialog(title: libL10n.error, child: Text(e.toString()));
}
},
child: Text(l10n.run),
),
],
);
}
Future<void> _showEditHostDialog() async {
final id = widget.args.spi.id;
final host = Stores.container.fetch(id);
final ctrl = TextEditingController(text: host);
await context.showRoundDialog(
title: libL10n.edit,
child: Input(
maxLines: 2,
controller: ctrl,
onSubmitted: _onSaveDockerHost,
hint: 'unix:///run/user/1000/docker.sock',
suggestion: false,
),
actions: Btn.ok(onTap: () => _onSaveDockerHost(ctrl.text)).toList,
);
}
void _onSaveDockerHost(String val) {
context.pop();
Stores.container.put(widget.args.spi.id, val.trim());
_containerNotifier.refresh();
}
void _showImageRmDialog(ContainerImg e) {
context.showRoundDialog(
title: libL10n.attention,
child: Text(libL10n.askContinue('${libL10n.delete} Image(${e.repository})')),
actions: Btn.ok(
onTap: () async {
context.pop();
final result = await _containerNotifier.run('rmi ${e.id} -f');
if (result != null) {
context.showSnackBar(result.message ?? 'null');
}
},
red: true,
).toList,
);
}
void _onTapMoreBtn(ContainerMenu item, ContainerPs dItem) async {
final id = dItem.id;
if (id == null) {
context.showSnackBar('Id is null');
return;
}
switch (item) {
case ContainerMenu.rm:
var force = false;
context.showRoundDialog(
title: libL10n.attention,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(libL10n.askContinue('${libL10n.delete} Container(${dItem.name})')),
UIs.height13,
Row(
children: [
StatefulBuilder(
builder: (_, setState) {
return Checkbox(value: force, onChanged: (val) => setState(() => force = val ?? false));
},
),
Text(l10n.force),
],
),
],
),
actions: Btn.ok(
onTap: () async {
context.pop();
final (result, err) = await context.showLoadingDialog(
fn: () => _containerNotifier.delete(id, force),
);
if (err != null || result != null) {
final e = result?.message ?? err?.toString();
context.showRoundDialog(title: libL10n.error, child: Text(e ?? 'null'));
}
},
).toList,
);
break;
case ContainerMenu.start:
final (result, err) = await context.showLoadingDialog(fn: () => _containerNotifier.start(id));
if (err != null || result != null) {
final e = result?.message ?? err?.toString();
context.showRoundDialog(title: libL10n.error, child: Text(e ?? 'null'));
}
break;
case ContainerMenu.stop:
final (result, err) = await context.showLoadingDialog(fn: () => _containerNotifier.stop(id));
if (err != null || result != null) {
final e = result?.message ?? err?.toString();
context.showRoundDialog(title: libL10n.error, child: Text(e ?? 'null'));
}
break;
case ContainerMenu.restart:
final (result, err) = await context.showLoadingDialog(fn: () => _containerNotifier.restart(id));
if (err != null || result != null) {
final e = result?.message ?? err?.toString();
context.showRoundDialog(title: libL10n.error, child: Text(e ?? 'null'));
}
break;
case ContainerMenu.logs:
final args = SshPageArgs(
spi: widget.args.spi,
initCmd:
'${switch (_containerState.type) {
ContainerType.podman => 'podman',
ContainerType.docker => 'docker',
}} logs -f --tail 100 ${dItem.id}',
);
SSHPage.route.go(context, args);
break;
case ContainerMenu.terminal:
final args = SshPageArgs(
spi: widget.args.spi,
initCmd:
'${switch (_containerState.type) {
ContainerType.podman => 'podman',
ContainerType.docker => 'docker',
}} exec -it ${dItem.id} sh',
);
SSHPage.route.go(context, args);
break;
}
}
void _initAutoRefresh() {
if (Stores.setting.containerAutoRefresh.fetch()) {
Timer.periodic(Duration(seconds: Stores.setting.serverStatusUpdateInterval.fetch()), (timer) {
if (mounted) {
_containerNotifier.refresh(isAuto: true);
} else {
timer.cancel();
}
});
}
}
}