diff --git a/src/AvatarProvider.cpp b/src/AvatarProvider.cpp
index 57b61c750139e2879b2c077dd4a1a1ac0b073a91..277a403059b06612eb6a2377a8270f6bfabf7fa2 100644
--- a/src/AvatarProvider.cpp
+++ b/src/AvatarProvider.cpp
@@ -16,30 +16,44 @@
  */
 
 #include <QBuffer>
+#include <QPixmapCache>
 #include <memory>
+#include <unordered_map>
 
 #include "AvatarProvider.h"
 #include "Cache.h"
 #include "Logging.h"
 #include "MatrixClient.h"
 
-namespace AvatarProvider {
+static QPixmapCache avatar_cache;
 
+namespace AvatarProvider {
 void
-resolve(const QString &room_id, const QString &user_id, QObject *receiver, AvatarCallback callback)
+resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback callback)
 {
-        const auto key       = QString("%1 %2").arg(room_id).arg(user_id);
-        const auto avatarUrl = Cache::avatarUrl(room_id, user_id);
+        avatar_cache.setCacheLimit(1024 * 1024);
 
-        if (!Cache::AvatarUrls.contains(key) || !cache::client())
+        const auto cacheKey = avatarUrl + "_size_" + size;
+
+        if (!cache::client())
                 return;
 
         if (avatarUrl.isEmpty())
                 return;
 
+        QPixmap pixmap;
+        if (avatar_cache.find(cacheKey, pixmap)) {
+                nhlog::net()->info("cached pixmap {}", avatarUrl.toStdString());
+                callback(pixmap);
+                return;
+        }
+
         auto data = cache::client()->image(avatarUrl);
         if (!data.isNull()) {
-                callback(QImage::fromData(data));
+                pixmap.loadFromData(data);
+                avatar_cache.insert(cacheKey, pixmap);
+                nhlog::net()->info("loaded pixmap from disk cache {}", avatarUrl.toStdString());
+                callback(pixmap);
                 return;
         }
 
@@ -47,7 +61,12 @@ resolve(const QString &room_id, const QString &user_id, QObject *receiver, Avata
         QObject::connect(proxy.get(),
                          &AvatarProxy::avatarDownloaded,
                          receiver,
-                         [callback](const QByteArray &data) { callback(QImage::fromData(data)); });
+                         [callback, cacheKey](const QByteArray &data) {
+                                 QPixmap pm;
+                                 pm.loadFromData(data);
+                                 avatar_cache.insert(cacheKey, pm);
+                                 callback(pm);
+                         });
 
         mtx::http::ThumbOpts opts;
         opts.width   = 256;
@@ -67,8 +86,26 @@ resolve(const QString &room_id, const QString &user_id, QObject *receiver, Avata
 
                   cache::client()->saveImage(opts.mxc_url, res);
 
-                  auto data = QByteArray(res.data(), res.size());
-                  emit proxy->avatarDownloaded(data);
+                  nhlog::net()->info("downloaded pixmap {}", opts.mxc_url);
+
+                  emit proxy->avatarDownloaded(QByteArray(res.data(), res.size()));
           });
 }
+
+void
+resolve(const QString &room_id,
+        const QString &user_id,
+        int size,
+        QObject *receiver,
+        AvatarCallback callback)
+{
+        const auto key       = QString("%1 %2").arg(room_id).arg(user_id);
+        const auto avatarUrl = Cache::avatarUrl(room_id, user_id);
+        const auto cacheKey  = avatarUrl + "_size_" + size;
+
+        if (!Cache::AvatarUrls.contains(key) || !cache::client())
+                return;
+
+        resolve(avatarUrl, size, receiver, callback);
+}
 }
diff --git a/src/AvatarProvider.h b/src/AvatarProvider.h
index 4b4e15e9d228aef2ed214a4b8e3e0e486fef01b3..47ed028ee1c92cf1aa678c1eabe9a5fd047dbf8d 100644
--- a/src/AvatarProvider.h
+++ b/src/AvatarProvider.h
@@ -17,7 +17,7 @@
 
 #pragma once
 
-#include <QImage>
+#include <QPixmap>
 #include <functional>
 
 class AvatarProxy : public QObject
@@ -28,9 +28,15 @@ signals:
         void avatarDownloaded(const QByteArray &data);
 };
 
-using AvatarCallback = std::function<void(QImage)>;
+using AvatarCallback = std::function<void(QPixmap)>;
 
 namespace AvatarProvider {
 void
-resolve(const QString &room_id, const QString &user_id, QObject *receiver, AvatarCallback cb);
+resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback cb);
+void
+resolve(const QString &room_id,
+        const QString &user_id,
+        int size,
+        QObject *receiver,
+        AvatarCallback cb);
 }
diff --git a/src/Cache.cpp b/src/Cache.cpp
index ef0f951e480532e8c29097d0b51c060fa5f31fde..083dbe8920c54cb1d6dec146b757cd41803da74e 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -1830,10 +1830,7 @@ Cache::searchRooms(const std::string &query, std::uint8_t max_items)
 
         std::vector<RoomSearchResult> results;
         for (auto it = items.begin(); it != end; it++) {
-                results.push_back(
-                  RoomSearchResult{it->second.first,
-                                   it->second.second,
-                                   QImage::fromData(image(txn, it->second.second.avatar_url))});
+                results.push_back(RoomSearchResult{it->second.first, it->second.second});
         }
 
         txn.commit();
diff --git a/src/Cache.h b/src/Cache.h
index 302bb65b9d3e4d071d4cbd7b5327cf9a8fd60b4a..0da49793995bc5b3e4c600bef4a0e3c7b6a701bf 100644
--- a/src/Cache.h
+++ b/src/Cache.h
@@ -153,7 +153,6 @@ struct RoomSearchResult
 {
         std::string room_id;
         RoomInfo info;
-        QImage img;
 };
 
 Q_DECLARE_METATYPE(RoomSearchResult)
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 2ed64b6bb192c5a98ad11f475ebfef9d8ff26464..21ded4b3af4bccf43ead05cf19bd660a2a106618 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -774,12 +774,12 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
 }
 
 void
-ChatPage::updateTopBarAvatar(const QString &roomid, const QPixmap &img)
+ChatPage::updateTopBarAvatar(const QString &roomid, const QString &img)
 {
         if (current_room_ != roomid)
                 return;
 
-        top_bar_->updateRoomAvatar(img.toImage());
+        top_bar_->updateRoomAvatar(img);
 }
 
 void
@@ -807,7 +807,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id)
                 if (img.isNull())
                         top_bar_->updateRoomAvatarFromName(name);
                 else
-                        top_bar_->updateRoomAvatar(img);
+                        top_bar_->updateRoomAvatar(avatar_url);
 
         } catch (const lmdb::error &e) {
                 nhlog::ui()->error("failed to change top bar room info: {}", e.what());
@@ -1337,37 +1337,7 @@ ChatPage::getProfileInfo()
 
                   emit setUserDisplayName(QString::fromStdString(res.display_name));
 
-                  if (cache::client()) {
-                          auto data = cache::client()->image(res.avatar_url);
-                          if (!data.isNull()) {
-                                  emit setUserAvatar(QImage::fromData(data));
-                                  return;
-                          }
-                  }
-
-                  if (res.avatar_url.empty())
-                          return;
-
-                  http::client()->download(
-                    res.avatar_url,
-                    [this, res](const std::string &data,
-                                const std::string &,
-                                const std::string &,
-                                mtx::http::RequestErr err) {
-                            if (err) {
-                                    nhlog::net()->warn(
-                                      "failed to download user avatar: {} - {}",
-                                      mtx::errors::to_string(err->matrix_error.errcode),
-                                      err->matrix_error.error);
-                                    return;
-                            }
-
-                            if (cache::client())
-                                    cache::client()->saveImage(res.avatar_url, data);
-
-                            emit setUserAvatar(
-                              QImage::fromData(QByteArray(data.data(), data.size())));
-                    });
+                  emit setUserAvatar(QString::fromStdString(res.avatar_url));
           });
 
         http::client()->joined_groups(
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 189af387db1e9b70b9ce31e65da3057ba431fc87..e41ae1ae4ac97fb72b1dad96e9db12360335a2fd 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -129,7 +129,7 @@ signals:
 
         void ownProfileOk();
         void setUserDisplayName(const QString &name);
-        void setUserAvatar(const QImage &avatar);
+        void setUserAvatar(const QString &avatar);
         void loggedOut();
 
         void trySyncCb();
@@ -159,7 +159,7 @@ signals:
 
 private slots:
         void showUnreadMessageNotification(int count);
-        void updateTopBarAvatar(const QString &roomid, const QPixmap &img);
+        void updateTopBarAvatar(const QString &roomid, const QString &img);
         void changeTopRoomInfo(const QString &room_id);
         void logout();
         void removeRoom(const QString &room_id);
diff --git a/src/Logging.cpp b/src/Logging.cpp
index 686274d8a828d564399b521aa8ebd31e1c6b6886..322875826f05af709140ec76288f4e5f7b1e3f4c 100644
--- a/src/Logging.cpp
+++ b/src/Logging.cpp
@@ -16,6 +16,8 @@ constexpr auto MAX_LOG_FILES = 3;
 }
 
 namespace nhlog {
+bool enable_debug_log_from_commandline = false;
+
 void
 init(const std::string &file_path)
 {
diff --git a/src/Logging.h b/src/Logging.h
index 2feae60d75ba6d7d40aa3d60a6ef5e815bf36260..e54f3c3f3b861062858bac8118b6669ab4108372 100644
--- a/src/Logging.h
+++ b/src/Logging.h
@@ -18,4 +18,6 @@ db();
 
 std::shared_ptr<spdlog::logger>
 crypto();
+
+extern bool enable_debug_log_from_commandline;
 }
diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp
index 9bcce1347e55e5ce884a3c445e72430c51244d4c..dbcd6806ffdcbc2131776de448f3caed30c61c23 100644
--- a/src/RoomInfoListItem.cpp
+++ b/src/RoomInfoListItem.cpp
@@ -21,6 +21,7 @@
 #include <QPainter>
 #include <QtGlobal>
 
+#include "AvatarProvider.h"
 #include "Cache.h"
 #include "Config.h"
 #include "RoomInfoListItem.h"
@@ -434,10 +435,12 @@ RoomInfoListItem::mousePressEvent(QMouseEvent *event)
 }
 
 void
-RoomInfoListItem::setAvatar(const QImage &img)
+RoomInfoListItem::setAvatar(const QString &avatar_url)
 {
-        roomAvatar_ = utils::scaleImageToPixmap(img, IconSize);
-        update();
+        AvatarProvider::resolve(avatar_url, IconSize, this, [this](const QPixmap &img) {
+                roomAvatar_ = img;
+                update();
+        });
 }
 
 void
diff --git a/src/RoomInfoListItem.h b/src/RoomInfoListItem.h
index 40c938c11e54f4204806c0a30e888e1734752474..54e02a7637ab410d366719588706ce6cbf93dc1b 100644
--- a/src/RoomInfoListItem.h
+++ b/src/RoomInfoListItem.h
@@ -73,7 +73,7 @@ public:
         bool isPressed() const { return isPressed_; }
         int unreadMessageCount() const { return unreadMsgCount_; }
 
-        void setAvatar(const QImage &avatar_image);
+        void setAvatar(const QString &avatar_url);
         void setDescriptionMessage(const DescInfo &info);
         DescInfo lastMessageInfo() const { return lastMsgInfo_; }
 
diff --git a/src/RoomList.cpp b/src/RoomList.cpp
index 1abf35336bf3b22317b09d9ec706b04047c1ce84..c5e056214335d76224a8b95ef45d401f9df44a02 100644
--- a/src/RoomList.cpp
+++ b/src/RoomList.cpp
@@ -89,40 +89,7 @@ RoomList::updateAvatar(const QString &room_id, const QString &url)
         if (url.isEmpty())
                 return;
 
-        QByteArray savedImgData;
-
-        if (cache::client())
-                savedImgData = cache::client()->image(url);
-
-        if (savedImgData.isEmpty()) {
-                mtx::http::ThumbOpts opts;
-                opts.mxc_url = url.toStdString();
-                http::client()->get_thumbnail(
-                  opts, [room_id, opts, this](const std::string &res, mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::net()->warn(
-                                    "failed to download room avatar: {} {} {}",
-                                    opts.mxc_url,
-                                    mtx::errors::to_string(err->matrix_error.errcode),
-                                    err->matrix_error.error);
-                                  return;
-                          }
-
-                          if (cache::client())
-                                  cache::client()->saveImage(opts.mxc_url, res);
-
-                          auto data = QByteArray(res.data(), res.size());
-                          QPixmap pixmap;
-                          pixmap.loadFromData(data);
-
-                          emit updateRoomAvatarCb(room_id, pixmap);
-                  });
-        } else {
-                QPixmap img;
-                img.loadFromData(savedImgData);
-
-                updateRoomAvatar(room_id, img);
-        }
+        emit updateRoomAvatarCb(room_id, url);
 }
 
 void
@@ -252,7 +219,7 @@ RoomList::highlightSelectedRoom(const QString &room_id)
 }
 
 void
-RoomList::updateRoomAvatar(const QString &roomid, const QPixmap &img)
+RoomList::updateRoomAvatar(const QString &roomid, const QString &img)
 {
         if (!roomExists(roomid)) {
                 nhlog::ui()->warn("avatar update on non-existent room_id: {}",
@@ -260,7 +227,7 @@ RoomList::updateRoomAvatar(const QString &roomid, const QPixmap &img)
                 return;
         }
 
-        rooms_[roomid]->setAvatar(img.toImage());
+        rooms_[roomid]->setAvatar(img);
 
         // Used to inform other widgets for the new image data.
         emit roomAvatarChanged(roomid, img);
diff --git a/src/RoomList.h b/src/RoomList.h
index 155a969c981571d26fe2d13a3d26aefdec9f3a84..95fc0d9b4451a6ddb6a76046d7d72bba25c8888f 100644
--- a/src/RoomList.h
+++ b/src/RoomList.h
@@ -61,12 +61,12 @@ signals:
         void totalUnreadMessageCountUpdated(int count);
         void acceptInvite(const QString &room_id);
         void declineInvite(const QString &room_id);
-        void roomAvatarChanged(const QString &room_id, const QPixmap &img);
+        void roomAvatarChanged(const QString &room_id, const QString &img);
         void joinRoom(const QString &room_id);
-        void updateRoomAvatarCb(const QString &room_id, const QPixmap &img);
+        void updateRoomAvatarCb(const QString &room_id, const QString &img);
 
 public slots:
-        void updateRoomAvatar(const QString &roomid, const QPixmap &img);
+        void updateRoomAvatar(const QString &roomid, const QString &img);
         void highlightSelectedRoom(const QString &room_id);
         void updateUnreadMessageCount(const QString &roomid, int count, int highlightedCount);
         void updateRoomDescription(const QString &roomid, const DescInfo &info);
diff --git a/src/TopRoomBar.cpp b/src/TopRoomBar.cpp
index a8049e3ad7b353fad6e6d8e1ad2ff4c3f4d6a0d7..712fe9aa1921c7787e8efb4aaaa7d4917496f0bd 100644
--- a/src/TopRoomBar.cpp
+++ b/src/TopRoomBar.cpp
@@ -46,9 +46,8 @@ TopRoomBar::TopRoomBar(QWidget *parent)
         topLayout_->setContentsMargins(
           2 * widgetMargin, widgetMargin, 2 * widgetMargin, widgetMargin);
 
-        avatar_ = new Avatar(this);
+        avatar_ = new Avatar(this, fontHeight * 2);
         avatar_->setLetter("");
-        avatar_->setSize(fontHeight * 2);
 
         textLayout_ = new QVBoxLayout();
         textLayout_->setSpacing(0);
@@ -183,7 +182,7 @@ TopRoomBar::reset()
 }
 
 void
-TopRoomBar::updateRoomAvatar(const QImage &avatar_image)
+TopRoomBar::updateRoomAvatar(const QString &avatar_image)
 {
         avatar_->setImage(avatar_image);
         update();
diff --git a/src/TopRoomBar.h b/src/TopRoomBar.h
index 5f2c936ea8b1af636e920021047b029652230916..3243064e843b4afccd95fbed89ac051c26264bfe 100644
--- a/src/TopRoomBar.h
+++ b/src/TopRoomBar.h
@@ -44,7 +44,7 @@ class TopRoomBar : public QWidget
 public:
         TopRoomBar(QWidget *parent = 0);
 
-        void updateRoomAvatar(const QImage &avatar_image);
+        void updateRoomAvatar(const QString &avatar_image);
         void updateRoomAvatar(const QIcon &icon);
         void updateRoomName(const QString &name);
         void updateRoomTopic(QString topic);
diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp
index 5345fb2a319415332ea895b1f77b157be4c4e0ab..19d7478e1d04c20e62f0643aae2da7eec531aeee 100644
--- a/src/UserInfoWidget.cpp
+++ b/src/UserInfoWidget.cpp
@@ -52,10 +52,9 @@ UserInfoWidget::UserInfoWidget(QWidget *parent)
         textLayout_->setSpacing(widgetMargin / 2);
         textLayout_->setContentsMargins(widgetMargin * 2, widgetMargin, widgetMargin, widgetMargin);
 
-        userAvatar_ = new Avatar(this);
+        userAvatar_ = new Avatar(this, fontHeight * 2.5);
         userAvatar_->setObjectName("userAvatar");
         userAvatar_->setLetter(QChar('?'));
-        userAvatar_->setSize(fontHeight * 2.5);
 
         QFont nameFont;
         nameFont.setPointSizeF(nameFont.pointSizeF() * 1.1);
@@ -134,14 +133,6 @@ UserInfoWidget::reset()
         userAvatar_->setLetter(QChar('?'));
 }
 
-void
-UserInfoWidget::setAvatar(const QImage &img)
-{
-        avatar_image_ = img;
-        userAvatar_->setImage(img);
-        update();
-}
-
 void
 UserInfoWidget::setDisplayName(const QString &name)
 {
@@ -160,6 +151,14 @@ UserInfoWidget::setUserId(const QString &userid)
 {
         user_id_ = userid;
         userIdLabel_->setText(userid);
+        update();
+}
+
+void
+UserInfoWidget::setAvatar(const QString &url)
+{
+        userAvatar_->setImage(url);
+        update();
 }
 
 void
diff --git a/src/UserInfoWidget.h b/src/UserInfoWidget.h
index 65de7be9202dadf18405ed5c69bbb3811fbd8285..263dd0c22823cc97746a65a19d133003e0c45739 100644
--- a/src/UserInfoWidget.h
+++ b/src/UserInfoWidget.h
@@ -33,9 +33,9 @@ class UserInfoWidget : public QWidget
 public:
         UserInfoWidget(QWidget *parent = 0);
 
-        void setAvatar(const QImage &img);
         void setDisplayName(const QString &name);
         void setUserId(const QString &userid);
+        void setAvatar(const QString &url);
 
         void reset();
 
diff --git a/src/dialogs/MemberList.cpp b/src/dialogs/MemberList.cpp
index 88a95403802ce2abd10b1bbeb12bbe51629b1d57..9e973efa5d715b032e2aa068b41f1faea990c5a6 100644
--- a/src/dialogs/MemberList.cpp
+++ b/src/dialogs/MemberList.cpp
@@ -9,7 +9,6 @@
 
 #include "dialogs/MemberList.h"
 
-#include "AvatarProvider.h"
 #include "Cache.h"
 #include "ChatPage.h"
 #include "Config.h"
@@ -28,17 +27,10 @@ MemberItem::MemberItem(const RoomMember &member, QWidget *parent)
         textLayout_->setMargin(0);
         textLayout_->setSpacing(0);
 
-        avatar_ = new Avatar(this);
-        avatar_->setSize(44);
+        avatar_ = new Avatar(this, 44);
         avatar_->setLetter(utils::firstChar(member.display_name));
 
-        if (!member.avatar.isNull())
-                avatar_->setImage(member.avatar);
-        else
-                AvatarProvider::resolve(ChatPage::instance()->currentRoom(),
-                                        member.user_id,
-                                        this,
-                                        [this](const QImage &img) { avatar_->setImage(img); });
+        avatar_->setImage(ChatPage::instance()->currentRoom(), member.user_id);
 
         QFont nameFont;
         nameFont.setPointSizeF(nameFont.pointSizeF() * 1.1);
diff --git a/src/dialogs/ReadReceipts.cpp b/src/dialogs/ReadReceipts.cpp
index 5a0d98c7843fc159ed4e75a938ae20c6d6fea34b..58ad59c3aacfe7a05c512c8986c04e1ef858cb3b 100644
--- a/src/dialogs/ReadReceipts.cpp
+++ b/src/dialogs/ReadReceipts.cpp
@@ -37,8 +37,7 @@ ReceiptItem::ReceiptItem(QWidget *parent,
 
         auto displayName = Cache::displayName(room_id, user_id);
 
-        avatar_ = new Avatar(this);
-        avatar_->setSize(44);
+        avatar_ = new Avatar(this, 44);
         avatar_->setLetter(utils::firstChar(displayName));
 
         // If it's a matrix id we use the second letter.
@@ -56,10 +55,7 @@ ReceiptItem::ReceiptItem(QWidget *parent,
         topLayout_->addWidget(avatar_);
         topLayout_->addLayout(textLayout_, 1);
 
-        AvatarProvider::resolve(ChatPage::instance()->currentRoom(),
-                                user_id,
-                                this,
-                                [this](const QImage &img) { avatar_->setImage(img); });
+        avatar_->setImage(ChatPage::instance()->currentRoom(), user_id);
 }
 
 void
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp
index 1fe5904bf4be7b9ae3a3c21b301033f972fdab7a..00b034ccd71f747d34d41b3efd6c3e03cf34719f 100644
--- a/src/dialogs/RoomSettings.cpp
+++ b/src/dialogs/RoomSettings.cpp
@@ -350,12 +350,12 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
                 keyRequestsToggle_->hide();
         }
 
-        avatar_ = new Avatar(this);
-        avatar_->setSize(128);
+        avatar_ = new Avatar(this, 128);
         if (avatarImg_.isNull())
                 avatar_->setLetter(utils::firstChar(QString::fromStdString(info_.name)));
         else
-                avatar_->setImage(avatarImg_);
+                avatar_->setImage(room_id_,
+                                  QString::fromStdString(http::client()->user_id().to_string()));
 
         if (canChangeAvatar(room_id_.toStdString(), utils::localUser().toStdString())) {
                 auto filter = new ClickableFilter(this);
@@ -487,7 +487,7 @@ RoomSettings::retrieveRoomInfo()
         try {
                 usesEncryption_ = cache::client()->isRoomEncrypted(room_id_.toStdString());
                 info_           = cache::client()->singleRoomInfo(room_id_.toStdString());
-                setAvatar(QImage::fromData(cache::client()->image(info_.avatar_url)));
+                setAvatar();
         } catch (const lmdb::error &e) {
                 nhlog::db()->warn("failed to retrieve room info from cache: {}",
                                   room_id_.toStdString());
@@ -633,14 +633,13 @@ RoomSettings::displayErrorMessage(const QString &msg)
 }
 
 void
-RoomSettings::setAvatar(const QImage &img)
+RoomSettings::setAvatar()
 {
         stopLoadingSpinner();
 
-        avatarImg_ = img;
-
         if (avatar_)
-                avatar_->setImage(img);
+                avatar_->setImage(room_id_,
+                                  QString::fromStdString(http::client()->user_id().to_string()));
 }
 
 void
@@ -733,7 +732,7 @@ RoomSettings::updateAvatar()
                                     return;
                             }
 
-                            emit proxy->avatarChanged(QImage::fromData(content));
+                            emit proxy->avatarChanged();
                     });
           });
 }
diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettings.h
index 6667b68b931b3895b6752c0815b2ee3e45c4ac43..e1807ba1ee924e04bd2222ef0af0dffc5f9e3b77 100644
--- a/src/dialogs/RoomSettings.h
+++ b/src/dialogs/RoomSettings.h
@@ -52,7 +52,7 @@ class ThreadProxy : public QObject
 
 signals:
         void error(const QString &msg);
-        void avatarChanged(const QImage &img);
+        void avatarChanged();
         void nameEventSent(const QString &);
         void topicEventSent();
 };
@@ -140,7 +140,7 @@ private:
         void resetErrorLabel();
         void displayErrorMessage(const QString &msg);
 
-        void setAvatar(const QImage &img);
+        void setAvatar();
         void setupEditButton();
         //! Retrieve the current room information from cache.
         void retrieveRoomInfo();
diff --git a/src/dialogs/UserProfile.cpp b/src/dialogs/UserProfile.cpp
index 6aea96a8cbd0a0b850baf313e2bd9df196a039cc..5ad3afa2eb731a0881d2d1194a9acebc664a950b 100644
--- a/src/dialogs/UserProfile.cpp
+++ b/src/dialogs/UserProfile.cpp
@@ -114,9 +114,8 @@ UserProfile::UserProfile(QWidget *parent)
         btnLayout->setSpacing(8);
         btnLayout->setMargin(0);
 
-        avatar_ = new Avatar(this);
+        avatar_ = new Avatar(this, 128);
         avatar_->setLetter("X");
-        avatar_->setSize(128);
 
         QFont font;
         font.setPointSizeF(font.pointSizeF() * 2);
@@ -210,8 +209,7 @@ UserProfile::init(const QString &userId, const QString &roomId)
         displayNameLabel_->setText(displayName);
         avatar_->setLetter(utils::firstChar(displayName));
 
-        AvatarProvider::resolve(
-          roomId, userId, this, [this](const QImage &img) { avatar_->setImage(img); });
+        avatar_->setImage(roomId, userId);
 
         auto localUser = utils::localUser();
 
diff --git a/src/popups/PopupItem.cpp b/src/popups/PopupItem.cpp
index f905983ad254e5e1c38defeb1a64a8e04fdeb951..c4d4327f43363337ecc91a0f54524bf27e35ec2d 100644
--- a/src/popups/PopupItem.cpp
+++ b/src/popups/PopupItem.cpp
@@ -11,7 +11,7 @@ constexpr int PopupItemMargin = 3;
 
 PopupItem::PopupItem(QWidget *parent)
   : QWidget(parent)
-  , avatar_{new Avatar(this)}
+  , avatar_{new Avatar(this, conf::popup::avatar)}
   , hovering_{false}
 {
         setMouseTracking(true);
@@ -40,7 +40,6 @@ UserItem::UserItem(QWidget *parent)
   : PopupItem(parent)
 {
         userName_ = new QLabel("Placeholder", this);
-        avatar_->setSize(conf::popup::avatar);
         avatar_->setLetter("P");
         topLayout_->addWidget(avatar_);
         topLayout_->addWidget(userName_, 1);
@@ -52,7 +51,6 @@ UserItem::UserItem(QWidget *parent, const QString &user_id)
 {
         auto displayName = Cache::displayName(ChatPage::instance()->currentRoom(), userId_);
 
-        avatar_->setSize(conf::popup::avatar);
         avatar_->setLetter(utils::firstChar(displayName));
 
         // If it's a matrix id we use the second letter.
@@ -87,16 +85,7 @@ UserItem::updateItem(const QString &user_id)
 void
 UserItem::resolveAvatar(const QString &user_id)
 {
-        AvatarProvider::resolve(
-          ChatPage::instance()->currentRoom(), userId_, this, [this, user_id](const QImage &img) {
-                  // The user on the widget when the avatar is resolved,
-                  // might be different from the user that made the call.
-                  if (user_id == userId_)
-                          avatar_->setImage(img);
-                  else
-                          // We try to resolve the avatar again.
-                          resolveAvatar(userId_);
-          });
+        avatar_->setImage(ChatPage::instance()->currentRoom(), user_id);
 }
 
 void
@@ -116,7 +105,6 @@ RoomItem::RoomItem(QWidget *parent, const RoomSearchResult &res)
         auto name = QFontMetrics(QFont()).elidedText(
           QString::fromStdString(res.info.name), Qt::ElideRight, parentWidget()->width() - 10);
 
-        avatar_->setSize(conf::popup::avatar + 6);
         avatar_->setLetter(utils::firstChar(name));
 
         roomName_ = new QLabel(name, this);
@@ -125,8 +113,7 @@ RoomItem::RoomItem(QWidget *parent, const RoomSearchResult &res)
         topLayout_->addWidget(avatar_);
         topLayout_->addWidget(roomName_, 1);
 
-        if (!res.img.isNull())
-                avatar_->setImage(res.img);
+        avatar_->setImage(QString::fromStdString(res.info.avatar_url));
 }
 
 void
@@ -141,10 +128,7 @@ RoomItem::updateItem(const RoomSearchResult &result)
 
         roomName_->setText(name);
 
-        if (!result.img.isNull())
-                avatar_->setImage(result.img);
-        else
-                avatar_->setLetter(utils::firstChar(name));
+        avatar_->setImage(QString::fromStdString(result.info.avatar_url));
 }
 
 void
@@ -154,4 +138,4 @@ RoomItem::mousePressEvent(QMouseEvent *event)
                 emit clicked(selectedText());
 
         QWidget::mousePressEvent(event);
-}
\ No newline at end of file
+}
diff --git a/src/timeline/.TimelineItem.cpp.swp b/src/timeline/.TimelineItem.cpp.swp
new file mode 100644
index 0000000000000000000000000000000000000000..75e03aebe8a2b20a05aec339ab9cab819ed7fe2e
--- /dev/null
+++ b/src/timeline/.TimelineItem.cpp.swp
@@ -0,0 +1,186 @@
+b0VIM 8.1������€c]7B[�'"��nicolas���������������������������������gentoo-neko�����������������������������~nicolas/Dokumente/devel/open-source/nheko/src/timeline/TimelineItem.cpp�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������utf-8
�3210����#"! U�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������tp�����������/����������������������������0�������1����������������������������a����������������������������x���������������������@�������~����������������������������¿��������������	��������������Ó����������������������������à���������������������;�������ö���������������������B�������0��������������������-�������s���������������������������Ÿ���������������������������¿��������������������I�������Á��������������������3�������	��������������������;�������=�������������
�������
+�������w��������������������<�������‚���������������������������¾���������������������������Ì���������������������������ß��������������������K�������ë���������������������������6�������������
+�������4�������M��������������������9�������‚���������������������������º�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ad��		��á	�����/�������ý��¸��µ��m��%��à��¹��¶��s��1��ð
����½
��x
��/
��+
��
��
��÷��Û��Â��±��Ÿ��‹��Š��t��`��K��3��"����ó��Ù��Ø��µ����f��>������õ
+��Ö
+��Õ
+��
+��d
+��c
+��á	��
+��C
+��
+��Ñ	��	��;	��9	��8	��3	��þ��ü��Ð��Ï��¬��d��*��)��à��Þ��Ý��Ø��­��«��x��`��_��F������þ��ý��ã��¸��Ž��w��m��?����ÿ��Ð��¢��‹����V��"������×��À��¶��´��³��®��x��v��^��]��D����é��Ò��¥��x��a��8����ù��Ð��¨��‘��g��G��0��&��%�������������}�        update();��        }�                break;�                setToolTip("");�        case StatusIndicatorState::Empty:�                break;�                setToolTip(tr("Sent"));�        case StatusIndicatorState::Sent:�                break;�                setToolTip(tr("Seen"));�        case StatusIndicatorState::Read:�                break;�                setToolTip(tr("Delivered"));�        case StatusIndicatorState::Received:�                break;�                setToolTip(tr("Encrypted"));�        case StatusIndicatorState::Encrypted:�        switch (state) {��        state_ = state;�{�StatusIndicator::setState(StatusIndicatorState state)�void��}�        }�                break;�        case StatusIndicatorState::Empty:�        }�                break;�                paintIcon(p, doubleCheckmarkIcon_);�        case StatusIndicatorState::Read: {�        }�                break;�                paintIcon(p, checkmarkIcon_);�        case StatusIndicatorState::Received: {�                break;�                paintIcon(p, lockIcon_);�        case StatusIndicatorState::Encrypted:�        }�                break;�                paintIcon(p, clockIcon_);�        case StatusIndicatorState::Sent: {�        switch (state_) {��        p.setPen(iconColor_);��        PainterHighQualityEnabler hq(p);�        Painter p(this);��                return;�        if (state_ == StatusIndicatorState::Empty)�{�StatusIndicator::paintEvent(QPaintEvent *)�void��}�        QIcon(pixmap).paint(&p, rect(), Qt::AlignCenter, QIcon::Normal);��        painter.fillRect(pixmap.rect(), p.pen().color());�        painter.setCompositionMode(QPainter::CompositionMode_SourceIn);�        QPainter painter(&pixmap);��        auto pixmap = icon.pixmap(width());�{�StatusIndicator::paintIcon(QPainter &p, QIcon &icon)�void��}�        doubleCheckmarkIcon_.addFile(":/icons/StatusIndicator::StaStatusIndicator::StaStatusIndicator::StatusIndicator(QWidget *parent)�������úw.�������������?¬StatusIndicator::StatusIndicator(QWidget *parent)�������úw.�������������úw.	�������"������úw.�������+������úw.��������constexpr int MSG_PADDING      = 20;�������úw.�������constexpr int MSG_RIGHT_MARGIN = 7;�������úw.��������#include "mtx/identifiers.hpp"�#include "dialogs/RawMessage.h"��#include "timeline/widgets/VideoItem.h"�#include "timeline/widgets/ImageItem.h"�#include "timeline/widgets/FileItem.h"�#include "timeline/widgets/AudioItem.h"�#include "timeline/TimelineItem.h"��#include "ui/TextLabel.h"�#include "ui/Painter.h"�#include "ui/Avatar.h"�#include "Olm.h"�#include "MainWindow.h"�#include "Logging.h"�#include "Config.h"�#include "ChatPage.h"��#include <QtGlobal>�#include <QTimer>�#include <QMenu>�#include <QFontDatabase>�#include <QDesktopServices>�#include <QContextMenuEvent>��#include <functional>� */� * along with this program.  If not, see <http://www.gnu.org/licenses/>.� * You should have received a copy of the GNU General Public License� *� * GNU General Public License for more details.� * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the� * but WITHOUT ANY WARRANTY; without even the implied warranty of� * This program is distributed in the hope that it will be useful,� *� * (at your option) any later version.� * the Free Software Foundation, either version 3 of the License, or� * it under the terms of the GNU General Public License as published by� * This program is free software: you can redistribute it and/or modify� *� * nheko Copyright (C) 2017  Konstantinos Sideris <siderisk@auth.gr>�/*�ad��x��°������������™��X��*��Ô��À��²��°��Ã��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������}�          });�    }�          });�                  }�                            "failed to serialize event ({}, {})", room_id, event_id);�                          nhlog::net()->warn(�                  } catch (const nlohmann::json::exception &e) {�                          emit proxy->eventRetrieved(utils::serialize_event(res));�������úw.
�������ad��ç��/�����K�������Þ����†��8����Ú��Ù��H����ã
��â
��œ
��o
��I
��"
��
��
��Î��¡��z��S��G��F��÷��«��Ÿ����œ��—������ç
+��º
+��
+��B
+��@
+��?
+��:
+��±	��¯	��‡	��3	��2	��ù��Ð��Ï��‰��K��J��	��Ò��Œ��‹��Y������ô����›��š��•��K��I����ç��æ��Ÿ��T����å��º��¸��·��²��/��Ô��������Ó��Ñ��Ð��Ë��B��@��&��î��ì��ë��æ��‚��€��R��:��ø��µ��³��²��­�����������void��}�        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);�        QPainter p(this);�	������?¬…±�������������?¬…±�������        opt.init(this);�        QStyleOptTimelineItem::setUseTimelineItem::setUserAvatar(const QString &userid)�������úw.�������������?TimelineItem::setUserAvatar(const QString &userid)�������úw.�������������?TimelineItem::setUserAvatar(const QString &userid)�������úw.�������������?TimelineItem::setUserAvatar(const QStrinTimelineItem::setUserAvatar(const QStrinTimelineItem::setUserAvatar(const QStrinTimelineItem::setUserAvatar(const QString &userid)�������úw.�������������?TimelineItem::setUserAvatar(const QString &userid)�������úw.����������
���úw.�������#������úw.�������,������úw.�������void��}�                                       0);�                                       0,�                                       conf::timeline::msgTopMargin,�                                         QFontMetrics(f).height() * 2 + 2,�        topLayout_->setContentsMargins(conf::timeline::msgLeftMargin +��        f.setPointSizeF(f.pointSizeF());�        QFont f;�	������úw.�������������úw.�������{�TimelineItem::setupSimpleLayout()�������úw.�������������úw.�������void��}�                mainLayout_->insertWidget(0, userName_, Qt::AlignTop | Qt::AlignLeft);�        if (userName_)��        topLayout_->setAlignment(userAvatar_, Qt::AlignTop | Qt::AlignLeft);�        topLayout_->insertWidget(0, userAvatar_);��                userAvatar_->setLetter(QChar(userName[1]).toUpper());�        if (userName[0] == '@' && userName.size() > 1)�        // TODO: The provided user name should be a UserId class��        userAvatar_->setLetter(QChar(userName[0]).toUpper());�        userAvatar_ = new Avatar(this, QFontMetrics(f).height() * 2);��        f.setPointSizeF(f.pointSizeF());�        QFont f;�	������úw.�������������úw.��������          conf::timeline::msgLeftMargin, conf::timeline::msgAvatarTopMargin, 0, 0);�        topLayout_->setContentsMargins(�{�TimelineItem::setupAvatarLayout(const QString &userName)�������úw.�������������úw.�������'������úw.�������0������úw.�������void��}�          QString("<span style=\"color: #999\"> %1 </span>").arg(time.toString("HH:mm")));�        timestamp_->setText(�        timestamp_->setFont(timestampFont_);�        timestamp_ = new QLabel(this);�{�TimelineItem::generateTimestamp(const QDateTime &time)�������úw.�������������úw.�������'���	���úw.�������2������úw.�������void��}�        });�                MainWindow::instance()->openUserProfile(user_id, room_id_);�        connect(filter, &UserProfileFilter::clicked, this, [this, user_id]() {��        });�                userName_->setFont(f);�                f.setUnderline(false);�                QFont f = userName_->font();�        connect(filter, &UserProfileFilter::hoverOff, this, [this]() {��        });�                userName_->setFont(f);�                f.setUnderline(true);�                QFont f = userName_->font();�        connect(filter, &UserProfileFilter::hoverOn, this, [this]() {��        userName_->setCursor(Qt::PointingHandCursor);�        userName_->installEventFilter(filter);�        auto filter = new UserProfileFilter(user_id, userName_);�������úw.�������������úw.�������-������úw.�������6���	���úw.
+��������        refreshAuthorColor();�	������úw.�������        // otherwise this will just set it.�        // Set the user color asynchronously if it hasn't been generated yet,�#endif�          QFontMetrics(userName_->font()).horizontalAdvance(userName_->text()));�        userName_->setFixedWidth(�ad��õ��=
������������Ú��°��S��+��þ��Ï����<��ï
��k
��=
��›
��B
��;
��í��Á��£��¢��a��2��ü��û��µ��ˆ��b��;��/��.��ç
+��º
+��“
+��l
+��`
+��_
+��
+��Ä	��¸	��¶	��µ	��°	��y	��w	��P	��#	��	��«��©��¨��£��j��h��@��ì��ë��Ú��±��°��j��,��+��ê��³��m��l��:��í��ì��Õ��~��|��{��v��T��R��A������Ð��…��@����ë��é��è��ã��°��®��Š��r��q��@��>��=��8��ÿ��ý��ã��«��©��¨��£��{��y��_��G��-��ê��è��ç��â��	����������������void��}�        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);�        QPainter p(this);�        opt.init(this);�        QStyleOption opt;�{�TimelineItem::paintEvent(QPaintEvent *)�void��}�                contextMenu_->exec(event->globalPos());�        if (contextMenu_)�{�TimelineItem::contextMenuEvent(QContextMenuEvent *event)�void��}�        userAvatar_->setImage(room_id_, userid);��                return;�        if (userAvatar_ == nullptr)�{�TimelineItem::setUserAvatar(const QString &userid)�void��}�                                       0);�                                       0,�                                       conf::timeline::msgTopMargin,�                                         QFontMetrics(f).height() * 2 + 2,�        topLayout_->setContentsMargins(conf::timeline::msgLeftMargin +��        f.setPointSizeF(f.pointSizeF());�        QFont f;�{�TimelineItem::setupSimpleLayout()�void��}�                mainLayout_->insertWidget(0, userName_, Qt::AlignTop | Qt::AlignLeft);�        if (userName_)��        topLayout_->setAlignment(userAvatar_, Qt::AlignTop | Qt::AlignLeft);�        topLayout_->insertWidget(0, userAvatar_);��                userAvatar_->setLetter(QChar(userName[1]).toUpper());�        if (userName[0] == '@' && userName.size() > 1)�        // TODO: The provided user name should be a UserId class��        userAvatar_->setLetter(QChar(userName[0]).toUpper());�        userAvatar_ = new Avatar(this, QFontMetrics(f).height() * 2);��        f.setPointSizeF(f.pointSizeF());�        QFont f;��          conf::timeline::msgLeftMargin, conf::timeline::msgAvatarTopMargin, 0, 0);�        topLayout_->setContentsMargins(�{�TimelineItem::setupAvatarLayout(const QString &userName)�void��}�          QString("<span style=\"color: #999\"> %1 </span>").arg(time.toString("HH:mm")));�        timestamp_->setText(�        timestamp_->setFont(timestampFont_);�        timestamp_ = new QLabel(this);�{�TimelineItem::generateTimestamp(const QDateTime &time)�void��}�        });�                MainWindow::instance()->openUserProfile(user_id, room_id_);�        connect(filter, &UserProfileFilter::clicked, this, [this, user_id]() {��        });�                userName_->setFont(f);�                f.setUnderline(false);�                QFont f = userName_->font();�        connect(filter, &UserProfileFilter::hoverOff, this, [this]() {��        });�                userName_->setFont(f);�                f.setUnderline(true);�                QFont f = userName_->font();�        connect(filter, &UserProfileFilter::hoverOn, this, [this]() {��        userName_->setCursor(Qt::PointingHandCursor);�        userName_->installEventFilter(filter);�        auto filter = new UserProfileFilter(user_id, userName_);��        refreshAuthorColor();�        // otherwise this will just set it.�        // Set the user color asynchrono#else��������ZhÑø�������������oÁ€�#else��������ZhÑø�������������oÁ€������        userName_->setFixedWidth(QFontMetrics(userName_->font()).width(userName_->text()));����\���ZhÑø���������\���oÁ€������        // width deprecated in 5.13:����%���ZhÑø���������%���oÁ€������#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)����
+���úw.
�������������úw.
�������        userName_->setAlignment(Qt::AlignLeft | Qt::AlignTop);�        userName_->setAttribute(Qt::WA_Hover);�        userName_->setToolTipDuration(1500);�        userName_->setToolTip(user_id);�        userName_->setText(utils::replaceEmoji(fm.elidedText(sender, Qt::ElideRight, 500)));�        userName_->setFont(usernameFont);�        userName_ = new QLabel(this);�ad��Ù��©�����-�������À��e����ý��Ê��´��²��Ž����G��E��D��Ç
��m
��-
��Ò��~��j��7��!����û��ú��´��²��±��4��Ç
+��†
+��+
+��×	��Ã	��	��z	��x	��!	��û��ú��É��È��}��{��z��û��©���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������                                               const mtx::ev                           const mtx::ev                                               const mtx::events::Sticker &event,�8������úw.�����                           const mtx::ev                                               const mtx::ev                           const mtx::ev                                               const mtx::events::Sticker &event,�8������úw.�����                                                                   const mtx::ev                           const mtx::ev                           const mtx::ev                           const mtx::events::Sticker &event,�8������úw.�����                                               const mtx::events::Sticker &event,�8������úw.�������TimelineItem::TimelineItem(StickerItem *image,�������úw.�������������úw.	�������������úw.�������)������úw.��������}�        addSaveImageAction(image);�	������úw.�������������úw.��������        markOwnMessagesAsReceived(event.sender);��          image, event, with_sender);�        setupWidgetLayout<mtx::events::RoomEvent<mtx::events::msg::Image>, ImageItem>(�{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Image)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������                           const mtx::events::RoomEvent<mtx::events::msg::Image> &event,�S������úw.�������TimelineItem::TimelineItem(ImageItem *image,�������úw.�������������úw.	����������	���úw.�������'������úw.��������}�        setupLocalWidgetLayout<VideoItem>(video, userid, withSender);��        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Video)�  : QWidget{parent}�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool withSender,�!���
+���úw.�������                           const QString &userid,�"������úw.�������+������úw.�������TimelineItem::TimelineItem(VideoItem *video,�������úw.�������������úw.	����������	���úw.�������'������úw.��������}�        setupLocalWidgetLayout<AudioItem>(audio, userid, withSender);��        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Audio)�  : QWidget{parent}�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool withSender,�!���
+���úw.�������ad��Q��u�����B�������²����Z��/��Ý��—��h��W��&��ú
��Ï
��¦
��`
��1
��'
��&
��æ��³��²��d��c��5��ò��Â��Á��r��a��3��ú
+��ð
+��ï
+��¼
+��º
+��¹
+��<
+��â	��¢	��G	��ó��ß��¬��–��”��p��o��)��(��Ý��Û��Ú��_����Å��j������Ð��º��¸��”��“��O��M��L��Ï��u��;��"��ö��â��¯��™��—��‡��†��@��>��=����Þ��²����S��?��                           const QString                                               const QString                                                                   const QString &userid,�"������úw.�������"������?¬                           const QString                                               const QString                           const QString                                               const QString                           const QString &userid,�"������úw.�������"������?¬                           const QString                                               const QString                           const QString                                               const QString &userid,�"������úw.�������"������?¬                           const QString                           const QString &userid,�"������úw.�������+������úw.�������TimelineItem::TimelineItem(AudioItem *audio,�������úw.�������������úw.	����������	���úw.�������'������úw.��������}�        setupLocalWidgetLayout<FileItem>(file, userid, withSender);��        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::File)�  : QWidget{parent}�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool withSender,�!���
+���úw.�������                           const QString &userid,�"������úw.�������+������úw.�������TimelineItem::TimelineItem(FileItem *file,�������úw.�������������úw.	�������������úw.�������&������úw.��������}�        addSaveImageAction(image);�	������úw.�������������úw.��������        setupLocalWidgetLayout<ImageItem>(image, userid, withSender);��        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Image)�  : QWidget{parent}�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool withSender,�!���
+���úw.�������                           const QString &userid,�"������úw.�������+������úw.�������TimelineItem::TimelineItem(ImageItem *image,�������úw.�������������úw.	����������	���úw.�������'������úw.��������}�        adjustMessageLayout();�	������úw.��������        }�                setupSimpleLayout();�������úw.�������                generateBody(formatted_body);�        } else {�                setUserAvatar(userid);����
���úw.�������������úw.��������                setupAvatarLayout(displayName);�                generateBody(userid, displayName, formatted_body);�        if (withSender) {�
���
+���úw.��������        generateTimestamp(timestamp);�	������úw.����������	���úw.��������        formatted_body.replace("mx-reply", "div");�        formatted_body = utils::linkifyMessage(formatted_body);��        }�                                   timestamp};�                                   utils::descriptiveTime(timestamp),�                                   body,�                                   userid,�                                   "You: ",�                descriptionMsg_ = {emptyEventId,�        } else {�                                   timestamp};�                                   utils::descriptiveTime(timestamp),�                                   QString("* %1 %2").arg(displayName).arg(body),�                                   userid,�                                   "",�                descriptionMsg_ = {emptyEventId,�                formatted_body  = QString("<em>%1</em>").arg(formatted_body);�ad��‹��ÿ������������®��\����ä��ã��ª��„��ƒ��[��
��ê
��¾
��½
��i
��E
��D
��
��î��³��B��A��ÿ��å��À��w��#��"��ö
+��Æ
+��‰
+��
+��
+��å	��	��q	��&	��ú��ù��°����J��I��ö��õ��¿��v��,��+��Ö��‘����Ž��‹��j��f��ò��˜��G����¬��l��X��B��,��*����Ø��×��‚��
����Ú��‹��Š��T����ß��Þ��˜��—��b��������        if (ty == mtx::events::MessageType::Emote) {��        QString emptyEventId;�	������?¬…±�������������?¬…±��������                formatted_body = body.toHtmlEscaped();�        if (formatted_body == body.trimmed().toHtmlEscaped())�        // Escape html if the input is not formatted.��        auto formatted_body = utils::markdownToHtml(body);�������?¬…±�������        // Generate the html body to be rendered.��        auto timestamp   = QDateTime::currentDateTime();����	���?¬…±����������	���?¬…±�������'������?¬…±�������        auto displayName = Cache::displayName(room_id_, userid);�������?¬…±��������        addReplyAction();�	������?¬…±�������        init();�	������?¬…±�������{�  , room_id_{room_id}�  , message_type_(ty)�  : QWidget(parent)�                           QWidget *parent)�%������?¬…±�������                           const QString &room_id,�"������?¬…±�������+������?¬…±�������                           bool withSender,�!���
+���?¬…±�������                           QString body,�������?¬…±�������$������?¬…±�������                           const QString &userid,�"������?¬…±�������+������?¬…±�������TimelineItem::TimelineItem(mtx::events::MessageType ty,�������?¬…±�������������?¬…±	�������5������?¬…±������� */� * For messages created locally.�/*��}�        setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);�        parentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);��        statusIndicator_->setFixedHeight(tsFm.height() - tsFm.leading());�        statusIndicator_->setFixedWidth(tsFm.height() - tsFm.leading());�        statusIndicator_ = new StatusIndicator(this);��        QFontMetrics tsFm(timestampFont_);�	������?¬…±�������������?¬…±��������        timestampFont_.setStyleHint(QFont::Monospace);�        timestampFont_.setFamily("Monospace");�        timestampFont_.setPointSizeF(timestampFont_.pointSizeF() * 0.9);��        contextBtn_->setMenu(contextMenu_);�        contextBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));�        contextBtn_->setIcon(context_icon);�        context_icon.addFile(":/icons/icons/ui/vertical-ellipsis.png");�        QIcon context_icon;�	������?¬…±��������        contextBtn_->setCornerRadius(buttonSize_ / 2);�	������?¬…±
+�������������?¬…±�������&������?¬…±�������        contextBtn_->setFixedSize(buttonSize_, buttonSize_);�        contextBtn_->setToolTip(tr("Options"));�        contextBtn_ = new FlatButton(this);��        connect(replyBtn_, &FlatButton::        QIcon reply_icon;�	������úw.�        QIcon reply_icon;�	������úw.�        QIcon reply_icon;�	������úw.�������	������?¬…±�        QIcon reply_icon;�	������úw.�        QIcon reply_icon;�	������úw.����������
+���úw.��������        replyBtn_->setCornerRadius(buttonSize_ / 2);�	���	���úw.
+�������������úw.�������$������úw.�������        replyBtn_->setFixedSize(buttonSize_, buttonSize_);�        replyBtn_->setToolTip(tr("Reply"));�        replyBtn_ = new FlatButton(this);��        mainLayout_->setSpacing(0);�        mainLayout_->setContentsMargins(conf::timeline::headerLeftMargin, 0, 0, 0);��        topLayout_->addLayout(mainLayout_);�        topLayout_->setSpacing(0);�          conf::timeline::msgLeftMargin, conf::timeline::msgTopMargin, 0, 0);�        topLayout_->setContentsMargins(��        actionLayout_->setSpacing(0);�        actionLayout_->setContentsMargins(13, 1, 13, 0);��        messageLayout_->setSpacing(MSG_PADDING);�        messageLayout_->setContentsMargins(0, 0, MSG_RIGHT_MARGIN, 0);�        actionLayout_  = new QHBoxLayout;�	���
���úw.
+�������������úw.�������        messageLayout_ = new QHBoxLayout;�	������úw.
+�������������úw.�������ad��/
��{
��������������D��â��á��£����M��7��þ
��ý
��Í
��{
��e
��O
��
��×��Ö����w��v��N�����Ý��±��°��\��8��7��
��á
+��¦
+��q
+��p
+��V
+��
+��ï	��¦	��R	��Q	��%	��õ��¸����€��d����ð��¥��y��x��/�����É��È����œ��f����Ó��Ò��}��8��6��5��2����
��Õ��£��z��N����ï��Û��Å��¯��­����ƒ��‚��A������Õ��š��™��c��%��î��í��Ï��Î��™��˜�����������        if (ty == mtx::events::MessageType::Emote) {��        QString emptyEventId;��                formatted_body = body.toHtmlEscaped();�        if (formatted_body == body.trimmed().toHtmlEscaped())�        // Escape html if the input is not formatted.��        auto formatted_body = utils::markdownToHtml(body);�        // Generate the html body to be rendered.��        auto timestamp   = QDateTime::currentDateTime();�        auto displayName = Cache::displayName(room_id_, userid);��        addReplyAction();�        init();�{�  , room_id_{room_id}�  , message_type_(ty)�  : QWidget(parent)�                           QWidget *parent)�                           const QString &room_id,�                           bool withSender,�                           QString body,�                           const QString &userid,�TimelineItem::TimelineItem(mtx::events::MessageType ty,� */� * For messages created locally.�/*��}�        setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);�        parentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);��        statusIndicator_->setFixedHeight(tsFm.height() - tsFm.leading());�        statusIndicator_->setFixedWidth(tsFm.height() - tsFm.leading());�        statusIndicator_ = new StatusIndicator(this);��        QFontMetrics tsFm(timestampFont_);��        timestampFont_.setStyleHint(QFont::Monospace);�        timestampFont_.setFamily("Monospace");�        timestampFont_.setPointSizeF(timestampFont_.pointSizeF() * 0.9);��        contextBtn_->setMenu(contextMenu_);�        contextBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));�        contextBtn_->setIcon(context_icon);�        context_icon.addFile(":/icons/icons/ui/vertical-ellipsis.png");�        QIcon context_icon;��        contextBtn_->setCornerRadius(buttonSize_ / 2);�        contextBtn_->setFixedSize(buttonSize_, buttonSize_);�        contextBtn_->setToolTip(tr("Options"));�        contextBtn_ = new FlatButton(this);��        connect(replyBtn_, &FlatButton::clicked, this, &TimelineItem::replyAction);�        replyBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));�        replyBtn_->setIcon(reply_icon);�        reply_icon.addFile(":/icons/icons/ui/mail-reply.png");�        QIcon reply_icon;��        replyBtn_->setCornerRadius(buttonSize_ / 2);�        replyBtn_->setFixedSize(buttonSize_, buttonSize_);�        replyBtn_->setToolTip(tr("Reply"));�        replyBtn_ = new FlatButton(this);��        mainLayout_->setSpacing(0);�        mainLayout_->setContentsMargins(conf::timeline::headerLeftMargin, 0, 0, 0);��        topLayout_->addLayout(mainLayout_);�        topLayout_->setSpacing(0);�          conf::timeline::msgLeftMargin, conf::timeline::msgTopMargin, 0, 0);�        topLayout_->setContentsMargins(��        actionLayout_->setSpacing(0);�        actionLayout_->setContentsMargins(13, 1, 13, 0);��        messageLayout_->setSpacing(MSG_PADDING);�        messageLayout_->setContentsMargins(0, 0, MSG_RIGHT_MARGIN, 0);�            mainLayout_    = new QVBoxLayout        mainLayout_    = new QVBoxLayout;�	������úw.
+�������������úw.�������        topLayout_     = new QHBoxLayout(this);��                &TimelineItem::finishedGeneratingColor);�                this,�                &QFutureWatcher<QString>::finished,�        connect(colorGenerating_,�        colorGenerating_ = new QFutureWatcher<QString>(this);��        connect(viewRawMessage_, &QAction::triggered, this, &TimelineItem::openRawMessageViewer);�        connect(markAsRead_, &QAction::triggered, this, &TimelineItem::sendReadReceipt);�          ChatPage::instance(), &ChatPage::themeChanged, this, &TimelineItem::refreshAuthorColor);�ad��`��L�����4�������}��{��K��õ��Á��À��l��b��`��_��Z������á
��Ž
��X
��W
��ú��ð��î��í��è��¤��¢��z��b��a����í��·����F������}
+��{
+��z
+��u
+��)
+��'
+��÷	��’	��\	��[	��	��´�� ��–��”��“��Ž��L��
+��%
+��
+��
+��Ê	��—	��V	��U	��&	��%	��ý��ü��Ý��Û��Ú��Õ��¯��­��‹��H����µ��w��(��Ê��u����é��º��¸��·��²��‡��…��:������Î��n����ð��ä��ã��À��­��™��`����Ó��Ò��µ��‡��0����ú��ù��á���������������������                  try {��                  }�                          return;�                            "failed to retrieve event {} from {}", event_id, room_id);�                          nhlog::net()->warn(�                  if (err) {��                  using namespace mtx::events;�            const mtx::events::collections::TimelineEvents &res, mtx::http::RequestErr err) {�          [event_id, room_id, proxy = std::move(proxy)](�          event_id,�          room_id,�        http::client()->get_event(��        });�                Q_UNUSED(dialog);�                auto dialog = new dialogs::RawMessage{QString::fromStdString(obj.dump(4))};�        connect(proxy.get(), &EventProxy::eventRetrieved, this, [](const nlohmann::json &obj) {�        auto proxy = std::make_shared<EventProxy>();��        const auto room_id  = room_id_.toStdString();�        const auto event_id = event_id_.toStdString();�������?¬…±�������{�TimelineItem::openRawMessageViewer() const�void��}�                                           });�                                                   }�                                      TimelineItem::addAvatar()�������úw.�������������?¬…±����������	���úw.�TimelineItem::addAvaTimelineItem::addAvaTimelineItem::addAvatar()�������úw.�TimelineItem::addAvaTimelineItem::addAvaTimelineItem::addAvatar()�������úw.�TimelineItem::addAvaTimelineItem::addAvatar()�������úw.�TimelineItem::addAvatar()�������úw.�������������?¬…±����������	���úw.����������	���?¬…±�TimelineItem::addAvatar()�������úw.�TimelineItem::addAvaTimelineItem::addAvaTimelineItem::addAvatar()�������úw.�TimelineItem::addAvatar()�������úw.����������	���úw.�������void��}�        }�                });�                        olm::request_keys(room_id_.toStdString(), event_id_.toStdString());�                connect(requestKeys, &QAction::triggered, this, [this]() {��                contextMenu_->addAction(requestKeys);�                auto requestKeys = new QAction("Request encryption keys", this);�������úw.�������        if (contextMenu_) {�
������úw.
+�������{�TimelineItem::addKeyRequestAction()�������úw.�������������úw.�������void��}�        emit ChatPage::instance()->messageReply(related);�	������úw.
�������������úw.�������������úw.�������$������úw.�������1������úw.��������        related.room          = room_id_;�        related.related_event = eventId().toStdString();�        related.quoted_user   = descriptionMsg_.userid;�        related.quoted_body   = body_->toPlainText();�        related.type          = message_type_;�        RelatedInfo related;�	������úw.�������������úw.��������                return;�        if (!body_)�������úw.
+�������{�TimelineItem::replyAction()�������úw.�������������úw.�������void��}�        }�                connect(replyAction, &QAction::triggered, this, &TimelineItem::replyAction);��                contextMenu_->addAction(replyAction);�                auto replyAction = new QAction("Reply", this);�������úw.�������        if (contextMenu_) {�
������úw.
+�������{�TimelineItem::addReplyAction()�������úw.�������������úw.�������void��}�        }�                connect(saveImage, &QAction::triggered, image, &ImageItem::saveAs);��                contextMenu_->addAction(saveImage);�                auto saveImage = new QAction("Save image", this);����	���úw.�������        if (contextMenu_) {�
������úw.
+�������{�TimelineItem::addSaveImageAction(ImageItem *image)�������úw.�������������úw.�������"���	���úw.�������-������úw.�������ad��‹	��#
+������������¿��d����ü��æ��ä��‹��Š��Y��X��5��3��2��·
��K
��
+
��¯��[��G����ÿ��ý��¨��ƒ��‚��Q��O��N��Ñ
+��d
+��#
+��r��T��@��
��÷
+��õ
+��ž
+��x
+��w
+��F
+��D
+��C
+��
+��½	��	��]	��1	��	��ê��Ô��Ò��{��U��T��#��!�� ����ò��î��”��g��4����ô��À��ª��¨��˜��~��}��L��K����¿��h��g��
+��¦��¥����>����è��ª��ƒ��‚��\��[��@��÷��ö��³��ƒ��‚��[��J����÷��í��ì��Í��Ë��Ê��Ç��Ú�����/*��}�        adjustMessageLayout();��        }�                setupSimpleLayout();�                generateBody(formatted_body);�        } else {�                setUserAvatar(sender);��                setupAvatarLayout(displayName);�                generateBody(sender, displayName, formatted_body);��                auto displayName = Cache::displayName(room_id_, sender);�        if (with_sender) {��        generateTimestamp(timestamp);��                           timestamp};�                           utils::descriptiveTime(timestamp),�                           " sent a notification",�                           sender,�                           Cache::displayName(room_id_, sender),�        descriptionMsg_ = {event_id_,��        auto body           = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped();�        auto formatted_body = utils::linkifyMessage(utils::getMessageBody(event).trimmed());��        const auto timestamp = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);�        const auto sender    = QString::fromStdString(event.sender);�        event_id_            = QString::fromStdString(event.event_id);��        markOwnMessagesAsReceived(event.sender);��        addReplyAction();�        init();�{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Notice)�  : QWidget(parent)�                           QWidget *parent)�                           const QString &room_id,�                           bool with_sender,�TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Notice> &event,� */� * Used to display remote notice messages.�/*��}�        markOwnMessagesAsReceived(event.sender);��          video, event, with_sender);�                                                   bool with_sen                           bool with_sen                           bool with_sender,�!������úw.�������!������?¬…±��                                                                   bool with_sen                           bool with_sen                           bool with_sender,�!������úw.�������!������?¬…±��                                                                   bool with_sender,�!������úw.�������                           const mtx::events::RoomEvent<mtx::events::msg::Audio> &event,�S������úw.�������TimelineItem::TimelineItem(AudioItem *audio,�������úw.�������������úw.	����������	���úw.�������'������úw.��������}�        markOwnMessagesAsReceived(event.sender);��          file, event, with_sender);�        setupWidgetLayout<mtx::events::RoomEvent<mtx::events::msg::File>, FileItem>(�{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::File)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������                           const mtx::events::RoomEvent<mtx::events::msg::File> &event,�R������úw.�������TimelineItem::TimelineItem(FileItem *file,�������úw.�������������úw.	�������������úw.�������&������úw.��������}�        addSaveImageAction(image);��        markOwnMessagesAsReceived(event.sender);��        setupWidgetLayout<mtx::events::Sticker, StickerItem>(image, event, with_sender);�{�  , room_id_{room_id}�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������ad��;��§������������¼��º��¹��´��é��ç��°��¯��„��J����»
��±
��°
��l
��'
��ø��÷��¨��§����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������        QFontMetrics fm(usernameFont);��        QFontMetrics fm(usernameFont);�	������úw.�������	������?¬…±�������������úw.�������������?¬…±��������        QFontMetric�        QFontMetrics fm(usernameFont);��        QFontMetrics fm(usernameFont);��        QFontMetrics fm(usernameFont);�	������úw.�������������úw.��������        usernameFont.setWeight(QFont::Medium);�        usernameFont.setPointSizeF(usernameFont.pointSizeF() * 1.1);�        QFont usernameFont;�	������úw.�������������úw.��������        }�                        sender = displayname.split(":")[0].split("@")[1];�                if (displayname.split(":")[0].split("@").size() > 1)�                // TODO: Fix this by using a UserId type.�        if (displayname.startsWith("@")) {��        auto sender = displayname;�������úw.�������{�TimelineItem::generateUserName(const QString &user_id, const QString &displayname)�������úw.�������������úw.�������&������úw.�������/������úw.�������>������úw.�������G������úw.�������void��}�        generateBody(body);�	������úw.�������������úw.�������ad��
��T
�����
+�������¼��m��Ñ��Ï��Î��É��ˆ��†��ì
��T
��Ì����˜��ó��ñ��­��¬��k��¦
+��™
+��Õ	��Ô	��¥	��£	��¢	��ƒ	��~	��Ö��Ô��”��4��3��×��–��8��,��*��)��$��Å��Ã��€��S��'��ò��è��§��v��7��ç��œ��r��_��^��Ö��Õ��‹��`����õ��š��ˆ��~��|��{��v������­��9��Ñ����¿        QString userColor = colorGenerating_->result();�	������?¬…±����������	���úw.����������	���?¬…±�������        nhlog::ui()->debug("finishedGeneratingColor for: {}", userName_->toolTip().toStdString());�{�TimelineItem::finishedGeneratingColor()�������úw.�������������?¬…±�������������?¬…±�������void��}�        }�                }�                        userName_->setStyleSheet("QLabel { color : " + userColor + "; }");�                } else {�                        colorGenerating_->setFuture(QtConcurrent::run(generate));�                if (userColor.isEmpty()) {�                // If the color is empty, then generate it asynchronously��                QString userColor = Cache::userColor(userName_->toolTip());�������?¬…±����������	���úw.����������	���?¬…±��������                };�                        return userColor;�                          userName_->toolTip(), backgroundColor().name());�                        QString userColor = utils::generateContrastingHexColor(�                std::function<QString()> generate = [this]() {�                // generate user's unique color.�        if (userName_) {�
���	���úw.
+�������
���	���?¬…±
+�������        }�                colorGenerating_->waitForFinished();�                colorGenerating_->cancel();�        if (colorGenerating_->isRunning()) {�        // Cancel and wait if we are already generating the color.�{�TimelineItem::refreshAuthorColor()�������úw.�������������?¬…±�������������?¬…±�������void��}�        });�                                                        ChatPage::instance()->currentRoom());�                MainWindow::instance()->openUserProfile(user_id,�        connect(body_, &TextLabel::userProfileTriggered, this, [](const QString &user_id) {��        body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);�        body_ = new TextLabel(utils::replaceEmoji(body), this);�{�TimelineItem::generateBody(const QString &body)�������úw.�������������?¬…±�������������?¬…±�������"������?¬…±�������+������úw.�������+������?¬…±�������void�// Only the body is displayed.��}�        sendReadReceipt();�	������?¬…±��������                statusIndicator_->setState(StatusIndicatorState::Received);�������úw.
+�������������?¬…±
+�������#������?¬…±�������,������?¬…±�������B������úw.�������B������?¬…±�������        else�                statusIndicator_->setState(StatusIndicatorState::Encrypted);�������úw.
+�������������?¬…±
+�������#������?¬…±�������,������?¬…±�������B���	���úw.�������B���	���?¬…±�������        if (isEncrypted)�
������úw.�������
������?¬…±��������        isReceived_ = true;�	��                statusIndicator_->setState(StatusIndicatorState::Read);�                statusIndicator_->setSta                statusIndicator_->setState(StatusIndicatorState::Read);�������                statusIndicator_->setSta                statusIndicator_->setState(StatusIndicatorState::Read);�������                statusIndicator_->setState(StatusIndicatorState::Read);�������                statusIndicator_->setState(StatusIndicatorState::Read);�������úw.
+�������#������úw.�������,������úw.�������B������úw.�������        if (statusIndicator_->state() != StatusIndicatorState::Encrypted)�
������úw.
+�������������úw.�������*������úw.�������@���	���úw.�������{�TimelineItem::markRead()�������úw.�������������úw.�������void��}�                statusIndicator_->setState(StatusIndicatorState::Received);�������úw.
+�������#������úw.�������,������úw.�������B������úw.�������        if (sender == settings.value("auth/user_id").toString().toStdString())�        QSettings settings;�	���	���úw.�������������úw.�������ad��-��Q������������¥��Q��™��Î��¸��¶��_��9��8��������7
��¶��a��Þ��v��b��/������À
+��š
+��™
+��h
+��f
+��e
+��b
+��7
+��3
+��a	��	��‰��!��
��Ù��Ã��Á��‰��G��F������Í��`��á��à��[��Ï��Î��¨��g��D����Ó��¬��«��…��„��A��Ð��Ï��Œ��\��[��4��#��õ��¨��ž����V��T��S��P��������������/*��}�        adjustMessageLayout();�	������úw.�������	������?¬…±��������        }�                setupSimpleLayout();�������úw.�������������?¬…±�������                generateBody(formatted_body);�        } else {�                setUserAvatar(sender);��                setupAvatarLayout(displayName);�                generateBody(sender, displayName, formatted_body);��                auto displayName = Cache::displayName(room_id_, sender);�������úw.�������������?¬…±�������        if (with_sender) {�
������úw.�������
������?¬…±��������        generateTimestamp(timestamp);��                           timestamp};�                           utils::descriptiveTime(timestamp),�                           " sent a notification",�                           sender,�                           Cache::displayName(room_id_, sender),�        descriptionMsg_ = {event_id_,��        auto body           = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped();�������úw.�������������?¬…±�������        auto formatted_body = utils::linkifyMessage(utils::getMessageBody(event).trimmed());�������úw.�������������?¬…±��������        const auto timestamp = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);����	���úw.����������	���?¬…±�������        const auto sender    = QString::fromStdString(event.sender);�������úw.�������������?¬…±�������        event_id_            = QString::fromStdString(event.event_id);��        markOwnMessagesAsReceived(event.sender);��        addReplyAction();�	������úw.�������	������?¬…±�������        init();�	������úw.�������	������?¬…±�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Notice)�  : QWidget(parent)�                           QWidget *parent)�������?¬…±�������%������úw.�������%������?¬…±�������                           const QString &room_id,�"������úw.�������"������?¬…±�������+������úw.�������+������?¬…±�������                           bool with_sender,�!������úw.�������!������?¬…±�������TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Notice> &event,�������úw.�������������?¬…±�������������úw.�������������?¬…±�������T������úw.�������T������?¬…±������� */� * Used to display remote notice messages.�/*��}�        markOwnMessagesAsReceived(event.sender);��          video, event, with_sender);�        setupWidgetLayout<mtx::events::RoomEvent<mtx::events::msg::Video>, VideoItem>(�{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Video)�  : QWidget(parent)�                           QWidget *parent)�������?¬…±�������%������úw.�������%������?¬…±�������                           const QString &room_id,�"������úw.�������"������?¬…±�������+������úw.�������+������?¬…±�������                           bool with_sender,�!������úw.�������!������?¬…±�������                           const mtx::events::RoomEvent<mtx::events::msg::Video> &event,�S������úw.�������S������?¬…±�������TimelineItem::TimelineItem(VideoItem *video,�������úw.�������������?¬…±�������������úw.	�������������?¬…±	����������	���úw.����������	���?¬…±�������'������úw.�������'������?¬…±��������}�        markOwnMessagesAsReceived(event.sender);��          audio, event, with_sender);�        setupWidgetLayout<mtx::events::RoomEvent<mtx::even                           QWidget *parent)�������úw.�������������?¬…±�������%������úw.�������                           QWidget *pare                           QWidget *pare                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������ad��r��Z�����3�������Ö��Ò��=��ü��¡��M��9����ð
��î
��Ê
��œ
��›
��j
��i
��%
��Ï��Î��]��å��ä��}��(��á
+��à
+��º
+��›
+��x
+��.
+��ð	��É	��È	��¢	��¡	��r	��/	��ÿ��þ��×��Æ��˜��_��U��T��!��������ò��î��Z��’��ž��r��^��,��������ê��é��¸��·��s��1��0��Ó��o��n����Ú��Ù��©��ƒ��(����Ï��‘��j��i��C��B��'��ä��´��³��Œ��{��M��(������þ��ü��û��Ý��Û��·��Š��ˆ��‡��‚��i��g��'��%��$����Ü��Ú��í��������{�TimelineItem::markOwnMessagesAsReceived(const std::string &sender)�void��}�        statusIndicator_->setState(StatusIndicatorState::Sent);�{�TimelineItem::markSent()�void��}�        colorGenerating_->waitForFinished();�        colorGenerating_->cancel();�{�TimelineItem::~TimelineItem()��}�        adjustMessageLayout();��        }�                setupSimpleLayout();�                generateBody(formatted_body);�        } else {�                setUserAvatar(sender);��                setupAvatarLayout(displayName);�                generateBody(sender, displayName, formatted_body);�        if (with_sender) {��        generateTimestamp(timestamp);��                           timestamp};�                           utils::descriptiveTime(timestamp),�                           QString(": %1").arg(body),�                           sender,�                           sender == settings.value("auth/user_id") ? "You" : displayName,�        descriptionMsg_ = {event_id_,�        QSettTimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx:TimelineItem::TimeliTimelineItem::TimelineItem(const mtx::evTimelineItem::TimelineItem(const mtx::evTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimeliTimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx:TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Text> &event,�������úw.�������������úw.	�������R������úw.������� */� * Used to display remote text messages.�/*��}�        adjustMessageLayout();�	������úw.��������        }�                setupSimpleLayout();�������úw.�������                generateBody(formatted_body);�        } else {�                setUserAvatar(sender);��                setupAvatarLayout(displayName);�                generateBody(sender, displayName, formatted_body);�        if (with_sender) {�
������úw.��������        generateTimestamp(timestamp);��                           timestamp};�                           utils::descriptiveTime(timestamp),�                           QString("* %1 %2").arg(displayName).arg(body),�                           sender,�                           "",�        descriptionMsg_ = {event_id_,��        formatted_body   = QString("<em>%1</em>").arg(formatted_body);�        auto displayName = Cache::displayName(room_id_, sender);�������úw.�������        auto timestamp   = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);����	���úw.��������        auto body           = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped();�������úw.�������        auto formatted_body = utils::linkifyMessage(utils::getMessageBody(event).trimmed());�������úw.��������        const auto sender = QString::fromStdString(event.sender);�������úw.�������        event_id_         = QString::fromStdString(event.event_id);��        markOwnMessagesAsReceived(event.sender);��        addReplyAction();�	������úw.�������        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Emote)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Emote> &event,�������úw.�������������úw.�������S������úw.������� */� * Used to display remote emote messages.�ad��¤��¬�����;�������¿��d����ü��Ê��´��²��Ž��`��_��.��-��é
��“
��’
��!
��©��¨��A��ì��ë��§����&����Í
+��
+��h
+��g
+��A
+��@
+��
+��Î	��ž	��	��v	��e	��7	��þ��ô��ó��À��¾��½��c��a��=������
����Ç��Å��5��3��2��-��®��¬������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{�TimelineItem::mark{�TimelineItem::markOwnMessagesAsReceive{�TimelineItem::markOwnMessagesAsReceive{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::markOwnMessagesAsReceive{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::mark{�TimelineItem::markOwnMessagesAsReceived(const std::string {�TimelineItem::markOwnMessagesAsReceive{�TimelineItem::markOwnMessagesAsReceived(const std::string &sender)�������úw.{�TimelineItem::markOwnMessagesAsReceived(const std::string {�TimelineItem::markOwnMessagesAsReceived(const std::string &sender)�������úw.�������������úw.�������<������úw.�������void��}�        statusIndicator_->setState(StatusIndicatorState::Sent);�	������úw.
+�������������úw.�������$������úw.�������:������úw.�������{�TimelineItem::markSent()�������úw.�������������úw.�������void��}�        colorGenerating_->waitForFinished();�        colorGenerating_->cancel();�{�TimelineItem::~TimelineItem()�������úw.�������������úw.�������������úw.��������}�        adjustMessageLayout();�	������úw.��������        }�                setupSimpleLayout();�������úw.�������                generateBody(formatted_body);�        } else {�                setUserAvatar(sender);��                setupAvatarLayout(displayName);�                generateBody(sender, displayName, formatted_body);�        if (with_sender) {�
������úw.��������        generateTimestamp(timestamp);��                           timestamp};�                           utils::descriptiveTime(timestamp),�                           QString(": %1").arg(body),�                           sender,�                           sender == settings.value("auth/user_id") ? "You" : displayName,�        descriptionMsg_ = {event_id_,�        QSettings settings;�	���	���úw.�������������úw.��������        auto displayName = Cache::displayName(room_id_, sender);�������úw.�������        auto timestamp   = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);����	���úw.��������        auto body           = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped();�������úw.�������        auto formatted_body = utils::linkifyMessage(utils::getMessageBody(event).trimmed());�������úw.��������        const auto sender = QString::fromStdString(event.sender);�������úw.�������        event_id_         = QString::fromStdString(event.event_id);��        markOwnMessagesAsReceived(event.sender);��        addReplyAction();�	������úw.�������        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Text)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������ad��J��&�����0�������ì��ê��²��x��6��â��à��ß��Ú��-��+��ë
��ê
��Ÿ
��W
��
��
��Ó��Ñ��Ð��Ë��d��b��ó��Û��Ú��™��H��G��)��(��ú
+��§
+��}
+��f
+��\
+��
+��Ý	��Æ	��o	��A	��*	�� 	��Í��™��‚��x��&��h��Á��¿��¾��¹��÷��õ����Œ��K��á��´����4����ð��‹��c��L��ç��¿��¨��B��T��ƒ��y��x        case StatusIndicatorState::Empty:�������?¬…±�������$������úw.�������$������?¬…±�������                break;�                setToolTip(tr("Sent"));�        case StatusIndicatorState::Sent:�������?¬…±�������$������úw.�������$������?¬…±�������                break;�                setToolTip(tr("Seen"));�        case StatusIndicatorState::Read:�������?¬…±�������$������úw.�������$������?¬…±�������                break;�                setToolTip(tr("Delivered"));�        case StatusIndicatorState::Received:�������?¬…±�������$������úw.�������$������?¬…±�������                break;�                setToolTip(tr("Encrypted"));�        case StatusIndicatorState::Encrypted:�������?¬…±�������$���	���úw.�������$���	���?¬…±�������        switch (state) {�������úw.�������������?¬…±��������        state_ = state;�	������úw.
+�������	������?¬…±
+�������������úw.�������������?¬…±�������{�StatusIndicator::setState(StatusIndicatorState state)�������úw.�������������?¬…±�������������úw.������        case StatusIndicatorState::Empty:�������úw.�������������?¬…±�������$������úw.�������        case StatusIndicatorState::Empty:�������úw.�������������?¬…±�������$������úw.�������$������?¬…±�����        case StatusI        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty:�������úw.�����        case StatusIndicatorState::Empty:�������úw.�����        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusI        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty:�������úw.�������$������úw.�������        }�                break;�                paintIcon(p, doubleCheckmarkIcon_);�        case StatusIndicatorState::Read: {�������úw.�������$������úw.�������        }�                break;�                paintIcon(p, checkmarkIcon_);�        case StatusIndicatorState::Received: {�������úw.�������$������úw.�������                break;�                paintIcon(p, lockIcon_);�        case StatusIndicatorState::Encrypted:�������úw.�������$���	���úw.�������        }�                break;�                paintIcon(p, clockIcon_);�        case StatusIndicatorState::Sent: {�������úw.�������$������úw.�������        switch (state_) {�������úw.
+��������        p.setPen(iconColor_);��        PainterHighQualityEnabler hq(p);�	������úw.�������#������úw.�������        Painter p(this);�	������úw.�������������úw.��������                return;�        if (state_ == StatusIndicatorState::Empty)�
������úw.
+�������������úw.�������-������úw.�������{�StatusIndicator::paintEvent(QPaintEvent *)�������úw.����������
+���úw.�������������úw.�������void��}�        QIcon(pixmap).paint(&p, rect(), Qt::AlignCenter, QIcon::Normal);��        painter.fillRect(pixmap.rect(), p.pen().color());�        painter.setCompositionMode(QPainter::CompositionMode_SourceIn);�        QPainter painter(&pixmap);�	������úw.�������������úw.��������        auto pixmap = icon.pixmap(width());�������úw.�������{�StatusIndicator::paintIcon(QPainter &p, QIcon &icon)�������úw.����������	���úw.�������������úw.�������&������úw.�������)������úw.�������0������úw.�������void��}�        doubleCheckmarkIcon_.addFile(":/icons/icons/ui/double-tick-indicator.png");�        checkmarkIcon_.addFile(":/icons/icons/ui/checkmark.png");�        clockIcon_.addFile(":/icons/icons/ui/clock.png");�        lockIcon_.addFile(":/icons/icons/ui/lock.png");�{�  : QWidget(parent)�ad��±��±�����9�������þ��Ñ��¹��¸��v����²��±��‚����Y��X��9��7��6��1��ã
��á
��¿
��|
��8
��é��«��\��þ��©��R����î
+��ì
+��ë
+��æ
+��“
+��‘
+��F
+��ü	��û	��²	��R	��ö��À��´��³����}��i��0��Ò��£��¢��…��W�����Þ��Ê��É��±���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������                  tr                  try {��                  }�                                 tr                  try {��                                 try {��                                 tr                  tr                  tr                  tr                  try {��                  }�                          return;�                            "failed to retrieve event {} from {}", event_id, room_id);�                          nhlog::net()->warn(�                  if (err) {��                  using namespace mtx::events;�            const mtx::events::collections::TimelineEvents &res, mtx::http::RequestErr err) {�          [event_id, room_id, proxy = std::move(proxy)](�          event_id,�          room_id,�        http::client()->get_event(��        });�                Q_UNUSED(dialog);�������úw.
�������                auto dialog = new dialogs::RawMessage{QString::fromStdString(obj.dump(4))};�        connect(proxy.get(), &EventProxy::eventRetrieved, this, [](const nlohmann::json &obj) {�        auto proxy = std::make_shared<EventProxy>();�������úw.��������        const auto room_id  = room_id_.toStdString();�������úw.�������        const auto event_id = event_id_.toStdString();�������úw.�������{�TimelineItem::openRawMessageViewer() const�������úw.�������������úw.�������void��}�                                           });�                                                   }�                                                             event_id_.toStdString());�                                                             room_id_.toStdString(),�                                                             "failed to read_event ({}, {})",�                                                           nhlog::net()->warn(�                                                   if (err) {�                                           [this](mtx::http::RequestErr err) {�                                           event_id_.toStdString(),�                http::client()->read_event(room_id_.toStdString(),�        if (!event_id_.isEmpty())�{�TimelineItem::sendReadReceipt() const�������úw.�������������úw.�������void��}�        setUserAvatar(userid);��        setupAvatarLayout(displayName);��        generateUserName(userid, displayName);��        auto displayName = Cache::displayName(room_id_, userid);�������úw.�������        auto userid      = descriptionMsg_.userid;�������úw.�������������úw.
+�������,������úw.�������        // TODO: should be replaced with the proper event struct.��                return;�        if (userAvatar_)�
������úw.
+�������{�ad��Ò��î�����@�������û��¦��¤��o��B����á��¬��}��|��-��Ü
��–
��V
��
��
��â��à��ß��Ú��Ž��Œ��_��2����Ñ��œ��m��l����Ì
+��†
+��F
+��
+��
+��Ò	��Ð	��Ï	��Ê	��	��‹	��S	��	��ã��«��x��w��J��
+��Ë��ˆ��G����á��³��†��…��<����¿��³��²��V��î��N��U������Å��›��e��3�����¡��t����´��U��#��ÿ��þ��½��Ÿ��“��‚��©��������������������        connect(�        });�                          });�                                  emit eventRedacted(event_id_);��                                  }�                                          return;�                                                                   err->matrix_error.error)));�                                                                 .arg(QString::fromStdString(�                                          emit redactionFailed(tr("Message redaction failed: %1")�                                  if (err) {�                          [this](const mtx::responses::EventId &, mtx::http::RequestErr err)                 emit ChatPage::instance(                emit ChatPage::instance(                emit ChatPage::instance(                emit                emit                emit                emit                emit                emit                emit ChatPage::instance()->removeTimelineEvent(room_id_, event_id);�������úw.
�������        connect(this, &TimelineItem::eventRedacted, this, [this](const QString &event_id) {��        });�                        MainWindow::instance()->openReadReceiptsDialog(event_id_);�                if (!event_id_.isEmpty())�        connect(showReadReceipts_, &QAction::triggered, this, [this]() {��        contextMenu_->addAction(redactMsg_);�        contextMenu_->addAction(markAsRead_);�        contextMenu_->addAction(viewRawMessage_);�        contextMenu_->addAction(showReadReceipts_);�        redactMsg_        = new QAction("Redact message", this);�        viewRawMessage_   = new QAction("View raw message", this);�        markAsRead_       = new QAction("Mark as read", this);�        showReadReceipts_ = new QAction("Read receipts", this);�        contextMenu_      = new QMenu(this);��        auto buttonSize_ = 32;�������úw.�������        body_            = nullptr;�	������úw.
+�������        userName_        = nullptr;�	���	���úw.
+�������        timestamp_       = nullptr;�	���
+���úw.
+�������        userAvatar_      = nullptr;�	������úw.
+�������{�TimelineItem::init()�������úw.�������������úw.�������void��}�        mainLayout_->addLayout(messageLayout_);��        messageLayout_->setAlignment(actionLayout_, Qt::AlignTop);�        messageLayout_->setAlignment(timestamp_, Qt::AlignTop);�        messageLayout_->setAlignment(statusIndicator_, Qt::AlignTop);�        actionLayout_->setAlignment(contextBtn_, Qt::AlignTop | Qt::AlignRight);�        actionLayout_->setAlignment(replyBtn_, Qt::AlignTop | Qt::AlignRight);��        messageLayout_->addWidget(timestamp_);�        messageLayout_->addWidget(statusIndicator_);�        messageLayout_->addLayout(actionLayout_);�        actionLayout_->addWidget(contextBtn_);�        actionLayout_->addWidget(replyBtn_);�        messageLayout_->addWidget(body_, 1);�{�TimelineItem::adjustMessageLayout()�������úw.�������������úw.�������void��}�        mainLayout_->addLayout(messageLayout_);��        messageLayout_->setAlignment(actionLayout_, Qt::AlignTop);�        messageLayout_->setAlignment(timestamp_, Qt::AlignTop);�        messageLayout_->setAlignment(statusIndicator_, Qt::AlignTop);�        actionLayout_->setAlignment(contextBtn_, Qt::AlignTop | Qt::AlignRight);�        actionLayout_->setAlignment(replyBtn_, Qt::AlignTop | Qt::AlignRight);��        messageLayout_->addWidget(timestamp_);�        messageLayout_->addWidget(statusIndicator_);�        messageLayout_->addLayout(actionLayout_);�        actionLayout_->addWidget(contextBtn_);�        actionLayout_->addWidget(replyBtn_);�        messageLayout_->addLayout(widgetLayout_, 1);�{�TimelineItem::adjustMessageLayoutForWidget()�������úw.�������������úw.�������void�ad�� ��������������ô��Ÿ��I��=��û��Ñ��›��i��6��×
��ª
��4
��Ö��w��E��!�� ��Ë��­��¡������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������        connect(�           connect(�           connect(�           connect(�        });�                          });�                                  emit eventRedacted(event_id_);�#������úw.
��������                                  }�                                          return;�                                                                   err->matrix_error.error)));�                                                                 .arg(QString::fromStdString(�                                          emit redactionFailed(tr("Message redaction failed: %1")�+������úw.
�������                                  if (err) {�                          [this](const mtx::responses::EventId &, mtx::http::RequestErr err) {�                          event_id_.toStdString(),�                          room_id_.toStdString(),�                        http::client()->redact_event(�                if (!event_id_.isEmpty())�        connect(redactMsg_, &QAction::triggered, this, [this]() {�        });�                emit ChatPage::instance()->showNotification(msg);�������úw.
�������        connect(this, &TimelineItem::redactionFailed, this, [](const QString &msg) {�        });�ad��u��É������������ÿ��Û��Ž��F��õ��ã����†��„��@��;��7
��5
��É�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������        generateUserName(user_id, displayname);�	������úw.�������	������?¬…±�������������úw.�������������?¬…±�������#������úw.�������#������?¬…±        generateUserName(user_id, displayname);�	������úw.        generateUserName(user_id, displayname);�	������úw.�������������úw.�������#������úw.�������{�TimelineItem::generateBody(const QString &user_id, const QString &displayname, const QString &body)�������úw.�������������úw.�������"������úw.�������+������úw.�������:������úw.�������C������úw.�������V������úw.�������_������úw.�������void�// The username/timestamp is displayed along with the message body.�}�        }�                userName_->setStyleSheet("QLabel { color : " + userColor + "; }");�                }�                        Cache::insertUserColor(userName_->toolTip(), userColor);�                if (Cache::userColor(userName_->toolTip()).isEmpty()) {�                // another TimelineItem might have inserted in the meantime.�        if (!userColor.isEmpty()) {��ad��Æ��B
������������þ��Æ��®��­��|��z��y��t��ë��é��Ï��—��•��”����+��)��ç
��Ï
��
��J
��H
��G
��B
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������void��}�        stylvoid��}�        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);�     void��}�        style()->drawPrimitive(QStyle::PE_Widget, &ovoid��}�        style()->drawPrimitive(Qvoid��}�        style()->drawPrimitive(Qvoid��}�        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);�        QPainter p(this);�	������úw.�������������úw.�������        opt.init(this);�        QStyleOption opt;�	������úw.�������������úw.�������{�TimelineItem::paintEvent(QPaintEvent *)�������úw.����������
+���úw.�������������úw.�������void��}�                contextMenu_->exec(event->globalPos());�        if (contextMenu_)�{�TimelineItem::contextMenuEvent(QContextMenuEvent *event)�������úw.�������������úw.������� ������úw.�������3������úw.�������void��}�        userAvatar_->setImage(room_id_, userid);��                return;�        if (userAvatar_ == nullptr)�
������úw.
+�������{�ad���������;�������Á��™��P��ü��û��Ï��Ÿ��b��ï
��î
��ª
��b
��6
��ë��¿��¾��u��F������»��º��„��;��ñ
+��ð
+��›
+��V
+��T
+��S
+��P
+��/
+��+
+��·	��]	��	��Ì��q����	��ó��Ý��Û��·��‰��ˆ��3��¾��½��‹��<��;����Ç������I��H���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������        if (ty == mtx::events::MessageType::Emote) {��              if (ty == mtx::events::MessageTy        if (ty == mtx::events::MessageTy        if (ty == mtx::events::MessageType::Emote) {��              if (ty == mtx::events::MessageTy        if (ty == mtx::events::MessageTy        if (ty == mt        if (ty == mtx::events::MessageTy        if (ty == mtx::events::MessageTy        if (ty == mt        if (ty == mt        if (ty == mt        if (ty == mtx::events::MessageType::Emote) {��              if (ty == mt        if (ty == mtx::events::MessageTy        if (ty == mtx::events::MessageType::Emote) {��        QString emptyEventId;�	������úw.�������������úw.��������                formatted_body = body.toHtmlEscaped();�        if (formatted_body == body.trimmed().toHtmlEscaped())�        // Escape html if the input is not formatted.��        auto formatted_body = utils::markdownToHtml(body);�������úw.�������        // Generate the html body to be rendered.��        auto timestamp   = QDateTime::currentDateTime();����	���úw.����������	���úw.�������'������úw.�������        auto displayName = Cache::displayName(room_id_, userid);�������úw.��������        addReplyAction();�	������úw.�������        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(ty)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool withSender,�!���
+���úw.�������                           QString body,�������úw.�������$������úw.�������                           const QString &userid,�"������úw.�������+������úw.�������TimelineItem::TimelineItem(mtx::events::MessageType ty,�������úw.�������������úw.	�������5������úw.������� */� * For messages created locally.�/*��}�        setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);�        parentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);��        statusIndicator_->setFixedHeight(tsFm.height() - tsFm.leading());�        statusIndicator_->setFixedWidth(tsFm.height() - tsFm.leading());�        statusIndicator_ = new StatusIndicator(this);��        QFontMetrics tsFm(timestampFont_);�	������úw.�������������úw.��������        timestampFont_.setStyleHint(QFont::Monospace);�        timestampFont_.setFamily("Monospace");�        timestampFont_.setPointSizeF(timestampFont_.pointSizeF() * 0.9);��        contextBtn_->setMenu(contextMenu_);�        contextBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));�        contextBtn_->setIcon(context_icon);�        context_icon.addFile(":/icons/icons/ui/vertical-ellipsis.png");�        QIcon context_icon;�	������úw.�������������úw.��������        contextBtn_->setCornerRadius(buttonSize_ / 2);�	������úw.
+�������������úw.�������&������úw.�������        contextBtn_->setFixedSize(buttonSize_, buttonSize_);�        contextBtn_->setToolTip(tr("Options"));�        contextBtn_ = new FlatButton(this);��        connect(replyBtn_, &FlatButton::clicked, this, &TimelineItem::replyAction);�        replyBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));�        replyBtn_->setIcon(reply_icon);�        reply_icon.addFile(":/icons/icons/ui/mail-reply.png");�ad��Í��Ù�����<�������þ��ý��ø������]��\��/��’��…��é
��è
��¹
��·
��¶
��—
��’
��
��
��Ð��p��o����Ò��t��h��f��e��`������Ð
+��£
+��w
+��B
+��8
+��
+��Ú	��›	��K	���	��Ö��Ã��Â��N��M����Ø��†��m�������ö��ô��ó��î��ž��œ��9��Ù�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������        QString userColor = colorGenerating_->result();�	���        QString user        QString user        QString userColor = colorGenerating_->result();�	������úw.�������	���        QString userColor = colorGenerating_->result();�	������úw.�������	���        QString user        QString userColor = colorGenerating_->result();�	������úw.�������	���        QString userColor = colorGenerat        QString user        QString userColor = colorGenerat        QString userColor = colorGenerat        QString userColor = colorGenerat        QString userColor = colorGenerating_->result();�	������úw.����������	���úw.�������        nhlog::ui()->debug("finishedGeneratingColor for: {}", userName_->toolTip().toStdString());�{�TimelineItem::finishedGeneratingColor()�������úw.�������������úw.�������void��}�        }�                }�                        userName_->setStyleSheet("QLabel { color : " + userColor + "; }");�                } else {�                        colorGenerating_->setFuture(QtConcurrent::run(generate));�                if (userColor.isEmpty()) {�                // If the color is empty, then generate it asynchronously��                QString userColor = Cache::userColor(userName_->toolTip());�������úw.����������	���úw.��������                };�                        return userColor;�                          userName_->toolTip(), backgroundColor().name());�                        QString userColor = utils::generateContrastingHexColor(�                std::function<QString()> generate = [this]() {�                // generate user's unique color.�        if (userName_) {�
���	���úw.
+�������        }�                colorGenerating_->waitForFinished();�                colorGenerating_->cancel();�        if (colorGenerating_->isRunning()) {�        // Cancel and wait if we are already generating the color.�{�TimelineItem::refreshAuthorColor()�������úw.�������������úw.�������void��}�        });�                                                        ChatPage::instance()->currentRoom());�                MainWindow::instance()->openUserProfile(user_id,�        connect(body_, &TextLabel::userProfileTriggered, this, [](const QString &user_id) {��        body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);�        body_ = new TextLabel(utils::replaceEmoji(body), this);�{�TimelineItem::generateBody(const QString &body)�������úw.�������������úw.�������"������úw.�������+������úw.�������void�// Only the body is displayed.��}�        sendReadReceipt();�	������úw.��������                statusIndicator_->setState(StatusIndicatorState::Received);�������úw.
+�������#������úw.�������,������úw.�������B������úw.�������        else�                statusIndicator_->setState(StatusIndicatorState::Encrypted);�������úw.
+�������#������úw.�������,������úw.�������B���	���úw.�������        if (isEncrypted)�
������úw.��������        isReceived_ = true;�	������úw.
+�������{�TimelineItem::markReceived(bool isEncrypted)�������úw.�������������úw.�������!������úw.�������void��}�ad��q��©������������à��É��¿��¾��¬��ª��©������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������}�        update();��        }�                break;�                setToolTip("");�ad����C�����I�������ì��¹��£��¡��J��$��#��ò��ð��ï��r����Ä
��i
��
��
��Î��¸��¶��_��9��8����������Ö��Ò��<��û
+�� 
+��L
+��8
+��
+��î	��ì	��È	��š	��™	��h	��g	�� 	��Ç��\��[��ê��r��q��K��
+��ç��´��v��O��N��(��'��ø��›��š��W��'��&��ÿ��î��À��‡��}��|��I��G��F��C�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*��}�        adjustMessageLayout();�	������úw.�������	������?¬…±��������  /*��}�        adjust/*��}�        adjust/*��}�        adjustMessageLayout();�	��/*��}�        adjustMessageLayout();�	��/*��}�        adjustMessageLayout();�	������úw.�������	��/*��}�        adjust/*��}�        adjustMessageLayout();�	��/*��}�        adjustMessageLayout();�	��/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjust/*��}�        adjustMessageLayout();�	������úw.��������        }�                setupSimpleLayout();�������úw.�������                generateBody(formatted_body);�        } else {�                setUserAvatar(sender);��                setupAvatarLayout(displayName);�                generateBody(sender, displayName, formatted_body);��                auto displayName = Cache::displayName(room_id_, sender);�������úw.�������        if (with_sender) {�
������úw.��������        generateTimestamp(timestamp);��                           timestamp};�                           utils::descriptiveTime(timestamp),�                           " sent a notification",�                           sender,�                           Cache::displayName(room_id_, sender),�        descriptionMsg_ = {event_id_,��        auto body           = QString::fromStdString(event.content.body).trimmed().toHtmlEscaped();�������úw.�������        auto formatted_body = utils::linkifyMessage(utils::getMessageBody(event).trimmed());�������úw.��������        const auto timestamp = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);����	���úw.�������        const auto sender    = QString::fromStdString(event.sender);�������úw.�������        event_id_            = QString::fromStdString(event.event_id);��        markOwnMessagesAsReceived(event.sender);��        addReplyAction();�	������úw.�������        init();�	������úw.�������{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Notice)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Notice> &event,�������úw.�������������úw.�������T������úw.������� */� * Used to display remote notice messages.�/*��}�        markOwnMessagesAsReceived(event.sender);��          video, event, with_sender);�        setupWidgetLayout<mtx::events::RoomEvent<mtx::events::msg::Video>, VideoItem>(�{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Video)�  : QWidget(parent)�                           QWidget *parent)�������úw.�������%������úw.�������                           const QString &room_id,�"������úw.�������+������úw.�������                           bool with_sender,�!������úw.�������                           const mtx::events::RoomEvent<mtx::events::msg::Video> &event,�S������úw.�������TimelineItem::TimelineItem(VideoItem *video,�������úw.�������������úw.	����������	���úw.�������'������úw.��������}�        markOwnMessagesAsReceived(event.sender);��          audio, event, with_sender);�        setupWidgetLayout<mtx::events::RoomEvent<mtx::events::msg::Audio>, AudioItem>(�{�  , room_id_{room_id}�  , message_type_(mtx::events::MessageType::Audio)�  : QWidget(parent)�ad��Ä��<������������é��ß��Ý��Ü��×��Q��O������á��‹��^��G��ò
��Å
��®
��]
��5
��
��Í��¥��Ž��<��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������        case StatusIndicatorState::Empty:�������úw.�������������?¬…±�����        case StatusIndicatorState::Empty        case StatusI        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty        case StatusIndicatorState::Empty:�������úw.�������$������úw.�������                break;�                setToolTip(tr("Sent"));�        case StatusIndicatorState::Sent:�������úw.�������$������úw.�������                break;�                setToolTip(tr("Seen"));�        case StatusIndicatorState::Read:�������úw.�������$������úw.�������                break;�                setToolTip(tr("Delivered"));�        case StatusIndicatorState::Received:�������úw.�������$������úw.�������                break;�                setToolTip(tr("Encrypted"));�        case StatusIndicatorState::Encrypted:�������úw.�������$���	���úw.�������        switch (state) {�������úw.��������        state_ = state;�	������úw.
+�������������úw.�������{�StatusIndicator::setState(StatusIndicatorState state)�������úw.�������������úw.�������������úw.�������0������úw.�������void��}�        }�                break;�
\ No newline at end of file
diff --git a/src/timeline/TimelineItem.cpp b/src/timeline/TimelineItem.cpp
index dd3b48c3b2642031109320a4e9a1db7d632eaa77..7916bd80c2efee1efef09b1d3f70772d3ad18802 100644
--- a/src/timeline/TimelineItem.cpp
+++ b/src/timeline/TimelineItem.cpp
@@ -326,8 +326,7 @@ TimelineItem::TimelineItem(mtx::events::MessageType ty,
                 generateBody(userid, displayName, formatted_body);
                 setupAvatarLayout(displayName);
 
-                AvatarProvider::resolve(
-                  room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
+                setUserAvatar(userid);
         } else {
                 generateBody(formatted_body);
                 setupSimpleLayout();
@@ -509,8 +508,7 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Notice
                 generateBody(sender, displayName, formatted_body);
                 setupAvatarLayout(displayName);
 
-                AvatarProvider::resolve(
-                  room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
+                setUserAvatar(sender);
         } else {
                 generateBody(formatted_body);
                 setupSimpleLayout();
@@ -558,8 +556,7 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Emote>
                 generateBody(sender, displayName, formatted_body);
                 setupAvatarLayout(displayName);
 
-                AvatarProvider::resolve(
-                  room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
+                setUserAvatar(sender);
         } else {
                 generateBody(formatted_body);
                 setupSimpleLayout();
@@ -607,8 +604,7 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Text>
                 generateBody(sender, displayName, formatted_body);
                 setupAvatarLayout(displayName);
 
-                AvatarProvider::resolve(
-                  room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
+                setUserAvatar(sender);
         } else {
                 generateBody(formatted_body);
                 setupSimpleLayout();
@@ -793,9 +789,8 @@ TimelineItem::setupAvatarLayout(const QString &userName)
         QFont f;
         f.setPointSizeF(f.pointSizeF());
 
-        userAvatar_ = new Avatar(this);
+        userAvatar_ = new Avatar(this, QFontMetrics(f).height() * 2);
         userAvatar_->setLetter(QChar(userName[0]).toUpper());
-        userAvatar_->setSize(QFontMetrics(f).height() * 2);
 
         // TODO: The provided user name should be a UserId class
         if (userName[0] == '@' && userName.size() > 1)
@@ -822,12 +817,12 @@ TimelineItem::setupSimpleLayout()
 }
 
 void
-TimelineItem::setUserAvatar(const QImage &avatar)
+TimelineItem::setUserAvatar(const QString &userid)
 {
         if (userAvatar_ == nullptr)
                 return;
 
-        userAvatar_->setImage(avatar);
+        userAvatar_->setImage(room_id_, userid);
 }
 
 void
@@ -911,8 +906,7 @@ TimelineItem::addAvatar()
 
         setupAvatarLayout(displayName);
 
-        AvatarProvider::resolve(
-          room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
+        setUserAvatar(userid);
 }
 
 void
diff --git a/src/timeline/TimelineItem.h b/src/timeline/TimelineItem.h
index fe354000e23669a4f2d7a50efcfaab132b49ff15..356976e5931f140a6ec37d714f221b04af233619 100644
--- a/src/timeline/TimelineItem.h
+++ b/src/timeline/TimelineItem.h
@@ -215,7 +215,7 @@ public:
         void setBackgroundColor(const QColor &color) { backgroundColor_ = color; }
         QColor backgroundColor() const { return backgroundColor_; }
 
-        void setUserAvatar(const QImage &pixmap);
+        void setUserAvatar(const QString &userid);
         DescInfo descriptionMessage() const { return descriptionMsg_; }
         QString eventId() const { return event_id_; }
         void setEventId(const QString &event_id) { event_id_ = event_id; }
@@ -336,8 +336,7 @@ TimelineItem::setupLocalWidgetLayout(Widget *widget, const QString &userid, bool
                 generateBody(userid, displayName, "");
                 setupAvatarLayout(displayName);
 
-                AvatarProvider::resolve(
-                  room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
+                setUserAvatar(userid);
         } else {
                 setupSimpleLayout();
         }
@@ -381,8 +380,7 @@ TimelineItem::setupWidgetLayout(Widget *widget, const Event &event, bool withSen
                 generateBody(sender, displayName, "");
                 setupAvatarLayout(displayName);
 
-                AvatarProvider::resolve(
-                  room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
+                setUserAvatar(sender);
         } else {
                 setupSimpleLayout();
         }
diff --git a/src/ui/Avatar.cpp b/src/ui/Avatar.cpp
index 4b4cd27237e8ba5ce734fc837d361e27252b9a02..98bf21c61d4f9a5ffdaf1414fae4ab5fae24b409 100644
--- a/src/ui/Avatar.cpp
+++ b/src/ui/Avatar.cpp
@@ -1,12 +1,13 @@
 #include <QPainter>
 
+#include "AvatarProvider.h"
 #include "Utils.h"
 #include "ui/Avatar.h"
 
-Avatar::Avatar(QWidget *parent)
+Avatar::Avatar(QWidget *parent, int size)
   : QWidget(parent)
+  , size_(size)
 {
-        size_   = ui::AvatarSize;
         type_   = ui::AvatarType::Letter;
         letter_ = "A";
 
@@ -61,35 +62,31 @@ Avatar::setBackgroundColor(const QColor &color)
 }
 
 void
-Avatar::setSize(int size)
+Avatar::setLetter(const QString &letter)
 {
-        size_ = size;
-
-        if (!image_.isNull())
-                pixmap_ = utils::scaleImageToPixmap(image_, size_);
-
-        QFont _font(font());
-        _font.setPointSizeF(size_ * (ui::FontSize) / 40);
-
-        setFont(_font);
+        letter_ = letter;
+        type_   = ui::AvatarType::Letter;
         update();
 }
 
 void
-Avatar::setLetter(const QString &letter)
+Avatar::setImage(const QString &avatar_url)
 {
-        letter_ = letter;
-        type_   = ui::AvatarType::Letter;
-        update();
+        AvatarProvider::resolve(avatar_url, size_, this, [this](QPixmap pm) {
+                type_   = ui::AvatarType::Image;
+                pixmap_ = pm;
+                update();
+        });
 }
 
 void
-Avatar::setImage(const QImage &image)
+Avatar::setImage(const QString &room, const QString &user)
 {
-        image_  = image;
-        type_   = ui::AvatarType::Image;
-        pixmap_ = utils::scaleImageToPixmap(image_, size_);
-        update();
+        AvatarProvider::resolve(room, user, size_, this, [this](QPixmap pm) {
+                type_   = ui::AvatarType::Image;
+                pixmap_ = pm;
+                update();
+        });
 }
 
 void
diff --git a/src/ui/Avatar.h b/src/ui/Avatar.h
index 41967af559b3752082524bee06a6650853a41a1f..b9225dd1a667eb1a1eeb07ca8d0fd2763cf0fb10 100644
--- a/src/ui/Avatar.h
+++ b/src/ui/Avatar.h
@@ -15,13 +15,14 @@ class Avatar : public QWidget
         Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
 
 public:
-        explicit Avatar(QWidget *parent = 0);
+        explicit Avatar(QWidget *parent = 0, int size = ui::AvatarSize);
 
         void setBackgroundColor(const QColor &color);
         void setIcon(const QIcon &icon);
-        void setImage(const QImage &image);
+        void setImage(const QString &avatar_url);
+        void setImage(const QString &room, const QString &user);
         void setLetter(const QString &letter);
-        void setSize(int size);
+        //        void setSize(int size);
         void setTextColor(const QColor &color);
 
         QColor backgroundColor() const;
@@ -41,7 +42,8 @@ private:
         QColor background_color_;
         QColor text_color_;
         QIcon icon_;
-        QImage image_;
         QPixmap pixmap_;
+        const std::string room;
+        const std::string user;
         int size_;
 };