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 _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 _showPruneDialog({ required String title, String? message, required Future 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 _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 _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(); } }); } } }