mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
parent
245fdb1917
commit
146aaa8746
11 changed files with 139 additions and 7 deletions
|
@ -26,6 +26,12 @@
|
|||
#include "RoomSettings.h"
|
||||
#include "RoomState.h"
|
||||
|
||||
struct DescInfo {
|
||||
QString username;
|
||||
QString body;
|
||||
QString timestamp;
|
||||
};
|
||||
|
||||
class RoomInfoListItem : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -46,6 +52,7 @@ public:
|
|||
inline RoomState state() const;
|
||||
inline void setAvatar(const QImage &avatar_image);
|
||||
inline int unreadMessageCount() const;
|
||||
inline void setDescriptionMessage(const DescInfo &info);
|
||||
|
||||
signals:
|
||||
void clicked(const QString &room_id);
|
||||
|
@ -71,8 +78,8 @@ private:
|
|||
|
||||
QString roomId_;
|
||||
QString roomName_;
|
||||
QString lastMessage_;
|
||||
QString lastTimestamp_;
|
||||
|
||||
DescInfo lastMsgInfo_;
|
||||
|
||||
QPixmap roomAvatar_;
|
||||
|
||||
|
@ -107,3 +114,8 @@ inline void RoomInfoListItem::setAvatar(const QImage &img)
|
|||
roomAvatar_ = QPixmap::fromImage(img.scaled(IconSize, IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
update();
|
||||
}
|
||||
|
||||
inline void RoomInfoListItem::setDescriptionMessage(const DescInfo &info)
|
||||
{
|
||||
lastMsgInfo_ = info;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ public slots:
|
|||
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
|
||||
void highlightSelectedRoom(const QString &room_id);
|
||||
void updateUnreadMessageCount(const QString &roomid, int count);
|
||||
void updateRoomDescription(const QString &roomid, const DescInfo &info);
|
||||
|
||||
private:
|
||||
void calculateUnreadMessageCount();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "Image.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "Notice.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Text.h"
|
||||
|
||||
namespace events = matrix::events;
|
||||
|
@ -48,6 +49,7 @@ public:
|
|||
TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, QWidget *parent);
|
||||
|
||||
void setUserAvatar(const QImage &pixmap);
|
||||
inline DescInfo descriptionMessage() const;
|
||||
|
||||
~TimelineItem();
|
||||
|
||||
|
@ -57,12 +59,15 @@ private:
|
|||
void generateBody(const QString &body);
|
||||
void generateBody(const QString &userid, const QString &color, const QString &body);
|
||||
void generateTimestamp(const QDateTime &time);
|
||||
QString descriptiveTime(const QDateTime &then);
|
||||
|
||||
void setupAvatarLayout(const QString &userName);
|
||||
void setupSimpleLayout();
|
||||
|
||||
QString replaceEmoji(const QString &body);
|
||||
|
||||
DescInfo descriptionMsg_;
|
||||
|
||||
QHBoxLayout *topLayout_;
|
||||
QVBoxLayout *sideLayout_; // Avatar or Timestamp
|
||||
QVBoxLayout *mainLayout_; // Header & Message body
|
||||
|
@ -77,3 +82,8 @@ private:
|
|||
QLabel *userName_;
|
||||
QLabel *body_;
|
||||
};
|
||||
|
||||
inline DescInfo TimelineItem::descriptionMessage() const
|
||||
{
|
||||
return descriptionMsg_;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "Image.h"
|
||||
#include "Notice.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Text.h"
|
||||
|
||||
namespace msgs = matrix::events::messages;
|
||||
|
@ -83,11 +84,15 @@ public slots:
|
|||
// Add old events at the top of the timeline.
|
||||
void addBackwardsEvents(const QString &room_id, const RoomMessages &msgs);
|
||||
|
||||
signals:
|
||||
void updateLastTimelineMessage(const QString &user, const DescInfo &info);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void removePendingMessage(const events::MessageEvent<msgs::Text> &e);
|
||||
void addTimelineItem(TimelineItem *item, TimelineDirection direction);
|
||||
void updateLastSender(const QString &user_id, TimelineDirection direction);
|
||||
void notifyForLastEvent();
|
||||
|
||||
// Used to determine whether or not we should prefix a message with the sender's name.
|
||||
bool isSenderRendered(const QString &user_id, TimelineDirection direction);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QWidget>
|
||||
|
||||
#include "MatrixClient.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Sync.h"
|
||||
#include "TimelineView.h"
|
||||
|
||||
|
@ -50,6 +51,7 @@ public:
|
|||
|
||||
signals:
|
||||
void unreadMessages(QString roomid, int count);
|
||||
void updateRoomsLastMessage(const QString &user, const DescInfo &info);
|
||||
|
||||
public slots:
|
||||
void setHistoryView(const QString &room_id);
|
||||
|
|
|
@ -138,6 +138,11 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
room_list_->updateUnreadMessageCount(roomid, count);
|
||||
});
|
||||
|
||||
connect(view_manager_,
|
||||
&TimelineViewManager::updateRoomsLastMessage,
|
||||
room_list_,
|
||||
&RoomList::updateRoomDescription);
|
||||
|
||||
connect(room_list_,
|
||||
SIGNAL(totalUnreadMessageCountUpdated(int)),
|
||||
this,
|
||||
|
|
|
@ -135,10 +135,34 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event)
|
|||
font.setPixelSize(conf::fontSize);
|
||||
p.setFont(font);
|
||||
|
||||
auto description = metrics.elidedText(state_.getTopic(), Qt::ElideRight, width() * descPercentage - 2 * Padding - IconSize);
|
||||
p.drawText(QPoint(2 * Padding + IconSize, bottom_y), description);
|
||||
auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5;
|
||||
|
||||
// The limit is the space between the end of the avatar and the start of the timestamp.
|
||||
int usernameLimit = std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20);
|
||||
auto userName = metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit);
|
||||
|
||||
font.setBold(true);
|
||||
p.setFont(font);
|
||||
p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName);
|
||||
|
||||
int nameWidth = QFontMetrics(font).width(userName);
|
||||
|
||||
font.setBold(false);
|
||||
p.setFont(font);
|
||||
|
||||
// The limit is the space between the end of the username and the start of the timestamp.
|
||||
int descriptionLimit = std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5);
|
||||
auto description = metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit);
|
||||
p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y), description);
|
||||
|
||||
// We either show the bubble or the last message timestamp.
|
||||
if (unreadMsgCount_ == 0) {
|
||||
font.setBold(true);
|
||||
p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y), lastMsgInfo_.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
font.setBold(false);
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
// We using the first letter of room's name.
|
||||
|
|
|
@ -174,10 +174,19 @@ void RoomList::highlightSelectedRoom(const QString &room_id)
|
|||
void RoomList::updateRoomAvatar(const QString &roomid, const QPixmap &img)
|
||||
{
|
||||
if (!rooms_.contains(roomid)) {
|
||||
qDebug() << "Avatar update on non existent room" << roomid;
|
||||
qWarning() << "Avatar update on non existent room" << roomid;
|
||||
return;
|
||||
}
|
||||
|
||||
auto list_item = rooms_.value(roomid);
|
||||
list_item->setAvatar(img.toImage());
|
||||
rooms_.value(roomid)->setAvatar(img.toImage());
|
||||
}
|
||||
|
||||
void RoomList::updateRoomDescription(const QString &roomid, const DescInfo &info)
|
||||
{
|
||||
if (!rooms_.contains(roomid)) {
|
||||
qWarning() << "Description update on non existent room" << roomid << info.body;
|
||||
return;
|
||||
}
|
||||
|
||||
rooms_.value(roomid)->setDescriptionMessage(info);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ TimelineItem::TimelineItem(const QString &userid, const QString &color, QString
|
|||
: QWidget(parent)
|
||||
{
|
||||
init();
|
||||
descriptionMsg_ = {"You: ", body, descriptiveTime(QDateTime::currentDateTime())};
|
||||
|
||||
body.replace(URL_REGEX, URL_HTML);
|
||||
auto displayName = TimelineViewManager::displayName(userid);
|
||||
|
@ -94,6 +95,7 @@ TimelineItem::TimelineItem(QString body, QWidget *parent)
|
|||
: QWidget(parent)
|
||||
{
|
||||
init();
|
||||
descriptionMsg_ = {"You: ", body, descriptiveTime(QDateTime::currentDateTime())};
|
||||
|
||||
body.replace(URL_REGEX, URL_HTML);
|
||||
|
||||
|
@ -119,6 +121,10 @@ TimelineItem::TimelineItem(ImageItem *image,
|
|||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||
|
||||
descriptionMsg_ = {displayName,
|
||||
" sent an image",
|
||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||
|
||||
generateTimestamp(timestamp);
|
||||
generateBody(displayName, color, "");
|
||||
|
||||
|
@ -141,6 +147,9 @@ TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Im
|
|||
: QWidget(parent)
|
||||
{
|
||||
init();
|
||||
descriptionMsg_ = {TimelineViewManager::displayName(event.sender()),
|
||||
" sent an image",
|
||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||
|
||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
generateTimestamp(timestamp);
|
||||
|
@ -162,6 +171,10 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool
|
|||
: QWidget(parent)
|
||||
{
|
||||
init();
|
||||
descriptionMsg_ = {
|
||||
TimelineViewManager::displayName(event.sender()),
|
||||
" sent a notification",
|
||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||
|
||||
auto body = event.content().body().trimmed().toHtmlEscaped();
|
||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
|
@ -199,6 +212,11 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool w
|
|||
auto body = event.content().body().trimmed().toHtmlEscaped();
|
||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||
|
||||
descriptionMsg_ = {
|
||||
TimelineViewManager::displayName(event.sender()),
|
||||
QString(": %1").arg(body),
|
||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||
|
||||
generateTimestamp(timestamp);
|
||||
|
||||
body.replace(URL_REGEX, URL_HTML);
|
||||
|
@ -352,6 +370,23 @@ void TimelineItem::setUserAvatar(const QImage &avatar)
|
|||
userAvatar_->setImage(avatar);
|
||||
}
|
||||
|
||||
QString TimelineItem::descriptiveTime(const QDateTime &then)
|
||||
{
|
||||
auto now = QDateTime::currentDateTime();
|
||||
|
||||
auto days = then.daysTo(now);
|
||||
|
||||
if (days == 0) {
|
||||
return then.toString("HH:mm");
|
||||
} else if (days < 2) {
|
||||
return QString("Yesterday");
|
||||
} else if (days < 365) {
|
||||
return then.toString("dd/MM");
|
||||
}
|
||||
|
||||
return then.toString("dd/MM/yy");
|
||||
}
|
||||
|
||||
TimelineItem::~TimelineItem()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -179,6 +179,10 @@ void TimelineView::addBackwardsEvents(const QString &room_id, const RoomMessages
|
|||
prev_batch_token_ = msgs.end();
|
||||
isPaginationInProgress_ = false;
|
||||
isPaginationScrollPending_ = true;
|
||||
|
||||
// Exclude the top stretch.
|
||||
if (!msgs.chunk().isEmpty() && scroll_layout_->count() > 1)
|
||||
notifyForLastEvent();
|
||||
}
|
||||
|
||||
TimelineItem *TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection direction)
|
||||
|
@ -295,6 +299,10 @@ int TimelineView::addEvents(const Timeline &timeline)
|
|||
client_->messages(room_id_, prev_batch_token_);
|
||||
}
|
||||
|
||||
// Exclude the top stretch.
|
||||
if (!timeline.events().isEmpty() && scroll_layout_->count() > 1)
|
||||
notifyForLastEvent();
|
||||
|
||||
return message_count;
|
||||
}
|
||||
|
||||
|
@ -441,3 +449,14 @@ void TimelineView::addUserTextMessage(const QString &body, int txn_id)
|
|||
|
||||
pending_msgs_.push_back(message);
|
||||
}
|
||||
|
||||
void TimelineView::notifyForLastEvent()
|
||||
{
|
||||
auto lastItem = scroll_layout_->itemAt(scroll_layout_->count() - 1);
|
||||
auto *lastTimelineItem = qobject_cast<TimelineItem *>(lastItem->widget());
|
||||
|
||||
if (lastTimelineItem)
|
||||
emit updateLastTimelineMessage(room_id_, lastTimelineItem->descriptionMessage());
|
||||
else
|
||||
qWarning() << "Cast to TimelineView failed" << room_id_;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,11 @@ void TimelineViewManager::initialize(const Rooms &rooms)
|
|||
TimelineView *view = new TimelineView(it.value().timeline(), client_, it.key());
|
||||
views_.insert(it.key(), QSharedPointer<TimelineView>(view));
|
||||
|
||||
connect(view,
|
||||
&TimelineView::updateLastTimelineMessage,
|
||||
this,
|
||||
&TimelineViewManager::updateRoomsLastMessage);
|
||||
|
||||
// Add the view in the widget stack.
|
||||
addWidget(view);
|
||||
}
|
||||
|
@ -92,6 +97,11 @@ void TimelineViewManager::initialize(const QList<QString> &rooms)
|
|||
TimelineView *view = new TimelineView(client_, roomid);
|
||||
views_.insert(roomid, QSharedPointer<TimelineView>(view));
|
||||
|
||||
connect(view,
|
||||
&TimelineView::updateLastTimelineMessage,
|
||||
this,
|
||||
&TimelineViewManager::updateRoomsLastMessage);
|
||||
|
||||
// Add the view in the widget stack.
|
||||
addWidget(view);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue