diff --git a/include/MatrixClient.h b/include/MatrixClient.h
index c20d02cc..58b24f9b 100644
--- a/include/MatrixClient.h
+++ b/include/MatrixClient.h
@@ -19,6 +19,7 @@
#include <QtNetwork/QNetworkAccessManager>
+#include "MessageEvent.h"
#include "Profile.h"
#include "RoomMessages.h"
#include "Sync.h"
@@ -29,145 +30,152 @@
*/
class MatrixClient : public QNetworkAccessManager
{
- Q_OBJECT
+ Q_OBJECT
public:
- MatrixClient(QString server, QObject *parent = 0);
+ MatrixClient(QString server, QObject *parent = 0);
- // Client API.
- void initialSync() noexcept;
- void sync() noexcept;
- void sendTextMessage(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 versions() noexcept;
- void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
- void fetchUserAvatar(const QString &userId, const QUrl &avatarUrl);
- void fetchOwnAvatar(const QUrl &avatar_url);
- void downloadImage(const QString &event_id, const QUrl &url);
- void messages(const QString &room_id, const QString &from_token, int limit = 20) noexcept;
+ // Client API.
+ void initialSync() noexcept;
+ void sync() 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 versions() noexcept;
+ void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
+ void fetchUserAvatar(const QString &userId, const QUrl &avatarUrl);
+ void fetchOwnAvatar(const QUrl &avatar_url);
+ void downloadImage(const QString &event_id, const QUrl &url);
+ void messages(const QString &room_id, const QString &from_token, int limit = 20) noexcept;
- inline QUrl getHomeServer();
- inline int transactionId();
- inline void incrementTransactionId();
+ inline QUrl getHomeServer();
+ inline int transactionId();
+ inline void incrementTransactionId();
- void reset() noexcept;
+ void reset() noexcept;
public slots:
- void getOwnProfile() noexcept;
- void logout() noexcept;
+ void getOwnProfile() noexcept;
+ void logout() noexcept;
- inline void setServer(const QString &server);
- inline void setAccessToken(const QString &token);
- inline void setNextBatchToken(const QString &next_batch);
+ inline void setServer(const QString &server);
+ inline void setAccessToken(const QString &token);
+ inline void setNextBatchToken(const QString &next_batch);
signals:
- void loginError(const QString &error);
- void registerError(const QString &error);
- void versionError(const QString &error);
+ void loginError(const QString &error);
+ void registerError(const QString &error);
+ void versionError(const QString &error);
- void loggedOut();
+ 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 versionSuccess();
+ void loginSuccess(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);
- void userAvatarRetrieved(const QString &userId, const QImage &img);
- void ownAvatarRetrieved(const QPixmap &img);
- void imageDownloaded(const QString &event_id, const QPixmap &img);
+ void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
+ void userAvatarRetrieved(const QString &userId, const QImage &img);
+ void ownAvatarRetrieved(const QPixmap &img);
+ void imageDownloaded(const QString &event_id, const QPixmap &img);
- // Returned profile data for the user's account.
- void getOwnProfileResponse(const QUrl &avatar_url, const QString &display_name);
- void initialSyncCompleted(const SyncResponse &response);
- void syncCompleted(const SyncResponse &response);
- void syncFailed(const QString &msg);
- void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
- void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
+ // Returned profile data for the user's account.
+ void getOwnProfileResponse(const QUrl &avatar_url, const QString &display_name);
+ void initialSyncCompleted(const SyncResponse &response);
+ 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:
- void onResponse(QNetworkReply *reply);
+ void onResponse(QNetworkReply *reply);
private:
- enum class Endpoint {
- GetOwnAvatar,
- GetOwnProfile,
- GetProfile,
- Image,
- InitialSync,
- Login,
- Logout,
- Messages,
- Register,
- RoomAvatar,
- UserAvatar,
- SendTextMessage,
- Sync,
- Versions,
- };
+ enum class Endpoint {
+ GetOwnAvatar,
+ GetOwnProfile,
+ GetProfile,
+ Image,
+ InitialSync,
+ Login,
+ Logout,
+ Messages,
+ Register,
+ RoomAvatar,
+ SendRoomMessage,
+ Sync,
+ UserAvatar,
+ Versions,
+ };
- // Response handlers.
- 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);
+ // 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 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_;
+ // Client API prefix.
+ QString api_url_;
- // The Matrix server used for communication.
- QUrl server_;
+ // The Matrix server used for communication.
+ QUrl server_;
- // The access token used for authentication.
- QString token_;
+ // The access token used for authentication.
+ QString token_;
- // Increasing transaction ID.
- int txn_id_;
+ // Increasing transaction ID.
+ int txn_id_;
- // Token to be used for the next sync.
- QString next_batch_;
+ // Token to be used for the next sync.
+ QString next_batch_;
};
inline QUrl
MatrixClient::getHomeServer()
{
- return server_;
+ return server_;
}
inline int
MatrixClient::transactionId()
{
- return txn_id_;
+ return txn_id_;
}
inline void
MatrixClient::setServer(const QString &server)
{
- server_ = QUrl(QString("https://%1").arg(server));
+ server_ = QUrl(QString("https://%1").arg(server));
}
inline void
MatrixClient::setAccessToken(const QString &token)
{
- token_ = token;
+ token_ = token;
}
inline void
MatrixClient::setNextBatchToken(const QString &next_batch)
{
- next_batch_ = next_batch;
+ next_batch_ = next_batch;
}
inline void
MatrixClient::incrementTransactionId()
{
- txn_id_ += 1;
+ txn_id_ += 1;
}
diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h
index 690a899b..73c2a603 100644
--- a/include/TextInputWidget.h
+++ b/include/TextInputWidget.h
@@ -25,49 +25,51 @@
#include "EmojiPickButton.h"
#include "FlatButton.h"
+static const QString EMOTE_COMMAND("/me ");
+
class FilteredTextEdit : public QTextEdit
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit FilteredTextEdit(QWidget *parent = nullptr);
- void keyPressEvent(QKeyEvent *event);
+ explicit FilteredTextEdit(QWidget *parent = nullptr);
+ void keyPressEvent(QKeyEvent *event);
signals:
- void enterPressed();
+ void enterPressed();
};
-class TextInputWidget : public QWidget
+class TextInputWidget : public QFrame
{
- Q_OBJECT
+ Q_OBJECT
public:
- TextInputWidget(QWidget *parent = 0);
- ~TextInputWidget();
+ TextInputWidget(QWidget *parent = 0);
+ ~TextInputWidget();
public slots:
- void onSendButtonClicked();
- inline void focusLineEdit();
+ void onSendButtonClicked();
+ inline void focusLineEdit();
private slots:
- void addSelectedEmoji(const QString &emoji);
+ void addSelectedEmoji(const QString &emoji);
signals:
- void sendTextMessage(QString msg);
-
-protected:
- void paintEvent(QPaintEvent *event) override;
+ void sendTextMessage(QString msg);
+ void sendEmoteMessage(QString msg);
private:
- QHBoxLayout *top_layout_;
- FilteredTextEdit *input_;
+ QString parseEmoteCommand(const QString &cmd);
+
+ QHBoxLayout *top_layout_;
+ FilteredTextEdit *input_;
- FlatButton *send_file_button_;
- FlatButton *send_message_button_;
- EmojiPickButton *emoji_button_;
+ FlatButton *send_file_button_;
+ FlatButton *send_message_button_;
+ EmojiPickButton *emoji_button_;
};
inline void
TextInputWidget::focusLineEdit()
{
- input_->setFocus();
+ input_->setFocus();
}
diff --git a/include/TimelineItem.h b/include/TimelineItem.h
index 59c79d50..edc15dab 100644
--- a/include/TimelineItem.h
+++ b/include/TimelineItem.h
@@ -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,
diff --git a/include/TimelineView.h b/include/TimelineView.h
index 7583e4c2..3ecf8ba7 100644
--- a/include/TimelineView.h
+++ b/include/TimelineView.h
@@ -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;
+ }
+ }
+}
diff --git a/include/TimelineViewManager.h b/include/TimelineViewManager.h
index 85e186dc..d3ca198e 100644
--- a/include/TimelineViewManager.h
+++ b/include/TimelineViewManager.h
@@ -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);
|