mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Send read receipts
Automatically dismiss unread notifications when the window regains focus. fixes #111 fixes #68
This commit is contained in:
parent
c6cf6c2b41
commit
0f363b5f44
11 changed files with 126 additions and 4 deletions
|
@ -59,6 +59,7 @@ public:
|
|||
void leaveRoom(const QString &roomId);
|
||||
void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000);
|
||||
void removeTypingNotification(const QString &roomid);
|
||||
void readEvent(const QString &room_id, const QString &event_id);
|
||||
|
||||
QUrl getHomeServer() { return server_; };
|
||||
int transactionId() { return txn_id_; };
|
||||
|
|
|
@ -66,6 +66,7 @@ public slots:
|
|||
void closeJoinRoomDialog(bool isJoining, QString roomAlias);
|
||||
void openLeaveRoomDialog(const QString &room_id);
|
||||
void closeLeaveRoomDialog(bool leaving, const QString &room_id);
|
||||
void clearRoomMessageCount(const QString &room_id);
|
||||
|
||||
private:
|
||||
void calculateUnreadMessageCount();
|
||||
|
|
|
@ -66,7 +66,8 @@ public:
|
|||
QWidget *parent);
|
||||
|
||||
void setUserAvatar(const QImage &pixmap);
|
||||
DescInfo descriptionMessage() const { return descriptionMsg_; };
|
||||
DescInfo descriptionMessage() const { return descriptionMsg_; }
|
||||
QString eventId() const { return event_id_; }
|
||||
|
||||
~TimelineItem();
|
||||
|
||||
|
@ -85,6 +86,7 @@ private:
|
|||
void setupSimpleLayout();
|
||||
|
||||
QString replaceEmoji(const QString &body);
|
||||
QString event_id_;
|
||||
|
||||
DescInfo descriptionMsg_;
|
||||
|
||||
|
|
|
@ -121,15 +121,20 @@ private slots:
|
|||
|
||||
signals:
|
||||
void updateLastTimelineMessage(const QString &user, const DescInfo &info);
|
||||
void clearUnreadMessageCount(const QString &room_id);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void addTimelineItem(TimelineItem *item, TimelineDirection direction);
|
||||
void updateLastSender(const QString &user_id, TimelineDirection direction);
|
||||
void notifyForLastEvent();
|
||||
void readLastEvent() const;
|
||||
QString getLastEventId() const;
|
||||
|
||||
// Used to determine whether or not we should prefix a message with the
|
||||
// sender's name.
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
static QMap<QString, QString> DISPLAY_NAMES;
|
||||
|
||||
signals:
|
||||
void clearRoomMessageCount(QString roomid);
|
||||
void unreadMessages(QString roomid, int count);
|
||||
void updateRoomsLastMessage(const QString &user, const DescInfo &info);
|
||||
|
||||
|
|
|
@ -125,6 +125,11 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
connect(
|
||||
room_list_, &RoomList::roomChanged, view_manager_, &TimelineViewManager::setHistoryView);
|
||||
|
||||
connect(view_manager_,
|
||||
&TimelineViewManager::clearRoomMessageCount,
|
||||
room_list_,
|
||||
&RoomList::clearRoomMessageCount);
|
||||
|
||||
connect(view_manager_,
|
||||
&TimelineViewManager::unreadMessages,
|
||||
this,
|
||||
|
|
|
@ -847,3 +847,31 @@ MatrixClient::removeTypingNotification(const QString &roomid)
|
|||
|
||||
put(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
void
|
||||
MatrixClient::readEvent(const QString &room_id, const QString &event_id)
|
||||
{
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("access_token", token_);
|
||||
|
||||
QUrl endpoint(server_);
|
||||
endpoint.setPath(clientApiUrl_ +
|
||||
QString("/rooms/%1/receipt/m.read/%2").arg(room_id).arg(event_id));
|
||||
endpoint.setQuery(query);
|
||||
|
||||
QNetworkRequest request(QString(endpoint.toEncoded()));
|
||||
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
|
||||
|
||||
auto reply = post(request, "{}");
|
||||
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
reply->deleteLater();
|
||||
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (status == 0 || status >= 400) {
|
||||
qWarning() << reply->errorString();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -203,6 +203,18 @@ RoomList::sync(const QMap<QString, RoomState> &states,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::clearRoomMessageCount(const QString &room_id)
|
||||
{
|
||||
if (!rooms_.contains(room_id))
|
||||
return;
|
||||
|
||||
auto room = rooms_[room_id];
|
||||
room->clearUnreadMessageCount();
|
||||
|
||||
calculateUnreadMessageCount();
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::highlightSelectedRoom(const QString &room_id)
|
||||
{
|
||||
|
@ -213,9 +225,7 @@ RoomList::highlightSelectedRoom(const QString &room_id)
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Send a read receipt for the last event.
|
||||
auto room = rooms_[room_id];
|
||||
room->clearUnreadMessageCount();
|
||||
clearRoomMessageCount(room_id);
|
||||
|
||||
calculateUnreadMessageCount();
|
||||
|
||||
|
|
|
@ -154,6 +154,8 @@ TimelineItem::TimelineItem(ImageItem *image,
|
|||
{
|
||||
init();
|
||||
|
||||
event_id_ = event.eventId();
|
||||
|
||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||
|
||||
|
@ -193,6 +195,9 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event,
|
|||
: QWidget(parent)
|
||||
{
|
||||
init();
|
||||
|
||||
event_id_ = event.eventId();
|
||||
|
||||
descriptionMsg_ = {TimelineViewManager::displayName(event.sender()),
|
||||
event.sender(),
|
||||
" sent a notification",
|
||||
|
@ -234,6 +239,8 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Emote> &event,
|
|||
{
|
||||
init();
|
||||
|
||||
event_id_ = event.eventId();
|
||||
|
||||
auto body = event.content().body().trimmed();
|
||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||
|
@ -273,6 +280,8 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event,
|
|||
{
|
||||
init();
|
||||
|
||||
event_id_ = event.eventId();
|
||||
|
||||
auto body = event.content().body().trimmed();
|
||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||
|
|
|
@ -379,6 +379,9 @@ TimelineView::addEvents(const Timeline &timeline)
|
|||
if (!timeline.events().isEmpty() && scroll_layout_->count() > 1)
|
||||
notifyForLastEvent();
|
||||
|
||||
if (isActiveWindow() && isVisible() && timeline.events().size() > 0)
|
||||
readLastEvent();
|
||||
|
||||
return message_count;
|
||||
}
|
||||
|
||||
|
@ -648,3 +651,52 @@ TimelineView::paintEvent(QPaintEvent *)
|
|||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineView::readLastEvent() const
|
||||
{
|
||||
const auto eventId = getLastEventId();
|
||||
|
||||
if (!eventId.isEmpty())
|
||||
client_->readEvent(room_id_, eventId);
|
||||
}
|
||||
|
||||
QString
|
||||
TimelineView::getLastEventId() const
|
||||
{
|
||||
auto index = scroll_layout_->count();
|
||||
|
||||
// Search backwards for the first event that has a valid event id.
|
||||
while (index > 0) {
|
||||
--index;
|
||||
|
||||
auto lastItem = scroll_layout_->itemAt(index);
|
||||
auto *lastTimelineItem = qobject_cast<TimelineItem *>(lastItem->widget());
|
||||
|
||||
if (lastTimelineItem && !lastTimelineItem->eventId().isEmpty())
|
||||
return lastTimelineItem->eventId();
|
||||
}
|
||||
|
||||
return QString("");
|
||||
}
|
||||
|
||||
void
|
||||
TimelineView::showEvent(QShowEvent *event)
|
||||
{
|
||||
readLastEvent();
|
||||
|
||||
QWidget::showEvent(event);
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineView::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::WindowActivate) {
|
||||
QTimer::singleShot(1000, this, [=]() {
|
||||
emit clearUnreadMessageCount(room_id_);
|
||||
readLastEvent();
|
||||
});
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
|
|
@ -131,6 +131,10 @@ TimelineViewManager::addRoom(const JoinedRoom &room, const QString &room_id)
|
|||
&TimelineView::updateLastTimelineMessage,
|
||||
this,
|
||||
&TimelineViewManager::updateRoomsLastMessage);
|
||||
connect(view,
|
||||
&TimelineView::clearUnreadMessageCount,
|
||||
this,
|
||||
&TimelineViewManager::clearRoomMessageCount);
|
||||
|
||||
// Add the view in the widget stack.
|
||||
addWidget(view);
|
||||
|
@ -147,6 +151,10 @@ TimelineViewManager::addRoom(const QString &room_id)
|
|||
&TimelineView::updateLastTimelineMessage,
|
||||
this,
|
||||
&TimelineViewManager::updateRoomsLastMessage);
|
||||
connect(view,
|
||||
&TimelineView::clearUnreadMessageCount,
|
||||
this,
|
||||
&TimelineViewManager::clearRoomMessageCount);
|
||||
|
||||
// Add the view in the widget stack.
|
||||
addWidget(view);
|
||||
|
|
Loading…
Reference in a new issue