Files
parallel-launcher/src/rhdc/ui/rhdc-login-dialog.cpp
2025-07-27 19:36:46 -04:00

277 lines
8.9 KiB
C++

#include "src/rhdc/ui/rhdc-login-dialog.hpp"
#include "ui_rhdc-login-dialog.h"
#include <QMessageBox>
#include "src/polyfill/file-dialog.hpp"
#include "src/polyfill/filetime.hpp"
#include "src/polyfill/sha1.hpp"
#include "src/core/preset-controllers.hpp"
#include "src/core/file-controller.hpp"
#include "src/core/steam-deck.hpp"
#include "src/core/vulkan.hpp"
#include "src/core/sm64.hpp"
#include "src/core/rom.hpp"
#include "src/db/data-provider.hpp"
#include "src/ui/icons.hpp"
#include "src/ui/util.hpp"
#include "src/rhdc/web/api.hpp"
#include "src/rhdc/web/api-helpers.hpp"
RhdcLoginDialog::RhdcLoginDialog( QWidget *parent ) :
QDialog( parent ),
m_ui( new Ui::RhdcLoginDialog ),
m_exists( new bool( true ) )
{
m_ui->setupUi( this );
m_ui->settingsContainer->setVisible( false );
m_ui->browseForRomButton->setIcon( Icon::browse() );
m_ui->downloadDirButton->setIcon( Icon::browse() );
m_ui->loginButton->setIcon( Icon::login() );
m_ui->verifyMfaButton->setIcon( Icon::ok() );
setWindowIcon( Icon::appIcon() );
UiUtil::fixDialogButtonsOnWindows( this );
QFont codeFont = m_ui->mfaInput->font();
codeFont.setLetterSpacing( QFont::PercentageSpacing, 150.0 );
m_ui->mfaInput->setFont( codeFont );
#ifdef __APPLE__
UiUtil::fixFontSizeOnMac( m_ui->label_4 );
UiUtil::fixFontSizeOnMac( m_ui->label_7 );
UiUtil::fixFontSizeOnMac( m_ui->label_8 );
UiUtil::fixFontSizeOnMac( m_ui->label_9 );
UiUtil::fixFontSizeOnMac( m_ui->label_10 );
UiUtil::fixFontSizeOnMac( m_ui->label_11 );
UiUtil::fixFontSizeOnMac( m_ui->label_14 );
UiUtil::fixFontSizeOnMac( m_ui->preferHleLabel );
#endif
}
RhdcLoginDialog::~RhdcLoginDialog() {
*m_exists = false;
delete m_ui;
}
void RhdcLoginDialog::showEvent( QShowEvent *event ) {
fs::path _discard;
m_ui->pages->setCurrentIndex( SM64::tryGetPath( _discard ) ? 1 : 0 );
m_ui->usernameInput->clear();
m_ui->passwordInput->clear();
m_ui->loginErrorMessage->clear();
m_ui->buttonTray->button( QDialogButtonBox::Cancel )->setVisible( true );
m_ui->buttonTray->button( QDialogButtonBox::Ok )->setVisible( false );
m_ui->loginSpinner->setVisible( false );
m_ui->loginButton->setEnabled( true );
m_ui->settingsContainer->setVisible( false );
QDialog::showEvent( event );
QRect geo = geometry();
geo.setWidth( 450 );
geo.setHeight( 275 );
setGeometry( geo );
if( SteamDeck::isSteamDeck() ) {
m_ui->preferHleCheckbox->setVisible( false );
m_ui->preferHleLabel->setVisible( false );
}
}
static const string SM64_SHA1 = "9bef1128717f958171a4afac3ed78ee2bb4e86ce";
void RhdcLoginDialog::browseForRom() {
const fs::path romPath = FileDialog::getFile(
tr( "Select SM64 ROM" ).toStdString().c_str(),
{{ "z64 ROM", "*.z64" }}
);
if( romPath.empty() ) return;
if( Sha1::compute( romPath ) != SM64_SHA1 ) {
QMessageBox::critical( this, tr( "ROM Does not Match" ), tr( "The provided rom does not match the expected checksum." ) );
return;
}
DataProvider::addManualRomPath( romPath );
DataProvider::addRomFile({
romPath,
Time::getLastModifiedSec( romPath ),
SM64_SHA1,
true
});
DataProvider::addRomInfo({
SM64_SHA1,
"Super Mario 64",
"SUPER MARIO 64",
GfxPlugin::ParaLLEl,
true,
true,
false,
true,
false,
0,
0,
std::set<string>(),
true,
false,
1021708041,
DefaultInputModes::Normal.id,
WidescreenMode::Off,
false,
false,
{ N64InputType::Unknown, N64InputType::None, N64InputType::None, N64InputType::None },
""
});
m_ui->pages->setCurrentIndex( 1 );
}
void RhdcLoginDialog::browseForDir() {
const fs::path downloadDir = FileDialog::getDirectory(
tr( "Select a new download directory" ).toStdString().c_str()
);
if( downloadDir.empty() ) return;
m_ui->downloadDirInput->setText( downloadDir.u8string().c_str() );
}
void RhdcLoginDialog::validateMfaCode() {
QString value = m_ui->mfaInput->text();
QString safeValue;
for( int i = 0; i < value.length() && safeValue.length() < 6; i++ ) {
if( value[i].isDigit() ) safeValue.append( value[i] );
}
if( safeValue != value ) {
m_ui->mfaInput->setText( safeValue );
}
m_ui->verifyMfaButton->setEnabled( safeValue.length() == 6 );
}
void RhdcLoginDialog::login() {
if( m_ui->usernameInput->text().isEmpty() ) {
m_ui->loginErrorMessage->setText( tr( "Enter your username" ) );
return;
}
if( m_ui->passwordInput->text().isEmpty() ) {
m_ui->loginErrorMessage->setText( tr( "Enter your password" ) );
return;
}
m_ui->loginButton->setEnabled( false );
m_ui->loginSpinner->setVisible( true );
m_ui->loginErrorMessage->clear();
std::shared_ptr<bool> dialogExists = m_exists;
RhdcApi::loginAsync(
m_ui->usernameInput->text().toStdString(),
m_ui->passwordInput->text().toStdString(),
/* mfaCode */ -1,
/* awaitRetryAfter */ true,
[this,dialogExists]() {
if( !*dialogExists ) return;
this->m_ui->pages->setCurrentIndex( 3 );
this->m_ui->buttonTray->button( QDialogButtonBox::Cancel )->setVisible( false );
this->m_ui->buttonTray->button( QDialogButtonBox::Ok )->setVisible( true );
QRect geo = this->geometry();
geo.setWidth( 525 );
geo.setHeight( 575 );
this->setGeometry( geo );
this->m_ui->settingsContainer->setVisible( true );
const RhdcSettings rhdcSettings = FileController::loadRhdcSettings();
this->m_ui->downloadDirInput->setText( rhdcSettings.downloadDirectory.u8string().c_str() );
this->m_ui->enableStarDisplayCheckbox->setChecked( rhdcSettings.enableStarDisplay );
this->m_ui->allSlotsCheckbox->setChecked( rhdcSettings.checkAllSaveSlots );
this->m_ui->preferHleCheckbox->setChecked( !VulkanInfo::supportsParaLLEl() );
this->m_ui->enableDefaultLayoutsCheckbox->setChecked( rhdcSettings.enableDefaultLayouts );
this->m_ui->starDisplaySubsection->setEnabled( rhdcSettings.enableStarDisplay );
this->m_ui->ignoreWidescreenCheckbox->setChecked( rhdcSettings.ignoreWidescreenHint );
},
[this,dialogExists](ApiErrorType error) {
if( !*dialogExists ) return;
if( error == ApiErrorType::MfaCodeRequired ) {
this->m_ui->pages->setCurrentIndex( 2 );
this->m_ui->loginSpinner2->setVisible( false );
this->m_ui->mfaErrorMessage->setVisible( false );
this->m_ui->verifyMfaButton->setEnabled( false );
this->m_ui->mfaInput->clear();
return;
}
this->m_ui->loginSpinner->setVisible( false );
this->m_ui->loginButton->setEnabled( true );
switch( error ) {
case ApiErrorType::NotAuthorized:
this->m_ui->loginErrorMessage->setText( tr( "Username or password is incorrect" ) );
break;
case ApiErrorType::ServerDown:
this->m_ui->loginErrorMessage->setText( tr( "The romhacking.com servers appear to be down." ) );
break;
default:
this->m_ui->loginErrorMessage->setText( tr( "An unknown error occurred." ) );
break;
}
}
);
}
void RhdcLoginDialog::sendMfaCode() {
this->m_ui->loginSpinner2->setVisible( true );
this->m_ui->verifyMfaButton->setEnabled( false );
std::shared_ptr<bool> dialogExists = m_exists;
RhdcApi::loginAsync(
m_ui->usernameInput->text().toStdString(),
m_ui->passwordInput->text().toStdString(),
m_ui->mfaInput->text().toInt( nullptr, 10 ),
/* awaitRetryAfter */ true,
[this,dialogExists]() {
if( !*dialogExists ) return;
this->m_ui->pages->setCurrentIndex( 3 );
this->m_ui->buttonTray->button( QDialogButtonBox::Cancel )->setVisible( false );
this->m_ui->buttonTray->button( QDialogButtonBox::Ok )->setVisible( true );
QRect geo = this->geometry();
geo.setWidth( 525 );
geo.setHeight( 575 );
this->setGeometry( geo );
this->m_ui->settingsContainer->setVisible( true );
const bool accountVerified = (ApiUtil::identity().role > RhdcRole::Unverified);
const RhdcSettings rhdcSettings = FileController::loadRhdcSettings();
this->m_ui->downloadDirInput->setText( rhdcSettings.downloadDirectory.u8string().c_str() );
this->m_ui->enableStarDisplayCheckbox->setChecked( rhdcSettings.enableStarDisplay );
this->m_ui->allSlotsCheckbox->setChecked( rhdcSettings.checkAllSaveSlots );
this->m_ui->preferHleCheckbox->setChecked( !VulkanInfo::supportsParaLLEl() );
this->m_ui->enableDefaultLayoutsCheckbox->setChecked( rhdcSettings.enableDefaultLayouts );
this->m_ui->starDisplaySubsection->setEnabled( rhdcSettings.enableStarDisplay );
this->m_ui->ignoreWidescreenCheckbox->setChecked( rhdcSettings.ignoreWidescreenHint );
this->m_ui->cloudSaveCheckbox->setEnabled( accountVerified );
this->m_ui->cloudSaveCheckbox->setChecked( accountVerified );
},
[this,dialogExists](ApiErrorType) {
if( !*dialogExists ) return;
this->m_ui->mfaErrorMessage->setVisible( true );
this->m_ui->verifyMfaButton->setEnabled( true );
this->m_ui->loginSpinner2->setVisible( false );
}
);
}
void RhdcLoginDialog::accept() {
FileController::saveRhdcSettings({
fs::to_path( m_ui->downloadDirInput->text().toStdString() ),
m_ui->enableStarDisplayCheckbox->isChecked(),
m_ui->allSlotsCheckbox->isChecked(),
m_ui->preferHleCheckbox->isChecked(),
m_ui->enableDefaultLayoutsCheckbox->isChecked(),
m_ui->ignoreWidescreenCheckbox->isChecked(),
m_ui->cloudSaveCheckbox->isChecked()
});
QDialog::accept();
}