Improve search experience somewhat

So I noticed that searching for messages feels "buggy". I dove into the
code and gave it a pretty nice refresh, I know you'll like it once you
try it!

Some of the issues I noticed and are now fixed:
* The search doesn't clear immediately when you clear the text box, it's
delayed like everything else. This also has the knock-on effect of
starting random network requests.
* If you now press the search button (either with a mouse, pen, etc. or
by the keyboard) the search delay timer was still running.
* The "nothing is here" placeholder message appears when the search
timer is running, making you think no messages were found.

These changes also help other places where SearchPage is used, not just
message search.
This commit is contained in:
Joshua Goins
2025-08-23 16:55:05 -04:00
parent 1424b8ce42
commit 6e0931e31b
2 changed files with 24 additions and 9 deletions

View File

@@ -112,7 +112,7 @@ Kirigami.ScrollablePage {
* @brief Force the search to be updated if the model has a valid search function. * @brief Force the search to be updated if the model has a valid search function.
*/ */
function updateSearch() { function updateSearch() {
searchTimer.restart(); root.model.search();
} }
header: QQC2.Control { header: QQC2.Control {
@@ -142,10 +142,13 @@ Kirigami.ScrollablePage {
Layout.fillWidth: true Layout.fillWidth: true
Keys.onEnterPressed: searchButton.clicked() Keys.onEnterPressed: searchButton.clicked()
Keys.onReturnPressed: searchButton.clicked() Keys.onReturnPressed: searchButton.clicked()
onTextChanged: { onTextChanged: root.model.searchText = text
searchTimer.restart(); onAccepted: {
if (root.model) { // If the text is empty, call the search model immediately because it will early-return.
root.model.searchText = text; if (root.model.searchText.length === 0) {
root.model.search();
} else {
searchTimer.restart();
} }
} }
} }
@@ -158,6 +161,7 @@ Kirigami.ScrollablePage {
onClicked: { onClicked: {
if (typeof root.model.search === 'function') { if (typeof root.model.search === 'function') {
searchTimer.stop();
root.model.search(); root.model.search();
} }
} }
@@ -197,7 +201,7 @@ Kirigami.ScrollablePage {
id: noResultMessage id: noResultMessage
icon.name: "search" icon.name: "search"
anchors.centerIn: parent anchors.centerIn: parent
visible: searchField.text.length > 0 && listView.count === 0 && !root.model.searching && customPlaceholder.text.length === 0 visible: searchField.text.length > 0 && listView.count === 0 && (!root.model.searching && !searchTimer.running) && customPlaceholder.text.length === 0
helpfulAction: root.noResultHelpfulAction helpfulAction: root.noResultHelpfulAction
} }
@@ -210,7 +214,7 @@ Kirigami.ScrollablePage {
Kirigami.LoadingPlaceholder { Kirigami.LoadingPlaceholder {
anchors.centerIn: parent anchors.centerIn: parent
visible: searchField.text.length > 0 && listView.count === 0 && root.model.searching && customPlaceholder.text.length === 0 visible: searchField.text.length > 0 && listView.count === 0 && (root.model.searching || searchTimer.running) && customPlaceholder.text.length === 0
} }
Keys.onUpPressed: { Keys.onUpPressed: {

View File

@@ -26,12 +26,24 @@ void SearchModel::setSearchText(const QString &searchText)
void SearchModel::search() void SearchModel::search()
{ {
Q_ASSERT(m_room); Q_ASSERT(m_room);
setSearching(true);
if (m_job) { if (m_job) {
m_job->abandon(); m_job->abandon();
m_job = nullptr; m_job = nullptr;
} }
// early-return case: the user sets the text to nothing, and we simply clear the results
if (m_searchText.isEmpty()) {
clearEventObjects();
beginResetModel();
m_result = std::nullopt;
endResetModel();
return;
}
setSearching(true);
RoomEventFilter filter; RoomEventFilter filter;
filter.unreadThreadNotifications = std::nullopt; filter.unreadThreadNotifications = std::nullopt;
filter.lazyLoadMembers = true; filter.lazyLoadMembers = true;
@@ -48,7 +60,6 @@ void SearchModel::search()
.eventContext = SearchJob::IncludeEventContext{3, 3, true}, .eventContext = SearchJob::IncludeEventContext{3, 3, true},
.includeState = false, .includeState = false,
.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});