mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-09 17:44:01 -07:00
[App] Send diagnostics on server connection
Took 32 seconds Took 22 seconds
This commit is contained in:
parent
bbd8671e6e
commit
b9198d99e9
13 changed files with 258 additions and 9 deletions
|
|
@ -42,6 +42,7 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/dialogs/dlg_manage_sets.cpp
|
||||
src/interface/widgets/dialogs/dlg_register.cpp
|
||||
src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp
|
||||
src/interface/widgets/dialogs/dlg_prompt_send_diagnostics.cpp
|
||||
src/interface/widgets/dialogs/dlg_settings.cpp
|
||||
src/interface/widgets/dialogs/dlg_startup_card_check.cpp
|
||||
src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ SettingsCache::SettingsCache()
|
|||
cardUpdateCheckInterval = settings->value("personal/cardUpdateCheckInterval", 7).toInt();
|
||||
lastCardUpdateCheck = settings->value("personal/lastCardUpdateCheck", QDateTime::currentDateTime().date()).toDate();
|
||||
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
|
||||
sendDiagnostics = settings->value("personal/senddiagnostics", 0).toInt();
|
||||
notifyAboutNewVersion = settings->value("personal/newversionnotification", true).toBool();
|
||||
|
||||
if (settings->contains("personal/updatereleasechannel")) {
|
||||
|
|
@ -1496,6 +1497,12 @@ void SettingsCache::setNotifyAboutUpdate(QT_STATE_CHANGED_T _notifyaboutupdate)
|
|||
settings->setValue("personal/updatenotification", notifyAboutUpdates);
|
||||
}
|
||||
|
||||
void SettingsCache::setSendDiagnostics(int _sendDiagnostics)
|
||||
{
|
||||
sendDiagnostics = _sendDiagnostics;
|
||||
settings->setValue("personal/senddiagnostics", sendDiagnostics);
|
||||
}
|
||||
|
||||
void SettingsCache::setNotifyAboutNewVersion(QT_STATE_CHANGED_T _notifyaboutnewversion)
|
||||
{
|
||||
notifyAboutNewVersion = static_cast<bool>(_notifyaboutnewversion);
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ private:
|
|||
int cardUpdateCheckInterval;
|
||||
QDate lastCardUpdateCheck;
|
||||
bool notifyAboutUpdates;
|
||||
int sendDiagnostics;
|
||||
bool notifyAboutNewVersion;
|
||||
bool showTipsOnStartup;
|
||||
QList<int> seenTips;
|
||||
|
|
@ -498,6 +499,10 @@ public:
|
|||
{
|
||||
return notifyAboutUpdates;
|
||||
}
|
||||
[[nodiscard]] int getSendDiagnostics() const override
|
||||
{
|
||||
return sendDiagnostics;
|
||||
}
|
||||
[[nodiscard]] bool getNotifyAboutNewVersion() const
|
||||
{
|
||||
return notifyAboutNewVersion;
|
||||
|
|
@ -1105,6 +1110,7 @@ public slots:
|
|||
void setCardUpdateCheckInterval(int value);
|
||||
void setLastCardUpdateCheck(QDate value);
|
||||
void setNotifyAboutUpdate(QT_STATE_CHANGED_T _notifyaboutupdate);
|
||||
void setSendDiagnostics(int _sendDiagnostics);
|
||||
void setNotifyAboutNewVersion(QT_STATE_CHANGED_T _notifyaboutnewversion);
|
||||
void setUpdateReleaseChannelIndex(int value);
|
||||
void setMaxFontSize(int _max);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
#include "dlg_prompt_send_diagnostics.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
DlgPromptSendDiagnostics::DlgPromptSendDiagnostics(QWidget *parent) : QDialog(parent), choice(SendDiagnosticsDisabled)
|
||||
{
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
|
||||
messageLabel = new QLabel(this);
|
||||
messageLabel->setWordWrap(true);
|
||||
layout->addWidget(messageLabel);
|
||||
|
||||
auto *buttonLayout = new QHBoxLayout;
|
||||
|
||||
noButton = new QPushButton(this);
|
||||
minimalButton = new QPushButton(this);
|
||||
fullButton = new QPushButton(this);
|
||||
|
||||
buttonLayout->addWidget(noButton);
|
||||
buttonLayout->addWidget(minimalButton);
|
||||
buttonLayout->addWidget(fullButton);
|
||||
|
||||
layout->addLayout(buttonLayout);
|
||||
|
||||
// Connect buttons
|
||||
connect(noButton, &QPushButton::clicked, this, [this]() {
|
||||
choice = SendDiagnosticsDisabled;
|
||||
accept();
|
||||
});
|
||||
connect(minimalButton, &QPushButton::clicked, this, [this]() {
|
||||
choice = SendDiagnosticsBasic;
|
||||
accept();
|
||||
});
|
||||
connect(fullButton, &QPushButton::clicked, this, [this]() {
|
||||
choice = SendDiagnosticsFull;
|
||||
accept();
|
||||
});
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void DlgPromptSendDiagnostics::retranslateUi()
|
||||
{
|
||||
setWindowTitle(tr("Help us improve Cockatrice"));
|
||||
|
||||
messageLabel->setText(tr("Hi there! Cockatrice is made by a small team, and we want to make it better for you.\n\n"
|
||||
"We’d love to collect a tiny bit of anonymous technical data about how you use the app — "
|
||||
"nothing personal, just usage info so we know what works and what needs improvement."));
|
||||
|
||||
noButton->setText(tr("No, thank you"));
|
||||
minimalButton->setText(tr("Minimal"));
|
||||
fullButton->setText(tr("Full"));
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef COCKATRICE_DLG_PROMPT_SEND_DIAGNOSTICS_H
|
||||
#define COCKATRICE_DLG_PROMPT_SEND_DIAGNOSTICS_H
|
||||
|
||||
#include "dlg_settings.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <libcockatrice/interfaces/interface_network_settings_provider.h>
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class DlgPromptSendDiagnostics : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DlgPromptSendDiagnostics(QWidget *parent = nullptr);
|
||||
|
||||
SendDiagnosticsMode selectedChoice() const
|
||||
{
|
||||
return choice;
|
||||
}
|
||||
|
||||
void retranslateUi();
|
||||
|
||||
private:
|
||||
SendDiagnosticsMode choice;
|
||||
|
||||
QLabel *messageLabel;
|
||||
QPushButton *noButton;
|
||||
QPushButton *minimalButton;
|
||||
QPushButton *fullButton;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_DLG_PROMPT_SEND_DIAGNOSTICS_H
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include "../interface/widgets/utility/get_text_with_max.h"
|
||||
#include "../interface/widgets/utility/sequence_edit.h"
|
||||
#include "../main.h"
|
||||
#include "dlg_prompt_send_diagnostics.h"
|
||||
|
||||
#include <../../client/settings/card_counter_settings.h>
|
||||
#include <QAbstractButton>
|
||||
|
|
@ -101,6 +102,27 @@ GeneralSettingsPage::GeneralSettingsPage()
|
|||
advertiseTranslationPageLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
||||
advertiseTranslationPageLabel.setOpenExternalLinks(true);
|
||||
|
||||
// Add items with the enum as userData
|
||||
populateSendDiagnosticsCombo(SettingsCache::instance().getSendDiagnostics());
|
||||
|
||||
connect(&sendDiagnosticsSelector, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
int mode = sendDiagnosticsSelector.itemData(index).toInt();
|
||||
|
||||
if (mode == SendDiagnosticsUnprompted) {
|
||||
DlgPromptSendDiagnostics dlg(this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
mode = dlg.selectedChoice();
|
||||
} else {
|
||||
mode = SendDiagnosticsDisabled;
|
||||
}
|
||||
}
|
||||
|
||||
SettingsCache::instance().setSendDiagnostics(mode);
|
||||
|
||||
// Rebuild combo if we transitioned out of Unprompted
|
||||
populateSendDiagnosticsCombo(mode);
|
||||
});
|
||||
|
||||
connect(&languageBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&GeneralSettingsPage::languageBoxChanged);
|
||||
connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings,
|
||||
|
|
@ -125,15 +147,17 @@ GeneralSettingsPage::GeneralSettingsPage()
|
|||
personalGrid->addWidget(&advertiseTranslationPageLabel, 1, 1, Qt::AlignRight);
|
||||
personalGrid->addWidget(&updateReleaseChannelLabel, 2, 0);
|
||||
personalGrid->addWidget(&updateReleaseChannelBox, 2, 1);
|
||||
personalGrid->addWidget(&startupUpdateCheckCheckBox, 4, 0, 1, 2);
|
||||
personalGrid->addWidget(&startupCardUpdateCheckBehaviorLabel, 5, 0);
|
||||
personalGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 5, 1);
|
||||
personalGrid->addWidget(&cardUpdateCheckIntervalLabel, 6, 0);
|
||||
personalGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 6, 1);
|
||||
personalGrid->addWidget(&lastCardUpdateCheckDateLabel, 7, 1);
|
||||
personalGrid->addWidget(&updateNotificationCheckBox, 8, 0, 1, 2);
|
||||
personalGrid->addWidget(&newVersionOracleCheckBox, 9, 0, 1, 2);
|
||||
personalGrid->addWidget(&showTipsOnStartup, 10, 0, 1, 2);
|
||||
personalGrid->addWidget(&sendDiagnosticsLabel, 3, 0);
|
||||
personalGrid->addWidget(&sendDiagnosticsSelector, 3, 1);
|
||||
personalGrid->addWidget(&startupUpdateCheckCheckBox, 5, 0, 1, 2);
|
||||
personalGrid->addWidget(&startupCardUpdateCheckBehaviorLabel, 6, 0);
|
||||
personalGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 6, 1);
|
||||
personalGrid->addWidget(&cardUpdateCheckIntervalLabel, 7, 0);
|
||||
personalGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 7, 1);
|
||||
personalGrid->addWidget(&lastCardUpdateCheckDateLabel, 8, 1);
|
||||
personalGrid->addWidget(&updateNotificationCheckBox, 9, 0, 1, 2);
|
||||
personalGrid->addWidget(&newVersionOracleCheckBox, 10, 0, 1, 2);
|
||||
personalGrid->addWidget(&showTipsOnStartup, 11, 0, 1, 2);
|
||||
|
||||
personalGroupBox = new QGroupBox;
|
||||
personalGroupBox->setLayout(personalGrid);
|
||||
|
|
@ -268,6 +292,32 @@ QString GeneralSettingsPage::languageName(const QString &lang)
|
|||
return qTranslator.translate("i18n", DEFAULT_LANG_NAME);
|
||||
}
|
||||
|
||||
void GeneralSettingsPage::populateSendDiagnosticsCombo(int mode)
|
||||
{
|
||||
QSignalBlocker blocker(sendDiagnosticsSelector);
|
||||
|
||||
sendDiagnosticsSelector.clear();
|
||||
|
||||
if (mode == SendDiagnosticsUnprompted) {
|
||||
sendDiagnosticsSelector.addItem(QString(), SendDiagnosticsUnprompted);
|
||||
}
|
||||
|
||||
sendDiagnosticsSelector.addItem(tr("Disabled"), SendDiagnosticsDisabled);
|
||||
sendDiagnosticsSelector.addItem(tr("Minimal"), SendDiagnosticsBasic);
|
||||
sendDiagnosticsSelector.addItem(tr("Full"), SendDiagnosticsFull);
|
||||
|
||||
// Restore selection
|
||||
for (int i = 0; i < sendDiagnosticsSelector.count(); ++i) {
|
||||
if (sendDiagnosticsSelector.itemData(i).toInt() == mode) {
|
||||
sendDiagnosticsSelector.setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: if unprompted was removed, default to Disabled
|
||||
sendDiagnosticsSelector.setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void GeneralSettingsPage::deckPathButtonClicked()
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), deckPathEdit->text());
|
||||
|
|
@ -376,6 +426,7 @@ void GeneralSettingsPage::retranslateUi()
|
|||
customCardDatabasePathLabel.setText(tr("Custom database directory:"));
|
||||
tokenDatabasePathLabel.setText(tr("Token database:"));
|
||||
updateReleaseChannelLabel.setText(tr("Update channel"));
|
||||
sendDiagnosticsLabel.setText(tr("Send usage statistics:"));
|
||||
startupUpdateCheckCheckBox.setText(tr("Check for client updates on startup"));
|
||||
startupCardUpdateCheckBehaviorLabel.setText(tr("Check for card database updates on startup"));
|
||||
startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexNone, tr("Don't check"));
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ private slots:
|
|||
private:
|
||||
QStringList findQmFiles();
|
||||
QString languageName(const QString &lang);
|
||||
void populateSendDiagnosticsCombo(int mode);
|
||||
QLineEdit *deckPathEdit;
|
||||
QLineEdit *filtersPathEdit;
|
||||
QLineEdit *replaysPathEdit;
|
||||
|
|
@ -84,6 +85,7 @@ private:
|
|||
QCheckBox updateNotificationCheckBox;
|
||||
QCheckBox newVersionOracleCheckBox;
|
||||
QComboBox updateReleaseChannelBox;
|
||||
QComboBox sendDiagnosticsSelector;
|
||||
QLabel languageLabel;
|
||||
QLabel deckPathLabel;
|
||||
QLabel filtersPathLabel;
|
||||
|
|
@ -93,6 +95,7 @@ private:
|
|||
QLabel customCardDatabasePathLabel;
|
||||
QLabel tokenDatabasePathLabel;
|
||||
QLabel updateReleaseChannelLabel;
|
||||
QLabel sendDiagnosticsLabel;
|
||||
QLabel advertiseTranslationPageLabel;
|
||||
QCheckBox showTipsOnStartup;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "../interface/widgets/dialogs/dlg_forgot_password_request.h"
|
||||
#include "../interface/widgets/dialogs/dlg_forgot_password_reset.h"
|
||||
#include "../interface/widgets/dialogs/dlg_manage_sets.h"
|
||||
#include "../interface/widgets/dialogs/dlg_prompt_send_diagnostics.h"
|
||||
#include "../interface/widgets/dialogs/dlg_register.h"
|
||||
#include "../interface/widgets/dialogs/dlg_settings.h"
|
||||
#include "../interface/widgets/dialogs/dlg_startup_card_check.h"
|
||||
|
|
@ -851,6 +852,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
connect(client, &RemoteClient::protocolVersionMismatch, this, &MainWindow::protocolVersionMismatch);
|
||||
connect(client, &RemoteClient::userInfoChanged, this, &MainWindow::userInfoReceived, Qt::BlockingQueuedConnection);
|
||||
connect(client, &RemoteClient::notifyUserAboutUpdate, this, &MainWindow::notifyUserAboutUpdate);
|
||||
connect(client, &RemoteClient::notifyUserAboutDiagnostics, this, &MainWindow::notifyUserAboutDiagnostics);
|
||||
connect(client, &RemoteClient::registerAccepted, this, &MainWindow::registerAccepted);
|
||||
connect(client, &RemoteClient::registerAcceptedNeedsActivate, this, &MainWindow::registerAcceptedNeedsActivate);
|
||||
connect(client, &RemoteClient::registerError, this, &MainWindow::registerError);
|
||||
|
|
@ -1385,6 +1387,21 @@ void MainWindow::notifyUserAboutUpdate()
|
|||
"running a custom or pre-release version.\n\nTo update your client, go to Help -> Check for Updates."));
|
||||
}
|
||||
|
||||
void MainWindow::notifyUserAboutDiagnostics()
|
||||
{
|
||||
int mode = SendDiagnosticsDisabled;
|
||||
DlgPromptSendDiagnostics dlg(this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
mode = dlg.selectedChoice();
|
||||
}
|
||||
|
||||
SettingsCache::instance().setSendDiagnostics(mode);
|
||||
|
||||
if (mode == SendDiagnosticsBasic || mode == SendDiagnosticsFull) {
|
||||
client->sendDiagnostics();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::actOpenCustomFolder()
|
||||
{
|
||||
QString dir = SettingsCache::instance().getCustomPicsPath();
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ private slots:
|
|||
void localGameEnded();
|
||||
void pixmapCacheSizeChanged(int newSizeInMBs);
|
||||
void notifyUserAboutUpdate();
|
||||
void notifyUserAboutDiagnostics();
|
||||
void actDisconnect();
|
||||
void actSinglePlayer();
|
||||
void actWatchReplay();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@
|
|||
#define COCKATRICE_INETWORKSETTINGSPROVIDER_H
|
||||
#include <QString>
|
||||
|
||||
enum SendDiagnosticsMode {
|
||||
SendDiagnosticsUnprompted = 0, // never asked
|
||||
SendDiagnosticsDisabled = 1,
|
||||
SendDiagnosticsBasic = 2,
|
||||
SendDiagnosticsFull = 3,
|
||||
};
|
||||
|
||||
class INetworkSettingsProvider
|
||||
{
|
||||
public:
|
||||
|
|
@ -12,6 +19,7 @@ public:
|
|||
[[nodiscard]] virtual int getTimeOut() const = 0;
|
||||
[[nodiscard]] virtual int getKeepAlive() const = 0;
|
||||
[[nodiscard]] virtual bool getNotifyAboutUpdates() const = 0;
|
||||
[[nodiscard]] virtual int getSendDiagnostics() const = 0;
|
||||
|
||||
virtual void setKnownMissingFeatures(const QString &_knownMissingFeatures) = 0;
|
||||
virtual QString getKnownMissingFeatures() = 0;
|
||||
|
|
|
|||
|
|
@ -278,6 +278,34 @@ void RemoteClient::passwordSaltResponse(const Response &response)
|
|||
}
|
||||
}
|
||||
|
||||
Command_ClientDiagnostics RemoteClient::generateClientDiagnostics()
|
||||
{
|
||||
Command_ClientDiagnostics diag;
|
||||
|
||||
diag.set_clientver(VERSION_STRING);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
diag.set_os("windows");
|
||||
#elif defined(Q_OS_MAC)
|
||||
diag.set_os("macos");
|
||||
#elif defined(Q_OS_LINUX)
|
||||
diag.set_os("linux");
|
||||
#else
|
||||
diag.set_os("unknown");
|
||||
#endif
|
||||
|
||||
diag.set_arch(QSysInfo::currentCpuArchitecture().toStdString());
|
||||
|
||||
return diag;
|
||||
}
|
||||
|
||||
void RemoteClient::addDiagnosticsFeature(Command_ClientDiagnostics *diag, const QString &name, const QString &value)
|
||||
{
|
||||
FeatureFlag *flag = diag->add_feature_flags();
|
||||
flag->set_name(name.toStdString());
|
||||
flag->set_value(value.toStdString());
|
||||
}
|
||||
|
||||
void RemoteClient::loginResponse(const Response &response)
|
||||
{
|
||||
const Response_Login &resp = response.GetExtension(Response_Login::ext);
|
||||
|
|
@ -302,6 +330,15 @@ void RemoteClient::loginResponse(const Response &response)
|
|||
ignoreList.append(resp.ignore_list(i));
|
||||
emit ignoreListReceived(ignoreList);
|
||||
|
||||
// send diagnostics if enabled
|
||||
SendDiagnosticsMode mode = SendDiagnosticsMode(networkSettingsProvider->getSendDiagnostics());
|
||||
|
||||
if (mode == SendDiagnosticsUnprompted) {
|
||||
emit notifyUserAboutDiagnostics();
|
||||
} else if (mode == SendDiagnosticsBasic || mode == SendDiagnosticsFull) {
|
||||
sendDiagnostics();
|
||||
}
|
||||
|
||||
if (newMissingFeatureFound(possibleMissingFeatures) && resp.missing_features_size() > 0 &&
|
||||
networkSettingsProvider->getNotifyAboutUpdates()) {
|
||||
networkSettingsProvider->setKnownMissingFeatures(possibleMissingFeatures);
|
||||
|
|
@ -320,6 +357,13 @@ void RemoteClient::loginResponse(const Response &response)
|
|||
}
|
||||
}
|
||||
|
||||
void RemoteClient::sendDiagnostics()
|
||||
{
|
||||
Command_ClientDiagnostics diag = generateClientDiagnostics();
|
||||
PendingCommand *pend = prepareSessionCommand(diag);
|
||||
sendCommand(pend);
|
||||
}
|
||||
|
||||
void RemoteClient::registerResponse(const Response &response)
|
||||
{
|
||||
const Response_Register &resp = response.GetExtension(Response_Register::ext);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ signals:
|
|||
const QString &_realname);
|
||||
void sigActivateToServer(const QString &_token);
|
||||
void sigDisconnectFromServer();
|
||||
void notifyUserAboutDiagnostics();
|
||||
void notifyUserAboutUpdate();
|
||||
void sigRequestForgotPasswordToServer(const QString &hostname, unsigned int port, const QString &_userName);
|
||||
void sigForgotPasswordSuccess();
|
||||
|
|
@ -80,6 +81,8 @@ private slots:
|
|||
void doLogin();
|
||||
void doHashedLogin();
|
||||
Command_Login generateCommandLogin();
|
||||
Command_ClientDiagnostics generateClientDiagnostics();
|
||||
void addDiagnosticsFeature(Command_ClientDiagnostics *diag, const QString &name, const QString &value);
|
||||
void doDisconnectFromServer();
|
||||
void doActivateToServer(const QString &_token);
|
||||
void doRequestForgotPasswordToServer(const QString &hostname, unsigned int port, const QString &_userName);
|
||||
|
|
@ -120,6 +123,9 @@ private:
|
|||
protected slots:
|
||||
void sendCommandContainer(const CommandContainer &cont) override;
|
||||
|
||||
public slots:
|
||||
void sendDiagnostics();
|
||||
|
||||
public:
|
||||
explicit RemoteClient(QObject *parent = nullptr, INetworkSettingsProvider *networkSettingsProvider = nullptr);
|
||||
~RemoteClient() override;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,22 @@ message Command_Login {
|
|||
optional string hashed_password = 6;
|
||||
}
|
||||
|
||||
message FeatureFlag {
|
||||
optional string name = 1;
|
||||
optional string value = 2;
|
||||
}
|
||||
|
||||
message Command_ClientDiagnostics {
|
||||
extend SessionCommand {
|
||||
optional Command_ClientDiagnostics ext = 1051;
|
||||
}
|
||||
|
||||
optional string clientver = 1;
|
||||
repeated FeatureFlag feature_flags = 2;
|
||||
optional string os = 3;
|
||||
optional string arch = 4;
|
||||
}
|
||||
|
||||
message Command_Message {
|
||||
extend SessionCommand {
|
||||
optional Command_Message ext = 1002;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue