Allow filtering the timeline for notifications
This commit is contained in:
parent
5b025fa2b0
commit
53cd31d181
7 changed files with 73 additions and 11 deletions
1
resources/icons/ui/alert.svg
Normal file
1
resources/icons/ui/alert.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg width="32" height="32" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 1.996a7.49 7.49 0 0 1 7.496 7.25l.004.25v4.097l1.38 3.156a1.25 1.25 0 0 1-1.145 1.75L15 18.502a3 3 0 0 1-5.995.177L9 18.499H4.275a1.251 1.251 0 0 1-1.147-1.747L4.5 13.594V9.496c0-4.155 3.352-7.5 7.5-7.5ZM13.5 18.5l-3 .002a1.5 1.5 0 0 0 2.993.145l.006-.147ZM12 3.496c-3.32 0-6 2.674-6 6v4.41L4.656 17h14.697L18 13.907V9.509l-.004-.225A5.988 5.988 0 0 0 12 3.496Z" fill="#212121"/></svg>
|
||||
|
After Width: | Height: | Size: 494 B |
|
|
@ -16,6 +16,7 @@ Item {
|
|||
property int availableWidth: width
|
||||
property int padding: Nheko.paddingMedium
|
||||
property string searchString: ""
|
||||
property bool filterByNotifications: false
|
||||
property Room roommodel: room
|
||||
|
||||
// HACK: https://bugreports.qt.io/browse/QTBUG-83972, qtwayland cannot auto hide menu
|
||||
|
|
@ -60,7 +61,7 @@ Item {
|
|||
boundsBehavior: Flickable.StopAtBounds
|
||||
displayMarginBeginning: height / 4
|
||||
displayMarginEnd: height / 4
|
||||
model: (filteredTimeline.filterByThread || filteredTimeline.filterByContent) ? filteredTimeline : room
|
||||
model: (filteredTimeline.filterByThread || filteredTimeline.filterByContent || filteredTimeline.filterByNotifications) ? filteredTimeline : room
|
||||
//pixelAligned: true
|
||||
spacing: 2
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
|
|
@ -145,6 +146,7 @@ Item {
|
|||
id: filteredTimeline
|
||||
|
||||
filterByContent: chatRoot.searchString
|
||||
filterByNotifications: chatRoot.filterByNotifications
|
||||
filterByThread: room ? room.thread : ""
|
||||
source: room
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ Item {
|
|||
Layout.fillWidth: true
|
||||
implicitHeight: msgView.height - typingIndicator.height
|
||||
searchString: topBar.searchString
|
||||
filterByNotifications: topBar.filterNotifications
|
||||
}
|
||||
Loader {
|
||||
source: CallManager.isOnCall && CallManager.callType != Voip.VOICE ? (Qt.platform.os != "windows" ? "voip/VideoCall.qml" : "voip/VideoCallD3D11.qml") : ""
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Pane {
|
|||
property bool searchHasFocus: searchField.focus && searchField.enabled
|
||||
property string searchString: ""
|
||||
property bool showBackButton: false
|
||||
property bool filterNotifications: false
|
||||
property int trustlevel: room ? room.trustlevel : Crypto.Unverified
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -129,13 +130,30 @@ Pane {
|
|||
selectByMouse: false
|
||||
text: roomTopic
|
||||
}
|
||||
ImageButton {
|
||||
id: notificationsButton
|
||||
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.column: 3
|
||||
Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.row: 1
|
||||
Layout.rowSpan: 2
|
||||
ToolTip.text: qsTr("Show only notifications")
|
||||
ToolTip.visible: hovered
|
||||
image: ":/icons/icons/ui/alert.svg"
|
||||
|
||||
onClicked: {
|
||||
topBar.filterNotifications = !topBar.filterNotifications
|
||||
}
|
||||
}
|
||||
ImageButton {
|
||||
id: pinButton
|
||||
|
||||
property bool pinsShown: !Settings.hiddenPins.includes(roomId)
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.column: 3
|
||||
Layout.column: 4
|
||||
Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.row: 1
|
||||
|
|
@ -160,7 +178,7 @@ Pane {
|
|||
}
|
||||
AbstractButton {
|
||||
id: memberButton
|
||||
Layout.column: 4
|
||||
Layout.column: 5
|
||||
Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.row: 1
|
||||
|
|
@ -200,7 +218,7 @@ Pane {
|
|||
property bool searchActive: false
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.column: 5
|
||||
Layout.column: 6
|
||||
Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.row: 1
|
||||
|
|
@ -224,7 +242,7 @@ Pane {
|
|||
id: roomOptionsButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.column: 6
|
||||
Layout.column: 7
|
||||
Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium
|
||||
Layout.row: 1
|
||||
|
|
@ -273,7 +291,7 @@ Pane {
|
|||
id: pinnedMessages
|
||||
|
||||
Layout.column: 2
|
||||
Layout.columnSpan: 4
|
||||
Layout.columnSpan: 5
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Math.min(contentHeight, Nheko.avatarSize * 4)
|
||||
Layout.row: 3
|
||||
|
|
@ -330,7 +348,7 @@ Pane {
|
|||
id: widgets
|
||||
|
||||
Layout.column: 2
|
||||
Layout.columnSpan: 4
|
||||
Layout.columnSpan: 5
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Math.min(contentHeight, Nheko.avatarSize * 1.5)
|
||||
Layout.row: 4
|
||||
|
|
@ -356,7 +374,7 @@ Pane {
|
|||
id: searchField
|
||||
|
||||
Layout.column: 2
|
||||
Layout.columnSpan: 4
|
||||
Layout.columnSpan: 5
|
||||
Layout.fillWidth: true
|
||||
Layout.row: 5
|
||||
enabled: visible
|
||||
|
|
@ -378,6 +396,7 @@ Pane {
|
|||
searchString = "";
|
||||
searchButton.searchActive = false;
|
||||
searchField.text = "";
|
||||
filterNotifications = false;
|
||||
}
|
||||
|
||||
// HACK: https://bugreports.qt.io/browse/QTBUG-83972, qtwayland cannot auto hide menu
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>icons/ui/add-square-button.svg</file>
|
||||
<file>icons/ui/alert.svg</file>
|
||||
<file>icons/ui/angle-arrow-left.svg</file>
|
||||
<file>icons/ui/attach.svg</file>
|
||||
<file>icons/ui/ban.svg</file>
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ TimelineFilter::setThreadId(const QString &t)
|
|||
{
|
||||
nhlog::ui()->debug("Filtering by thread '{}'", t.toStdString());
|
||||
if (this->threadId != t) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
beginFilterChange();
|
||||
#endif
|
||||
|
||||
this->threadId = t;
|
||||
|
||||
emit threadIdChanged();
|
||||
|
|
@ -104,11 +108,30 @@ TimelineFilter::setThreadId(const QString &t)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimelineFilter::setFilterNotifications(bool filter)
|
||||
{
|
||||
nhlog::ui()->debug("Filtering by notifications '{}'", filter);
|
||||
if (this->filterByNotifications_ != filter) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
beginFilterChange();
|
||||
#endif
|
||||
this->filterByNotifications_ = filter;
|
||||
|
||||
emit filterNotificationsChanged();
|
||||
startFiltering();
|
||||
fetchMore({});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimelineFilter::setContentFilter(const QString &c)
|
||||
{
|
||||
nhlog::ui()->debug("Filtering by content '{}'", c.toStdString());
|
||||
if (this->contentFilter != c) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
beginFilterChange();
|
||||
#endif
|
||||
this->contentFilter = c;
|
||||
|
||||
emit contentFilterChanged();
|
||||
|
|
@ -145,7 +168,8 @@ TimelineFilter::sourceDataChanged(const QModelIndex &topLeft,
|
|||
const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles)
|
||||
{
|
||||
if (!roles.contains(TimelineModel::Roles::Body) && !roles.contains(TimelineModel::ThreadId))
|
||||
if (!roles.contains(TimelineModel::Roles::Body) && !roles.contains(TimelineModel::ThreadId) &&
|
||||
!roles.contains(TimelineModel::Notificationlevel))
|
||||
return;
|
||||
|
||||
if (auto s = source()) {
|
||||
|
|
@ -233,19 +257,27 @@ TimelineFilter::filterAcceptsRow(int source_row, const QModelIndex &) const
|
|||
if (source_row > incrementalSearchIndex)
|
||||
return false;
|
||||
|
||||
if (threadId.isEmpty() && contentFilter.isEmpty())
|
||||
if (threadId.isEmpty() && contentFilter.isEmpty() && !filterByNotifications_)
|
||||
return true;
|
||||
|
||||
if (auto s = sourceModel()) {
|
||||
auto idx = s->index(source_row, 0);
|
||||
|
||||
if (!contentFilter.isEmpty() && !s->data(idx, TimelineModel::Body)
|
||||
.toString()
|
||||
.contains(contentFilter, Qt::CaseInsensitive)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (threadId.isEmpty())
|
||||
if (filterByNotifications_ && s->data(idx, TimelineModel::Notificationlevel)
|
||||
.value<qml_mtx_events::NotificationLevel>() !=
|
||||
qml_mtx_events::NotificationLevel::Highlight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (threadId.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return s->data(idx, TimelineModel::EventId) == threadId ||
|
||||
s->data(idx, TimelineModel::ThreadId) == threadId;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class TimelineFilter : public QSortFilterProxyModel
|
|||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(QString filterByThread READ filterByThread WRITE setThreadId NOTIFY threadIdChanged)
|
||||
Q_PROPERTY(bool filterByNotifications READ filterByNotifications WRITE setFilterNotifications
|
||||
NOTIFY filterNotificationsChanged)
|
||||
Q_PROPERTY(QString filterByContent READ filterByContent WRITE setContentFilter NOTIFY
|
||||
contentFilterChanged)
|
||||
Q_PROPERTY(TimelineModel *source READ source WRITE setSource NOTIFY sourceChanged)
|
||||
|
|
@ -28,12 +30,14 @@ public:
|
|||
explicit TimelineFilter(QObject *parent = nullptr);
|
||||
|
||||
QString filterByThread() const { return threadId; }
|
||||
bool filterByNotifications() const { return filterByNotifications_; }
|
||||
QString filterByContent() const { return contentFilter; }
|
||||
TimelineModel *source() const;
|
||||
int currentIndex() const;
|
||||
bool isFiltering() const;
|
||||
|
||||
void setThreadId(const QString &t);
|
||||
void setFilterNotifications(bool v);
|
||||
void setContentFilter(const QString &t);
|
||||
void setSource(TimelineModel *t);
|
||||
void setCurrentIndex(int idx);
|
||||
|
|
@ -47,6 +51,7 @@ public:
|
|||
|
||||
signals:
|
||||
void threadIdChanged();
|
||||
void filterNotificationsChanged();
|
||||
void contentFilterChanged();
|
||||
void sourceChanged();
|
||||
void currentIndexChanged();
|
||||
|
|
@ -67,4 +72,5 @@ private:
|
|||
|
||||
QString threadId, contentFilter;
|
||||
int cachedCount = 0, incrementalSearchIndex = 0;
|
||||
bool filterByNotifications_ = false;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue