diff --git a/callwidget.cpp b/callwidget.cpp
index ec76335b655c42f1f81cce54e6bd111404c57b69..4667a205ccaf3b5d35fa16e0561105709740f685 100644
--- a/callwidget.cpp
+++ b/callwidget.cpp
@@ -863,6 +863,33 @@ CallWidget::showChatView(const std::string& accountId, const lrc::api::conversat
     setupChatView(convInfo);
 }
 
+void
+CallWidget::setConversationProfileData(const lrc::api::conversation::Info& convInfo)
+{
+    auto convModel = LRCInstance::getCurrentConversationModel();
+    auto accInfo = &LRCInstance::getCurrentAccountInfo();
+    auto contactUri = convInfo.participants.front();
+    try {
+        auto& contact = accInfo->contactModel->getContact(contactUri);
+        auto bestName = Utils::bestNameForConversation(convInfo, *convModel);
+        ui->messageView->setInvitation(
+            (contact.profileInfo.type == lrc::api::profile::Type::PENDING),
+            bestName,
+            contactUri
+        );
+        if (!contact.profileInfo.avatar.empty()) {
+            ui->messageView->setSenderImage(contactUri, contact.profileInfo.avatar);
+        } else {
+            auto avatar = Utils::conversationPhoto(convInfo.uid, *accInfo);
+            QByteArray ba;
+            QBuffer bu(&ba);
+            avatar.save(&bu, "PNG");
+            std::string avatarString = ba.toBase64().toStdString();
+            ui->messageView->setSenderImage(contactUri, avatarString);
+        }
+    } catch (...) {}
+}
+
 void
 CallWidget::setupChatView(const lrc::api::conversation::Info& convInfo)
 {
@@ -898,8 +925,6 @@ CallWidget::setupChatView(const lrc::api::conversation::Info& convInfo)
     ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn);
 
     ui->messageView->setMessagesVisibility(false);
-    ui->messageView->clear();
-    ui->messageView->setInvitation(false);
     Utils::oneShotConnect(ui->messageView, &MessageWebView::messagesCleared,
         [this, convInfo] {
             auto convModel = LRCInstance::getCurrentConversationModel();
@@ -908,33 +933,10 @@ CallWidget::setupChatView(const lrc::api::conversation::Info& convInfo)
                 [this] {
                     ui->messageView->setMessagesVisibility(true);
                 });
-            // Contact Avatars
-            auto accInfo = &LRCInstance::getCurrentAccountInfo();
-            auto contactUri = convInfo.participants.front();
-            try {
-                auto& contact = accInfo->contactModel->getContact(contactUri);
-                auto bestName = Utils::bestNameForConversation(convInfo, *convModel);
-                ui->messageView->setInvitation(
-                    (contact.profileInfo.type == lrc::api::profile::Type::PENDING),
-                    bestName,
-                    accInfo->contactModel->getContactProfileId(contact.profileInfo.uri)
-                );
-                if (!contact.profileInfo.avatar.empty()) {
-                    ui->messageView->setSenderImage(
-                        accInfo->contactModel->getContactProfileId(contactUri),
-                        contact.profileInfo.avatar);
-                } else {
-                    auto avatar = Utils::conversationPhoto(convInfo.uid, *accInfo);
-                    QByteArray ba;
-                    QBuffer bu(&ba);
-                    avatar.save(&bu, "PNG");
-                    std::string avatarString = ba.toBase64().toStdString();
-                    ui->messageView->setSenderImage(
-                        accInfo->contactModel->getContactProfileId(contactUri),
-                        avatarString);
-                }
-            } catch (...) {}
+            setConversationProfileData(convInfo);
         });
+    ui->messageView->setInvitation(false);
+    ui->messageView->clear();
 }
 
 void
@@ -1272,15 +1274,21 @@ CallWidget::connectAccount(const std::string& accId)
     auto& contactModel = LRCInstance::getCurrentAccountInfo().contactModel;
     disconnect(contactAddedConnection_);
     contactAddedConnection_ = connect(contactModel.get(), &lrc::api::ContactModel::contactAdded,
-        [this, &contactModel](const std::string & contactId) {
+        [this, &contactModel](const std::string & contactUri) {
             auto convModel = LRCInstance::getCurrentConversationModel();
             auto currentConversation = Utils::getConversationFromUid(LRCInstance::getSelectedConvUid(),
                 *convModel);
             if (currentConversation == convModel->allFilteredConversations().end()) {
                 return;
             }
-            if (contactId == contactModel.get()->getContact((*currentConversation).participants.at(0)).profileInfo.uri) {
+            if (contactUri == contactModel.get()->getContact((*currentConversation).participants.at(0)).profileInfo.uri) {
+                // update call screen
+                auto avatarImg = QPixmap::fromImage(imageForConv((*currentConversation).uid));
+                ui->callingPhoto->setPixmap(avatarImg);
+                ui->callerPhoto->setPixmap(avatarImg);
+                // update conversation
                 ui->messageView->clear();
+                setConversationProfileData(*currentConversation);
                 ui->messageView->printHistory(*convModel, currentConversation->interactions);
             }
         });
diff --git a/callwidget.h b/callwidget.h
index a2eb2873925f92d5d3a1642900ad0bbee6169a54..4efcc0e0381bf1b25b95994adfe246321e50416c 100644
--- a/callwidget.h
+++ b/callwidget.h
@@ -72,6 +72,7 @@ public slots:
     void settingsButtonClicked();
     void showChatView(const QModelIndex& nodeIdx);
     void showChatView(const std::string & accountId, const lrc::api::conversation::Info & convInfo);
+    void setConversationProfileData(const lrc::api::conversation::Info & convInfo);
     void setupChatView(const lrc::api::conversation::Info& convInfo);
     void slotAcceptInviteClicked(const QModelIndex& index);
     void slotBlockInviteClicked(const QModelIndex& index);
diff --git a/conversationitemdelegate.cpp b/conversationitemdelegate.cpp
index 7418fc57a1d576931c0ca4f790070d516b99237e..4cbc7aae1ca032012085ed34d6f92973445da86f 100644
--- a/conversationitemdelegate.cpp
+++ b/conversationitemdelegate.cpp
@@ -22,6 +22,7 @@
 #include <QApplication>
 #include <QPainter>
 #include <QPixmap>
+#include <QSvgRenderer>
 
 // Client
 #include "smartlistmodel.h"
@@ -35,6 +36,11 @@
 ConversationItemDelegate::ConversationItemDelegate(QObject* parent)
     : QItemDelegate(parent)
 {
+    QSvgRenderer svgRenderer(QString(":/images/icons/ic_baseline-search-24px.svg"));
+    searchIcon_ = new QPixmap(QSize(sizeImage_, sizeImage_));
+    searchIcon_->fill(Qt::transparent);
+    QPainter pixPainter(searchIcon_);
+    svgRenderer.render(&pixPainter);
 }
 
 void
@@ -59,92 +65,99 @@ ConversationItemDelegate::paint(QPainter* painter
         highlightMap_[index.row()] = option.state & QStyle::State_MouseOver;
     }
 
+    using namespace lrc::api;
+    auto type = Utils::toEnum<profile::Type>(
+            index.data(static_cast<int>(SmartListModel::Role::ContactType)).value<int>()
+        );
+
     // One does not simply keep the highlighted state drawn when the context
     // menu is open�
-    QColor presenceBorderColor = Qt::white;
-    auto rowHighlight = highlightMap_.find(index.row());
-    if (selected) {
-       painter->fillRect(option.rect, RingTheme::smartlistSelection_);
-       presenceBorderColor = RingTheme::smartlistSelection_;
-    } else if (rowHighlight != highlightMap_.end() && (*rowHighlight).second) {
-       painter->fillRect(option.rect, RingTheme::smartlistHighlight_);
-       presenceBorderColor = RingTheme::smartlistHighlight_;
-    }
-    auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>().toStdString();
-    auto conversation = Utils::getConversationFromUid(convUid, *LRCInstance::getCurrentConversationModel());
-    if (LRCInstance::getCurrentCallModel()->hasCall(conversation->callId)) {
-        auto color = QColor(RingTheme::blue_.lighter(180));
-        presenceBorderColor = color;
-        color.setAlpha(128);
-        painter->fillRect(option.rect, color);
+    QString uriStr = index.data(static_cast<int>(SmartListModel::Role::URI)).value<QString>();
+    if (not (type == profile::Type::TEMPORARY and uriStr.isEmpty())) {
+        auto rowHighlight = highlightMap_.find(index.row());
+        if (selected) {
+            painter->fillRect(option.rect, RingTheme::smartlistSelection_);
+        } else if (rowHighlight != highlightMap_.end() && (*rowHighlight).second) {
+            painter->fillRect(option.rect, RingTheme::smartlistHighlight_);
+        }
+        auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>().toStdString();
+        auto conversation = Utils::getConversationFromUid(convUid, *LRCInstance::getCurrentConversationModel());
+        if (LRCInstance::getCurrentCallModel()->hasCall(conversation->callId)) {
+            auto color = QColor(RingTheme::blue_.lighter(180));
+            color.setAlpha(128);
+            painter->fillRect(option.rect, color);
+        }
     }
 
     QRect &rect = opt.rect;
 
-    // Avatar drawing
     opt.decorationSize = QSize(sizeImage_, sizeImage_);
     opt.decorationPosition = QStyleOptionViewItem::Left;
     opt.decorationAlignment = Qt::AlignCenter;
-
     QRect rectAvatar(dx_ + rect.left(), rect.top() + dy_, sizeImage_, sizeImage_);
-    drawDecoration(painter, opt, rectAvatar,
-                   QPixmap::fromImage(index.data(Qt::DecorationRole).value<QImage>())
-                   .scaled(sizeImage_, sizeImage_, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+    if (type == profile::Type::TEMPORARY and uriStr.isEmpty()) {
+        // Search icon
+        drawDecoration(painter, opt, rectAvatar, *searchIcon_);
+    } else {
+        // Avatar drawing
+        drawDecoration(painter, opt, rectAvatar,
+            QPixmap::fromImage(index.data(Qt::DecorationRole).value<QImage>())
+            .scaled(sizeImage_, sizeImage_, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+    }
 
     QFont font(painter->font());
 
-    // If there's unread messages, a message count is displayed
-    if (auto messageCount = index.data(static_cast<int>(SmartListModel::Role::UnreadMessagesCount)).toInt()) {
-        QString messageCountText = (messageCount > 9) ? "9+" : QString::number(messageCount);
-        qreal fontSize = messageCountText.count() > 1 ? 7 : 8;
-        font.setPointSize(fontSize);
-
-        // ellipse
-        QPainterPath ellipse;
-        qreal ellipseHeight = sizeImage_ / 6;
-        qreal ellipseWidth = ellipseHeight;
-        QPointF ellipseCenter(rectAvatar.right() - ellipseWidth + 1, rectAvatar.top() + ellipseHeight + 1);
-        QRect ellipseRect(ellipseCenter.x() - ellipseWidth, ellipseCenter.y() - ellipseHeight,
-            ellipseWidth * 2, ellipseHeight * 2);
-        ellipse.addRoundedRect(ellipseRect, ellipseWidth, ellipseHeight);
-        painter->fillPath(ellipse, RingTheme::notificationRed_);
-
-        // text
-        painter->setPen(Qt::white);
-        painter->setOpacity(1);
-        painter->setFont(font);
-        ellipseRect.setTop(ellipseRect.top() - 2);
-        painter->drawText(ellipseRect, Qt::AlignCenter, messageCountText);
-    }
+    if (type != profile::Type::TEMPORARY) {
+        // If there's unread messages, a message count is displayed
+        if (auto messageCount = index.data(static_cast<int>(SmartListModel::Role::UnreadMessagesCount)).toInt()) {
+            QString messageCountText = (messageCount > 9) ? "9+" : QString::number(messageCount);
+            qreal fontSize = messageCountText.count() > 1 ? 7 : 8;
+            font.setPointSize(fontSize);
+
+            // ellipse
+            QPainterPath ellipse;
+            qreal ellipseHeight = sizeImage_ / 6;
+            qreal ellipseWidth = ellipseHeight;
+            QPointF ellipseCenter(rectAvatar.right() - ellipseWidth + 1, rectAvatar.top() + ellipseHeight + 1);
+            QRect ellipseRect(ellipseCenter.x() - ellipseWidth, ellipseCenter.y() - ellipseHeight,
+                ellipseWidth * 2, ellipseHeight * 2);
+            ellipse.addRoundedRect(ellipseRect, ellipseWidth, ellipseHeight);
+            painter->fillPath(ellipse, RingTheme::notificationRed_);
+
+            // text
+            painter->setPen(Qt::white);
+            painter->setOpacity(1);
+            painter->setFont(font);
+            ellipseRect.setTop(ellipseRect.top() - 2);
+            painter->drawText(ellipseRect, Qt::AlignCenter, messageCountText);
+        }
 
-    // Presence indicator
-    if (index.data(static_cast<int>(SmartListModel::Role::Presence)).value<bool>()) {
-        qreal radius = sizeImage_ / 6;
-        QPainterPath outerCircle, innerCircle;
-        QPointF center(rectAvatar.right() - radius + 2, (rectAvatar.bottom() - radius) + 1 + 2);
-        qreal outerCRadius = radius;
-        qreal innerCRadius = outerCRadius * 0.75;
-        outerCircle.addEllipse(center, outerCRadius, outerCRadius);
-        innerCircle.addEllipse(center, innerCRadius, innerCRadius);
-        painter->fillPath(outerCircle, presenceBorderColor);
-        painter->fillPath(innerCircle, RingTheme::presenceGreen_);
+        // Presence indicator
+        if (index.data(static_cast<int>(SmartListModel::Role::Presence)).value<bool>()) {
+            qreal radius = sizeImage_ / 6;
+            QPainterPath outerCircle, innerCircle;
+            QPointF center(rectAvatar.right() - radius + 2, (rectAvatar.bottom() - radius) + 1 + 2);
+            qreal outerCRadius = radius;
+            qreal innerCRadius = outerCRadius * 0.75;
+            outerCircle.addEllipse(center, outerCRadius, outerCRadius);
+            innerCircle.addEllipse(center, innerCRadius, innerCRadius);
+            painter->fillPath(outerCircle, Qt::white);
+            painter->fillPath(innerCircle, RingTheme::presenceGreen_);
+        }
     }
 
-    using namespace lrc::api;
-    auto type = Utils::toEnum<profile::Type>(
-            index.data(static_cast<int>(SmartListModel::Role::ContactType)).value<int>()
-        );
     switch (type) {
+    case profile::Type::TEMPORARY:
     case profile::Type::RING:
     case profile::Type::SIP:
-    case profile::Type::TEMPORARY:
-        paintConversationItem(painter, option, rect, index);
+        paintConversationItem(painter, option, rect, index,
+                              type == profile::Type::TEMPORARY);
         break;
     case profile::Type::PENDING:
-        paintRingInviteConversationItem(painter, option, rect, index);
+        paintInvitationItem(painter, option, rect, index);
         break;
     default:
-        paintConversationItem(painter, option, rect, index);
+        paintConversationItem(painter, option, rect, index, true);
         break;
     }
 }
@@ -162,7 +175,8 @@ void
 ConversationItemDelegate::paintConversationItem(QPainter* painter,
                                                 const QStyleOptionViewItem& option,
                                                 const QRect& rect,
-                                                const QModelIndex& index) const
+                                                const QModelIndex& index,
+                                                const bool isTemporary) const
 {
     Q_UNUSED(option);
     QFont font(painter->font());
@@ -186,9 +200,16 @@ ConversationItemDelegate::paintConversationItem(QPainter* painter,
     auto topMargin = 4;
     auto bottomMargin = 8;
 
+    int rect1Width;
+    if (!isTemporary) {
+        rect1Width = rect.width() - leftMargin - infoTextWidth_ - infoTextWidthModifier - 8;
+    } else {
+        rect1Width = rect.width() - leftMargin - rightMargin;
+    }
+
     QRect rectName1(rect.left() + leftMargin,
                     rect.top() + topMargin,
-                    rect.width() - leftMargin - infoTextWidth_ - infoTextWidthModifier - 8,
+                    rect1Width,
                     rect.height() / 2 - 2);
 
     QRect rectName2(rectName1.left(),
@@ -196,16 +217,6 @@ ConversationItemDelegate::paintConversationItem(QPainter* painter,
                     rectName1.width(),
                     rectName1.height() - bottomMargin + infoText2HeightModifier);
 
-    QRect rectInfo1(rectName1.left() + rectName1.width(),
-                    rect.top() + topMargin,
-                    infoTextWidth_ - rightMargin + infoTextWidthModifier + 2,
-                    rect.height() / 2 - 2);
-
-    QRect rectInfo2(rectInfo1.left(),
-                    rectInfo1.top() + rectInfo1.height() - infoText2HeightModifier,
-                    rectInfo1.width(),
-                    rectInfo1.height() - bottomMargin + infoText2HeightModifier + 4);
-
     QFontMetrics fontMetrics(font);
 
     // The name is displayed at the avatar's right
@@ -232,6 +243,20 @@ ConversationItemDelegate::paintConversationItem(QPainter* painter,
         painter->drawText(rectName2, Qt::AlignVCenter | Qt::AlignLeft, idStr);
     }
 
+    if (isTemporary) {
+        return;
+    }
+
+    QRect rectInfo1(rectName1.left() + rectName1.width(),
+                    rect.top() + topMargin,
+                    infoTextWidth_ - rightMargin + infoTextWidthModifier + 2,
+                    rect.height() / 2 - 2);
+
+    QRect rectInfo2(rectInfo1.left(),
+                    rectInfo1.top() + rectInfo1.height() - infoText2HeightModifier,
+                    rectInfo1.width(),
+                    rectInfo1.height() - bottomMargin + infoText2HeightModifier + 4);
+
     // top-right: last interaction date/time
     QString lastUsedStr = index.data(static_cast<int>(SmartListModel::Role::LastInteractionDate)).value<QString>();
     if (!lastUsedStr.isNull()) {
@@ -268,11 +293,6 @@ ConversationItemDelegate::paintConversationItem(QPainter* painter,
                 }
             }
             interactionStr = QString::fromUcs4(&emojiless.at(0), emojiless.size());
-            // remove everythin after 'call'
-            auto indexOfCallStr = interactionStr.lastIndexOf(QString("call"), -1, Qt::CaseInsensitive);
-            if (indexOfCallStr != -1) {
-                interactionStr = interactionStr.left(indexOfCallStr + 4);
-            }
         } else {
             QFont emojiMsgFont(QStringLiteral("Segoe UI Emoji"));
             emojiMsgFont.setItalic(false);
@@ -289,10 +309,10 @@ ConversationItemDelegate::paintConversationItem(QPainter* painter,
 }
 
 void
-ConversationItemDelegate::paintRingInviteConversationItem(QPainter* painter,
-                                                          const QStyleOptionViewItem& option,
-                                                          const QRect& rect,
-                                                          const QModelIndex& index) const
+ConversationItemDelegate::paintInvitationItem(QPainter* painter,
+                                              const QStyleOptionViewItem& option,
+                                              const QRect& rect,
+                                              const QModelIndex& index) const
 {
     QFont font(painter->font());
     QPen pen(painter->pen());
diff --git a/conversationitemdelegate.h b/conversationitemdelegate.h
index feaf1876a14cc852865d2f370cd5a700f86b5653..f87184e5c29e855cfea73e06e58fabd0ccb29af3 100644
--- a/conversationitemdelegate.h
+++ b/conversationitemdelegate.h
@@ -34,8 +34,15 @@ protected:
     QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
 
 private:
-    void paintConversationItem(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QModelIndex& index) const;
-    void paintRingInviteConversationItem(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QModelIndex& index) const;
+    void paintConversationItem(QPainter* painter,
+                               const QStyleOptionViewItem& option,
+                               const QRect& rect,
+                               const QModelIndex& index,
+                               const bool isTemporary) const;
+    void paintInvitationItem(  QPainter* painter,
+                               const QStyleOptionViewItem& option,
+                               const QRect& rect,
+                               const QModelIndex& index) const;
 
     constexpr static int sizeImage_ = 48;
     constexpr static int cellHeight_ = 60;
@@ -44,5 +51,7 @@ private:
     constexpr static int fontSize_ = 11;
     constexpr static int infoTextWidth_ = 176;
 
+    QPixmap* searchIcon_;
+
     mutable std::map<int, bool> highlightMap_;
 };
diff --git a/images/icons/ic_baseline-search-24px.svg b/images/icons/ic_baseline-search-24px.svg
new file mode 100644
index 0000000000000000000000000000000000000000..19c9df70d273a1c1e98ebf04d8d62f81ad3de30f
--- /dev/null
+++ b/images/icons/ic_baseline-search-24px.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
\ No newline at end of file
diff --git a/images/icons/ic_search_black_18dp_2x.png b/images/icons/ic_search_black_18dp_2x.png
deleted file mode 100644
index c593e7ad854f5c28ca21f59916bef001daf91141..0000000000000000000000000000000000000000
Binary files a/images/icons/ic_search_black_18dp_2x.png and /dev/null differ
diff --git a/lrcinstance.h b/lrcinstance.h
index 2f23cca858d016852a34c4978aef7bf9740dbf4f..a66f715fb398bbcd970bc59278ec1f8e89cbc428 100644
--- a/lrcinstance.h
+++ b/lrcinstance.h
@@ -48,17 +48,21 @@
 
 using namespace lrc::api;
 
+using migrateCallback = std::function<void()>;
+
 class LRCInstance : public QObject
 {
     Q_OBJECT
 
 public:
-    static LRCInstance& instance() {
-        static LRCInstance instance_;
+    static LRCInstance& instance(migrateCallback willMigrate = {},
+                                 migrateCallback didMigrate = {}) {
+        static LRCInstance instance_(willMigrate, didMigrate);
         return instance_;
     };
-    static void init() {
-        instance();
+    static void init(migrateCallback willMigrate = {},
+                     migrateCallback didMigrate = {}) {
+        instance(willMigrate, didMigrate);
     };
     static Lrc& getAPI() {
         return *(instance().lrc_);
@@ -174,6 +178,10 @@ public:
         return instance().getCurrentAccountInfo().confProperties;
     }
 
+    static void subscribeToDebugReceived() {
+        instance().lrc_->subscribeToDebugReceived();
+    }
+
 signals:
     /// emit once at least one valid account is loaded
     void accountOnBoarded();
@@ -182,8 +190,9 @@ private:
     std::unique_ptr<Lrc> lrc_;
     AccountListModel accountListModel_;
 
-    LRCInstance() {
-        lrc_ = std::make_unique<Lrc>();
+    LRCInstance(migrateCallback willMigrateCb = {},
+                migrateCallback didMigrateCb = {}) {
+        lrc_ = std::make_unique<Lrc>(willMigrateCb, didMigrateCb);
     };
 
     std::string selectedAccountId_;
diff --git a/main.cpp b/main.cpp
index db1a9a109690c676d4833d5e265e19d6cb5489e7..4ab64cdf7a9eb65e4bed7dc5f5f1c6ac6687861c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,24 +19,23 @@
 
 #include "mainwindow.h"
 
+#include "globalinstances.h"
+#include "downloadmanager.h"
+#include "lrcinstance.h"
+#include "pixbufmanipulator.h"
+#include "runguard.h"
+#include "utils.h"
+#include "splashscreen.h"
+
 #include <QApplication>
 #include <QFile>
 #include <QMessageBox>
-
-#include "globalinstances.h"
-
 #include <QFontDatabase>
 #include <QLibraryInfo>
 #include <QTranslator>
 
 #include <ciso646>
 
-#include "downloadmanager.h"
-#include "lrcinstance.h"
-#include "pixbufmanipulator.h"
-#include "runguard.h"
-#include "utils.h"
-
 #ifdef Q_OS_WIN
 #include <windows.h>
 #endif
@@ -134,35 +133,6 @@ main(int argc, char* argv[])
     auto startMinimized = false;
     QString uri = "";
 
-#if defined _MSC_VER && !COMPILE_ONLY
-    gnutls_global_init();
-#endif
-
-    GlobalInstances::setPixmapManipulator(std::make_unique<PixbufManipulator>());
-    LRCInstance::init();
-
-    QFile debugFile(qApp->applicationDirPath() + "/" + "jami.log");
-
-    for (auto string : QCoreApplication::arguments()) {
-        if (string.startsWith("jami:")) {
-            uri = string;
-        } else {
-            if (string == "-m" || string == "--minimized") {
-                startMinimized = true;
-            }
-            if (string == "-f" || string == "--file") {
-                debugFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
-                debugFile.close();
-                fileDebug(debugFile);
-            }
-#ifdef _MSC_VER
-            if (string == "-c" || string == "--vsconsole") {
-                vsConsoleDebug();
-            }
-#endif
-        }
-    }
-
     auto appDir = qApp->applicationDirPath() + "/";
     const auto locale_name = QLocale::system().name();
     const auto locale_lang = locale_name.split('_')[0];
@@ -206,6 +176,63 @@ main(int argc, char* argv[])
     }
 #endif
 
+#if defined _MSC_VER && !COMPILE_ONLY
+    gnutls_global_init();
+#endif
+
+    GlobalInstances::setPixmapManipulator(std::make_unique<PixbufManipulator>());
+
+    SplashScreen* splash = new SplashScreen();
+    std::atomic_bool isMigrating = false;
+    LRCInstance::init(
+        [&splash, &a, &isMigrating] {
+            splash->setupUI(
+                QPixmap(":/images/logo-jami-standard-coul.png"),
+                QString("Jami - ") + QObject::tr("Migration needed"),
+                QObject::tr("Migration in progress... This may take a while."),
+                QColor(232, 232, 232)
+            );
+            splash->show();
+            isMigrating = true;
+            while (isMigrating) {
+                a.processEvents();
+            }
+        },
+        [&splash, &isMigrating] {
+            while (!isMigrating) {
+                std::this_thread::sleep_for(std::chrono::milliseconds(10));
+            }
+            isMigrating = false;
+        });
+    splash->hide();
+    LRCInstance::subscribeToDebugReceived();
+
+    QFile debugFile(qApp->applicationDirPath() + "/" + "jami.log");
+
+    for (auto string : QCoreApplication::arguments()) {
+        if (string.startsWith("jami:")) {
+            uri = string;
+        } else {
+            if (string == "-m" || string == "--minimized") {
+                startMinimized = true;
+            }
+            auto dbgFile = string == "-f" || string == "--file";
+            auto dbgConsole = string == "-c" || string == "--vsconsole";
+            if (dbgFile || dbgConsole) {
+                if (dbgFile) {
+                    debugFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
+                    debugFile.close();
+                    fileDebug(debugFile);
+                }
+#ifdef _MSC_VER
+                if (dbgConsole) {
+                    vsConsoleDebug();
+                }
+#endif
+            }
+        }
+    }
+
     QFontDatabase::addApplicationFont(":/images/FontAwesome.otf");
 
     MainWindow::instance().createThumbBar();
@@ -218,9 +245,12 @@ main(int argc, char* argv[])
     }
 
     QObject::connect(&a, &QApplication::aboutToQuit, [&guard] { guard.release(); });
-
+    splash->finish(&MainWindow::instance());
+    splash->deleteLater();
     auto ret = a.exec();
 
+    LRCInstance::reset();
+
 #ifdef Q_OS_WIN
     FreeConsole();
 #endif
@@ -230,4 +260,4 @@ main(int argc, char* argv[])
     GlobalSystemTray::instance().hide();
 
     return ret;
-}
+}
\ No newline at end of file
diff --git a/messagewebview.cpp b/messagewebview.cpp
index 7444dbf8cf9b87393816550ae0508c4c4625b984..cf9f9076e09ede800afcdb4a7fefd52cf5bc6f9f 100644
--- a/messagewebview.cpp
+++ b/messagewebview.cpp
@@ -311,6 +311,9 @@ MessageWebView::printNewInteraction(lrc::api::ConversationModel& conversationMod
                                     const lrc::api::interaction::Info& interaction)
 {
     auto interactionObject = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8();
+    if (interactionObject.isEmpty()) {
+        return;
+    }
     QString s = QString::fromLatin1("addMessage(%1);")
         .arg(interactionObject.constData());
     page()->runJavaScript(s, QWebEngineScript::MainWorld);
@@ -322,6 +325,9 @@ MessageWebView::updateInteraction(lrc::api::ConversationModel& conversationModel
                                   const lrc::api::interaction::Info& interaction)
 {
     auto interactionObject = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8();
+    if (interactionObject.isEmpty()) {
+        return;
+    }
     QString s = QString::fromLatin1("updateMessage(%1);")
         .arg(interactionObject.constData());
     page()->runJavaScript(s, QWebEngineScript::MainWorld);
diff --git a/pixbufmanipulator.cpp b/pixbufmanipulator.cpp
index 8a49d4ff9c515b6a6a7b2ae2f701442fc551f509..19eb0d60c60b21156d493fea710f053f4b963b89 100644
--- a/pixbufmanipulator.cpp
+++ b/pixbufmanipulator.cpp
@@ -89,40 +89,41 @@ PixbufManipulator::decorationRole(const lrc::api::conversation::Info & conversat
 {
     QImage photo;
     auto contacts = conversationInfo.participants;
-    if (!contacts.empty()) {
-        try {
-            // Get first contact photo
-            auto contactUri = contacts.front();
-            auto contactInfo = accountInfo.contactModel->getContact(contactUri);
-            auto contactPhoto = contactInfo.profileInfo.avatar;
-            auto bestName = Utils::bestNameForContact(contactInfo);
-            auto bestId = Utils::bestIdForContact(contactInfo);
-            if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP &&
-                contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
-                photo = Utils::fallbackAvatar(IMAGE_SIZE, QString(), QString());
-            }
-            else if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP) {
-                photo = Utils::fallbackAvatar(IMAGE_SIZE,
-                                              QString::fromStdString("sip:" + bestId),
-                                              QString());
-            }
-            else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.uri.empty()) {
-                photo = Utils::fallbackAvatar(IMAGE_SIZE, QString(), QString());
-            }
-            else if (!contactPhoto.empty()) {
-                QByteArray byteArray(contactPhoto.c_str(), contactPhoto.length());
-                photo = personPhoto(byteArray, nullptr).value<QImage>();
-            }
-            else {
+    if (contacts.empty()) {
+        return QVariant::fromValue(photo);
+    }
+    try {
+        // Get first contact photo
+        auto contactUri = contacts.front();
+        auto contactInfo = accountInfo.contactModel->getContact(contactUri);
+        auto contactPhoto = contactInfo.profileInfo.avatar;
+        auto bestName = Utils::bestNameForContact(contactInfo);
+        auto bestId = Utils::bestIdForContact(contactInfo);
+        if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP &&
+            contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
+            photo = Utils::fallbackAvatar(IMAGE_SIZE, QString(), QString());
+        } else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.uri.empty()) {
+            photo = Utils::fallbackAvatar(IMAGE_SIZE, QString(), QString());
+        } else if (!contactPhoto.empty()) {
+            QByteArray byteArray(contactPhoto.c_str(), contactPhoto.length());
+            photo = personPhoto(byteArray, nullptr).value<QImage>();
+            if (photo.isNull()) {
                 auto avatarName = contactInfo.profileInfo.uri == bestName ?
                                   QString() :
                                   QString::fromStdString(bestName);
                 photo = Utils::fallbackAvatar(IMAGE_SIZE,
-                                              QString::fromStdString("ring:" + bestId),
+                                              QString::fromStdString("ring:" + contactInfo.profileInfo.uri),
                                               avatarName);
             }
+        } else {
+            auto avatarName = contactInfo.profileInfo.uri == bestName ?
+                              QString() :
+                              QString::fromStdString(bestName);
+            photo = Utils::fallbackAvatar(IMAGE_SIZE,
+                                          QString::fromStdString("ring:" + contactInfo.profileInfo.uri),
+                                          avatarName);
         }
-        catch (...) {}
     }
+    catch (...) {}
     return QVariant::fromValue(Utils::scaleAndFrame(photo, IMAGE_SIZE));
 }
\ No newline at end of file
diff --git a/ressources.qrc b/ressources.qrc
index 9ca1fcb9cff94304430510f3e5c31fa3c6cdc44a..5a8cde997b5d0fe52b9df4c5eb537edceb4b8694 100644
--- a/ressources.qrc
+++ b/ressources.qrc
@@ -47,7 +47,7 @@
     <file>images/icons/ic_person_add_white_24dp.png</file>
     <file>images/icons/ic_phone_24px.svg</file>
     <file>images/icons/ic_photo_camera_white_24dp_2x.png</file>
-    <file>images/icons/ic_search_black_18dp_2x.png</file>
+    <file>images/icons/ic_baseline-search-24px.svg</file>
     <file>images/icons/ic_send_24px.svg</file>
     <file>images/icons/ic_send_white_24dp.png</file>
     <file>images/icons/ic_settings_white_48dp_2x.png</file>
diff --git a/ring-client-windows.vcxproj b/ring-client-windows.vcxproj
index 5ae6c2ad308f26e0c18b2335e75f61376ebb37a5..0e5550b5b4a872803dc3c8a6d240c8d6448ee281 100644
--- a/ring-client-windows.vcxproj
+++ b/ring-client-windows.vcxproj
@@ -235,6 +235,7 @@
     <ClCompile Include="currentaccountcombobox.cpp" />
     <ClCompile Include="aboutdialog.cpp" />
     <ClCompile Include="levelmeter.cpp" />
+    <ClCompile Include="splashscreen.cpp" />
     <ClCompile Include="updatedownloaddialog.cpp" />
     <ClCompile Include="downloadmanager.cpp" />
     <ClCompile Include="accountitemdelegate.cpp" />
@@ -507,6 +508,10 @@
       <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)..\ring-daemon\contrib\msvc\include;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\ring-lrc\src;$(ProjectDir)..\lrc\src;$(ProjectDir)winsparkle\include;$(ProjectDir)qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWebEngineWidgets;$(QTDIR)\include\QtWebChannel;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
       <IncludePath Condition="'$(Configuration)|$(Platform)'=='ReleaseCompile|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)..\ring-daemon\contrib\msvc\include;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\ring-lrc\src;$(ProjectDir)..\lrc\src;$(ProjectDir)winsparkle\include;$(ProjectDir)qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWebEngineWidgets;$(QTDIR)\include\QtWebChannel;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
     </QtMoc>
+    <QtMoc Include="splashscreen.h">
+      <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)..\ring-daemon\contrib\msvc\include;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\ring-lrc\src;$(ProjectDir)..\lrc\src;$(ProjectDir)qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWebEngineWidgets;$(QTDIR)\include\QtWebChannel;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+      <IncludePath Condition="'$(Configuration)|$(Platform)'=='ReleaseCompile|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;$(ProjectDir)..\ring-daemon\contrib\msvc\include;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\ring-lrc\src;$(ProjectDir)..\lrc\src;$(ProjectDir)winsparkle\include;$(ProjectDir)qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWebEngineWidgets;$(QTDIR)\include\QtWebChannel;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath>
+    </QtMoc>
     <ClInclude Include="utils.h" />
     <QtMoc Include="videooverlay.h">
     </QtMoc>
diff --git a/ring-client-windows.vcxproj.filters b/ring-client-windows.vcxproj.filters
index 2e8ef70fbd443080b3aeb36f26a96f3cb2abe50f..23d603fd2e8c199c39bdddd8ba690e94cac4d074 100644
--- a/ring-client-windows.vcxproj.filters
+++ b/ring-client-windows.vcxproj.filters
@@ -213,6 +213,9 @@
     <ClCompile Include="contactpickeritemdelegate.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="splashscreen.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="levelmeter.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -374,6 +377,9 @@
     <QtMoc Include="levelmeter.h">
       <Filter>Header Files</Filter>
     </QtMoc>
+    <QtMoc Include="splashscreen.h">
+      <Filter>Generated Files</Filter>
+    </QtMoc>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="debug\moc_predefs.h.cbt">
diff --git a/ringcontactlineedit.cpp b/ringcontactlineedit.cpp
index a4fec59198512f302edd6e896cc73d44a7f36f49..7d64f8d4f5a495d8f82e587b8321e61f27a9c732 100644
--- a/ringcontactlineedit.cpp
+++ b/ringcontactlineedit.cpp
@@ -29,7 +29,7 @@ RingContactLineEdit::RingContactLineEdit(QWidget* parent) :
 
     setFrame(false);
 
-    addAction(QIcon(":images/icons/ic_search_black_18dp_2x.png"), QLineEdit::ActionPosition::LeadingPosition);
+    addAction(QIcon(":images/icons/ic_baseline-search-24px.svg"), QLineEdit::ActionPosition::LeadingPosition);
 }
 
 RingContactLineEdit::~RingContactLineEdit()
diff --git a/smartlistselectorbuttonnotifier.cpp b/smartlistselectorbuttonnotifier.cpp
index cb65a2a130d649f609146b5a8a618e434475c04d..ce61378b5c49979241c20b27fc38d7c447ef8585 100644
--- a/smartlistselectorbuttonnotifier.cpp
+++ b/smartlistselectorbuttonnotifier.cpp
@@ -19,6 +19,7 @@
 #include "smartlistselectorbuttonnotifier.h"
 
 #include "lrcinstance.h"
+#include "utils.h"
 #include "ringthemeutils.h"
 
 #include "api/conversationmodel.h"
@@ -56,7 +57,7 @@ SmartlistSelectorButtonNotifier::paintEvent(QPaintEvent *event)
         auto ringConversations = convModel->getFilteredConversations(Type::RING);
         std::for_each(ringConversations.begin(), ringConversations.end(),
             [&totalUnreadMessages, convModel](const auto& conversation) {
-                totalUnreadMessages += convModel->getNumberOfUnreadMessagesFor(conversation.uid);
+                totalUnreadMessages += conversation.unreadMessages;
             });
         break;
     }
diff --git a/splashscreen.cpp b/splashscreen.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f5aa6155471eca104f588a61bb544452be792ea
--- /dev/null
+++ b/splashscreen.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * Copyright (C) 2019 by Savoir-faire Linux                                *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>          *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 3 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ **************************************************************************/
+#include "splashscreen.h"
+
+#include <QEvent>
+#include <QMovie>
+
+constexpr static const int textSectionHeight = 48;
+
+SplashScreen::SplashScreen()
+{
+
+    this->installEventFilter(this);
+}
+
+SplashScreen::~SplashScreen()
+{
+    if (spinner_) {
+        disconnect(spinner_);
+        delete spinner_;
+    }
+}
+
+void
+SplashScreen::setupUI(const QPixmap& logo,
+    const QString& headerText,
+    const QString& footerText,
+    const QColor& bgColor,
+    const QColor& textColor)
+{
+    logo_ = logo;
+    headerText_ = headerText;
+    footerText_ = footerText;
+    bgColor_ = bgColor;
+    textColor_ = textColor;
+
+    spinner_ = new QMovie(":/images/waiting.gif");
+    connect(spinner_, &QMovie::frameChanged,
+        [this](int frame) {
+            Q_UNUSED(frame);
+            update();
+        });
+    spinner_->start();
+
+    QFont font;
+    font.setFamily("Arial");
+    font.setPixelSize(16);
+    setFont(font);
+    setWindowFlags(Qt::WindowStaysOnTopHint | Qt::SplashScreen);
+    QFontMetrics fontMetrics(font);
+    auto baseWidth = logo_.width();
+    auto baseHeight = logo_.height()
+        + textSectionHeight * 2
+        + spinner_->frameRect().height() * 3;
+    QPixmap bgPixmap(baseWidth, baseHeight);
+    bgPixmap.fill(Qt::transparent);
+    QSplashScreen::setPixmap(bgPixmap);
+}
+
+bool SplashScreen::eventFilter(QObject *target, QEvent *e)
+{
+    Q_UNUSED(target)
+        if ((e->type() == QEvent::MouseButtonPress) ||
+            (e->type() == QEvent::MouseButtonDblClick) ||
+            (e->type() == QEvent::MouseButtonRelease) ||
+            (e->type() == QEvent::KeyPress) ||
+            (e->type() == QEvent::KeyRelease))
+            return true;
+
+    return false;
+}
+
+void SplashScreen::paintEvent(QPaintEvent* e)
+{
+    Q_UNUSED(e);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
+    auto rect = QRect(0, 0, this->geometry().width(), this->geometry().height());
+
+    // background
+    QPainterPath path;
+    path.addRoundedRect(rect, 10, 10);
+    painter.fillPath(path, bgColor_);
+
+    // footer text
+    QFont font(this->font());
+    font.setWeight(QFont::Weight::DemiBold);
+    painter.setFont(font);
+    painter.setPen(textColor_);
+    auto textRect = QRect(rect.x(), 0,
+                          rect.width(), textSectionHeight);
+    painter.drawText(textRect, Qt::AlignCenter, headerText_);
+
+    // logo
+    painter.drawPixmap(0, textSectionHeight, logo_);
+
+    // footer text
+    font.setWeight(QFont::Weight::Normal);
+    painter.setFont(font);
+    painter.setPen(textColor_);
+    textRect = QRect(rect.x(), rect.y() + textSectionHeight + logo_.height(),
+                     rect.width(), textSectionHeight);
+    painter.drawText(textRect, Qt::AlignCenter, footerText_);
+
+    // spinner
+    auto spinnerRect = QRect(rect.x() + rect.width() / 2 - textSectionHeight / 2,
+                             textRect.y() + textSectionHeight,
+                             spinner_->frameRect().width(), spinner_->frameRect().height());
+    painter.drawPixmap(spinnerRect, spinner_->currentPixmap());
+
+    QSplashScreen::paintEvent(e);
+}
diff --git a/splashscreen.h b/splashscreen.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6c03fadbca7777f35f217ad333f83ac03b6d1c9
--- /dev/null
+++ b/splashscreen.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * Copyright (C) 2019 by Savoir-faire Linux                                *
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>          *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 3 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ **************************************************************************/
+#pragma once
+
+#include <QSplashScreen>
+#include <QPainter>
+
+class SplashScreen : public QSplashScreen
+{
+    Q_OBJECT;
+
+public:
+    SplashScreen();
+    ~SplashScreen();
+
+    void setupUI(const QPixmap& logo,
+                 const QString& headerText = "",
+                 const QString& footerText = "",
+                 const QColor& bgColor = Qt::white,
+                 const QColor& textColor = Qt::black);
+
+protected:
+    bool eventFilter(QObject *target, QEvent *e);
+    void paintEvent(QPaintEvent* e) override;
+
+private:
+    QString headerText_;
+    QPixmap logo_;
+    QString footerText_;
+    QColor bgColor_;
+    QColor textColor_;
+    QMovie* spinner_;
+};
diff --git a/web/chatview.css b/web/chatview.css
index c02d1b2663bb771a6e57172b508a2eedab89ca3a..68661147470bc79e991c72a69be34d17547116b7 100644
--- a/web/chatview.css
+++ b/web/chatview.css
@@ -711,6 +711,10 @@ div.last_message > span {
     min-width: 16px;
 }
 
+.message_in .sender_image_cell {
+    min-width: 56px;
+}
+
 .dummy_cell {
     padding: 0;
 }
@@ -1145,8 +1149,8 @@ pre {
 
     /* Media interactions */
     .media_wrapper img {
-        max-width: 200px;
-        max-height: 200px;
+        max-width: 300px;
+        max-height: 300px;
     }
 }
 
diff --git a/web/chatview.js b/web/chatview.js
index c4b1bddad3f63c962dbca033d13fab72efaf2bb2..39f8e7facb8524259a0b9eaf6f99d05fd5f0b8a8 100644
--- a/web/chatview.js
+++ b/web/chatview.js
@@ -161,8 +161,9 @@ function showInvitation(contactAlias, contactId) {
         if (!inviteImage.classList.contains('invite_sender_image')) {
             inviteImage.classList.add('invite_sender_image');
         }
-        if (!inviteImage.classList.contains(`invite_sender_image_${contactId}`)) {
-            inviteImage.classList.add(`invite_sender_image_${contactId}`);
+        const className = `invite_sender_image_${contactId}`.replace(/@/g, "_").replace(/\./g, "_")
+        if (!inviteImage.classList.contains(className)) {
+            inviteImage.classList.add(className);
         }
         hasInvitation = true
         invitationText.innerHTML = "<span id='invite_contact_name'>" + contactAlias + "</span> is not in your contacts<br/>"
@@ -629,6 +630,7 @@ function updateFileInteraction(message_div, message_object, forceTypeToFile = fa
         message_div.insertBefore(new_wrapper, message_div.querySelector(".menu_interaction"))
         message_div.querySelector("img").id = message_id
         message_div.querySelector("img").msg_obj = message_object
+        addSenderImage(message_div, message_object["type"], message_object["sender_contact_method"]);
         return
     }
 
@@ -1106,19 +1108,24 @@ function buildNewMessage(message_object) {
     }
 
     // Add sender images if necessary (like if the interaction doesn't take the whole width)
+    addSenderImage(message_div, message_type, message_sender_contact_method)
+
+    return message_div
+}
+
+function addSenderImage(message_div, message_type, message_sender_contact_method) {
     const need_sender = (message_type === "data_transfer" || message_type === "text")
     if (need_sender) {
         var sender_image_cell = message_div.querySelector(".sender_image_cell")
         if (sender_image_cell) {
             var message_sender_image = document.createElement("span")
-            message_sender_image.setAttribute("class", `sender_image sender_image_${message_sender_contact_method}`)
+            var cssSafeStr = message_sender_contact_method.replace(/@/g, "_").replace(/\./g, "_");
+            message_sender_image.setAttribute("class", `sender_image sender_image_${cssSafeStr}`)
             sender_image_cell.appendChild(message_sender_image)
         } else {
             console.warn("can't find sender_image_cell");
         }
     }
-
-    return message_div
 }
 
 /**
@@ -1602,7 +1609,7 @@ function printHistory(messages_array)
 /* exported setSenderImage */
 function setSenderImage(set_sender_image_object)
 {
-    var sender_contact_method = set_sender_image_object["sender_contact_method"],
+    var sender_contact_method = set_sender_image_object["sender_contact_method"].replace(/@/g, "_").replace(/\./g, "_"),
         sender_image = set_sender_image_object["sender_image"],
         sender_image_id = "sender_image_" + sender_contact_method,
         invite_sender_image_id = "invite_sender_image_" + sender_contact_method,
@@ -1709,7 +1716,6 @@ function addImage_base64(base64) {
  */
 function addImage_path(path) {
 
-
     var html = '<div class="img_wrapper">' +
                '<img src="' + path + '"/>' +
                '<button class="btn" onclick="remove(this)">X</button>' +
diff --git a/webchathelpers.cpp b/webchathelpers.cpp
index 5e5fe4318c81837ec07c5752749c5a467ebd1f73..b6b6308198b27ad4d98ce7f01885f8fb0e92cae8 100644
--- a/webchathelpers.cpp
+++ b/webchathelpers.cpp
@@ -50,8 +50,7 @@ buildInteractionJson(lrc::api::ConversationModel& conversationModel,
     case lrc::api::interaction::Type::CONTACT:
         interactionObject.insert("type", QJsonValue("contact"));
         break;
-    case lrc::api::interaction::Type::OUTGOING_DATA_TRANSFER:
-    case lrc::api::interaction::Type::INCOMING_DATA_TRANSFER: {
+    case lrc::api::interaction::Type::DATA_TRANSFER: {
         interactionObject.insert("type", QJsonValue("data_transfer"));
         lrc::api::datatransfer::Info info = {};
         conversationModel.getTransferInfo(msgId, info);
@@ -63,19 +62,19 @@ buildInteractionJson(lrc::api::ConversationModel& conversationModel,
     }
     case lrc::api::interaction::Type::INVALID:
     default:
-        interactionObject.insert("type", QJsonValue(""));
-        break;
+        return {};
+    }
+
+    if (interaction.isRead) {
+        interactionObject.insert("delivery_status", QJsonValue("read"));
     }
 
     switch (interaction.status)
     {
-    case lrc::api::interaction::Status::READ:
-        interactionObject.insert("delivery_status", QJsonValue("read"));
-        break;
-    case lrc::api::interaction::Status::SUCCEED:
+    case lrc::api::interaction::Status::SUCCESS:
         interactionObject.insert("delivery_status", QJsonValue("sent"));
         break;
-    case lrc::api::interaction::Status::FAILED:
+    case lrc::api::interaction::Status::FAILURE:
     case lrc::api::interaction::Status::TRANSFER_ERROR:
         interactionObject.insert("delivery_status", QJsonValue("failure"));
         break;
@@ -111,7 +110,6 @@ buildInteractionJson(lrc::api::ConversationModel& conversationModel,
         break;
     case lrc::api::interaction::Status::INVALID:
     case lrc::api::interaction::Status::UNKNOWN:
-    case lrc::api::interaction::Status::UNREAD:
     default:
         interactionObject.insert("delivery_status", QJsonValue("unknown"));
         break;
@@ -135,7 +133,10 @@ interactionsToJsonArrayObject(lrc::api::ConversationModel& conversationModel,
 {
     QJsonArray array;
     for (const auto& interaction : interactions) {
-        array.append(buildInteractionJson(conversationModel, interaction.first, interaction.second));
+        auto interactionObject = buildInteractionJson(conversationModel, interaction.first, interaction.second);
+        if (!interactionObject.isEmpty()) {
+            array.append(interactionObject);
+        }
     }
     return QString(QJsonDocument(array).toJson(QJsonDocument::Compact));
 }
\ No newline at end of file