Merge pull request #1539 from Trial97/refactor_modpack_ux

Improvements to modpack UX
This commit is contained in:
TheKodeToad
2023-08-31 14:58:54 +01:00
committed by GitHub
35 changed files with 718 additions and 177 deletions

View File

@ -38,8 +38,8 @@
#include "BuildConfig.h"
#include "Json.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "modplatform/modrinth/ModrinthAPI.h"
#include "net/NetJob.h"
#include "ui/widgets/ProjectItem.h"
#include "net/ApiDownload.h"
@ -130,7 +130,24 @@ bool ModpackListModel::setData(const QModelIndex& index, const QVariant& value,
void ModpackListModel::performPaginatedSearch()
{
// TODO: Move to standalone API
if (hasActiveSearchJob())
return;
if (currentSearchTerm.startsWith("#")) {
auto projectId = currentSearchTerm.mid(1);
if (!projectId.isEmpty()) {
ResourceAPI::ProjectInfoCallbacks callbacks;
callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); };
callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); };
static const ModrinthAPI api;
if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) {
jobPtr = job;
jobPtr->start();
}
return;
}
} // TODO: Move to standalone API
auto netJob = makeShared<NetJob>("Modrinth::SearchModpack", APPLICATION->network());
auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL +
"/search?"
@ -167,16 +184,17 @@ void ModpackListModel::performPaginatedSearch()
void ModpackListModel::refresh()
{
if (jobPtr) {
if (hasActiveSearchJob()) {
jobPtr->abort();
searchState = ResetRequested;
return;
} else {
beginResetModel();
modpacks.clear();
endResetModel();
searchState = None;
}
beginResetModel();
modpacks.clear();
endResetModel();
searchState = None;
nextSearchOffset = 0;
performPaginatedSearch();
}
@ -307,9 +325,29 @@ void ModpackListModel::searchRequestFinished(QJsonDocument& doc_all)
endInsertRows();
}
void ModpackListModel::searchRequestForOneSucceeded(QJsonDocument& doc)
{
jobPtr.reset();
auto packObj = doc.object();
Modrinth::Modpack pack;
try {
Modrinth::loadIndexedPack(pack, packObj);
pack.id = Json::ensureString(packObj, "id", pack.id);
} catch (const JSONValidationError& e) {
qWarning() << "Error while loading mod from " << m_parent->debugName() << ": " << e.cause();
return;
}
beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1);
modpacks.append({ pack });
endInsertRows();
}
void ModpackListModel::searchRequestFailed(QString reason)
{
auto failed_action = jobPtr->getFailedActions().at(0);
auto failed_action = dynamic_cast<NetJob*>(jobPtr.get())->getFailedActions().at(0);
if (!failed_action->m_reply) {
// Network error
QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load modpacks."));

View File

@ -73,6 +73,9 @@ class ModpackListModel : public QAbstractListModel {
void refresh();
void searchWithTerm(const QString& term, const int sort);
[[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); }
[[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; }
void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
inline auto canFetchMore(const QModelIndex& parent) const -> bool override
@ -83,6 +86,7 @@ class ModpackListModel : public QAbstractListModel {
public slots:
void searchRequestFinished(QJsonDocument& doc_all);
void searchRequestFailed(QString reason);
void searchRequestForOneSucceeded(QJsonDocument&);
protected slots:
@ -111,7 +115,7 @@ class ModpackListModel : public QAbstractListModel {
int nextSearchOffset = 0;
enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
NetJob::Ptr jobPtr;
Task::Ptr jobPtr;
std::shared_ptr<QByteArray> m_all_response = std::make_shared<QByteArray>();
QByteArray m_specific_response;

View File

@ -52,7 +52,8 @@
#include <QKeyEvent>
#include <QPushButton>
ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog)
ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent)
: QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog), m_fetch_progress(this, false)
{
ui->setupUi(this);
@ -64,6 +65,17 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
m_search_timer.setTimerType(Qt::TimerType::CoarseTimer);
m_search_timer.setSingleShot(true);
connect(&m_search_timer, &QTimer::timeout, this, &ModrinthPage::triggerSearch);
m_fetch_progress.hideIfInactive(true);
m_fetch_progress.setFixedHeight(24);
m_fetch_progress.progressFormat("");
ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount());
ui->sortByBox->addItem(tr("Sort by Relevance"));
ui->sortByBox->addItem(tr("Sort by Total Downloads"));
ui->sortByBox->addItem(tr("Sort by Follows"));
@ -102,6 +114,11 @@ bool ModrinthPage::eventFilter(QObject* watched, QEvent* event)
this->triggerSearch();
keyEvent->accept();
return true;
} else {
if (m_search_timer.isActive())
m_search_timer.stop();
m_search_timer.start(350);
}
}
return QObject::eventFilter(watched, event);
@ -309,6 +326,7 @@ void ModrinthPage::suggestCurrent()
void ModrinthPage::triggerSearch()
{
m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
m_fetch_progress.watch(m_model->activeSearchJob().get());
}
void ModrinthPage::onVersionSelectionChanged(QString version)

View File

@ -41,7 +41,9 @@
#include "ui/pages/BasePage.h"
#include "modplatform/modrinth/ModrinthPackManifest.h"
#include "ui/widgets/ProgressWidget.h"
#include <QTimer>
#include <QWidget>
namespace Ui {
@ -88,4 +90,9 @@ class ModrinthPage : public QWidget, public BasePage {
Modrinth::Modpack current;
QString selectedVersion;
ProgressWidget m_fetch_progress;
// Used to do instant searching with a delay to cache quick changes
QTimer m_search_timer;
};

View File

@ -10,8 +10,8 @@
<height>600</height>
</rect>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
@ -29,7 +29,7 @@
</property>
</widget>
</item>
<item>
<item row="1" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QLineEdit" name="searchEdit">
@ -47,7 +47,7 @@
</item>
</layout>
</item>
<item>
<item row="3" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QListView" name="packView">
@ -77,7 +77,7 @@
</item>
</layout>
</item>
<item>
<item row="4" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QComboBox" name="sortByBox"/>