Implemented sending of typing notifications (#105)

pull/1/head
Thomas Herzog 7 years ago committed by mujx
parent 91b8427795
commit 287b5aa4c0
  1. 6
      include/ChatPage.h
  2. 2
      include/MatrixClient.h
  3. 13
      include/TextInputWidget.h
  4. 29
      src/ChatPage.cc
  5. 50
      src/MatrixClient.cc
  6. 36
      src/TextInputWidget.cc

@ -45,8 +45,9 @@ class UserInfoWidget;
class JoinedRoom; class JoinedRoom;
class LeftRoom; class LeftRoom;
constexpr int CONSENSUS_TIMEOUT = 1000; constexpr int CONSENSUS_TIMEOUT = 1000;
constexpr int SHOW_CONTENT_TIMEOUT = 3000; constexpr int SHOW_CONTENT_TIMEOUT = 3000;
constexpr int TYPING_REFRESH_TIMEOUT = 10000;
class ChatPage : public QWidget class ChatPage : public QWidget
{ {
@ -141,6 +142,7 @@ private:
// Keeps track of the users currently typing on each room. // Keeps track of the users currently typing on each room.
QMap<QString, QList<QString>> typingUsers_; QMap<QString, QList<QString>> typingUsers_;
QTimer *typingRefresher_;
QSharedPointer<QuickSwitcher> quickSwitcher_; QSharedPointer<QuickSwitcher> quickSwitcher_;
QSharedPointer<OverlayModal> quickSwitcherModal_; QSharedPointer<OverlayModal> quickSwitcherModal_;

@ -56,6 +56,8 @@ public:
void uploadImage(const QString &roomid, const QString &filename); void uploadImage(const QString &roomid, const QString &filename);
void joinRoom(const QString &roomIdOrAlias); void joinRoom(const QString &roomIdOrAlias);
void leaveRoom(const QString &roomId); void leaveRoom(const QString &roomId);
void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000);
void removeTypingNotification(const QString &roomid);
QUrl getHomeServer() { return server_; }; QUrl getHomeServer() { return server_; };
int transactionId() { return txn_id_; }; int transactionId() { return txn_id_; };

@ -35,12 +35,20 @@ static const QString JOIN_COMMAND("/join ");
class FilteredTextEdit : public QTextEdit class FilteredTextEdit : public QTextEdit
{ {
Q_OBJECT Q_OBJECT
private:
QTimer *typingTimer_;
public: public:
explicit FilteredTextEdit(QWidget *parent = nullptr); explicit FilteredTextEdit(QWidget *parent = nullptr);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
void stopTyping();
signals: signals:
void enterPressed(); void enterPressed();
void startedTyping();
void stoppedTyping();
}; };
class TextInputWidget : public QFrame class TextInputWidget : public QFrame
@ -51,6 +59,8 @@ public:
TextInputWidget(QWidget *parent = 0); TextInputWidget(QWidget *parent = 0);
~TextInputWidget(); ~TextInputWidget();
void stopTyping();
public slots: public slots:
void onSendButtonClicked(); void onSendButtonClicked();
void openFileSelection(); void openFileSelection();
@ -66,6 +76,9 @@ signals:
void uploadImage(QString filename); void uploadImage(QString filename);
void sendJoinRoomRequest(const QString &room); void sendJoinRoomRequest(const QString &room);
void startedTyping();
void stoppedTyping();
private: private:
void showUploadSpinner(); void showUploadSpinner();
QString parseEmoteCommand(const QString &cmd); QString parseEmoteCommand(const QString &cmd);

@ -122,6 +122,9 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
contentLayout_->addWidget(typingDisplay_); contentLayout_->addWidget(typingDisplay_);
contentLayout_->addWidget(text_input_); contentLayout_->addWidget(text_input_);
typingRefresher_ = new QTimer(this);
typingRefresher_->setInterval(TYPING_REFRESH_TIMEOUT);
user_info_widget_ = new UserInfoWidget(sideBarTopWidget_); user_info_widget_ = new UserInfoWidget(sideBarTopWidget_);
sideBarTopWidgetLayout_->addWidget(user_info_widget_); sideBarTopWidgetLayout_->addWidget(user_info_widget_);
@ -139,6 +142,7 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
typingDisplay_->setUsers(users); 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, this, &ChatPage::changeTopRoomInfo);
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit); 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); 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_, connect(view_manager_,
&TimelineViewManager::updateRoomsLastMessage, &TimelineViewManager::updateRoomsLastMessage,
room_list_, room_list_,
@ -600,13 +618,20 @@ ChatPage::updateTypingUsers(const QString &roomid, const QList<QString> &user_id
{ {
QStringList users; 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.append(TimelineViewManager::displayName(uid));
}
users.sort(); users.sort();
if (current_room_ == roomid) if (current_room_ == roomid) {
typingDisplay_->setUsers(users); typingDisplay_->setUsers(users);
}
typingUsers_.insert(roomid, users); typingUsers_.insert(roomid, users);
} }

@ -794,3 +794,53 @@ MatrixClient::leaveRoom(const QString &roomId)
emit leftRoom(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));
}

@ -29,15 +29,37 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent)
: QTextEdit(parent) : QTextEdit(parent)
{ {
setAcceptRichText(false); setAcceptRichText(false);
typingTimer_ = new QTimer(this);
typingTimer_->setInterval(1000);
typingTimer_->setSingleShot(true);
connect(typingTimer_, &QTimer::timeout, this, &FilteredTextEdit::stopTyping);
} }
void void
FilteredTextEdit::keyPressEvent(QKeyEvent *event) 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(); emit enterPressed();
else } else {
QTextEdit::keyPressEvent(event); QTextEdit::keyPressEvent(event);
}
}
void
FilteredTextEdit::stopTyping()
{
typingTimer_->stop();
emit stoppedTyping();
} }
TextInputWidget::TextInputWidget(QWidget *parent) TextInputWidget::TextInputWidget(QWidget *parent)
@ -104,6 +126,10 @@ TextInputWidget::TextInputWidget(QWidget *parent)
SIGNAL(emojiSelected(const QString &)), SIGNAL(emojiSelected(const QString &)),
this, this,
SLOT(addSelectedEmoji(const QString &))); SLOT(addSelectedEmoji(const QString &)));
connect(input_, &FilteredTextEdit::startedTyping, this, &TextInputWidget::startedTyping);
connect(input_, &FilteredTextEdit::stoppedTyping, this, &TextInputWidget::stoppedTyping);
} }
void void
@ -227,3 +253,9 @@ TextInputWidget::hideUploadSpinner()
} }
TextInputWidget::~TextInputWidget() {} TextInputWidget::~TextInputWidget() {}
void
TextInputWidget::stopTyping()
{
input_->stopTyping();
}

Loading…
Cancel
Save