diff --git a/src/app_network.cpp b/src/app_network.cpp index c41659d..d305760 100644 --- a/src/app_network.cpp +++ b/src/app_network.cpp @@ -3772,7 +3772,7 @@ void App::banPeer(const std::string& ip, int duration_seconds) } return [this, err]() { if (!err.empty()) ui::Notifications::instance().error(std::string(TR("toast_ban_failed")) + util::friendlyRpcError(err)); - else refreshPeerInfo(); + else { ui::Notifications::instance().success(TR("toast_peer_banned")); refreshPeerInfo(); } }; }); } @@ -3790,7 +3790,7 @@ void App::unbanPeer(const std::string& ip) } return [this, err]() { if (!err.empty()) ui::Notifications::instance().error(std::string(TR("toast_unban_failed")) + util::friendlyRpcError(err)); - else refreshPeerInfo(); + else { ui::Notifications::instance().success(TR("toast_peer_unbanned")); refreshPeerInfo(); } }; }); } @@ -3809,6 +3809,7 @@ void App::clearBans() return [this, err]() { if (!err.empty()) { ui::Notifications::instance().error(std::string(TR("toast_clear_bans_failed")) + util::friendlyRpcError(err)); return; } state_.banned_peers.clear(); + ui::Notifications::instance().success(TR("toast_bans_cleared")); refreshPeerInfo(); }; }); diff --git a/src/ui/windows/peers_tab.cpp b/src/ui/windows/peers_tab.cpp index 238d316..5aae817 100644 --- a/src/ui/windows/peers_tab.cpp +++ b/src/ui/windows/peers_tab.cpp @@ -33,6 +33,7 @@ using namespace material; // Track selected peer for ban action static int s_selected_peer_idx = -1; static int s_selected_banned_idx = -1; +static bool s_confirm_clear_bans = false; // inline confirm for the bulk Clear-All-Bans action // Helper: Extract IP without port static std::string ExtractIP(const std::string& addr) @@ -931,10 +932,25 @@ void RenderPeersTab(App* app) // ================================================================ if (s_show_banned && !state.bannedPeers.empty()) { ImGui::BeginDisabled(!app->isConnected()); - if (TactileSmallButton(TR("peers_clear_all_bans"), S.resolveFont("button"))) { - app->clearBans(); + if (!s_confirm_clear_bans) { + if (TactileSmallButton(TR("peers_clear_all_bans"), S.resolveFont("button"))) + s_confirm_clear_bans = true; // bulk action takes a confirming second click + } else { + char cb[96]; + snprintf(cb, sizeof(cb), TR("peers_clear_bans_confirm"), (int)state.bannedPeers.size()); + ImGui::TextColored(material::WarningVec4(), "%s", cb); + ImGui::SameLine(); + if (TactileSmallButton(TR("peers_clear_bans_confirm_yes"), S.resolveFont("button"))) { + app->clearBans(); + s_confirm_clear_bans = false; + } + ImGui::SameLine(); + if (TactileSmallButton(TR("cancel"), S.resolveFont("button"))) + s_confirm_clear_bans = false; } ImGui::EndDisabled(); + } else { + s_confirm_clear_bans = false; // no stale confirm across tab toggles / after bans clear } ImGui::EndChild(); // ##PeersScroll