Generic Search Page

Pull the generic aspects from Room search and join room pages into it's own component. This is done in anticipation of using the new generic search page for a user search functionality.

- `SearchPage` is now used for the generic version with the old one being renamed `RoomSearchPage`
- `JoinRoomPage` is renamed to `ExploreRoomsPage` inline with everywhere else in NeoChat

There is also some cleanup of the code for both search pages in here.
This commit is contained in:
James Graham
2024-01-19 17:59:45 +00:00
parent 80f3bd64b6
commit f6a5cc7c25
17 changed files with 459 additions and 393 deletions

View File

@@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
import QtQuick
import QtQuick.Controls as QQC2
@@ -7,29 +7,87 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.neochat
/**
* @brief Component for a generic search page.
*
* This component provides a header with the search field and a ListView to visualise
* search results from the given model.
*/
Kirigami.ScrollablePage {
id: root
property NeoChatRoom currentRoom
required property NeoChatConnection connection
/**
* @brief Any additional controls after the search button.
*/
property alias headerTrailing: headerContent.children
title: i18nc("@action:title", "Search Messages")
/**
* @brief The model that provides the search results.
*
* The model needs to provide the following properties:
* - searchText
* - searching
* Where searchText is the text from the searchField and is used to match results
* and searching is true while the model is finding results.
*
* The model must also provide a search() function to start the search if
* it doesn't do so when the searchText is changed.
*/
property alias model: listView.model
Kirigami.Theme.colorSet: Kirigami.Theme.Window
/**
* @brief The number of delegates currently in the view.
*/
property alias count: listView.count
SearchModel {
id: searchModel
connection: root.connection
searchText: searchField.text
room: root.currentRoom
/**
* @brief The delegate to use to visualize the model data.
*/
property alias modelDelegate: listView.delegate
/**
* @brief The delegate to appear as the header of the list.
*/
property alias listHeaderDelegate: listView.header
/**
* @brief The delegate to appear as the footer of the list.
*/
property alias listFooterDelegate: listView.footer
/**
* @brief The placeholder text in the search field.
*/
property alias searchFieldPlaceholder: searchField.placeholderText
/**
* @brief The text to show when no search term has been entered.
*/
property alias noSearchPlaceholderMessage: noSearchMessage.text
/**
* @brief The text to show when no results have been found.
*/
property alias noResultPlaceholderMessage: noResultMessage.text
/**
* @brief The verticalLayoutDirection property of the internal ListView.
*/
property alias listVerticalLayoutDirection: listView.verticalLayoutDirection
/**
* @brief Force the search field to be focussed.
*/
function focusSearch() {
searchField.forceActiveFocus();
}
header: QQC2.Control {
padding: Kirigami.Units.largeSpacing
background: Rectangle {
Kirigami.Theme.colorSet: Kirigami.Theme.Window
Kirigami.Theme.inherit: false
color: Kirigami.Theme.backgroundColor
Kirigami.Separator {
@@ -42,6 +100,7 @@ Kirigami.ScrollablePage {
}
contentItem: RowLayout {
id: headerContent
spacing: Kirigami.Units.largeSpacing
Kirigami.SearchField {
@@ -50,44 +109,48 @@ Kirigami.ScrollablePage {
Layout.fillWidth: true
Keys.onEnterPressed: searchButton.clicked()
Keys.onReturnPressed: searchButton.clicked()
onTextChanged: {
if (model) {
model.searchText = text;
}
}
}
QQC2.Button {
id: searchButton
onClicked: searchModel.search()
icon.name: "search"
onClicked: {
if (typeof model.search === 'function') {
model.search()
}
}
}
}
}
ListView {
id: messageListView
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
verticalLayoutDirection: ListView.BottomToTop
section.property: "section"
Kirigami.PlaceholderMessage {
id: noSearchMessage
anchors.centerIn: parent
visible: searchField.text.length === 0 && messageListView.count === 0
text: i18n("Enter a text to start searching")
visible: searchField.text.length === 0 && listView.count === 0
}
Kirigami.PlaceholderMessage {
id: noResultMessage
anchors.centerIn: parent
visible: searchField.text.length > 0 && messageListView.count === 0 && !searchModel.searching
text: i18n("No results found")
visible: searchField.text.length > 0 && listView.count === 0 && !root.model.searching
}
Kirigami.LoadingPlaceholder {
anchors.centerIn: parent
visible: searchModel.searching
}
model: searchModel
delegate: EventDelegate {
room: root.currentRoom
visible: root.model.searching
}
}
}