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