mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
[PublicDecks] Time out the loading state so a dropped reply cannot wedge the tab
loading only cleared in decksReceived, but the ping sweep can drop a pending command without ever emitting finished, leaving the tab stuck on 'Loading public decks...' and the refresh button permanently inert. A single-shot timer started per refresh clears the latch and reports a timeout; the latch also clears when the client disconnects.
This commit is contained in:
parent
64e0b2bbee
commit
454806d20e
2 changed files with 30 additions and 0 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
#include "remote_public_decks_model.h"
|
#include "remote_public_decks_model.h"
|
||||||
|
|
||||||
|
#include "../../../client/settings/cache_settings.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
||||||
#include <libcockatrice/protocol/pb/command_deck_list_other_user.pb.h>
|
#include <libcockatrice/protocol/pb/command_deck_list_other_user.pb.h>
|
||||||
|
|
@ -7,10 +10,26 @@
|
||||||
#include <libcockatrice/protocol/pb/response_deck_list.pb.h>
|
#include <libcockatrice/protocol/pb/response_deck_list.pb.h>
|
||||||
#include <libcockatrice/protocol/pb/serverinfo_deckstorage.pb.h>
|
#include <libcockatrice/protocol/pb/serverinfo_deckstorage.pb.h>
|
||||||
#include <libcockatrice/protocol/pending_command.h>
|
#include <libcockatrice/protocol/pending_command.h>
|
||||||
|
#include <libcockatrice/settings/network_settings.h>
|
||||||
|
|
||||||
RemotePublicDecksModel::RemotePublicDecksModel(AbstractClient *_client, QObject *parent)
|
RemotePublicDecksModel::RemotePublicDecksModel(AbstractClient *_client, QObject *parent)
|
||||||
: QAbstractListModel(parent), client(_client)
|
: QAbstractListModel(parent), client(_client)
|
||||||
{
|
{
|
||||||
|
// The ping sweep can drop a pending command without ever emitting finished,
|
||||||
|
// so loading must not be a latch: time it out and clear it when the client
|
||||||
|
// goes away, or the tab is stuck on the loading state for the session.
|
||||||
|
loadingTimeoutTimer = new QTimer(this);
|
||||||
|
loadingTimeoutTimer->setSingleShot(true);
|
||||||
|
loadingTimeoutTimer->setInterval(
|
||||||
|
static_cast<int>((static_cast<qint64>(SettingsCache::instance().network().getTimeOut()) + 1) *
|
||||||
|
SettingsCache::instance().network().getKeepAlive() * 1000));
|
||||||
|
connect(loadingTimeoutTimer, &QTimer::timeout, this, &RemotePublicDecksModel::onLoadingTimeout);
|
||||||
|
connect(client, &AbstractClient::statusChanged, this, [this](ClientStatus status) {
|
||||||
|
if (status == StatusDisconnected) {
|
||||||
|
loadingTimeoutTimer->stop();
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemotePublicDecksModel::rowCount(const QModelIndex &parent) const
|
int RemotePublicDecksModel::rowCount(const QModelIndex &parent) const
|
||||||
|
|
@ -136,6 +155,7 @@ void RemotePublicDecksModel::refresh(const QString &userName)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
loadingTimeoutTimer->start();
|
||||||
Command_DeckListOtherUser cmd;
|
Command_DeckListOtherUser cmd;
|
||||||
cmd.set_user_name(userName.toStdString());
|
cmd.set_user_name(userName.toStdString());
|
||||||
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
||||||
|
|
@ -143,6 +163,12 @@ void RemotePublicDecksModel::refresh(const QString &userName)
|
||||||
client->sendCommand(pend);
|
client->sendCommand(pend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemotePublicDecksModel::onLoadingTimeout()
|
||||||
|
{
|
||||||
|
setLoading(false);
|
||||||
|
emit loadFailed(tr("The server did not respond in time. Try again."));
|
||||||
|
}
|
||||||
|
|
||||||
void RemotePublicDecksModel::clear()
|
void RemotePublicDecksModel::clear()
|
||||||
{
|
{
|
||||||
decks.clear();
|
decks.clear();
|
||||||
|
|
@ -161,6 +187,7 @@ void RemotePublicDecksModel::setLoading(bool value)
|
||||||
void RemotePublicDecksModel::decksReceived(const Response &response, const CommandContainer & /*commandContainer*/)
|
void RemotePublicDecksModel::decksReceived(const Response &response, const CommandContainer & /*commandContainer*/)
|
||||||
{
|
{
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
loadingTimeoutTimer->stop();
|
||||||
if (response.response_code() != Response::RespOk) {
|
if (response.response_code() != Response::RespOk) {
|
||||||
emit loadFailed(tr("Failed to load the user's public decks (server response code %1).")
|
emit loadFailed(tr("Failed to load the user's public decks (server response code %1).")
|
||||||
.arg(QString::number(static_cast<int>(response.response_code()))));
|
.arg(QString::number(static_cast<int>(response.response_code()))));
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
class AbstractClient;
|
class AbstractClient;
|
||||||
class CommandContainer;
|
class CommandContainer;
|
||||||
|
class QTimer;
|
||||||
class Response;
|
class Response;
|
||||||
class ServerInfo_DeckStorage_Folder;
|
class ServerInfo_DeckStorage_Folder;
|
||||||
class ServerInfo_DeckStorage_TreeItem;
|
class ServerInfo_DeckStorage_TreeItem;
|
||||||
|
|
@ -103,6 +104,7 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void decksReceived(const Response &response, const CommandContainer &commandContainer);
|
void decksReceived(const Response &response, const CommandContainer &commandContainer);
|
||||||
|
void onLoadingTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addFolder(const ServerInfo_DeckStorage_Folder &folder);
|
void addFolder(const ServerInfo_DeckStorage_Folder &folder);
|
||||||
|
|
@ -111,6 +113,7 @@ private:
|
||||||
void setLoading(bool value);
|
void setLoading(bool value);
|
||||||
|
|
||||||
AbstractClient *client;
|
AbstractClient *client;
|
||||||
|
QTimer *loadingTimeoutTimer;
|
||||||
QList<DeckEntry> decks;
|
QList<DeckEntry> decks;
|
||||||
QList<int> visibleIndices; ///< Row indices into `decks` that pass the current filters.
|
QList<int> visibleIndices; ///< Row indices into `decks` that pass the current filters.
|
||||||
bool loading = false;
|
bool loading = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue