[DeckStorage] Summarize batch publish failures when the batch drains

Each rejected node stacked its own modal dialog, so publishing a ten-deck
selection against a rejecting server made the user dismiss ten dialogs one
at a time. Failures are now collected while the batch is in flight and shown
as a single summary when the visibility refresh timer fires; a reply that
lands outside an active batch still reports right away.
This commit is contained in:
Lukas Brübach 2026-09-19 07:47:21 +02:00
parent 3608e53453
commit 972b7a7c27
2 changed files with 27 additions and 5 deletions

View file

@ -44,7 +44,8 @@
#include <libcockatrice/settings/paths_settings.h>
#include <libcockatrice/utility/string_limits.h>
namespace {
namespace
{
// How long to wait after the last visibility change before reading back the
// Public/Private column, in milliseconds.
constexpr int VISIBILITY_REFRESH_DELAY = 500;
@ -843,6 +844,7 @@ void TabDeckStorage::onShareFromTreeTimeout()
void TabDeckStorage::actPublishDeck()
{
visibilityFailures.clear();
const auto selection = serverDirView->getCurrentSelection();
for (const auto *node : selection) {
Command_DeckSetVisibility cmd;
@ -872,15 +874,33 @@ void TabDeckStorage::actPublishDeck()
void TabDeckStorage::setVisibilityFinished(const Response &r, const CommandContainer & /*commandContainer*/)
{
if (r.response_code() != Response::RespOk) {
QMessageBox::critical(this, tr("Error"),
tr("Failed to change deck visibility on server (response code %1).")
.arg(QString::number(static_cast<int>(r.response_code()))));
if (r.response_code() == Response::RespOk) {
if (visibilityRefreshStarted) {
visibilityRefreshTimer->start();
}
return;
}
// Collect batch failures and surface them once, when publishing quiets
// down, instead of stacking one modal dialog per rejected node.
const QString message = tr("Failed to change deck visibility on server (response code %1).")
.arg(QString::number(static_cast<int>(r.response_code())));
if (visibilityRefreshStarted) {
visibilityFailures.append(message);
visibilityRefreshTimer->start();
} else {
QMessageBox::critical(this, tr("Error"), message);
}
}
void TabDeckStorage::onVisibilityRefreshTimeout()
{
visibilityRefreshStarted = false;
if (!visibilityFailures.isEmpty()) {
QMessageBox::critical(
this, tr("Error"),
tr("Failed to change the visibility of %n selected deck(s).", "", visibilityFailures.size()));
visibilityFailures.clear();
}
serverDirView->refreshTree();
}

View file

@ -11,6 +11,7 @@
#include "../interface/widgets/server/remote/remote_decklist_tree_widget.h"
#include "tab.h"
#include <QStringList>
#include <libcockatrice/network/client/abstract/abstract_client.h>
struct LoadedDeck;
@ -45,6 +46,7 @@ private:
QAction *aOpenRemoteDeck, *aDownload, *aShareDecks, *aPublishDeck, *aNewFolder, *aDeleteRemoteDeck;
bool visibilityRefreshStarted = false;
QTimer *visibilityRefreshTimer;
QStringList visibilityFailures;
QString getTargetPath() const;
void setRemoteEnabled(bool enabled);