Add the ability to scroll up in the message search window

This wasn't a thing yet, so the search experience compared to something
like Element Web was much worse. Now you can scroll back as far as any
other client can!

I had to do a bit of refactoring to stop resetting the model all the
time, and append instead. Otherwise, it was quite straightforward to
implement.
This commit is contained in:
Joshua Goins
2025-09-05 13:35:42 -04:00
parent 94ea1305b2
commit 88e1e1dd2a
2 changed files with 33 additions and 17 deletions

View File

@@ -5,8 +5,6 @@
using namespace Quotient; using namespace Quotient;
// TODO search only in the current room
SearchModel::SearchModel(QObject *parent) SearchModel::SearchModel(QObject *parent)
: MessageModel(parent) : MessageModel(parent)
{ {
@@ -37,7 +35,8 @@ void SearchModel::search()
clearEventObjects(); clearEventObjects();
beginResetModel(); beginResetModel();
m_result = std::nullopt; m_nextBatch.clear();
m_results.clear();
endResetModel(); endResetModel();
return; return;
} }
@@ -65,43 +64,56 @@ void SearchModel::search()
.groupings = std::nullopt, .groupings = std::nullopt,
}; };
auto job = m_room->connection()->callApi<SearchJob>(SearchJob::Categories{criteria}); auto job = m_room->connection()->callApi<SearchJob>(SearchJob::Categories{criteria}, m_nextBatch);
m_job = job; m_job = job;
connect(job, &BaseJob::finished, this, [this, job] { connect(job, &BaseJob::finished, this, [this, job] {
clearEventObjects(); clearEventObjects();
beginResetModel(); auto results = job->searchCategories().roomEvents;
m_result = job->searchCategories().roomEvents; if (results.has_value()) {
beginInsertRows({}, rowCount({}), rowCount({}) + int(results->results.size()) - 1);
if (m_result.has_value()) { for (const auto &result : results.value().results) {
for (const auto &result : m_result.value().results) {
Q_EMIT newEventAdded(result.result.get()); Q_EMIT newEventAdded(result.result.get());
} }
std::move(results->results.begin(), results->results.end(), std::back_inserter(m_results));
endInsertRows();
m_nextBatch = results->nextBatch;
} else {
m_nextBatch.clear();
} }
endResetModel();
setSearching(false); setSearching(false);
m_job = nullptr; m_job = nullptr;
// TODO error handling // TODO error handling
}); });
} }
void SearchModel::fetchMore(const QModelIndex &parent)
{
Q_UNUSED(parent)
search();
}
bool SearchModel::canFetchMore(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return !m_nextBatch.isEmpty() && !searching();
}
std::optional<std::reference_wrapper<const RoomEvent>> SearchModel::getEventForIndex(QModelIndex index) const std::optional<std::reference_wrapper<const RoomEvent>> SearchModel::getEventForIndex(QModelIndex index) const
{ {
if (!m_result.has_value()) { if (m_results.empty()) {
return std::nullopt; return std::nullopt;
} }
return *m_result.value().results.at(index.row()).result.get(); return *m_results.at(index.row()).result.get();
} }
int SearchModel::rowCount(const QModelIndex &parent) const int SearchModel::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent); Q_UNUSED(parent);
if (m_result.has_value()) { return m_results.size();
return m_result->results.size();
}
return 0;
} }
bool SearchModel::searching() const bool SearchModel::searching() const

View File

@@ -65,6 +65,9 @@ public:
*/ */
Q_INVOKABLE void search(); Q_INVOKABLE void search();
void fetchMore(const QModelIndex &parent) override;
bool canFetchMore(const QModelIndex &parent) const override;
Q_SIGNALS: Q_SIGNALS:
void searchTextChanged(); void searchTextChanged();
void roomChanged(); void roomChanged();
@@ -77,8 +80,9 @@ private:
void setSearching(bool searching); void setSearching(bool searching);
QString m_searchText; QString m_searchText;
std::optional<Quotient::SearchJob::ResultRoomEvents> m_result = std::nullopt; std::vector<Quotient::SearchJob::Result> m_results;
Quotient::SearchJob *m_job = nullptr; Quotient::SearchJob *m_job = nullptr;
bool m_searching = false; bool m_searching = false;
QString m_senderId; QString m_senderId;
QString m_nextBatch;
}; };