summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2017-10-04 11:33:34 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2017-10-04 11:33:34 +0300
commitd60c2b76e30dcbdb1eae2a69b2d3ddff128d00c5 (patch)
treeb54dfe5e789c3f42ce8ef26f988a2f30ab62ad4c /src
parentRecover from corrupted cache data (diff)
downloadnheko-d60c2b76e30dcbdb1eae2a69b2d3ddff128d00c5.tar.xz
Receive typing notifications (#88)
Diffstat (limited to 'src')
-rw-r--r--src/ChatPage.cc31
-rw-r--r--src/MatrixClient.cc5
-rw-r--r--src/Sync.cc16
-rw-r--r--src/TextInputWidget.cc16
-rw-r--r--src/TypingDisplay.cc56
5 files changed, 113 insertions, 11 deletions
diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index 9f983b9f..52468f64 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -101,8 +101,10 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
         view_manager_ = new TimelineViewManager(client, this);
         mainContentLayout_->addWidget(view_manager_);
 
-        text_input_ = new TextInputWidget(this);
+        text_input_    = new TextInputWidget(this);
+        typingDisplay_ = new TypingDisplay(this);
         contentLayout_->addWidget(text_input_);
+        contentLayout_->addWidget(typingDisplay_);
 
         user_info_widget_ = new UserInfoWidget(sideBarTopWidget_);
         sideBarTopWidgetLayout_->addWidget(user_info_widget_);
@@ -117,6 +119,15 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
         connect(
           top_bar_, &TopRoomBar::leaveRoom, this, [=]() { client_->leaveRoom(current_room_); });
 
+        connect(room_list_, &RoomList::roomChanged, this, [=](const QString &roomid) {
+                QStringList users;
+
+                if (typingUsers_.contains(roomid))
+                        users = typingUsers_[roomid];
+
+                typingDisplay_->setUsers(users);
+        });
+
         connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
         connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
         connect(
@@ -308,6 +319,8 @@ ChatPage::syncCompleted(const SyncResponse &response)
         auto joined = response.rooms().join();
 
         for (auto it = joined.constBegin(); it != joined.constEnd(); it++) {
+                updateTypingUsers(it.key(), it.value().typingUserIDs());
+
                 RoomState room_state;
 
                 // Merge the new updates for rooms that we are tracking.
@@ -620,6 +633,22 @@ ChatPage::removeRoom(const QString &room_id)
         room_list_->removeRoom(room_id, room_id == current_room_);
 }
 
+void
+ChatPage::updateTypingUsers(const QString &roomid, const QList<QString> &user_ids)
+{
+        QStringList users;
+
+        for (const auto uid : user_ids)
+                users.append(TimelineViewManager::displayName(uid));
+
+        users.sort();
+
+        if (current_room_ == roomid)
+                typingDisplay_->setUsers(users);
+
+        typingUsers_.insert(roomid, users);
+}
+
 ChatPage::~ChatPage()
 {
         sync_timer_->stop();
diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc
index bd43efd8..265b51ce 100644
--- a/src/MatrixClient.cc
+++ b/src/MatrixClient.cc
@@ -611,8 +611,9 @@ void
 MatrixClient::sync() noexcept
 {
         QJsonObject filter{ { "room",
-                              QJsonObject{ { "include_leave", true },
-                                           { "ephemeral", QJsonObject{ { "limit", 0 } } } } },
+                              QJsonObject{
+                                { "include_leave", true },
+                              } },
                             { "presence", QJsonObject{ { "limit", 0 } } } };
 
         QUrlQuery query;
diff --git a/src/Sync.cc b/src/Sync.cc
index 90314352..39d84acb 100644
--- a/src/Sync.cc
+++ b/src/Sync.cc
@@ -168,7 +168,21 @@ JoinedRoom::deserialize(const QJsonValue &data)
                         if (!ephemeral.value("events").isArray())
                                 qWarning() << "join/ephemeral/events should be an array";
 
-                        // TODO: Implement ephemeral handling
+                        auto ephemeralEvents = ephemeral.value("events").toArray();
+
+                        for (const auto e : ephemeralEvents) {
+                                auto obj = e.toObject();
+
+                                if (obj.contains("type") && obj.value("type") == "m.typing") {
+                                        auto ids = obj.value("content")
+                                                     .toObject()
+                                                     .value("user_ids")
+                                                     .toArray();
+
+                                        for (const auto uid : ids)
+                                                typingUserIDs_.push_back(uid.toString());
+                                }
+                        }
                 }
         }
 
diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc
index 5f06d992..4d5f4d5f 100644
--- a/src/TextInputWidget.cc
+++ b/src/TextInputWidget.cc
@@ -45,13 +45,14 @@ TextInputWidget::TextInputWidget(QWidget *parent)
 {
         setFont(QFont("Emoji One"));
 
+        setFixedHeight(45);
         setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
         setCursor(Qt::ArrowCursor);
-        setStyleSheet("background-color: #fff; height: 45px;");
+        setStyleSheet("background-color: #fff;");
 
         topLayout_ = new QHBoxLayout();
-        topLayout_->setSpacing(2);
-        topLayout_->setMargin(4);
+        topLayout_->setSpacing(0);
+        topLayout_->setContentsMargins(5, 15, 0, 5);
 
         QIcon send_file_icon;
         send_file_icon.addFile(":/icons/icons/clip-dark.png", QSize(), QIcon::Normal, QIcon::Off);
@@ -63,18 +64,19 @@ TextInputWidget::TextInputWidget(QWidget *parent)
 
         spinner_ = new LoadingIndicator(this);
         spinner_->setColor("#acc7dc");
-        spinner_->setFixedHeight(40);
-        spinner_->setFixedWidth(40);
+        spinner_->setFixedHeight(32);
+        spinner_->setFixedWidth(32);
         spinner_->hide();
 
         QFont font;
         font.setPixelSize(conf::fontSize);
 
         input_ = new FilteredTextEdit(this);
-        input_->setFixedHeight(45);
+        input_->setFixedHeight(32);
         input_->setFont(font);
+        input_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
         input_->setPlaceholderText(tr("Write a message..."));
-        input_->setStyleSheet("color: #333333; border-radius: 0; padding-top: 10px;");
+        input_->setStyleSheet("color: #333333; border: none; margin: 0 5px");
 
         sendMessageBtn_ = new FlatButton(this);
         sendMessageBtn_->setForegroundColor(QColor("#acc7dc"));
diff --git a/src/TypingDisplay.cc b/src/TypingDisplay.cc
new file mode 100644
index 00000000..619b70cb
--- /dev/null
+++ b/src/TypingDisplay.cc
@@ -0,0 +1,56 @@
+#include <QDebug>
+#include <QPainter>
+#include <QPoint>
+
+#include "Config.h"
+#include "TypingDisplay.h"
+
+TypingDisplay::TypingDisplay(QWidget *parent)
+  : QWidget(parent)
+  , leftPadding_{ 57 }
+{
+        QFont font;
+        font.setPixelSize(conf::typingNotificationFontSize);
+
+        setFixedHeight(QFontMetrics(font).height() + 2);
+}
+
+void
+TypingDisplay::setUsers(const QStringList &uid)
+{
+        if (uid.isEmpty())
+                text_.clear();
+        else
+                text_ = uid.join(", ");
+
+        if (uid.size() == 1)
+                text_ += tr(" is typing ...");
+        else if (uid.size() > 1)
+                text_ += tr(" are typing ...");
+
+        update();
+}
+
+void
+TypingDisplay::paintEvent(QPaintEvent *)
+{
+        QPen pen(QColor("#333"));
+
+        QFont font;
+        font.setPixelSize(conf::typingNotificationFontSize);
+        font.setWeight(40);
+        font.setItalic(true);
+
+        QPainter p(this);
+        p.setRenderHint(QPainter::Antialiasing);
+        p.setFont(font);
+        p.setPen(pen);
+
+        QRect region = rect();
+        region.translate(leftPadding_, 0);
+
+        QFontMetrics fm(font);
+        text_ = fm.elidedText(text_, Qt::ElideRight, width() - 3 * leftPadding_);
+
+        p.drawText(region, Qt::AlignTop, text_);
+}