Add 'clear' button to search bar and implement search indicator via spinner

This commit is contained in:
Joseph Donofry 2022-12-20 16:34:55 -05:00
parent d4336b56d6
commit a2e120a8a3
5 changed files with 51 additions and 2 deletions

View File

@ -20,6 +20,7 @@ ColumnLayout {
property alias font: input.font property alias font: input.font
property alias echoMode: input.echoMode property alias echoMode: input.echoMode
property alias selectByMouse: input.selectByMouse property alias selectByMouse: input.selectByMouse
property var hasClear: false
Timer { Timer {
id: timer id: timer
@ -129,6 +130,39 @@ ColumnLayout {
color: labelC.text ? "transparent" : backgroundColor 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 { Rectangle {

View File

@ -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) 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 displayMarginBeginning: height / 2
displayMarginEnd: height / 2 displayMarginEnd: height / 2
@ -561,7 +563,7 @@ Item {
footer: Item { footer: Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: Nheko.paddingLarge anchors.margins: Nheko.paddingLarge
visible: room && room.paginationInProgress visible: (room && room.paginationInProgress) || chat.filteringInProgress
// hacky, but works // hacky, but works
height: loadingSpinner.height + 2 * Nheko.paddingLarge height: loadingSpinner.height + 2 * Nheko.paddingLarge
@ -570,7 +572,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
anchors.margins: Nheko.paddingLarge anchors.margins: Nheko.paddingLarge
running: room && room.paginationInProgress running: (room && room.paginationInProgress) || chat.filteringInProgress
foreground: Nheko.colors.mid foreground: Nheko.colors.mid
z: 3 z: 3
} }

View File

@ -450,6 +450,7 @@ Pane {
id: searchField id: searchField
visible: searchButton.searchActive visible: searchButton.searchActive
enabled: visible enabled: visible
hasClear: true
Layout.row: 5 Layout.row: 5
Layout.column: 2 Layout.column: 2

View File

@ -39,6 +39,7 @@ void
TimelineFilter::startFiltering() TimelineFilter::startFiltering()
{ {
incrementalSearchIndex = 0; incrementalSearchIndex = 0;
emit isFilteringChanged();
invalidateFilter(); invalidateFilter();
continueFiltering(); continueFiltering();
@ -82,6 +83,7 @@ TimelineFilter::event(QEvent *ev)
continueFiltering(); continueFiltering();
} }
} }
emit isFilteringChanged();
} }
return true; return true;
} }
@ -172,6 +174,7 @@ TimelineFilter::setSource(TimelineModel *s)
incrementalSearchIndex = 0; incrementalSearchIndex = 0;
emit sourceChanged(); emit sourceChanged();
emit isFilteringChanged();
invalidateFilter(); invalidateFilter();
} }
} }
@ -200,6 +203,12 @@ TimelineFilter::currentIndex() const
return -1; return -1;
} }
bool
TimelineFilter::isFiltering() const
{
return incrementalSearchIndex != std::numeric_limits<int>::max() && !(threadId.isEmpty() && contentFilter.isEmpty());
}
bool bool
TimelineFilter::filterAcceptsRow(int source_row, const QModelIndex &) const TimelineFilter::filterAcceptsRow(int source_row, const QModelIndex &) const
{ {

View File

@ -20,6 +20,7 @@ class TimelineFilter : public QSortFilterProxyModel
contentFilterChanged) contentFilterChanged)
Q_PROPERTY(TimelineModel *source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(TimelineModel *source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(bool filteringInProgress READ isFiltering NOTIFY isFilteringChanged)
public: public:
explicit TimelineFilter(QObject *parent = nullptr); explicit TimelineFilter(QObject *parent = nullptr);
@ -28,6 +29,7 @@ public:
QString filterByContent() const { return contentFilter; } QString filterByContent() const { return contentFilter; }
TimelineModel *source() const; TimelineModel *source() const;
int currentIndex() const; int currentIndex() const;
bool isFiltering() const;
void setThreadId(const QString &t); void setThreadId(const QString &t);
void setContentFilter(const QString &t); void setContentFilter(const QString &t);
@ -46,6 +48,7 @@ signals:
void contentFilterChanged(); void contentFilterChanged();
void sourceChanged(); void sourceChanged();
void currentIndexChanged(); void currentIndexChanged();
void isFilteringChanged();
private slots: private slots:
void fetchAgain(); void fetchAgain();