On 5/2/25 13:32, Michael Köppl wrote: > On 4/29/25 15:16, Alexander Abraham wrote: >> diff --git a/lib/bloc/pve_node_overview_bloc.dart b/lib/bloc/ >> pve_node_overview_bloc.dart >> index 19d6563..98005fd 100644 >> --- a/lib/bloc/pve_node_overview_bloc.dart >> +++ b/lib/bloc/pve_node_overview_bloc.dart >> @@ -1,5 +1,5 @@ >> import 'dart:async'; >> - >> +import 'package:flutter/material.dart'; >> import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart'; >> import 'package:pve_flutter_frontend/bloc/proxmox_base_bloc.dart'; >> import 'package:pve_flutter_frontend/states/ >> pve_node_overview_state.dart'; >> @@ -8,12 +8,13 @@ class PveNodeOverviewBloc >> extends ProxmoxBaseBloc<PveNodeOverviewEvent, >> PveNodeOverviewState> { >> final ProxmoxApiClient apiClient; >> final String nodeID; >> + final BuildContext context; >> final PveNodeOverviewState init; >> @override >> PveNodeOverviewState get initialState => init; >> PveNodeOverviewBloc( >> - {required this.apiClient, required this.nodeID, required >> this.init}); >> + {required this.apiClient, required this.nodeID, required >> this.init, required this.context}); >> Timer? sTimer; >> @override >> @@ -32,36 +33,56 @@ class PveNodeOverviewBloc >> @override >> Stream<PveNodeOverviewState> processEvents( >> PveNodeOverviewEvent event) async* { >> - if (event is UpdateNodeStatus) { >> - final status = await apiClient.getNodeStatus(nodeID); >> - yield latestState.rebuild((b) => b..status.replace(status)); >> - final rrdData = >> - await apiClient.getNodeRRDdata(nodeID, >> PveRRDTimeframeType.hour); >> - yield latestState.rebuild((b) => b..rrdData.replace(rrdData)); >> - final services = await apiClient.getNodeServices(nodeID); >> - yield latestState.rebuild((b) => b..services.replace(services)); >> - try { >> - final updates = await apiClient.getNodeAptUpdate(nodeID); >> - yield latestState.rebuild((b) => b..updates.replace(updates)); >> - yield latestState >> - .rebuild((b) => b..updatesQueryPermissionFailure = false); >> - } on ProxmoxApiException catch (e) { >> - // only throw on non permission related errors >> - if (e.statusCode != 403) { >> - rethrow; >> - } else { >> + PveNodeStatusModel? status; >> + try { >> + status = await apiClient.getNodeStatus(nodeID); >> + if (event is UpdateNodeStatus) { >> + yield latestState.rebuild((b) => b..status.replace(status!)); >> + final rrdData = >> + await apiClient.getNodeRRDdata(nodeID, >> PveRRDTimeframeType.hour); >> + yield latestState.rebuild((b) => b..rrdData.replace(rrdData)); >> + final services = await apiClient.getNodeServices(nodeID); >> + yield latestState.rebuild((b) => b..services.replace(services)); >> + try { >> + final updates = await apiClient.getNodeAptUpdate(nodeID); >> + yield latestState.rebuild((b) => b..updates.replace(updates)); >> yield latestState >> - .rebuild((b) => b..updatesQueryPermissionFailure = true); >> + .rebuild((b) => b..updatesQueryPermissionFailure = false); >> + } >> + on ProxmoxApiException catch (e) { >> + // only throw on non permission related errors >> + if (e.statusCode != 403) { >> + rethrow; >> + } >> + else { >> + yield latestState >> + .rebuild((b) => b..updatesQueryPermissionFailure = >> true); >> + } >> + } >> + final disks = await apiClient.getNodeDisksList(nodeID); >> + yield latestState.rebuild((b) => b..disks.replace(disks)); >> + } >> + >> + if (event is PerformNodeAction) { >> + await apiClient.doResourceAction( >> + nodeID, >> + '', >> + 'node', >> + event.action, >> + parameters: <String, String>{}); >> + yield latestState; >> } >> } >> - final disks = await apiClient.getNodeDisksList(nodeID); >> - yield latestState.rebuild((b) => b..disks.replace(disks)); >> - } >> - if (event is PerformNodeAction) { >> - await apiClient.doResourceAction(nodeID, '', 'node', event.action, >> - parameters: <String, String>{}); >> - yield latestState; >> - } >> + catch(e){ >> + yield latestState.rebuild( >> + (b) => b >> + ..updatesQueryPermissionFailure = true >> + ); >> + if (context.mounted){ >> + Navigator.of(context).pop(); > > Instead of navigating back immediately, I think it would make sense to > instead display an AlertDialog, showing the error message to the user > and letting them leave the screen through a "Close" button in the > dialog. Otherwise, it feels a bit like the app is taking control away > from the user. We use this approach in other places in the app (e.g. . > What do you think?
Adding to this, I think you could use something similar to what the PveGuestBackupWidget is using: Future<bool?> _showConfirmDialog( BuildContext context, String title, String body) async { return await showDialog( context: context, builder: (context) => AlertDialog( title: Text(title), content: Text(body), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text( 'Cancel', style: TextStyle(fontWeight: FontWeight.bold), ), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text( 'Confirm', style: TextStyle(fontWeight: FontWeight.bold), ), ) ], ), ); } You could then wrap the Navigator.of(context).pop() like this: final confirm = (await _showConfirmDialog( context, "Node offline", "Node is offline. Do you want to navigate back?", ))!; if (confirm && context.mounted) { Navigator.of(context).pop(); } I think it would also make sense to have a utils method for opening an AlertDialog for confirmation. But that could also be done separately in another patch. I just noticed that we're using this in multiple widgets already. _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel