NOISSUE Add pagination support to twitch pack search

Try searching for 'craft'. Now it gives ALL the results, not just
the first page of 25.
This commit is contained in:
Petr Mrázek 2020-04-01 02:08:11 +02:00
parent 5e951299b2
commit 296ff6de96
2 changed files with 85 additions and 13 deletions

View File

@ -142,23 +142,36 @@ Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
return QAbstractListModel::flags(index); return QAbstractListModel::flags(index);
} }
void ListModel::searchWithTerm(const QString& term) bool ListModel::canFetchMore(const QModelIndex& parent) const
{ {
if(currentSearchTerm == term) { return searchState == CanPossiblyFetchMore;
}
void ListModel::fetchMore(const QModelIndex& parent)
{
if (parent.isValid())
return;
if(nextSearchOffset == 0) {
qWarning() << "fetchMore with 0 offset is wrong...";
return; return;
} }
performPaginatedSearch();
}
void ListModel::performPaginatedSearch()
{
NetJob *netJob = new NetJob("Twitch::Search"); NetJob *netJob = new NetJob("Twitch::Search");
auto searchUrl = QString( auto searchUrl = QString(
"https://addons-ecs.forgesvc.net/api/v2/addon/search?" "https://addons-ecs.forgesvc.net/api/v2/addon/search?"
"categoryId=0&" "categoryId=0&"
"gameId=432&" "gameId=432&"
//"gameVersion=1.12.2&" //"gameVersion=1.12.2&"
"index=0&" "index=%1&"
"pageSize=25&" "pageSize=25&"
"searchFilter=%1&" "searchFilter=%2&"
"sectionId=4471&" "sectionId=4471&"
"sort=0" "sort=0"
).arg(term); ).arg(nextSearchOffset).arg(currentSearchTerm);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
jobPtr = netJob; jobPtr = netJob;
jobPtr->start(); jobPtr->start();
@ -166,6 +179,27 @@ void ListModel::searchWithTerm(const QString& term)
QObject::connect(netJob, &NetJob::failed, this, &ListModel::searchRequestFailed); QObject::connect(netJob, &NetJob::failed, this, &ListModel::searchRequestFailed);
} }
void ListModel::searchWithTerm(const QString& term)
{
if(currentSearchTerm == term) {
return;
}
currentSearchTerm = term;
if(jobPtr) {
jobPtr->abort();
searchState = ResetRequested;
return;
}
else {
beginResetModel();
modpacks.clear();
endResetModel();
searchState = None;
}
nextSearchOffset = 0;
performPaginatedSearch();
}
void Twitch::ListModel::searchRequestFinished() void Twitch::ListModel::searchRequestFinished()
{ {
jobPtr.reset(); jobPtr.reset();
@ -185,20 +219,27 @@ void Twitch::ListModel::searchRequestFinished()
auto project = projectIter.toObject(); auto project = projectIter.toObject();
pack.addonId = project.value("id").toInt(0); pack.addonId = project.value("id").toInt(0);
if (pack.addonId == 0) { if (pack.addonId == 0) {
qWarning() << "Pack without an ID, skipping: " << pack.name;
continue; continue;
} }
pack.name = project.value("name").toString(); pack.name = project.value("name").toString();
pack.websiteUrl = project.value("websiteUrl").toString(); pack.websiteUrl = project.value("websiteUrl").toString();
pack.description = project.value("summary").toString(); pack.description = project.value("summary").toString();
bool thumbnailFound = false;
auto attachments = project.value("attachments").toArray(); auto attachments = project.value("attachments").toArray();
for(auto attachmentIter: attachments) { for(auto attachmentIter: attachments) {
auto attachment = attachmentIter.toObject(); auto attachment = attachmentIter.toObject();
bool isDefault = attachment.value("isDefault").toBool(false); bool isDefault = attachment.value("isDefault").toBool(false);
if(!isDefault) { if(isDefault) {
continue; thumbnailFound = true;
}
pack.logoName = attachment.value("title").toString(); pack.logoName = attachment.value("title").toString();
pack.logoUrl = attachment.value("thumbnailUrl").toString(); pack.logoUrl = attachment.value("thumbnailUrl").toString();
break;
}
}
if(!thumbnailFound) {
qWarning() << "Pack without an icon, skipping: " << pack.name;
continue;
} }
auto authors = project.value("authors").toArray(); auto authors = project.value("authors").toArray();
for(auto authorIter: authors) { for(auto authorIter: authors) {
@ -210,6 +251,7 @@ void Twitch::ListModel::searchRequestFinished()
} }
int defaultFileId = project.value("defaultFileId").toInt(0); int defaultFileId = project.value("defaultFileId").toInt(0);
if(defaultFileId == 0) { if(defaultFileId == 0) {
qWarning() << "Pack without default file, skipping: " << pack.name;
continue; continue;
} }
bool found = false; bool found = false;
@ -235,19 +277,38 @@ void Twitch::ListModel::searchRequestFinished()
break; break;
} }
if(!found) { if(!found) {
return; qWarning() << "Pack with no good file, skipping: " << pack.name;
continue;
} }
pack.broken = false; pack.broken = false;
newList.append(pack); newList.append(pack);
} }
beginResetModel(); if(objs.size() < 25) {
newList.swap(modpacks); searchState = Finished;
endResetModel(); } else {
nextSearchOffset += 25;
searchState = CanPossiblyFetchMore;
}
beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + newList.size() - 1);
modpacks.append(newList);
endInsertRows();
} }
void Twitch::ListModel::searchRequestFailed(QString reason) void Twitch::ListModel::searchRequestFailed(QString reason)
{ {
jobPtr.reset(); jobPtr.reset();
if(searchState == ResetRequested) {
beginResetModel();
modpacks.clear();
endResetModel();
nextSearchOffset = 0;
performPaginatedSearch();
} else {
searchState = Finished;
}
} }
} }

View File

@ -36,11 +36,15 @@ public:
int columnCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
bool canFetchMore(const QModelIndex & parent) const override;
void fetchMore(const QModelIndex & parent) override;
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
void searchWithTerm(const QString & term); void searchWithTerm(const QString & term);
private slots: private slots:
void performPaginatedSearch();
void logoFailed(QString logo); void logoFailed(QString logo);
void logoLoaded(QString logo, QIcon out); void logoLoaded(QString logo, QIcon out);
@ -58,6 +62,13 @@ private:
QMap<QString, LogoCallback> waitingCallbacks; QMap<QString, LogoCallback> waitingCallbacks;
QString currentSearchTerm; QString currentSearchTerm;
int nextSearchOffset = 0;
enum SearchState {
None,
CanPossiblyFetchMore,
ResetRequested,
Finished
} searchState = None;
NetJobPtr jobPtr; NetJobPtr jobPtr;
QByteArray response; QByteArray response;
}; };