From a2e120a8a3764ff0ec45aa6c1515e335bb910589 Mon Sep 17 00:00:00 2001 From: Joseph Donofry Date: Tue, 20 Dec 2022 16:34:55 -0500 Subject: Add 'clear' button to search bar and implement search indicator via spinner --- resources/qml/MatrixTextField.qml | 34 ++++++++++++++++++++++++++++++++++ resources/qml/MessageView.qml | 6 ++++-- resources/qml/TopBar.qml | 1 + src/timeline/TimelineFilter.cpp | 9 +++++++++ src/timeline/TimelineFilter.h | 3 +++ 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/resources/qml/MatrixTextField.qml b/resources/qml/MatrixTextField.qml index 3f0f77ed..e3632b61 100644 --- a/resources/qml/MatrixTextField.qml +++ b/resources/qml/MatrixTextField.qml @@ -20,6 +20,7 @@ ColumnLayout { property alias font: input.font property alias echoMode: input.echoMode property alias selectByMouse: input.selectByMouse + property var hasClear: false Timer { id: timer @@ -129,6 +130,39 @@ ColumnLayout { color: labelC.text ? "transparent" : backgroundColor } + ToolButton { + id: clearText + Layout.fillWidth: true + visible: c.hasClear && searchField.text !== '' + icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearText.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) + focusPolicy: Qt.NoFocus + onClicked: { + searchField.clear() + topBar.searchString = ""; + } + hoverEnabled: true + background: null + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + } + // clear the default hover effects. + + Image { + height: parent.height - 2 * Nheko.paddingSmall + width: height + source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearText.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + margins: Nheko.paddingSmall + } + + } + + } + } Rectangle { diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index e3e02ee9..a49c046c 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -38,6 +38,8 @@ Item { property int delegateMaxWidth: ((Settings.timelineMaxWidth > 100 && Settings.timelineMaxWidth < chatRoot.availableWidth) ? Settings.timelineMaxWidth : chatRoot.availableWidth) - chatRoot.padding * 2 - (scrollbar.interactive? scrollbar.width : 0) + readonly property alias filteringInProgress: filteredTimeline.filteringInProgress + displayMarginBeginning: height / 2 displayMarginEnd: height / 2 @@ -561,7 +563,7 @@ Item { footer: Item { anchors.horizontalCenter: parent.horizontalCenter anchors.margins: Nheko.paddingLarge - visible: room && room.paginationInProgress + visible: (room && room.paginationInProgress) || chat.filteringInProgress // hacky, but works height: loadingSpinner.height + 2 * Nheko.paddingLarge @@ -570,7 +572,7 @@ Item { anchors.centerIn: parent anchors.margins: Nheko.paddingLarge - running: room && room.paginationInProgress + running: (room && room.paginationInProgress) || chat.filteringInProgress foreground: Nheko.colors.mid z: 3 } diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index 760f20e6..cce2c89b 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -450,6 +450,7 @@ Pane { id: searchField visible: searchButton.searchActive enabled: visible + hasClear: true Layout.row: 5 Layout.column: 2 diff --git a/src/timeline/TimelineFilter.cpp b/src/timeline/TimelineFilter.cpp index 7dc4c7aa..9389b815 100644 --- a/src/timeline/TimelineFilter.cpp +++ b/src/timeline/TimelineFilter.cpp @@ -39,6 +39,7 @@ void TimelineFilter::startFiltering() { incrementalSearchIndex = 0; + emit isFilteringChanged(); invalidateFilter(); continueFiltering(); @@ -82,6 +83,7 @@ TimelineFilter::event(QEvent *ev) continueFiltering(); } } + emit isFilteringChanged(); } return true; } @@ -172,6 +174,7 @@ TimelineFilter::setSource(TimelineModel *s) incrementalSearchIndex = 0; emit sourceChanged(); + emit isFilteringChanged(); invalidateFilter(); } } @@ -200,6 +203,12 @@ TimelineFilter::currentIndex() const return -1; } +bool +TimelineFilter::isFiltering() const +{ + return incrementalSearchIndex != std::numeric_limits::max() && !(threadId.isEmpty() && contentFilter.isEmpty()); +} + bool TimelineFilter::filterAcceptsRow(int source_row, const QModelIndex &) const { diff --git a/src/timeline/TimelineFilter.h b/src/timeline/TimelineFilter.h index 30ec3300..c35f8da3 100644 --- a/src/timeline/TimelineFilter.h +++ b/src/timeline/TimelineFilter.h @@ -20,6 +20,7 @@ class TimelineFilter : public QSortFilterProxyModel contentFilterChanged) Q_PROPERTY(TimelineModel *source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(bool filteringInProgress READ isFiltering NOTIFY isFilteringChanged) public: explicit TimelineFilter(QObject *parent = nullptr); @@ -28,6 +29,7 @@ public: QString filterByContent() const { return contentFilter; } TimelineModel *source() const; int currentIndex() const; + bool isFiltering() const; void setThreadId(const QString &t); void setContentFilter(const QString &t); @@ -46,6 +48,7 @@ signals: void contentFilterChanged(); void sourceChanged(); void currentIndexChanged(); + void isFilteringChanged(); private slots: void fetchAgain(); -- cgit 1.4.1