GH-5166 refine offline account handling on launch to allow going online

Added a button to the offline name selection dialog that allows
switching the intent from offline launch to online launch.

This lets you launch online with a currently offline account when you regain
network connectivity.
This commit is contained in:
Petr Mrázek 2024-12-17 03:40:09 +01:00
parent 7bd130ebaf
commit a026fabd20
9 changed files with 139 additions and 38 deletions

View File

@ -768,6 +768,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/NewInstanceDialog.h ui/dialogs/NewInstanceDialog.h
ui/dialogs/NotificationDialog.cpp ui/dialogs/NotificationDialog.cpp
ui/dialogs/NotificationDialog.h ui/dialogs/NotificationDialog.h
ui/dialogs/OfflineNameDialog.cpp
ui/dialogs/OfflineNameDialog.h
ui/pagedialog/PageDialog.cpp ui/pagedialog/PageDialog.cpp
ui/pagedialog/PageDialog.h ui/pagedialog/PageDialog.h
ui/dialogs/ProgressDialog.cpp ui/dialogs/ProgressDialog.cpp

View File

@ -11,6 +11,7 @@
#include "ui/dialogs/EditAccountDialog.h" #include "ui/dialogs/EditAccountDialog.h"
#include "ui/dialogs/ProfileSetupDialog.h" #include "ui/dialogs/ProfileSetupDialog.h"
#include "ui/dialogs/MSALoginDialog.h" #include "ui/dialogs/MSALoginDialog.h"
#include "ui/dialogs/OfflineNameDialog.h"
#include <QLineEdit> #include <QLineEdit>
#include <QInputDialog> #include <QInputDialog>
@ -107,20 +108,14 @@ void LaunchController::login() {
return; return;
} }
// we try empty password first :)
QString password;
// we loop until the user succeeds in logging in or gives up // we loop until the user succeeds in logging in or gives up
bool tryagain = true; bool tryagain = true;
// the failure. the default failure.
const QString needLoginAgain = tr("Your account is currently not logged in. Please enter your password to log in again. <br /> <br /> This could be caused by a password change.");
QString failReason = needLoginAgain;
while (tryagain) while (tryagain)
{ {
m_session = std::make_shared<AuthSession>(); m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online; m_session->wants_online = m_userWantsOnline;
m_accountToUse->fillSession(m_session); m_accountToUse->fillSession(m_session);
switch(m_accountToUse->accountState()) { switch(m_accountToUse->accountState()) {
case AccountState::Offline: { case AccountState::Offline: {
m_session->wants_online = false; m_session->wants_online = false;
@ -131,26 +126,32 @@ void LaunchController::login() {
QString usedname; QString usedname;
if(m_offlineName.isEmpty()) { if(m_offlineName.isEmpty()) {
// we ask the user for a player name // we ask the user for a player name
bool ok = false;
QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString(); QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString();
usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName; usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName;
QString name = QInputDialog::getText( OfflineNameDialog dialog(usedname, m_parentWidget);
m_parentWidget, int result = dialog.exec();
tr("Player name"), if(result == OfflineNameDialog::Accepted)
tr("Choose your offline mode player name."), {
QLineEdit::Normal, usedname = dialog.textValue();
usedname, APPLICATION->settings()->set("LastOfflinePlayerName", usedname);
&ok }
); else if (result == OfflineNameDialog::Rejected)
if (!ok)
{ {
tryagain = false; tryagain = false;
break; break;
} }
if (name.length()) else if(result == OfflineNameDialog::OnlineRequested)
{ {
usedname = name; m_userWantsOnline = true;
APPLICATION->settings()->set("LastOfflinePlayerName", usedname); if(m_accountToUse->accountState() == AccountState::Offline)
{
auto task = m_accountToUse->refresh();
if(task)
{
task->start();
}
}
break;
} }
} }
else { else {
@ -210,7 +211,7 @@ void LaunchController::login() {
case AccountState::Working: { case AccountState::Working: {
// refresh is in progress, we need to wait for it to finish to proceed. // refresh is in progress, we need to wait for it to finish to proceed.
ProgressDialog progDialog(m_parentWidget); ProgressDialog progDialog(m_parentWidget);
if (m_online) if (m_userWantsOnline)
{ {
progDialog.setSkipButton(true, tr("Play Offline")); progDialog.setSkipButton(true, tr("Play Offline"));
} }
@ -238,10 +239,7 @@ void LaunchController::login() {
bool isDefault = accounts->defaultAccount() == m_accountToUse; bool isDefault = accounts->defaultAccount() == m_accountToUse;
accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(m_accountToUse->profileId()))); accounts->removeAccount(accounts->index(accounts->findAccountByProfileId(m_accountToUse->profileId())));
MinecraftAccountPtr newAccount = nullptr; MinecraftAccountPtr newAccount = nullptr;
newAccount = MSALoginDialog::newAccount( newAccount = MSALoginDialog::newAccount(m_parentWidget);
m_parentWidget,
tr("Please enter your Mojang account email and password to add your account.")
);
if (newAccount) { if (newAccount) {
accounts->addAccount(newAccount); accounts->addAccount(newAccount);
if (isDefault) { if (isDefault) {

View File

@ -25,7 +25,7 @@ public:
} }
void setOnline(bool online) { void setOnline(bool online) {
m_online = online; m_userWantsOnline = online;
} }
void setOfflineName(const QString &offlineName) { void setOfflineName(const QString &offlineName) {
@ -69,7 +69,7 @@ private slots:
private: private:
BaseProfilerFactory *m_profiler = nullptr; BaseProfilerFactory *m_profiler = nullptr;
bool m_online = true; bool m_userWantsOnline = true;
QString m_offlineName; QString m_offlineName;
InstancePtr m_instance; InstancePtr m_instance;
QWidget * m_parentWidget = nullptr; QWidget * m_parentWidget = nullptr;

View File

@ -400,7 +400,7 @@ bool AccountList::loadList()
{ {
if (m_listFilePath.isEmpty()) if (m_listFilePath.isEmpty())
{ {
qCritical() << "Can't load Mojang account list. No file path given and no default set."; qCritical() << "Can't load account list. No file path given and no default set.";
return false; return false;
} }
@ -492,7 +492,7 @@ bool AccountList::saveList()
{ {
if (m_listFilePath.isEmpty()) if (m_listFilePath.isEmpty())
{ {
qCritical() << "Can't save Mojang account list. No file path given and no default set."; qCritical() << "Can't save account list. No file path given and no default set.";
return false; return false;
} }

View File

@ -143,10 +143,9 @@ void MSALoginDialog::onTaskProgress(qint64 current, qint64 total)
} }
// Public interface // Public interface
MinecraftAccountPtr MSALoginDialog::newAccount(QWidget *parent, QString msg) MinecraftAccountPtr MSALoginDialog::newAccount(QWidget *parent)
{ {
MSALoginDialog dlg(parent); MSALoginDialog dlg(parent);
dlg.ui->label->setText(msg);
if (dlg.exec() == QDialog::Accepted) if (dlg.exec() == QDialog::Accepted)
{ {
return dlg.m_account; return dlg.m_account;

View File

@ -33,7 +33,7 @@ class MSALoginDialog : public QDialog
public: public:
~MSALoginDialog(); ~MSALoginDialog();
static MinecraftAccountPtr newAccount(QWidget *parent, QString message); static MinecraftAccountPtr newAccount(QWidget *parent);
int exec() override; int exec() override;
private: private:

View File

@ -0,0 +1,66 @@
/*
* Copyright 2024 Petr Mrázek
*
* This source is subject to the Microsoft Permissive License (MS-PL).
* Please see the COPYING.md file for more information.
*/
#include <QLabel>
#include <QLineEdit>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QPushButton>
#include "OfflineNameDialog.h"
OfflineNameDialog::OfflineNameDialog(QString current_name, QWidget* parent)
{
setWindowTitle(tr("Player name"));
m_lineEdit = new QLineEdit(this);
m_lineEdit->setText(current_name);
connect(m_lineEdit, &QLineEdit::textChanged, this, &OfflineNameDialog::textChanged);
QLabel *label = new QLabel(tr("Choose your offline mode player name."), this);
label->setBuddy(m_lineEdit);
label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
QPushButton * retryButton = m_buttonBox->addButton(tr("Retry Online"), QDialogButtonBox::ActionRole);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(retryButton, &QPushButton::clicked, this, &OfflineNameDialog::retryOnline);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
mainLayout->addWidget(label);
mainLayout->addWidget(m_lineEdit);
mainLayout->addWidget(m_buttonBox);
textChanged(current_name);
}
void OfflineNameDialog::accept()
{
if(!m_acceptEnabled)
{
return;
}
QDialog::accept();
}
QString OfflineNameDialog::textValue() const
{
return m_lineEdit->text();
}
void OfflineNameDialog::textChanged(const QString& text)
{
m_acceptEnabled = !text.isEmpty();
m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_acceptEnabled);
}
void OfflineNameDialog::retryOnline()
{
done(OnlineRequested);
}

View File

@ -0,0 +1,40 @@
#pragma once
/*
* Copyright 2024 Petr Mrázek
*
* This source is subject to the Microsoft Permissive License (MS-PL).
* Please see the COPYING.md file for more information.
*/
#include <QDialog>
#include <QString>
class OfflineNameDialog : public QDialog
{
Q_OBJECT
public:
enum OfflineNameDialogCode {
Rejected = QDialog::Rejected,
Accepted = QDialog::Accepted,
OnlineRequested,
};
OfflineNameDialog(QString current_name, QWidget * parent = nullptr);
virtual ~OfflineNameDialog() = default;
QString textValue() const;
public slots:
void accept() override;
private slots:
void textChanged(const QString& text);
void retryOnline();
private:
class QDialogButtonBox * m_buttonBox;
class QLineEdit* m_lineEdit;
bool m_acceptEnabled = false;
};

View File

@ -110,11 +110,7 @@ void AccountListPage::listChanged()
void AccountListPage::on_actionAddMicrosoft_triggered() void AccountListPage::on_actionAddMicrosoft_triggered()
{ {
MinecraftAccountPtr account = MSALoginDialog::newAccount( MinecraftAccountPtr account = MSALoginDialog::newAccount(this);
this,
tr("Please enter your Mojang account email and password to add your account.")
);
if (account) if (account)
{ {
m_accounts->addAccount(account); m_accounts->addAccount(account);