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/NotificationDialog.cpp
ui/dialogs/NotificationDialog.h
ui/dialogs/OfflineNameDialog.cpp
ui/dialogs/OfflineNameDialog.h
ui/pagedialog/PageDialog.cpp
ui/pagedialog/PageDialog.h
ui/dialogs/ProgressDialog.cpp

View File

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

View File

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

View File

@ -400,7 +400,7 @@ bool AccountList::loadList()
{
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;
}
@ -492,7 +492,7 @@ bool AccountList::saveList()
{
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;
}

View File

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

View File

@ -33,7 +33,7 @@ class MSALoginDialog : public QDialog
public:
~MSALoginDialog();
static MinecraftAccountPtr newAccount(QWidget *parent, QString message);
static MinecraftAccountPtr newAccount(QWidget *parent);
int exec() override;
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()
{
MinecraftAccountPtr account = MSALoginDialog::newAccount(
this,
tr("Please enter your Mojang account email and password to add your account.")
);
MinecraftAccountPtr account = MSALoginDialog::newAccount(this);
if (account)
{
m_accounts->addAccount(account);