summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Herzog <thomas.herzog@mail.com>2017-10-31 19:11:49 +0100
committermujx <mujx@users.noreply.github.com>2017-10-31 20:11:49 +0200
commit287b5aa4c0d52e1ac80a0785ab136aa0f98b3e9f (patch)
tree8535d6ec3717ba551b17fc70f0cc80306273e82c
parent91b8427795db943694333e5a9e56fae42c61d4b0 (diff)
Implemented sending of typing notifications (#105)
-rw-r--r--include/ChatPage.h6
-rw-r--r--include/MatrixClient.h2
-rw-r--r--include/TextInputWidget.h13
-rw-r--r--src/ChatPage.cc29
-rw-r--r--src/MatrixClient.cc50
-rw-r--r--src/TextInputWidget.cc36
6 files changed, 130 insertions, 6 deletions
diff --git a/include/ChatPage.h b/include/ChatPage.h
index 416f7870..849d60e7 100644
--- a/include/ChatPage.h
+++ b/include/ChatPage.h
@@ -45,8 +45,9 @@ class UserInfoWidget;
class JoinedRoom;
class LeftRoom;
-constexpr int CONSENSUS_TIMEOUT = 1000;
-constexpr int SHOW_CONTENT_TIMEOUT = 3000;
+constexpr int CONSENSUS_TIMEOUT = 1000;
+constexpr int SHOW_CONTENT_TIMEOUT = 3000;
+constexpr int TYPING_REFRESH_TIMEOUT = 10000;
class ChatPage : public QWidget
{
@@ -141,6 +142,7 @@ private:
// Keeps track of the users currently typing on each room.
QMap<QString, QList<QString>> typingUsers_;
+ QTimer *typingRefresher_;
QSharedPointer<QuickSwitcher> quickSwitcher_;
QSharedPointer<OverlayModal> quickSwitcherModal_;
diff --git a/include/MatrixClient.h b/include/MatrixClient.h
index ef9e82e6..d6dd7162 100644
--- a/include/MatrixClient.h
+++ b/include/MatrixClient.h
@@ -56,6 +56,8 @@ public:
void uploadImage(const QString &roomid, const QString &filename);
void joinRoom(const QString &roomIdOrAlias);
void leaveRoom(const QString &roomId);
+ void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000);
+ void removeTypingNotification(const QString &roomid);
QUrl getHomeServer() { return server_; };
int transactionId() { return txn_id_; };
diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h
index 08b62f45..e32ce2ff 100644
--- a/include/TextInputWidget.h
+++ b/include/TextInputWidget.h
@@ -35,12 +35,20 @@ static const QString JOIN_COMMAND("/join ");
class FilteredTextEdit : public QTextEdit
{
Q_OBJECT
+
+private:
+ QTimer *typingTimer_;
+
public:
explicit FilteredTextEdit(QWidget *parent = nullptr);
void keyPressEvent(QKeyEvent *event);
+ void stopTyping();
+
signals:
void enterPressed();
+ void startedTyping();
+ void stoppedTyping();
};
class TextInputWidget : public QFrame
@@ -51,6 +59,8 @@ public:
TextInputWidget(QWidget *parent = 0);
~TextInputWidget();
+ void stopTyping();
+
public slots:
void onSendButtonClicked();
void openFileSelection();
@@ -66,6 +76,9 @@ signals:
void uploadImage(QString filename);
void sendJoinRoomRequest(const QString &room);
+ void startedTyping();
+ void stoppedTyping();
+
private:
void showUploadSpinner();
QString parseEmoteCommand(const QString &cmd);
diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index 5fefd767..d81b64fb 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -122,6 +122,9 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
contentLayout_->addWidget(typingDisplay_);
contentLayout_->addWidget(text_input_);
+ typingRefresher_ = new QTimer(this);
+ typingRefresher_->setInterval(TYPING_REFRESH_TIMEOUT);
+
user_info_widget_ = new UserInfoWidget(sideBarTopWidget_);
sideBarTopWidgetLayout_->addWidget(user_info_widget_);
@@ -139,6 +142,7 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
typingDisplay_->setUsers(users);
});
+ connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::stopTyping);
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
@@ -159,6 +163,20 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
room_list_->updateUnreadMessageCount(roomid, count);
});
+ connect(text_input_, &TextInputWidget::startedTyping, this, [=]() {
+ typingRefresher_->start();
+ client_->sendTypingNotification(current_room_);
+ });
+
+ connect(text_input_, &TextInputWidget::stoppedTyping, this, [=]() {
+ typingRefresher_->stop();
+ client_->removeTypingNotification(current_room_);
+ });
+
+ connect(typingRefresher_, &QTimer::timeout, this, [=]() {
+ client_->sendTypingNotification(current_room_);
+ });
+
connect(view_manager_,
&TimelineViewManager::updateRoomsLastMessage,
room_list_,
@@ -600,13 +618,20 @@ ChatPage::updateTypingUsers(const QString &roomid, const QList<QString> &user_id
{
QStringList users;
- for (const auto uid : user_ids)
+ QSettings settings;
+ QString user_id = settings.value("auth/user_id").toString();
+
+ for (const auto uid : user_ids) {
+ if (uid == user_id)
+ continue;
users.append(TimelineViewManager::displayName(uid));
+ }
users.sort();
- if (current_room_ == roomid)
+ if (current_room_ == roomid) {
typingDisplay_->setUsers(users);
+ }
typingUsers_.insert(roomid, users);
}
diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc
index e1085e82..c6ef501f 100644
--- a/src/MatrixClient.cc
+++ b/src/MatrixClient.cc
@@ -794,3 +794,53 @@ MatrixClient::leaveRoom(const QString &roomId)
emit leftRoom(roomId);
});
}
+
+void
+MatrixClient::sendTypingNotification(const QString &roomid, int timeoutInMillis)
+{
+ QSettings settings;
+ QString user_id = settings.value("auth/user_id").toString();
+
+ QUrlQuery query;
+ query.addQueryItem("access_token", token_);
+
+ QUrl endpoint(server_);
+ endpoint.setPath(clientApiUrl_ + QString("/rooms/%1/typing/%2").arg(roomid).arg(user_id));
+
+ endpoint.setQuery(query);
+
+ QString msgType("");
+ QJsonObject body;
+
+ body = { { "typing", true }, { "timeout", timeoutInMillis } };
+
+ QNetworkRequest request(QString(endpoint.toEncoded()));
+ request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
+
+ put(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
+}
+
+void
+MatrixClient::removeTypingNotification(const QString &roomid)
+{
+ QSettings settings;
+ QString user_id = settings.value("auth/user_id").toString();
+
+ QUrlQuery query;
+ query.addQueryItem("access_token", token_);
+
+ QUrl endpoint(server_);
+ endpoint.setPath(clientApiUrl_ + QString("/rooms/%1/typing/%2").arg(roomid).arg(user_id));
+
+ endpoint.setQuery(query);
+
+ QString msgType("");
+ QJsonObject body;
+
+ body = { { "typing", false } };
+
+ QNetworkRequest request(QString(endpoint.toEncoded()));
+ request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
+
+ put(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
+}
diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc
index 0d5e1102..7ebef6b1 100644
--- a/src/TextInputWidget.cc
+++ b/src/TextInputWidget.cc
@@ -29,15 +29,37 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent)
: QTextEdit(parent)
{
setAcceptRichText(false);
+
+ typingTimer_ = new QTimer(this);
+ typingTimer_->setInterval(1000);
+ typingTimer_->setSingleShot(true);
+
+ connect(typingTimer_, &QTimer::timeout, this, &FilteredTextEdit::stopTyping);
}
void
FilteredTextEdit::keyPressEvent(QKeyEvent *event)
{
- if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
+ if (!typingTimer_->isActive()) {
+ emit startedTyping();
+ }
+
+ typingTimer_->start();
+
+ if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
+ stopTyping();
+
emit enterPressed();
- else
+ } else {
QTextEdit::keyPressEvent(event);
+ }
+}
+
+void
+FilteredTextEdit::stopTyping()
+{
+ typingTimer_->stop();
+ emit stoppedTyping();
}
TextInputWidget::TextInputWidget(QWidget *parent)
@@ -104,6 +126,10 @@ TextInputWidget::TextInputWidget(QWidget *parent)
SIGNAL(emojiSelected(const QString &)),
this,
SLOT(addSelectedEmoji(const QString &)));
+
+ connect(input_, &FilteredTextEdit::startedTyping, this, &TextInputWidget::startedTyping);
+
+ connect(input_, &FilteredTextEdit::stoppedTyping, this, &TextInputWidget::stoppedTyping);
}
void
@@ -227,3 +253,9 @@ TextInputWidget::hideUploadSpinner()
}
TextInputWidget::~TextInputWidget() {}
+
+void
+TextInputWidget::stopTyping()
+{
+ input_->stopTyping();
+}