1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-04-21 20:27:45 +00:00

Overhaul initial setup flow, again

This improves the flow drastically, first by porting it from MobileForm
to FormCard. Next, it fixes some of the annoying bugs such as the
profile not switching properly when adding a new profile. Selecting an
existing game path is now possible, and it's less likely you can enter
in invalid account credentials. The overall look and behavior of some
of the pages is improved.
This commit is contained in:
Joshua Goins 2023-10-08 20:01:17 -04:00
parent 3a7dc40826
commit 67dcd90058
16 changed files with 344 additions and 261 deletions

View file

@ -109,6 +109,16 @@ qt_target_qml_sources(astra
ui/Main.qml
)
set_source_files_properties(../zone.xiv.astra.svg PROPERTIES
QT_RESOURCE_ALIAS /zone.xiv.astra.svg
)
qt_target_qml_sources(astra
PREFIX /
RESOURCES
../zone.xiv.astra.svg
)
kconfig_add_kcfg_files(astra GENERATE_MOC config.kcfgc accountconfig.kcfgc profileconfig.kcfgc)
target_include_directories(astra PRIVATE include ${CMAKE_BINARY_DIR})
target_link_libraries(astra PRIVATE

View file

@ -37,6 +37,8 @@ public:
Q_INVOKABLE bool canDelete(Account *account) const;
Q_INVOKABLE void deleteAccount(Account *account);
Q_INVOKABLE bool hasAnyAccounts() const;
private:
void insertAccount(Account *account);

View file

@ -40,6 +40,8 @@ public:
Q_INVOKABLE bool canDelete(Profile *account) const;
Q_INVOKABLE bool hasAnyExistingInstallations() const;
static QString getDefaultGamePath(const QString &uuid);
static QString getDefaultWinePrefixPath(const QString &uuid);

View file

@ -111,3 +111,8 @@ void AccountManager::insertAccount(Account *account)
m_accounts.append(account);
endInsertRows();
}
bool AccountManager::hasAnyAccounts() const
{
return !m_accounts.empty();
}

View file

@ -794,7 +794,7 @@ void LauncherCore::setCurrentProfile(Profile *profile)
{
Q_ASSERT(profile != nullptr);
const int newIndex = m_profileManager->getProfileIndex(profile->name());
const int newIndex = m_profileManager->getProfileIndex(profile->uuid());
if (newIndex != m_currentProfileIndex) {
m_currentProfileIndex = newIndex;
Q_EMIT currentProfileChanged();

View file

@ -510,13 +510,13 @@ QString Profile::bootVersion() const
QString Profile::baseGameVersion() const
{
Q_ASSERT(m_repositories.repositories_count > 1);
Q_ASSERT(m_repositories.repositories_count >= 1);
return m_repositories.repositories[0].version;
}
int Profile::numInstalledExpansions() const
{
Q_ASSERT(m_repositories.repositories_count > 1);
Q_ASSERT(m_repositories.repositories_count >= 1);
return m_repositories.repositories_count - 1;
}

View file

@ -22,7 +22,7 @@ Profile *ProfileManager::getProfile(const int index)
int ProfileManager::getProfileIndex(const QString &name)
{
for (int i = 0; i < m_profiles.size(); i++) {
if (m_profiles[i]->name() == name)
if (m_profiles[i]->uuid() == name)
return i;
}
@ -147,3 +147,14 @@ bool ProfileManager::canDelete(Profile *account) const
Q_UNUSED(account)
return m_profiles.size() != 1;
}
bool ProfileManager::hasAnyExistingInstallations() const
{
for (auto &profile : m_profiles) {
if (profile->isGameInstalled()) {
return true;
}
}
return false;
}

View file

@ -4,9 +4,9 @@
import QtCore
import QtQuick.Dialogs
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: control
property string file

View file

@ -88,7 +88,6 @@ FormCard.FormCardPage {
}
}
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true

View file

@ -5,37 +5,52 @@ import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
import zone.xiv.astra
Kirigami.Page {
FormCard.FormCardPage {
id: page
property var profile
title: i18n("Account Setup")
ColumnLayout {
width: parent.width
MobileForm.FormCard {
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Accounts")
FormCard.FormTextDelegate {
id: helpTextDelegate
text: i18n("Select an account to use for '%1'", LauncherCore.currentProfile.name)
}
}
MobileForm.FormTextDelegate {
text: i18n("Select an account below to use for profile '%1'.", LauncherCore.currentProfile.name)
FormCard.FormHeader {
title: i18n("Existing Accounts")
visible: LauncherCore.accountManager.hasAnyAccounts()
}
FormCard.FormCard {
visible: LauncherCore.accountManager.hasAnyAccounts()
Layout.fillWidth: true
FormCard.FormTextDelegate {
id: existingHelpDelegate
text: i18n("You can select an existing account.")
}
FormCard.FormDelegateSeparator {
above: existingHelpDelegate
}
Repeater {
model: LauncherCore.accountManager
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
required property var account
text: account.name
@ -47,15 +62,14 @@ Kirigami.Page {
}
}
}
}
MobileForm.FormCard {
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: addSquareEnixButton
text: i18n("Add Square Enix Account")
icon.name: "list-add-symbolic"
onClicked: pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "AddSquareEnix"), {
@ -63,10 +77,14 @@ Kirigami.Page {
})
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: addSquareEnixButton
below: addSapphireButton
}
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: addSapphireButton
text: i18n("Add Sapphire Account")
icon.name: "list-add-symbolic"
onClicked: pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "AddSapphire"), {
@ -75,5 +93,3 @@ Kirigami.Page {
}
}
}
}
}

View file

@ -6,51 +6,58 @@ import QtQuick.Layouts
import QtQuick.Window
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
import zone.xiv.astra
Kirigami.Page {
FormCard.FormCardPage {
id: page
property var profile
title: i18n("Add Sapphire Account")
ColumnLayout {
width: parent.width
MobileForm.FormCard {
readonly property bool isValid: usernameField.text.length !== 0 && lobbyUrlField.text.length !== 0
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormTextDelegate {
description: i18n("Passwords will be entered on the login page. The username will be associated with this profile but can be changed later.")
FormCard.FormTextDelegate {
id: helpTextDelegate
description: i18n("The password will be entered on the login page. A username will be associated with this account but can always be changed later.")
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: helpTextDelegate
below: usernameField
}
MobileForm.FormTextFieldDelegate {
id: lobbyUrlField
label: i18n("Lobby URL")
}
MobileForm.FormDelegateSeparator {
}
MobileForm.FormTextFieldDelegate {
FormCard.FormTextFieldDelegate {
id: usernameField
label: i18n("Username")
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: usernameField
below: lobbyUrlField
}
MobileForm.FormButtonDelegate {
FormCard.FormTextFieldDelegate {
id: lobbyUrlField
label: i18n("Lobby URL")
}
FormCard.FormDelegateSeparator {
above: lobbyUrlField
below: buttonDelegate
}
FormCard.FormButtonDelegate {
id: buttonDelegate
text: i18n("Add Account")
icon.name: "list-add-symbolic"
enabled: page.isValid
onClicked: {
let account = LauncherCore.accountManager.createSapphireAccount(lobbyUrlField.text, usernameField.text)
if (page.profile) {
@ -63,5 +70,3 @@ Kirigami.Page {
}
}
}
}
}

View file

@ -6,41 +6,44 @@ import QtQuick.Layouts
import QtQuick.Window
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
import zone.xiv.astra
Kirigami.Page {
FormCard.FormCardPage {
id: page
property var profile
title: i18n("Add Square Enix Account")
ColumnLayout {
width: parent.width
MobileForm.FormCard {
readonly property bool isValid: usernameField.text.length !== 0
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormTextDelegate {
description: i18n("Passwords will be entered on the login page. The username will be associated with this profile but can be changed later.")
FormCard.FormTextDelegate {
id: helpTextDelegate
description: i18n("The password will be entered on the login page. A username will be associated with this account but can always be changed later.")
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: helpTextDelegate
below: usernameField
}
MobileForm.FormTextFieldDelegate {
FormCard.FormTextFieldDelegate {
id: usernameField
label: i18n("Username")
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: usernameField
below: licenseField
}
MobileForm.FormComboBoxDelegate {
FormCard.FormComboBoxDelegate {
id: licenseField
text: i18n("License")
description: i18n("If the account holds multiple licenses, choose the preferred one.")
@ -48,21 +51,27 @@ Kirigami.Page {
currentIndex: 0
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: licenseField
below: freeTrialField
}
MobileForm.FormCheckDelegate {
FormCard.FormCheckDelegate {
id: freeTrialField
text: i18n("Free Trial")
description: i18n("Check if the account is currently on free trial.")
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: freeTrialField
below: buttonDelegate
}
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: buttonDelegate
text: i18n("Add Account")
icon.name: "list-add-symbolic"
enabled: page.isValid
onClicked: {
let account = LauncherCore.accountManager.createSquareEnixAccount(usernameField.text, licenseField.currentIndex, freeTrialField.checkState === Qt.Checked)
if (page.profile) {
@ -75,5 +84,3 @@ Kirigami.Page {
}
}
}
}
}

View file

@ -5,38 +5,36 @@ import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
import zone.xiv.astra
Kirigami.Page {
FormCard.FormCardPage {
id: page
property var profile
title: i18n("Download Game")
ColumnLayout {
width: parent.width
MobileForm.FormCard {
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Download Game")
}
FormCard.FormTextDelegate {
id: helpTextDelegate
MobileForm.FormTextDelegate {
text: i18n("Press the button below to download and setup the game.")
description: i18n("This is for the base files required for start-up, only when logged in will Astra begin downloading the full game.")
description: i18n("This only installs the base files required for the initial update. Astra can only download patches with a legitimate Square Enix account.")
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: helpTextDelegate
below: buttonDelegate
}
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: buttonDelegate
text: i18n("Begin installation")
icon.name: "cloud-download"
onClicked: pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "InstallProgress"), {
@ -45,5 +43,3 @@ Kirigami.Page {
}
}
}
}
}

View file

@ -3,31 +3,52 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Dialogs
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
import zone.xiv.astra
Kirigami.Page {
title: i18n("Find Game Installation")
import "../Components"
ColumnLayout {
width: parent.width
MobileForm.FormCard {
FormCard.FormCardPage {
id: page
property var profile
title: i18n("Find Existing Installation")
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Find an existing installation")
}
FormCard.FormTextDelegate {
id: helpTextDelegate
MobileForm.FormTextDelegate {
text: i18n("Please select the path to your existing installation.")
}
}
FormCard.FormDelegateSeparator {
above: helpTextDelegate
below: selectDelegate
}
FormCard.FormButtonDelegate {
id: selectDelegate
text: i18n("Select Existing Path")
icon.name: "document-open-folder"
onClicked: dialog.open()
}
}
data: FolderDialog {
id: dialog
onAccepted: {
page.profile.gamePath = decodeURIComponent(selectedFolder.toString().replace("file://", ""));
applicationWindow().checkSetup();
}
}
}

View file

@ -5,7 +5,6 @@ import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import zone.xiv.astra

View file

@ -5,62 +5,71 @@ import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.mobileform as MobileForm
import org.kde.kirigamiaddons.formcard as FormCard
import zone.xiv.astra
Kirigami.Page {
FormCard.FormCardPage {
id: page
property var profile
readonly property bool isInitialSetup: !LauncherCore.profileManager.hasAnyExistingInstallations()
title: i18n("Game Setup")
title: isInitialSetup ? i18n("Initial Setup") : i18n("Profile Setup")
Image {
source: "qrc:/zone.xiv.astra.svg"
fillMode: Image.PreserveAspectFit
ColumnLayout {
width: parent.width
MobileForm.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Welcome to Astra")
Layout.fillHeight: true
Layout.margins: Kirigami.Units.largeSpacing * 3
}
MobileForm.FormTextDelegate {
text: i18n("The profile '%1' must be set up before first.", LauncherCore.currentProfile.name)
}
MobileForm.FormTextDelegate {
text: i18n("A copy of the game must be located or installed.")
description: i18n("A valid game account will be required at the end of installation.")
}
}
}
MobileForm.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
FormCard.FormCard {
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
FormCard.FormTextDelegate {
text: {
if (isInitialSetup) {
return i18n("You must have a legitimate installation of the FFXIV to continue.");
} else {
return i18n("You must select a legitimate installation of FFXIV for '%1'", page.profile.name);
}
}
}
}
FormCard.FormHeader {
title: i18n("Existing Installations")
visible: LauncherCore.profileManager.hasAnyExistingInstallations()
}
MobileForm.FormTextDelegate {
text: i18n("Select an existing installation from another profile below.")
FormCard.FormCard {
visible: LauncherCore.profileManager.hasAnyExistingInstallations()
Layout.fillWidth: true
FormCard.FormTextDelegate {
id: existingHelpDelegate
text: i18n("You can select an existing installation from another profile.")
}
FormCard.FormDelegateSeparator {
above: existingHelpDelegate
}
Repeater {
model: LauncherCore.profileManager
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
required property var profile
text: profile.name
description: profile.gamePath
visible: profile.isGameInstalled
onClicked: {
LauncherCore.currentProfile.gamePath = profile.gamePath;
@ -69,15 +78,14 @@ Kirigami.Page {
}
}
}
}
MobileForm.FormCard {
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: findExistingDelegate
text: i18n("Find Existing Installation")
icon.name: "edit-find"
onClicked: pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "ExistingSetup"), {
@ -85,10 +93,14 @@ Kirigami.Page {
})
}
MobileForm.FormDelegateSeparator {
FormCard.FormDelegateSeparator {
above: findExistingDelegate
below: downloadDelegate
}
MobileForm.FormButtonDelegate {
FormCard.FormButtonDelegate {
id: downloadDelegate
text: i18n("Download Game")
icon.name: "cloud-download"
onClicked: pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "DownloadSetup"), {
@ -97,5 +109,3 @@ Kirigami.Page {
}
}
}
}
}