Add a button to cycle through unread highlights
BUG: 465095
This commit is contained in:
committed by
James Graham
parent
fd44ff972a
commit
58ea229b67
@@ -169,6 +169,7 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
|
|||||||
const auto neochatconnection = static_cast<NeoChatConnection *>(connection);
|
const auto neochatconnection = static_cast<NeoChatConnection *>(connection);
|
||||||
Q_ASSERT(neochatconnection);
|
Q_ASSERT(neochatconnection);
|
||||||
connect(neochatconnection, &NeoChatConnection::globalUrlPreviewEnabledChanged, this, &NeoChatRoom::urlPreviewEnabledChanged);
|
connect(neochatconnection, &NeoChatConnection::globalUrlPreviewEnabledChanged, this, &NeoChatRoom::urlPreviewEnabledChanged);
|
||||||
|
connect(this, &Room::fullyReadMarkerMoved, this, &NeoChatRoom::invalidateLastUnreadHighlightId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NeoChatRoom::visible() const
|
bool NeoChatRoom::visible() const
|
||||||
@@ -1843,4 +1844,52 @@ void NeoChatRoom::report(const QString &reason)
|
|||||||
connection()->callApi<NeochatReportRoomJob>(id(), reason);
|
connection()->callApi<NeochatReportRoomJob>(id(), reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString NeoChatRoom::findNextUnreadHighlightId()
|
||||||
|
{
|
||||||
|
const QString startEventId = !m_lastUnreadHighlightId.isEmpty() ? m_lastUnreadHighlightId : lastFullyReadEventId();
|
||||||
|
const auto startIt = findInTimeline(startEventId);
|
||||||
|
if (startIt == historyEdge()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = startIt.base(); it != messageEvents().cend(); ++it) {
|
||||||
|
const RoomEvent *ev = it->event();
|
||||||
|
if (highlights.contains(ev)) {
|
||||||
|
m_lastUnreadHighlightId = ev->id();
|
||||||
|
Q_EMIT highlightCycleStartedChanged();
|
||||||
|
return m_lastUnreadHighlightId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_lastUnreadHighlightId.isEmpty()) {
|
||||||
|
m_lastUnreadHighlightId.clear();
|
||||||
|
Q_EMIT highlightCycleStartedChanged();
|
||||||
|
return findNextUnreadHighlightId();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NeoChatRoom::highlightCycleStarted() const
|
||||||
|
{
|
||||||
|
return !m_lastUnreadHighlightId.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeoChatRoom::invalidateLastUnreadHighlightId(const QString &fromEventId, const QString &toEventId)
|
||||||
|
{
|
||||||
|
Q_UNUSED(fromEventId);
|
||||||
|
|
||||||
|
if (m_lastUnreadHighlightId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto lastIt = findInTimeline(m_lastUnreadHighlightId);
|
||||||
|
const auto newReadIt = findInTimeline(toEventId);
|
||||||
|
|
||||||
|
// opposite comparision because both are reverse iterators :p
|
||||||
|
if (newReadIt <= lastIt) {
|
||||||
|
m_lastUnreadHighlightId.clear();
|
||||||
|
Q_EMIT highlightCycleStartedChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_neochatroom.cpp"
|
#include "moc_neochatroom.cpp"
|
||||||
|
|||||||
@@ -208,6 +208,11 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
*/
|
*/
|
||||||
Q_PROPERTY(QString pinnedMessage READ pinnedMessage NOTIFY pinnedMessageChanged)
|
Q_PROPERTY(QString pinnedMessage READ pinnedMessage NOTIFY pinnedMessageChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether the highlight finding cycle has started.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool highlightCycleStarted READ highlightCycleStarted NOTIFY highlightCycleStartedChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit NeoChatRoom(Quotient::Connection *connection, QString roomId, Quotient::JoinState joinState = {});
|
explicit NeoChatRoom(Quotient::Connection *connection, QString roomId, Quotient::JoinState joinState = {});
|
||||||
|
|
||||||
@@ -627,6 +632,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
Q_INVOKABLE void report(const QString &reason);
|
Q_INVOKABLE void report(const QString &reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the ID of the next unread highlight in the room.
|
||||||
|
*
|
||||||
|
* Each call advances the internal highlight cursor. Once the last unread highlight
|
||||||
|
* is reached, the cycle is reset.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE QString findNextUnreadHighlightId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether the highlight finding cycle has started.
|
||||||
|
*/
|
||||||
|
bool highlightCycleStarted() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_visible = false;
|
bool m_visible = false;
|
||||||
|
|
||||||
@@ -662,11 +680,15 @@ private:
|
|||||||
QString m_pinnedMessage;
|
QString m_pinnedMessage;
|
||||||
void loadPinnedMessage();
|
void loadPinnedMessage();
|
||||||
|
|
||||||
|
QString m_lastUnreadHighlightId;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void updatePushNotificationState(QString type);
|
void updatePushNotificationState(QString type);
|
||||||
|
|
||||||
void cacheLastEvent();
|
void cacheLastEvent();
|
||||||
|
|
||||||
|
void invalidateLastUnreadHighlightId(const QString &fromEventId, const QString &toEventId);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void cachedInputChanged();
|
void cachedInputChanged();
|
||||||
void busyChanged();
|
void busyChanged();
|
||||||
@@ -692,6 +714,7 @@ Q_SIGNALS:
|
|||||||
void extraEventNotFound(const QString &eventId);
|
void extraEventNotFound(const QString &eventId);
|
||||||
void inviteTimestampChanged();
|
void inviteTimestampChanged();
|
||||||
void pinnedMessageChanged();
|
void pinnedMessageChanged();
|
||||||
|
void highlightCycleStartedChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Request a message be shown to the user of the given type.
|
* @brief Request a message be shown to the user of the given type.
|
||||||
|
|||||||
@@ -193,9 +193,7 @@ QQC2.ScrollView {
|
|||||||
room: _private.room
|
room: _private.room
|
||||||
}
|
}
|
||||||
|
|
||||||
KirigamiComponents.FloatingButton {
|
ColumnLayout {
|
||||||
id: goReadMarkerFab
|
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
right: parent.right
|
right: parent.right
|
||||||
top: parent.top
|
top: parent.top
|
||||||
@@ -203,28 +201,59 @@ QQC2.ScrollView {
|
|||||||
rightMargin: Kirigami.Units.largeSpacing
|
rightMargin: Kirigami.Units.largeSpacing
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitWidth: Kirigami.Settings.hasTransientTouchInput ? Kirigami.Units.gridUnit * 3 : Kirigami.Units.gridUnit * 2
|
spacing: Kirigami.Units.largeSpacing
|
||||||
implicitHeight: Kirigami.Settings.hasTransientTouchInput ? Kirigami.Units.gridUnit * 3 : Kirigami.Units.gridUnit * 2
|
|
||||||
|
|
||||||
padding: Kirigami.Units.largeSpacing
|
KirigamiComponents.FloatingButton {
|
||||||
|
id: goReadMarkerFab
|
||||||
|
|
||||||
z: 2
|
implicitWidth: Kirigami.Settings.hasTransientTouchInput ? Kirigami.Units.gridUnit * 3 : Kirigami.Units.gridUnit * 2
|
||||||
visible: !_private.room?.partiallyReadStats.empty()
|
implicitHeight: Kirigami.Settings.hasTransientTouchInput ? Kirigami.Units.gridUnit * 3 : Kirigami.Units.gridUnit * 2
|
||||||
|
|
||||||
text: _private.room.readMarkerLoaded ? i18nc("@action:button", "Jump to first unread message") : i18nc("@action:button", "Jump to oldest loaded message")
|
padding: Kirigami.Units.largeSpacing
|
||||||
icon.name: "go-up"
|
|
||||||
onClicked: {
|
z: 2
|
||||||
goReadMarkerFab.textChanged()
|
visible: !_private.room?.partiallyReadStats.empty()
|
||||||
root.goToEvent(_private.room.lastFullyReadEventId);
|
|
||||||
}
|
text: _private.room.readMarkerLoaded ? i18nc("@action:button", "Jump to first unread message") : i18nc("@action:button", "Jump to oldest loaded message")
|
||||||
Kirigami.Action {
|
icon.name: "go-up"
|
||||||
shortcut: "Shift+PgUp"
|
onClicked: {
|
||||||
onTriggered: goReadMarkerFab.clicked()
|
goReadMarkerFab.textChanged()
|
||||||
|
root.goToEvent(_private.room.lastFullyReadEventId);
|
||||||
|
}
|
||||||
|
Kirigami.Action {
|
||||||
|
shortcut: "Shift+PgUp"
|
||||||
|
onTriggered: goReadMarkerFab.clicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.ToolTip.text: goReadMarkerFab.text
|
||||||
|
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||||
|
QQC2.ToolTip.visible: goReadMarkerFab.hovered
|
||||||
}
|
}
|
||||||
|
KirigamiComponents.FloatingButton {
|
||||||
|
id: goUnreadHighlightFab
|
||||||
|
|
||||||
QQC2.ToolTip.text: goReadMarkerFab.text
|
implicitWidth: Kirigami.Settings.hasTransientTouchInput ? Kirigami.Units.gridUnit * 3 : Kirigami.Units.gridUnit * 2
|
||||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
implicitHeight: Kirigami.Settings.hasTransientTouchInput ? Kirigami.Units.gridUnit * 3 : Kirigami.Units.gridUnit * 2
|
||||||
QQC2.ToolTip.visible: goReadMarkerFab.hovered
|
|
||||||
|
padding: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
z: 2
|
||||||
|
visible: _private.room?.highlightCount > 0
|
||||||
|
|
||||||
|
text: _private.room?.highlightCycleStarted ? i18nc("@action:button", "Jump to next unread highlight") : i18nc("@action:button", "Jump to first unread message")
|
||||||
|
icon.name: "mail-unread-symbolic"
|
||||||
|
onClicked: {
|
||||||
|
const eventId = _private.room.findNextUnreadHighlightId();
|
||||||
|
if (eventId !== "") {
|
||||||
|
goUnreadHighlightFab.textChanged();
|
||||||
|
root.goToEvent(eventId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.ToolTip.text: goUnreadHighlightFab.text
|
||||||
|
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||||
|
QQC2.ToolTip.visible: goUnreadHighlightFab.hovered
|
||||||
|
}
|
||||||
}
|
}
|
||||||
KirigamiComponents.FloatingButton {
|
KirigamiComponents.FloatingButton {
|
||||||
id: goMarkAsReadFab
|
id: goMarkAsReadFab
|
||||||
|
|||||||
Reference in New Issue
Block a user