diff --git a/tools/chatgui/src/accountlist.cpp b/tools/chatgui/src/accountlist.cpp index 285c4ae8b..3823b4951 100644 --- a/tools/chatgui/src/accountlist.cpp +++ b/tools/chatgui/src/accountlist.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include "../../../lib/platform_compat.h" @@ -243,7 +244,9 @@ void AccountList::setChannel(const QString& channelId, quint64 dmGeneration) { if (!dmGeneration && channelId.startsWith("dm:") && m_db && m_db->isOpen()) for (const auto& conv : m_db->getDmConversations()) if (conv.convId == channelId.mid(3) && conv.mode == DM_MODE_GROUPS) { dmGeneration = conv.generation; break; } - if (m_channelId != channelId || m_dmGeneration != dmGeneration) { clearMemberDetail(); m_dmDevices->clear(); } + if (m_channelId != channelId || m_dmGeneration != dmGeneration) { + clearMemberDetail(); m_dmDevices->clear(); m_dmSnapshot.clear(); + } m_channelId = channelId; m_dmGeneration = channelId.startsWith("dm:") ? dmGeneration : 0; m_dmDevices->setVisible(m_dmGeneration != 0); @@ -288,6 +291,8 @@ void AccountList::onDmMembers(const uint8_t* data, int len) { if (count > DM_TARGET_MAX || len != 11 + cl + count * DM_MEMBER_WIRE_SIZE) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "DM members: invalid count=%d bytes=%d", count, len); return; } + const QByteArray snapshot(reinterpret_cast(data), len); + if (snapshot == m_dmSnapshot) return; QVector> members; QSet nodes; for (int i = 0; i < count; i++) { const auto* row = data + 11 + cl + i * DM_MEMBER_WIRE_SIZE; chat_member_display member{}; @@ -303,6 +308,7 @@ void AccountList::onDmMembers(const uint8_t* data, int len) { return a.second.node_id < b.second.node_id; }); const quint64 selected = m_dmDevices->currentItem() ? m_dmDevices->currentItem()->data(0, Qt::UserRole).toULongLong() : 0; + const int scroll = m_dmDevices->verticalScrollBar()->value(); m_dmDevices->clear(); QTreeWidgetItem* sections[2]; for (int side = 0; side < 2; side++) { sections[side] = new QTreeWidgetItem(m_dmDevices, {QCoreApplication::translate("ChatGui", side ? "Peer devices" : "My devices")}); @@ -318,6 +324,7 @@ void AccountList::onDmMembers(const uint8_t* data, int len) { if (member.is_self) { QFont font = row->font(0); font.setBold(true); row->setFont(0, font); } if (member.node_id == selected) m_dmDevices->setCurrentItem(row); } + m_dmDevices->verticalScrollBar()->setValue(scroll); m_dmSnapshot = snapshot; DEBUG_DEBUG(DEBUG_CATEGORY_DM, "DM members: panel updated channel=%s count=%d", qPrintable(channel), count); } diff --git a/tools/chatgui/src/accountlist.h b/tools/chatgui/src/accountlist.h index 64e5f4701..7e4a5e041 100644 --- a/tools/chatgui/src/accountlist.h +++ b/tools/chatgui/src/accountlist.h @@ -126,6 +126,7 @@ private: QTreeWidget* m_dmDevices; // Два раздела текущего состава GROUPS; не снимок доставки сообщения. QTimer* m_dmTimer; // Опрос текущего состава/online раз в 2 с только для видимой панели. quint64 m_dmGeneration = 0; // 0 — обычная панель или DEVICE; ненулевое привязывает запросы к истории. + QByteArray m_dmSnapshot; // Повторный неизменившийся снимок не перестраивает видимые строки. quint64 m_detailNodeId = 0; qint64 m_detailLastSeen = 0, m_detailCreated = 0; // Unix seconds, 0=неизвестно diff --git a/tools/chatgui/tests/test_member_detail.cpp b/tools/chatgui/tests/test_member_detail.cpp index 903c8aa8e..75c8a99b8 100644 --- a/tools/chatgui/tests/test_member_detail.cpp +++ b/tools/chatgui/tests/test_member_detail.cpp @@ -405,6 +405,8 @@ private slots: QCOMPARE(tree->topLevelItem(0)->childCount(), 2); QCOMPARE(tree->topLevelItem(1)->childCount(), 1); QCOMPARE(tree->topLevelItem(0)->child(0)->data(0, Qt::UserRole).toULongLong(), quint64(21)); QCOMPARE(tree->topLevelItem(0)->child(1)->text(1), QString("offline")); + const QString screenshot = qEnvironmentVariable("UTUN_TEST_DM_MEMBERS_SCREENSHOT"); + if (!screenshot.isEmpty()) QVERIFY(panel.grab().save(screenshot)); apply(snapshot(6, {}, 0)); QCOMPARE(tree->topLevelItem(0)->childCount(), 2); apply(snapshot(7, peer + peer, 2)); QCOMPARE(tree->topLevelItem(0)->childCount(), 2); apply(snapshot(7, peer, 1)); QCOMPARE(tree->topLevelItem(0)->childCount(), 0);