summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-01-17 01:25:14 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2020-01-17 01:25:14 +0100
commitfe912240bc1ab89b8a20ce87d5183f328f704d23 (patch)
treefd86e16977dc068c8ad404dc4ede4eb6640374de /src
parentRemove embedded fonts (diff)
downloadnheko-fe912240bc1ab89b8a20ce87d5183f328f704d23.tar.xz
Move typing display to qml
Diffstat (limited to 'src')
-rw-r--r--src/ChatPage.cpp53
-rw-r--r--src/ChatPage.h9
-rw-r--r--src/TypingDisplay.cpp86
-rw-r--r--src/TypingDisplay.h36
-rw-r--r--src/timeline/TimelineModel.cpp30
-rw-r--r--src/timeline/TimelineModel.h13
-rw-r--r--src/timeline/TimelineViewManager.cpp18
7 files changed, 58 insertions, 187 deletions
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp

index 777709be..125e229a 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp
@@ -34,7 +34,6 @@ #include "Splitter.h" #include "TextInputWidget.h" #include "TopRoomBar.h" -#include "TypingDisplay.h" #include "UserInfoWidget.h" #include "UserSettingsPage.h" #include "Utils.h" @@ -130,11 +129,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent) text_input_ = new TextInputWidget(this); contentLayout_->addWidget(text_input_); - typingDisplay_ = new TypingDisplay(content_); - typingDisplay_->hide(); - connect( - text_input_, &TextInputWidget::heightChanged, typingDisplay_, &TypingDisplay::setOffset); - typingRefresher_ = new QTimer(this); typingRefresher_->setInterval(TYPING_REFRESH_TIMEOUT); @@ -225,19 +219,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent) } }); - connect(room_list_, &RoomList::roomChanged, this, [this](const QString &roomid) { - QStringList users; - - if (!userSettings_->isTypingNotificationsEnabled()) { - typingDisplay_->setUsers(users); - return; - } - - if (typingUsers_.find(roomid) != typingUsers_.end()) - users = typingUsers_[roomid]; - - 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, splitter, &Splitter::showChatView); @@ -472,8 +453,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent) bool hasNotifications = false; for (const auto &room : rooms.join) { auto room_id = QString::fromStdString(room.first); - - updateTypingUsers(room_id, room.second.ephemeral.typing); updateRoomNotificationCount( room_id, room.second.unread_notifications.notification_count, @@ -787,38 +766,6 @@ ChatPage::removeRoom(const QString &room_id) } void -ChatPage::updateTypingUsers(const QString &roomid, const std::vector<std::string> &user_ids) -{ - if (!userSettings_->isTypingNotificationsEnabled()) - return; - - typingUsers_[roomid] = generateTypingUsers(roomid, user_ids); - - if (current_room_ == roomid) - typingDisplay_->setUsers(typingUsers_[roomid]); -} - -QStringList -ChatPage::generateTypingUsers(const QString &room_id, const std::vector<std::string> &typing_users) -{ - QStringList users; - auto local_user = utils::localUser(); - - for (const auto &uid : typing_users) { - const auto remote_user = QString::fromStdString(uid); - - if (remote_user == local_user) - continue; - - users.append(cache::displayName(room_id, remote_user)); - } - - users.sort(); - - return users; -} - -void ChatPage::removeLeftRooms(const std::map<std::string, mtx::responses::LeftRoom> &rooms) { for (auto it = rooms.cbegin(); it != rooms.cend(); ++it) { diff --git a/src/ChatPage.h b/src/ChatPage.h
index e4c0ef16..354a21f3 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h
@@ -48,7 +48,6 @@ class Splitter; class TextInputWidget; class TimelineViewManager; class TopRoomBar; -class TypingDisplay; class UserInfoWidget; class UserSettings; class NotificationsManager; @@ -187,8 +186,6 @@ private: using LeftRooms = std::map<std::string, mtx::responses::LeftRoom>; void removeLeftRooms(const LeftRooms &rooms); - void updateTypingUsers(const QString &roomid, const std::vector<std::string> &user_ids); - void loadStateFromCache(); void resetUI(); //! Decides whether or not to hide the group's sidebar. @@ -206,9 +203,6 @@ private: void showNotificationsDialog(const QPoint &point); - QStringList generateTypingUsers(const QString &room_id, - const std::vector<std::string> &typing_users); - QHBoxLayout *topLayout_; Splitter *splitter; @@ -228,7 +222,6 @@ private: TopRoomBar *top_bar_; TextInputWidget *text_input_; - TypingDisplay *typingDisplay_; QTimer connectivityTimer_; std::atomic_bool isConnected_; @@ -240,8 +233,6 @@ private: popups::UserMentions *user_mentions_popup_; - // Keeps track of the users currently typing on each room. - std::map<QString, QList<QString>> typingUsers_; QTimer *typingRefresher_; // Global user settings. diff --git a/src/TypingDisplay.cpp b/src/TypingDisplay.cpp deleted file mode 100644
index 43fabcd8..00000000 --- a/src/TypingDisplay.cpp +++ /dev/null
@@ -1,86 +0,0 @@ -#include <QDebug> -#include <QPainter> -#include <QPoint> -#include <QShowEvent> -#include <QtGlobal> - -#include "Config.h" -#include "TypingDisplay.h" -#include "ui/Painter.h" - -constexpr int LEFT_PADDING = 24; -constexpr int RECT_PADDING = 2; - -TypingDisplay::TypingDisplay(QWidget *parent) - : OverlayWidget(parent) - , offset_{conf::textInput::height} -{ - setFixedHeight(QFontMetrics(font()).height() + RECT_PADDING); - setAttribute(Qt::WA_TransparentForMouseEvents); -} - -void -TypingDisplay::setOffset(int margin) -{ - offset_ = margin; - move(0, parentWidget()->height() - offset_ - height()); -} - -void -TypingDisplay::setUsers(const QStringList &uid) -{ - move(0, parentWidget()->height() - offset_ - height()); - - text_.clear(); - - QString temp = text_ += - tr("%1 and %2 are typing", - "Multiple users are typing. First argument is a comma separated list of potentially " - "multiple users. Second argument is the last user of that list. (If only one user is " - "typing, %1 is empty. You should still use it in your string though to silence Qt " - "warnings.)", - uid.size()); - - if (uid.isEmpty()) { - hide(); - update(); - - return; - } - - QStringList uidWithoutLast = uid; - uidWithoutLast.pop_back(); - text_ = temp.arg(uidWithoutLast.join(", ")).arg(uid.back()); - - show(); - update(); -} - -void -TypingDisplay::paintEvent(QPaintEvent *) -{ - Painter p(this); - PainterHighQualityEnabler hq(p); - - QFont f; - f.setPointSizeF(f.pointSizeF() * 0.9); - - p.setFont(f); - p.setPen(QPen(textColor())); - - QRect region = rect(); - region.translate(LEFT_PADDING, 0); - - QFontMetrics fm(f); - text_ = fm.elidedText(text_, Qt::ElideRight, (double)(width() * 0.75)); - - QPainterPath path; -#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) - path.addRoundedRect(QRectF(0, 0, fm.width(text_) + 2 * LEFT_PADDING, height()), 3, 3); -#else - path.addRoundedRect( - QRectF(0, 0, fm.horizontalAdvance(text_) + 2 * LEFT_PADDING, height()), 3, 3); -#endif - p.fillPath(path, backgroundColor()); - p.drawText(region, Qt::AlignVCenter, text_); -} diff --git a/src/TypingDisplay.h b/src/TypingDisplay.h deleted file mode 100644
index 332d9c66..00000000 --- a/src/TypingDisplay.h +++ /dev/null
@@ -1,36 +0,0 @@ -#pragma once - -#include "ui/OverlayWidget.h" - -class QPaintEvent; - -class TypingDisplay : public OverlayWidget -{ - Q_OBJECT - - Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor) - Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) - -public: - TypingDisplay(QWidget *parent = nullptr); - - void setUsers(const QStringList &user_ids); - - void setTextColor(const QColor &color) { textColor_ = color; }; - QColor textColor() const { return textColor_; }; - - void setBackgroundColor(const QColor &color) { bgColor_ = color; }; - QColor backgroundColor() const { return bgColor_; }; - -public slots: - void setOffset(int margin); - -protected: - void paintEvent(QPaintEvent *event) override; - -private: - int offset_; - QColor textColor_; - QColor bgColor_; - QString text_; -}; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 08c29927..2fd4b6d4 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp
@@ -1388,3 +1388,33 @@ TimelineModel::cacheMedia(QString eventId) emit mediaCached(mxcUrl, filename.filePath()); }); } + +QString +TimelineModel::formatTypingUsers(const std::vector<QString> &users, QColor bg) +{ + QString temp = + tr("%1 and %2 are typing", + "Multiple users are typing. First argument is a comma separated list of potentially " + "multiple users. Second argument is the last user of that list. (If only one user is " + "typing, %1 is empty. You should still use it in your string though to silence Qt " + "warnings.)", + users.size()); + + if (users.empty()) { + return ""; + } + + QStringList uidWithoutLast; + + auto formatUser = [this, bg](const QString &user_id) -> QString { + return QString("<font color=\"%1\">%2</font>") + .arg(userColor(user_id, bg).name()) + .arg(escapeEmoji(displayName(user_id).toHtmlEscaped())); + }; + + for (size_t i = 0; i + 1 < users.size(); i++) { + uidWithoutLast.append(formatUser(users[i])); + } + + return temp.arg(uidWithoutLast.join(", ")).arg(formatUser(users.back())); +} diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index ae505c17..6d351359 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h
@@ -120,6 +120,8 @@ class TimelineModel : public QAbstractListModel Q_OBJECT Q_PROPERTY( int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY + typingUsersChanged) public: explicit TimelineModel(TimelineViewManager *manager, QString room_id, QObject *parent = 0); @@ -162,6 +164,7 @@ public: Q_INVOKABLE QString displayName(QString id) const; Q_INVOKABLE QString avatarUrl(QString id) const; Q_INVOKABLE QString formatDateSeparator(QDate date) const; + Q_INVOKABLE QString formatTypingUsers(const std::vector<QString> &users, QColor bg); Q_INVOKABLE QString escapeEmoji(QString str) const; Q_INVOKABLE void viewRawMessage(QString id) const; @@ -183,6 +186,14 @@ public slots: int currentIndex() const { return idToIndex(currentId); } void markEventsAsRead(const std::vector<QString> &event_ids); QVariantMap getDump(QString eventId) const; + void updateTypingUsers(const std::vector<QString> &users) + { + if (this->typingUsers_ != users) { + this->typingUsers_ = users; + emit typingUsersChanged(typingUsers_); + } + } + std::vector<QString> typingUsers() const { return typingUsers_; } private slots: // Add old events at the top of the timeline. @@ -202,6 +213,7 @@ signals: void mediaCached(QString mxcUrl, QString cacheUrl); void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo); void replyFetched(QString requestingEvent, mtx::events::collections::TimelineEvents event); + void typingUsersChanged(std::vector<QString> users); private: DecryptionResult decryptEvent( @@ -232,6 +244,7 @@ private: QHash<QString, QColor> userColors; QString currentId; + std::vector<QString> typingUsers_; TimelineViewManager *manager_; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index ddbc6af8..c7a4e50e 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp
@@ -8,6 +8,7 @@ #include "ColorImageProvider.h" #include "DelegateChooser.h" #include "Logging.h" +#include "MatrixClient.h" #include "MxcImageProvider.h" #include "UserSettingsPage.h" #include "dialogs/ImageOverlay.h" @@ -92,10 +93,21 @@ TimelineViewManager::TimelineViewManager(QWidget *parent) void TimelineViewManager::sync(const mtx::responses::Rooms &rooms) { - for (auto it = rooms.join.cbegin(); it != rooms.join.cend(); ++it) { + for (const auto &[room_id, room] : rooms.join) { // addRoom will only add the room, if it doesn't exist - addRoom(QString::fromStdString(it->first)); - models.value(QString::fromStdString(it->first))->addEvents(it->second.timeline); + addRoom(QString::fromStdString(room_id)); + const auto &room_model = models.value(QString::fromStdString(room_id)); + room_model->addEvents(room.timeline); + + if (ChatPage::instance()->userSettings()->isTypingNotificationsEnabled()) { + std::vector<QString> typing; + typing.reserve(room.ephemeral.typing.size()); + for (const auto &user : room.ephemeral.typing) { + if (user != http::client()->user_id().to_string()) + typing.push_back(QString::fromStdString(user)); + } + room_model->updateTypingUsers(typing); + } } this->isInitialSync_ = false;