parent
a44a4f36af
commit
b5ae84c3c3
@ -19,6 +19,7 @@
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
|
||||
#include "MessageEvent.h"
|
||||
#include "Profile.h"
|
||||
#include "RoomMessages.h"
|
||||
#include "Sync.h"
|
||||
@ -36,9 +37,13 @@ public:
|
||||
// Client API.
|
||||
void initialSync() noexcept;
|
||||
void sync() noexcept;
|
||||
void sendTextMessage(const QString &roomid, const QString &msg) noexcept;
|
||||
void sendRoomMessage(matrix::events::MessageEventType ty,
|
||||
const QString &roomid,
|
||||
const QString &msg) noexcept;
|
||||
void login(const QString &username, const QString &password) noexcept;
|
||||
void registerUser(const QString &username, const QString &password, const QString &server) noexcept;
|
||||
void registerUser(const QString &username,
|
||||
const QString &password,
|
||||
const QString &server) noexcept;
|
||||
void versions() noexcept;
|
||||
void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
|
||||
void fetchUserAvatar(const QString &userId, const QUrl &avatarUrl);
|
||||
@ -68,7 +73,9 @@ signals:
|
||||
void loggedOut();
|
||||
|
||||
void loginSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
||||
void registerSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
||||
void registerSuccess(const QString &userid,
|
||||
const QString &homeserver,
|
||||
const QString &token);
|
||||
void versionSuccess();
|
||||
|
||||
void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
|
||||
@ -82,6 +89,7 @@ signals:
|
||||
void syncCompleted(const SyncResponse &response);
|
||||
void syncFailed(const QString &msg);
|
||||
void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||
void emoteSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||
void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
|
||||
|
||||
private slots:
|
||||
@ -99,26 +107,26 @@ private:
|
||||
Messages,
|
||||
Register,
|
||||
RoomAvatar,
|
||||
UserAvatar,
|
||||
SendTextMessage,
|
||||
SendRoomMessage,
|
||||
Sync,
|
||||
UserAvatar,
|
||||
Versions,
|
||||
};
|
||||
|
||||
// Response handlers.
|
||||
void onGetOwnAvatarResponse(QNetworkReply *reply);
|
||||
void onGetOwnProfileResponse(QNetworkReply *reply);
|
||||
void onImageResponse(QNetworkReply *reply);
|
||||
void onInitialSyncResponse(QNetworkReply *reply);
|
||||
void onLoginResponse(QNetworkReply *reply);
|
||||
void onLogoutResponse(QNetworkReply *reply);
|
||||
void onRegisterResponse(QNetworkReply *reply);
|
||||
void onVersionsResponse(QNetworkReply *reply);
|
||||
void onGetOwnProfileResponse(QNetworkReply *reply);
|
||||
void onGetOwnAvatarResponse(QNetworkReply *reply);
|
||||
void onSendTextMessageResponse(QNetworkReply *reply);
|
||||
void onInitialSyncResponse(QNetworkReply *reply);
|
||||
void onSyncResponse(QNetworkReply *reply);
|
||||
void onRoomAvatarResponse(QNetworkReply *reply);
|
||||
void onUserAvatarResponse(QNetworkReply *reply);
|
||||
void onImageResponse(QNetworkReply *reply);
|
||||
void onMessagesResponse(QNetworkReply *reply);
|
||||
void onRegisterResponse(QNetworkReply *reply);
|
||||
void onRoomAvatarResponse(QNetworkReply *reply);
|
||||
void onSendRoomMessage(QNetworkReply *reply);
|
||||
void onSyncResponse(QNetworkReply *reply);
|
||||
void onUserAvatarResponse(QNetworkReply *reply);
|
||||
void onVersionsResponse(QNetworkReply *reply);
|
||||
|
||||
// Client API prefix.
|
||||
QString api_url_;
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "EmojiPickButton.h"
|
||||
#include "FlatButton.h"
|
||||
|
||||
static const QString EMOTE_COMMAND("/me ");
|
||||
|
||||
class FilteredTextEdit : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -36,7 +38,7 @@ signals:
|
||||
void enterPressed();
|
||||
};
|
||||
|
||||
class TextInputWidget : public QWidget
|
||||
class TextInputWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -53,11 +55,11 @@ private slots:
|
||||
|
||||
signals:
|
||||
void sendTextMessage(QString msg);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void sendEmoteMessage(QString msg);
|
||||
|
||||
private:
|
||||
QString parseEmoteCommand(const QString &cmd);
|
||||
|
||||
QHBoxLayout *top_layout_;
|
||||
FilteredTextEdit *input_;
|
||||
|
||||
|
@ -50,8 +50,11 @@ public:
|
||||
QWidget *parent = 0);
|
||||
|
||||
// For local messages.
|
||||
TimelineItem(const QString &userid, QString body, QWidget *parent = 0);
|
||||
TimelineItem(QString body, QWidget *parent = 0);
|
||||
TimelineItem(events::MessageEventType ty,
|
||||
const QString &userid,
|
||||
QString body,
|
||||
bool withSender,
|
||||
QWidget *parent = 0);
|
||||
|
||||
TimelineItem(ImageItem *img,
|
||||
const events::MessageEvent<msgs::Image> &e,
|
||||
|
@ -27,8 +27,9 @@
|
||||
#include "Sync.h"
|
||||
#include "TimelineItem.h"
|
||||
|
||||
#include "Image.h"
|
||||
#include "Emote.h"
|
||||
#include "Image.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "Notice.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Text.h"
|
||||
@ -83,7 +84,7 @@ public:
|
||||
|
||||
// Add new events at the end of the timeline.
|
||||
int addEvents(const Timeline &timeline);
|
||||
void addUserTextMessage(const QString &msg, int txn_id);
|
||||
void addUserMessage(matrix::events::MessageEventType ty, const QString &msg, int txn_id);
|
||||
void updatePendingMessage(int txn_id, QString event_id);
|
||||
void scrollDown();
|
||||
|
||||
@ -100,14 +101,19 @@ signals:
|
||||
|
||||
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);
|
||||
bool isPendingMessage(const events::MessageEvent<msgs::Text> &e, const QString &userid);
|
||||
|
||||
template<class T>
|
||||
bool isPendingMessage(const events::MessageEvent<T> &e, const QString &userid);
|
||||
|
||||
template<class T>
|
||||
void removePendingMessage(const events::MessageEvent<T> &e);
|
||||
|
||||
inline bool isDuplicate(const QString &event_id);
|
||||
|
||||
// Return nullptr if the event couldn't be parsed.
|
||||
@ -153,3 +159,32 @@ TimelineView::isDuplicate(const QString &event_id)
|
||||
{
|
||||
return eventIds_.contains(event_id);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TimelineView::isPendingMessage(const events::MessageEvent<T> &e, const QString &local_userid)
|
||||
{
|
||||
if (e.sender() != local_userid)
|
||||
return false;
|
||||
|
||||
for (const auto &msg : pending_msgs_) {
|
||||
if (msg.event_id == e.eventId() || msg.body == e.content().body())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
TimelineView::removePendingMessage(const events::MessageEvent<T> &e)
|
||||
{
|
||||
for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); it++) {
|
||||
int index = std::distance(pending_msgs_.begin(), it);
|
||||
|
||||
if (it->event_id == e.eventId() || it->body == e.content().body()) {
|
||||
pending_msgs_.removeAt(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "MatrixClient.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Sync.h"
|
||||
#include "TimelineView.h"
|
||||
@ -54,6 +55,7 @@ signals:
|
||||
public slots:
|
||||
void setHistoryView(const QString &room_id);
|
||||
void sendTextMessage(const QString &msg);
|
||||
void sendEmoteMessage(const QString &msg);
|
||||
|
||||
private slots:
|
||||
void messageSent(const QString &eventid, const QString &roomid, int txnid);
|
||||
|
@ -148,6 +148,11 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||
view_manager_,
|
||||
SLOT(sendTextMessage(const QString &)));
|
||||
|
||||
connect(text_input_,
|
||||
SIGNAL(sendEmoteMessage(const QString &)),
|
||||
view_manager_,
|
||||
SLOT(sendEmoteMessage(const QString &)));
|
||||
|
||||
connect(client_.data(),
|
||||
SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
|
||||
this,
|
||||
|
@ -63,7 +63,8 @@ MatrixClient::onVersionsResponse(QNetworkReply *reply)
|
||||
int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (status_code == 404) {
|
||||
emit versionError("Versions endpoint was not found on the server. Possibly not a Matrix server");
|
||||
emit versionError(
|
||||
"Versions endpoint was not found on the server. Possibly not a Matrix server");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -165,7 +166,8 @@ MatrixClient::onRegisterResponse(QNetworkReply *reply)
|
||||
|
||||
try {
|
||||
response.deserialize(json);
|
||||
emit registerSuccess(response.getUserId(), response.getHomeServer(), response.getAccessToken());
|
||||
emit registerSuccess(
|
||||
response.getUserId(), response.getHomeServer(), response.getAccessToken());
|
||||
} catch (DeserializationException &e) {
|
||||
qWarning() << "Register" << e.what();
|
||||
emit registerError("Received malformed response.");
|
||||
@ -258,7 +260,7 @@ MatrixClient::onSyncResponse(QNetworkReply *reply)
|
||||
}
|
||||
|
||||
void
|
||||
MatrixClient::onSendTextMessageResponse(QNetworkReply *reply)
|
||||
MatrixClient::onSendRoomMessage(QNetworkReply *reply)
|
||||
{
|
||||
reply->deleteLater();
|
||||
|
||||
@ -445,8 +447,8 @@ MatrixClient::onResponse(QNetworkReply *reply)
|
||||
case Endpoint::Sync:
|
||||
onSyncResponse(reply);
|
||||
break;
|
||||
case Endpoint::SendTextMessage:
|
||||
onSendTextMessageResponse(reply);
|
||||
case Endpoint::SendRoomMessage:
|
||||
onSendRoomMessage(reply);
|
||||
break;
|
||||
case Endpoint::RoomAvatar:
|
||||
onRoomAvatarResponse(reply);
|
||||
@ -522,7 +524,8 @@ MatrixClient::registerUser(const QString &user, const QString &pass, const QStri
|
||||
void
|
||||
MatrixClient::sync() noexcept
|
||||
{
|
||||
QJsonObject filter{ { "room", QJsonObject{ { "ephemeral", QJsonObject{ { "limit", 0 } } } } },
|
||||
QJsonObject filter{ { "room",
|
||||
QJsonObject{ { "ephemeral", QJsonObject{ { "limit", 0 } } } } },
|
||||
{ "presence", QJsonObject{ { "limit", 0 } } } };
|
||||
|
||||
QUrlQuery query;
|
||||
@ -532,7 +535,8 @@ MatrixClient::sync() noexcept
|
||||
query.addQueryItem("access_token", token_);
|
||||
|
||||
if (next_batch_.isEmpty()) {
|
||||
qDebug() << "Sync requires a valid next_batch token. Initial sync should be performed.";
|
||||
qDebug()
|
||||
<< "Sync requires a valid next_batch token. Initial sync should be performed.";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -549,23 +553,39 @@ MatrixClient::sync() noexcept
|
||||
}
|
||||
|
||||
void
|
||||
MatrixClient::sendTextMessage(const QString &roomid, const QString &msg) noexcept
|
||||
MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty,
|
||||
const QString &roomid,
|
||||
const QString &msg) noexcept
|
||||
{
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("access_token", token_);
|
||||
|
||||
QUrl endpoint(server_);
|
||||
endpoint.setPath(api_url_ + QString("/rooms/%1/send/m.room.message/%2").arg(roomid).arg(txn_id_));
|
||||
endpoint.setPath(api_url_ +
|
||||
QString("/rooms/%1/send/m.room.message/%2").arg(roomid).arg(txn_id_));
|
||||
endpoint.setQuery(query);
|
||||
|
||||
QJsonObject body{ { "msgtype", "m.text" }, { "body", msg } };
|
||||
QString msgType("");
|
||||
|
||||
switch (ty) {
|
||||
case matrix::events::MessageEventType::Text:
|
||||
msgType = "m.text";
|
||||
break;
|
||||
case matrix::events::MessageEventType::Emote:
|
||||
msgType = "m.emote";
|
||||
break;
|
||||
default:
|
||||
msgType = "m.text";
|
||||
break;
|
||||
}
|
||||
|
||||
QJsonObject body{ { "msgtype", msgType }, { "body", msg } };
|
||||
|
||||
QNetworkRequest request(QString(endpoint.toEncoded()));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QNetworkReply *reply = put(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||
|
||||
reply->setProperty("endpoint", static_cast<int>(Endpoint::SendTextMessage));
|
||||
reply->setProperty("endpoint", static_cast<int>(Endpoint::SendRoomMessage));
|
||||
reply->setProperty("txn_id", txn_id_);
|
||||
reply->setProperty("roomid", roomid);
|
||||
|
||||
@ -615,7 +635,8 @@ MatrixClient::versions() noexcept
|
||||
void
|
||||
MatrixClient::getOwnProfile() noexcept
|
||||
{
|
||||
// FIXME: Remove settings from the matrix client. The class should store the user's matrix ID.
|
||||
// FIXME: Remove settings from the matrix client. The class should store the user's matrix
|
||||
// ID.
|
||||
QSettings settings;
|
||||
auto userid = settings.value("auth/user_id", "").toString();
|
||||
|
||||
@ -647,7 +668,8 @@ MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url)
|
||||
query.addQueryItem("height", "512");
|
||||
query.addQueryItem("method", "crop");
|
||||
|
||||
QString media_url = QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||
QString media_url =
|
||||
QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||
|
||||
QUrl endpoint(media_url);
|
||||
endpoint.setQuery(query);
|
||||
@ -674,7 +696,8 @@ MatrixClient::fetchUserAvatar(const QString &userId, const QUrl &avatarUrl)
|
||||
query.addQueryItem("height", "128");
|
||||
query.addQueryItem("method", "crop");
|
||||
|
||||
QString media_url = QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||
QString media_url =
|
||||
QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||
|
||||
QUrl endpoint(media_url);
|
||||
endpoint.setQuery(query);
|
||||
@ -711,7 +734,8 @@ MatrixClient::fetchOwnAvatar(const QUrl &avatar_url)
|
||||
query.addQueryItem("height", "512");
|
||||
query.addQueryItem("method", "crop");
|
||||
|
||||
QString media_url = QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||
QString media_url =
|
||||
QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||
|
||||
QUrl endpoint(media_url);
|
||||
endpoint.setQuery(query);
|
||||
|
@ -39,7 +39,7 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event)
|
||||
}
|
||||
|
||||
TextInputWidget::TextInputWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
setFont(QFont("Emoji One"));
|
||||
|
||||
@ -72,7 +72,8 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
||||
send_message_button_->setForegroundColor(QColor("#acc7dc"));
|
||||
|
||||
QIcon send_message_icon;
|
||||
send_message_icon.addFile(":/icons/icons/share-dark.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||
send_message_icon.addFile(
|
||||
":/icons/icons/share-dark.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||
send_message_button_->setIcon(send_message_icon);
|
||||
send_message_button_->setIconSize(QSize(24, 24));
|
||||
|
||||
@ -93,7 +94,10 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
||||
|
||||
connect(send_message_button_, SIGNAL(clicked()), this, SLOT(onSendButtonClicked()));
|
||||
connect(input_, SIGNAL(enterPressed()), send_message_button_, SIGNAL(clicked()));
|
||||
connect(emoji_button_, SIGNAL(emojiSelected(const QString &)), this, SLOT(addSelectedEmoji(const QString &)));
|
||||
connect(emoji_button_,
|
||||
SIGNAL(emojiSelected(const QString &)),
|
||||
this,
|
||||
SLOT(addSelectedEmoji(const QString &)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -123,26 +127,32 @@ TextInputWidget::addSelectedEmoji(const QString &emoji)
|
||||
void
|
||||
TextInputWidget::onSendButtonClicked()
|
||||
{
|
||||
auto msg_text = input_->document()->toPlainText().trimmed();
|
||||
auto msgText = input_->document()->toPlainText().trimmed();
|
||||
|
||||
if (msg_text.isEmpty())
|
||||
if (msgText.isEmpty())
|
||||
return;
|
||||
|
||||
emit sendTextMessage(msg_text);
|
||||
if (msgText.startsWith(EMOTE_COMMAND)) {
|
||||
auto text = parseEmoteCommand(msgText);
|
||||
|
||||
if (!text.isEmpty())
|
||||
emit sendEmoteMessage(text);
|
||||
} else {
|
||||
emit sendTextMessage(msgText);
|
||||
}
|
||||
|
||||
input_->clear();
|
||||
}
|
||||
|
||||
void
|
||||
TextInputWidget::paintEvent(QPaintEvent *event)
|
||||
QString
|
||||
TextInputWidget::parseEmoteCommand(const QString &cmd)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
auto text = cmd.right(cmd.size() - EMOTE_COMMAND.size()).trimmed();
|
||||
|
||||
QStyleOption option;
|
||||
option.initFrom(this);
|
||||
if (!text.isEmpty())
|
||||
return text;
|
||||
|
||||
QPainter painter(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
|
||||
return QString("");
|
||||
}
|
||||
|
||||
TextInputWidget::~TextInputWidget()
|
||||
|
@ -67,46 +67,42 @@ TimelineItem::init()
|
||||
}
|
||||
|
||||
/*
|
||||
* For messages created locally. The avatar and the username are displayed.
|
||||
* For messages created locally.
|
||||
*/
|
||||
TimelineItem::TimelineItem(const QString &userid, QString body, QWidget *parent)
|
||||
TimelineItem::TimelineItem(events::MessageEventType ty,
|
||||
const QString &userid,
|
||||
QString body,
|
||||
bool withSender,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
init();
|
||||
descriptionMsg_ = { "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime()) };
|
||||
|
||||
auto displayName = TimelineViewManager::displayName(userid);
|
||||
auto timestamp = QDateTime::currentDateTime();
|
||||
|
||||
if (ty == events::MessageEventType::Emote) {
|
||||
body = QString("* %1 %2").arg(displayName).arg(body);
|
||||
descriptionMsg_ = { "", userid, body, descriptiveTime(timestamp) };
|
||||
} else {
|
||||
descriptionMsg_ = {
|
||||
"You: ", userid, body, descriptiveTime(QDateTime::currentDateTime())
|
||||
};
|
||||
}
|
||||
|
||||
body.replace(URL_REGEX, URL_HTML);
|
||||
auto displayName = TimelineViewManager::displayName(userid);
|
||||
generateTimestamp(timestamp);
|
||||
|
||||
generateTimestamp(QDateTime::currentDateTime());
|
||||
if (withSender) {
|
||||
generateBody(displayName, body);
|
||||
|
||||
setupAvatarLayout(displayName);
|
||||
|
||||
mainLayout_->addLayout(headerLayout_);
|
||||
mainLayout_->addWidget(body_);
|
||||
|
||||
AvatarProvider::resolve(userid, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* For messages created locally. Only the text is displayed.
|
||||
*/
|
||||
TimelineItem::TimelineItem(QString body, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QSettings settings;
|
||||
auto userid = settings.value("auth/user_id").toString();
|
||||
|
||||
init();
|
||||
descriptionMsg_ = { "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime()) };
|
||||
|
||||
body.replace(URL_REGEX, URL_HTML);
|
||||
|
||||
generateTimestamp(QDateTime::currentDateTime());
|
||||
} else {
|
||||
generateBody(body);
|
||||
|
||||
setupSimpleLayout();
|
||||
}
|
||||
|
||||
mainLayout_->addWidget(body_);
|
||||
}
|
||||
|
@ -289,7 +289,10 @@ TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection dire
|
||||
|
||||
eventIds_[emote.eventId()] = true;
|
||||
|
||||
// TODO Check if it's a message waiting for validation
|
||||
if (isPendingMessage(emote, local_user_)) {
|
||||
removePendingMessage(emote);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto with_sender = isSenderRendered(emote.sender(), direction);
|
||||
|
||||
@ -452,55 +455,19 @@ TimelineView::updatePendingMessage(int txn_id, QString event_id)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineView::isPendingMessage(const events::MessageEvent<msgs::Text> &e,
|
||||
const QString &local_userid)
|
||||
{
|
||||
if (e.sender() != local_userid)
|
||||
return false;
|
||||
|
||||
for (const auto &msg : pending_msgs_) {
|
||||
if (msg.event_id == e.eventId() || msg.body == e.content().body())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineView::removePendingMessage(const events::MessageEvent<msgs::Text> &e)
|
||||
{
|
||||
for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); it++) {
|
||||
int index = std::distance(pending_msgs_.begin(), it);
|
||||
|
||||
if (it->event_id == e.eventId() || it->body == e.content().body()) {
|
||||
pending_msgs_.removeAt(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimelineView::addUserTextMessage(const QString &body, int txn_id)
|
||||
TimelineView::addUserMessage(matrix::events::MessageEventType ty, const QString &body, int txn_id)
|
||||
{
|
||||
QSettings settings;
|
||||
auto user_id = settings.value("auth/user_id").toString();
|
||||
|
||||
auto with_sender = lastSender_ != user_id;
|
||||
|
||||
TimelineItem *view_item;
|
||||
|
||||
if (with_sender)
|
||||
view_item = new TimelineItem(user_id, body, scroll_widget_);
|
||||
else
|
||||
view_item = new TimelineItem(body, scroll_widget_);
|
||||
|
||||
TimelineItem *view_item = new TimelineItem(ty, user_id, body, with_sender, scroll_widget_);
|
||||
scroll_layout_->addWidget(view_item);
|
||||
|
||||
lastSender_ = user_id;
|
||||
|
||||
PendingMessage message(txn_id, body, "", view_item);
|
||||
|
||||
pending_msgs_.push_back(message);
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,8 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<MatrixClient> client, QW
|
||||
{
|
||||
setStyleSheet("QWidget { background: #f8fbfe; color: #e8e8e8; border: none;}");
|
||||
|
||||
connect(client_.data(),
|
||||
SIGNAL(messageSent(const QString &, const QString &, int)),
|
||||
this,
|
||||
SLOT(messageSent(const QString &, const QString &, int)));
|
||||
connect(
|
||||
client_.data(), &MatrixClient::messageSent, this, &TimelineViewManager::messageSent);
|
||||
}
|
||||
|
||||
TimelineViewManager::~TimelineViewManager()
|
||||
@ -59,8 +57,19 @@ TimelineViewManager::sendTextMessage(const QString &msg)
|
||||
auto room_id = active_room_;
|
||||
auto view = views_[room_id];
|
||||
|
||||
view->addUserTextMessage(msg, client_->transactionId());
|
||||
client_->sendTextMessage(room_id, msg);
|
||||
view->addUserMessage(matrix::events::MessageEventType::Text, msg, client_->transactionId());
|
||||
client_->sendRoomMessage(matrix::events::MessageEventType::Text, room_id, msg);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineViewManager::sendEmoteMessage(const QString &msg)
|
||||
{
|
||||
auto room_id = active_room_;
|
||||
auto view = views_[room_id];
|
||||
|
||||
view->addUserMessage(
|
||||
matrix::events::MessageEventType::Emote, msg, client_->transactionId());
|
||||
client_->sendRoomMessage(matrix::events::MessageEventType::Emote, room_id, msg);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user