Improve the search pages, especially in error and searching states

Someone hit a nasty bug while attempting to find a KDE room on the
kde.org server, the error wouldn't come up normally and the dialog would
be blank. That's because that specific placeholder message doesn't
appear until you type something into the search field, which is weird.

There is a few other oddities with SearchPage that I squashed, including
showing the loading placeholder in more appropiate situations.
This commit is contained in:
Joshua Goins
2026-01-23 15:44:47 -05:00
parent 593ad27e8c
commit 9d2a427619
4 changed files with 44 additions and 8 deletions

View File

@@ -51,8 +51,16 @@ SearchPage {
signal roomSelected(string roomId, string displayName, url avatarUrl, string alias, string topic, int memberCount, bool isJoined)
title: i18nc("@action:title Explore public rooms and spaces", "Explore")
customPlaceholderText: publicRoomListModel.redirectedText
customPlaceholderText: {
if (publicRoomListModel.redirectedText.length > 0)
return publicRoomListModel.redirectedText;
if (publicRoomListModel.errorText.length > 0)
return publicRoomListModel.errorText;
return "";
}
customPlaceholderIcon: "data-warning"
enableSearch: publicRoomListModel.errorText.length === 0
Component.onCompleted: focusSearch()
@@ -63,6 +71,7 @@ SearchPage {
display: QQC2.Button.IconOnly
checkable: true
text: i18nc("@action:button", "Only show spaces")
enabled: root.enableSearch
QQC2.ToolTip.visible: hovered
QQC2.ToolTip.text: text
@@ -96,7 +105,7 @@ SearchPage {
activeFocusOnTab: false // We handle moving to this item via up/down arrows, otherwise the tab order is wacky
text: i18n("Enter a Room Manually")
visible: publicRoomListModel.redirectedText.length === 0
visible: root.customPlaceholderText.length === 0
icon.name: "compass"
icon.width: Kirigami.Units.gridUnit * 2
icon.height: Kirigami.Units.gridUnit * 2

View File

@@ -80,6 +80,11 @@ Kirigami.ScrollablePage {
*/
property bool showSearchButton: true
/**
* @brief Enable the search controls like the text field and button.
*/
property bool enableSearch: true
/**
* @brief Message to be shown in a custom placeholder.
* The custom placeholder will be shown if the text is not empty
@@ -139,6 +144,7 @@ Kirigami.ScrollablePage {
Kirigami.SearchField {
id: searchField
focus: true
enabled: root.enableSearch
Layout.fillWidth: true
Keys.onEnterPressed: searchButton.clicked()
Keys.onReturnPressed: searchButton.clicked()
@@ -158,6 +164,7 @@ Kirigami.ScrollablePage {
display: QQC2.Button.IconOnly
visible: root.showSearchButton
text: i18nc("@action:button", "Search")
enabled: root.enableSearch
onClicked: {
if (typeof root.model.search === 'function') {
@@ -173,7 +180,6 @@ Kirigami.ScrollablePage {
Timer {
id: searchTimer
interval: 500
running: true
onTriggered: if (typeof root.model.search === 'function') {
root.model.search();
}
@@ -193,7 +199,7 @@ Kirigami.ScrollablePage {
id: noSearchMessage
icon.name: "search"
anchors.centerIn: parent
visible: searchField.text.length === 0 && listView.count === 0 && customPlaceholder.text.length === 0
visible: searchField.text.length === 0 && listView.count === 0 && !root.model.searching && customPlaceholder.text.length === 0
helpfulAction: root.noSearchHelpfulAction
}
@@ -208,13 +214,13 @@ Kirigami.ScrollablePage {
Kirigami.PlaceholderMessage {
id: customPlaceholder
anchors.centerIn: parent
visible: searchField.text.length > 0 && listView.count === 0 && !root.model.searching && text.length > 0
visible: listView.count === 0 && !root.model.searching && text.length > 0
icon.name: root.customPlaceholderIcon
}
Kirigami.LoadingPlaceholder {
anchors.centerIn: parent
visible: searchField.text.length > 0 && listView.count === 0 && (root.model.searching || searchTimer.running) && customPlaceholder.text.length === 0
visible: listView.count === 0 && (root.model.searching || searchTimer.running)
}
Keys.onUpPressed: {

View File

@@ -172,6 +172,8 @@ void PublicRoomListModel::next(int limit)
}
m_redirectedText.clear();
Q_EMIT redirectedChanged();
m_errorText.clear();
Q_EMIT errorTextChanged();
if (job) {
qCDebug(PublicRoomList) << "Other job running, ignore";
@@ -200,9 +202,12 @@ void PublicRoomListModel::next(int limit)
this->beginInsertRows({}, rooms.count(), rooms.count() + job->chunk().count() - 1);
rooms.append(job->chunk());
this->endInsertRows();
} else if (job->error() == BaseJob::ContentAccessError) {
} else if (job->error() == BaseJob::ContentAccessError && !m_searchText.isEmpty()) {
m_redirectedText = job->jsonData()[u"error"_s].toString();
Q_EMIT redirectedChanged();
} else {
m_errorText = job->jsonData()[u"error"_s].toString();
Q_EMIT errorTextChanged();
}
this->job = nullptr;
@@ -329,4 +334,9 @@ QString PublicRoomListModel::redirectedText() const
return m_redirectedText;
}
QString PublicRoomListModel::errorText() const
{
return m_errorText;
}
#include "moc_publicroomlistmodel.cpp"

View File

@@ -53,10 +53,17 @@ class PublicRoomListModel : public QAbstractListModel
Q_PROPERTY(bool searching READ searching NOTIFY searchingChanged)
/**
* @brief The text returned by the server after redirection
* @brief The text returned by the server after redirection (after performing a search)
*/
Q_PROPERTY(QString redirectedText READ redirectedText NOTIFY redirectedChanged)
/**
* @brief The error while trying to list the rooms (not after searching, which is covered by redirectedText)
*
* This is useful when a server completely shut off room search, or any kind of network error.
*/
Q_PROPERTY(QString errorText READ errorText NOTIFY errorTextChanged)
public:
/**
* @brief Defines the model roles.
@@ -120,6 +127,8 @@ public:
QString redirectedText() const;
QString errorText() const;
private:
QPointer<NeoChatConnection> m_connection = nullptr;
QString m_server;
@@ -143,6 +152,7 @@ private:
Quotient::QueryPublicRoomsJob *job = nullptr;
QString m_redirectedText;
QString m_errorText;
Q_SIGNALS:
void connectionChanged();
@@ -151,4 +161,5 @@ Q_SIGNALS:
void showOnlySpacesChanged();
void searchingChanged();
void redirectedChanged();
void errorTextChanged();
};