Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into feature/java-downloader

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97
2024-06-30 22:54:23 +03:00
28 changed files with 635 additions and 226 deletions

View File

@@ -34,6 +34,8 @@
*/
#include "MSALoginDialog.h"
#include "Application.h"
#include "ui_MSALoginDialog.h"
#include "DesktopServices.h"
@@ -41,6 +43,7 @@
#include <QApplication>
#include <QClipboard>
#include <QPixmap>
#include <QUrl>
#include <QtWidgets/QPushButton>
@@ -48,28 +51,48 @@ MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MS
{
ui->setupUi(this);
ui->cancel->setEnabled(false);
ui->link->setVisible(false);
ui->copy->setVisible(false);
ui->progressBar->setVisible(false);
// make font monospace
QFont font;
font.setPixelSize(ui->code->fontInfo().pixelSize());
font.setFamily(APPLICATION->settings()->get("ConsoleFont").toString());
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
ui->code->setFont(font);
connect(ui->cancel, &QPushButton::pressed, this, &QDialog::reject);
connect(ui->copy, &QPushButton::pressed, this, &MSALoginDialog::copyUrl);
connect(ui->copyCode, &QPushButton::clicked, this, [this] { QApplication::clipboard()->setText(ui->code->text()); });
ui->qr->setPixmap(QIcon((":/documents/login-qr.svg")).pixmap(QSize(150, 150)));
connect(ui->loginButton, &QPushButton::clicked, this, [this] {
if (m_url.isValid()) {
if (!DesktopServices::openUrl(m_url)) {
QApplication::clipboard()->setText(m_url.toString());
}
}
});
}
int MSALoginDialog::exec()
{
// Setup the login task and start it
m_account = MinecraftAccount::createBlankMSA();
m_task = m_account->login(m_using_device_code);
connect(m_task.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_task.get(), &Task::succeeded, this, &MSALoginDialog::onTaskSucceeded);
connect(m_task.get(), &Task::status, this, &MSALoginDialog::onTaskStatus);
connect(m_task.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_task.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(ui->cancel, &QPushButton::pressed, m_task.get(), &Task::abort);
connect(&m_external_timer, &QTimer::timeout, this, &MSALoginDialog::externalLoginTick);
m_task->start();
m_authflow_task = m_account->login(false);
connect(m_authflow_task.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_authflow_task.get(), &Task::succeeded, this, &QDialog::accept);
connect(m_authflow_task.get(), &Task::aborted, this, &MSALoginDialog::reject);
connect(m_authflow_task.get(), &Task::status, this, &MSALoginDialog::onTaskStatus);
connect(m_authflow_task.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_authflow_task.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_authflow_task.get(), &Task::abort);
m_devicecode_task.reset(new AuthFlow(m_account->accountData(), AuthFlow::Action::DeviceCode, this));
connect(m_devicecode_task.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
connect(m_devicecode_task.get(), &Task::succeeded, this, &QDialog::accept);
connect(m_devicecode_task.get(), &Task::aborted, this, &MSALoginDialog::reject);
connect(m_devicecode_task.get(), &Task::status, this, &MSALoginDialog::onTaskStatus);
connect(m_devicecode_task.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
connect(m_devicecode_task.get(), &AuthFlow::authorizeWithBrowserWithExtra, this, &MSALoginDialog::authorizeWithBrowserWithExtra);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_devicecode_task.get(), &Task::abort);
QMetaObject::invokeMethod(m_authflow_task.get(), &Task::start, Qt::QueuedConnection);
QMetaObject::invokeMethod(m_devicecode_task.get(), &Task::start, Qt::QueuedConnection);
return QDialog::exec();
}
@@ -79,9 +102,12 @@ MSALoginDialog::~MSALoginDialog()
delete ui;
}
void MSALoginDialog::onTaskFailed(const QString& reason)
void MSALoginDialog::onTaskFailed(QString reason)
{
// Set message
m_authflow_task->disconnect();
m_devicecode_task->disconnect();
ui->stackedWidget->setCurrentIndex(0);
auto lines = reason.split('\n');
QString processed;
for (auto line : lines) {
@@ -91,91 +117,53 @@ void MSALoginDialog::onTaskFailed(const QString& reason)
processed += "<br />";
}
}
ui->message->setText(processed);
}
void MSALoginDialog::onTaskSucceeded()
{
QDialog::accept();
}
void MSALoginDialog::onTaskStatus(const QString& status)
{
ui->message->setText(status);
ui->cancel->setEnabled(false);
ui->link->setVisible(false);
ui->copy->setVisible(false);
ui->progressBar->setVisible(false);
}
// Public interface
MinecraftAccountPtr MSALoginDialog::newAccount(QWidget* parent, QString msg, bool usingDeviceCode)
{
MSALoginDialog dlg(parent);
dlg.m_using_device_code = usingDeviceCode;
dlg.ui->message->setText(msg);
if (dlg.exec() == QDialog::Accepted) {
return dlg.m_account;
ui->status->setText(processed);
auto task = m_authflow_task;
if (task->failReason().isEmpty()) {
task = m_devicecode_task;
}
return nullptr;
if (task) {
ui->loadingLabel->setText(task->getStatus());
}
disconnect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_authflow_task.get(), &Task::abort);
disconnect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, m_devicecode_task.get(), &Task::abort);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &MSALoginDialog::reject);
}
void MSALoginDialog::authorizeWithBrowser(const QUrl& url)
{
ui->cancel->setEnabled(true);
ui->link->setVisible(true);
ui->copy->setVisible(true);
DesktopServices::openUrl(url);
ui->link->setText(url.toDisplayString());
ui->message->setText(
tr("Browser opened to complete the login process."
"<br /><br />"
"If your browser hasn't opened, please manually open the below link in your browser:"));
}
void MSALoginDialog::copyUrl()
{
QClipboard* cb = QApplication::clipboard();
cb->setText(ui->link->text());
ui->stackedWidget->setCurrentIndex(1);
ui->loginButton->setToolTip(QString("<div style='width: 200px;'>%1</div>").arg(url.toString()));
m_url = url;
}
void MSALoginDialog::authorizeWithBrowserWithExtra(QString url, QString code, int expiresIn)
{
m_external_elapsed = 0;
m_external_timeout = expiresIn;
ui->stackedWidget->setCurrentIndex(1);
m_external_timer.setInterval(1000);
m_external_timer.setSingleShot(false);
m_external_timer.start();
ui->progressBar->setMaximum(expiresIn);
ui->progressBar->setValue(m_external_elapsed);
QString linkString = QString("<a href=\"%1\">%2</a>").arg(url, url);
if (url == "https://www.microsoft.com/link" && !code.isEmpty()) {
url += QString("?otc=%1").arg(code);
ui->message->setText(tr("<p>Please login in the opened browser. If no browser was opened, please open up %1 in "
"a browser and put in the code <b>%2</b> to proceed with login.</p>")
.arg(linkString, code));
const auto linkString = QString("<a href=\"%1\">%2</a>").arg(url, url);
ui->code->setText(code);
auto isDefaultUrl = url == "https://www.microsoft.com/link";
ui->qr->setVisible(isDefaultUrl);
if (isDefaultUrl) {
ui->qrMessage->setText(tr("Open %1 or scan the QR and enter the above code.").arg(linkString));
} else {
ui->message->setText(
tr("<p>Please open up %1 in a browser and put in the code <b>%2</b> to proceed with login.</p>").arg(linkString, code));
ui->qrMessage->setText(tr("Open %1 and enter the above code.").arg(linkString));
}
ui->cancel->setEnabled(true);
ui->link->setVisible(true);
ui->copy->setVisible(true);
ui->progressBar->setVisible(true);
DesktopServices::openUrl(url);
ui->link->setText(code);
}
void MSALoginDialog::externalLoginTick()
void MSALoginDialog::onTaskStatus(QString status)
{
m_external_elapsed++;
ui->progressBar->setValue(m_external_elapsed);
ui->progressBar->repaint();
ui->stackedWidget->setCurrentIndex(0);
ui->status->setText(status);
}
if (m_external_elapsed >= m_external_timeout) {
m_external_timer.stop();
// Public interface
MinecraftAccountPtr MSALoginDialog::newAccount(QWidget* parent)
{
MSALoginDialog dlg(parent);
if (dlg.exec() == QDialog::Accepted) {
return dlg.m_account;
}
return nullptr;
}

View File

@@ -32,29 +32,23 @@ class MSALoginDialog : public QDialog {
public:
~MSALoginDialog();
static MinecraftAccountPtr newAccount(QWidget* parent, QString message, bool usingDeviceCode = false);
static MinecraftAccountPtr newAccount(QWidget* parent);
int exec() override;
private:
explicit MSALoginDialog(QWidget* parent = 0);
protected slots:
void onTaskFailed(const QString& reason);
void onTaskSucceeded();
void onTaskStatus(const QString& status);
void onTaskFailed(QString reason);
void onTaskStatus(QString status);
void authorizeWithBrowser(const QUrl& url);
void authorizeWithBrowserWithExtra(QString url, QString code, int expiresIn);
void copyUrl();
void externalLoginTick();
private:
Ui::MSALoginDialog* ui;
MinecraftAccountPtr m_account;
shared_qobject_ptr<AuthFlow> m_task;
shared_qobject_ptr<AuthFlow> m_devicecode_task;
shared_qobject_ptr<AuthFlow> m_authflow_task;
int m_external_elapsed;
int m_external_timeout;
QTimer m_external_timer;
bool m_using_device_code = false;
QUrl m_url;
};

View File

@@ -6,87 +6,345 @@
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>208</height>
<width>440</width>
<height>430</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="minimumSize">
<size>
<width>0</width>
<height>430</height>
</size>
</property>
<property name="windowTitle">
<string>Add Microsoft Account</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="message">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>500</height>
</size>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="loadingPage">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="loadingLabel">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Please wait...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="status">
<property name="text">
<string>Status</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="mpPage">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="loginButton">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>Sign in with Microsoft</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="Line" name="line_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="orLabel">
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="text">
<string>Or</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="qr">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>150</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>150</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="code">
<property name="font">
<font>
<pointsize>30</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>CODE</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="copyCode">
<property name="toolTip">
<string>Copy code to clipboard</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="copy">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="qrMessage">
<property name="text">
<string>Info</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="linkLayout">
<item>
<widget class="QLineEdit" name="link">
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="copy">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="copy">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>Cancel</string>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel</set>
</property>
</widget>
</item>

View File

@@ -145,6 +145,7 @@ void ResourceDownloadDialog::confirm()
confirm_dialog->retranslateUi(resourcesString());
QHash<QString, GetModDependenciesTask::PackDependencyExtraInfo> dependencyExtraInfo;
QStringList depNames;
if (auto task = getModDependenciesTask(); task) {
connect(task.get(), &Task::failed, this,
[&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); });
@@ -167,8 +168,10 @@ void ResourceDownloadDialog::confirm()
QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection);
return;
} else {
for (auto dep : task->getDependecies())
for (auto dep : task->getDependecies()) {
addResource(dep->pack, dep->version);
depNames << dep->pack->name;
}
dependencyExtraInfo = task->getExtraInfo();
}
}
@@ -193,6 +196,9 @@ void ResourceDownloadDialog::confirm()
}
this->accept();
} else {
for (auto name : depNames)
removeResource(name);
}
}