Browse Source

chatgui: fix scroll jump on refresh, force debounce, add DEBUG logs

- Same-channel refresh: save scroll pos in memory, restore from memory (no DB race)
- Force m_readDebounce->start() after loadChannel (scrollToBottom may not trigger valueChanged)
- DEBUG_DEBUG logs in updateReadPosition, saveChannelState, onMessageReceived, setChannelUnreadCount
topo_upd
Evgeny 2 months ago
parent
commit
37c5fa5607
  1. 4
      tools/chatgui/src/channellist.cpp
  2. 7
      tools/chatgui/src/mainwindow.cpp
  3. 47
      tools/chatgui/src/messagelist.cpp
  4. 2
      tools/chatgui/src/messagelist.h

4
tools/chatgui/src/channellist.cpp

@ -245,11 +245,15 @@ void ChannelList::setChannelUnreadCount(const QString& channelId, int count) {
for (int row = 0; row < m_model->rowCount(); row++) {
QStandardItem* item = m_model->item(row);
if (item && item->data(ChannelChannelIdRole).toString() == channelId) {
int old = item->data(ChannelUnreadCountRole).toInt();
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "ChannelList::setChannelUnreadCount ch=%s %d->%d",
qPrintable(channelId), old, count);
item->setData(count, ChannelUnreadCountRole);
emit m_model->dataChanged(m_model->index(row, 0), m_model->index(row, 0));
return;
}
}
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "ChannelList::setChannelUnreadCount ch=%s not found", qPrintable(channelId));
}
int ChannelList::getChannelUnreadCount(const QString& channelId) const {

7
tools/chatgui/src/mainwindow.cpp

@ -327,14 +327,17 @@ void MainWindow::showSettings() {
}
void MainWindow::onMessageReceived(const char* ch_id) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "MainWindow: msg received ch=%s", ch_id);
SoundManager::instance()->play("msg_incoming");
QString cid = QString::fromUtf8(ch_id);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "MainWindow::onMessageReceived ch=%s cur=%s",
qPrintable(cid), qPrintable(m_currentChannelId));
SoundManager::instance()->play("msg_incoming");
if (m_messageList) {
if (cid == m_currentChannelId) {
m_messageList->refresh();
} else if (m_channelList) {
int unread = m_channelList->getChannelUnreadCount(cid) + 1;
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow::onMessageReceived increment unread ch=%s %d->%d",
qPrintable(cid), unread - 1, unread);
m_channelList->setChannelUnreadCount(cid, unread);
}
}

47
tools/chatgui/src/messagelist.cpp

@ -23,6 +23,7 @@ extern "C" {
#include "../transport/chat_core.h"
#include "../../lib/u_async.h"
#include "../../lib/mem.h"
#include "../../lib/debug_config.h"
}
static QPixmap makeAvatar(const QColor &color, const QString &letter, int size = 36) {
@ -176,16 +177,30 @@ MessageList::MessageList(DbManager* db, QWidget *parent)
void MessageList::loadChannel(const QString& channelId) {
QWidget* prevFocus = QApplication::focusWidget();
bool sameChannel = (m_currentChannelId == channelId);
/* Save state of current channel before switching */
if (!m_currentChannelId.isEmpty() && m_currentChannelId != channelId)
saveChannelState();
if (!m_currentChannelId.isEmpty()) {
if (!sameChannel) {
saveChannelState();
} else {
QModelIndex topIdx = m_view->indexAt(QPoint(0, 0));
m_savedTopMsgId = topIdx.isValid() ? topIdx.data(MsgIdRole).toLongLong() : 0;
QScrollBar* sb = m_view->verticalScrollBar();
m_wasAtBottom = sb && (sb->value() >= sb->maximum());
}
}
m_model->clear();
m_avatarCache.clear();
m_currentChannelId = channelId;
m_readDebounce->stop();
m_lastReadMsgId = m_db->getUiStateInt64(
QStringLiteral("ch_%1_last_read").arg(channelId), 0);
if (!m_db || !m_db->isOpen()) return;
if (sameChannel)
m_lastReadMsgId = m_db->getUiStateInt64(
QStringLiteral("ch_%1_last_read").arg(channelId), 0);
if (!m_db || !m_db->isOpen()) return;
auto msgs = m_db->getMessages(channelId, 100);
@ -211,7 +226,22 @@ void MessageList::loadChannel(const QString& channelId) {
m_model->appendRow(item);
}
restoreScrollPosition(channelId);
if (sameChannel) {
if (m_wasAtBottom || m_savedTopMsgId == 0)
m_view->scrollToBottom();
else
for (int row = 0; row < m_model->rowCount(); row++)
if (m_model->item(row)->data(MsgIdRole).toLongLong() == m_savedTopMsgId) {
m_view->scrollTo(m_model->index(row, 0), QAbstractItemView::PositionAtTop);
break;
}
} else {
m_lastReadMsgId = m_db->getUiStateInt64(
QStringLiteral("ch_%1_last_read").arg(channelId), 0);
restoreScrollPosition(channelId);
}
m_readDebounce->start();
if (prevFocus)
prevFocus->setFocus();
@ -264,6 +294,8 @@ void MessageList::saveChannelState() {
lastPosMsgId = topIdx.data(MsgIdRole).toLongLong();
qint64 lastReadMsgId = m_lastReadMsgId;
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MessageList::saveChannelState ch=%s read=%lld pos=%lld",
qPrintable(m_currentChannelId), (long long)lastReadMsgId, (long long)lastPosMsgId);
if (lastReadMsgId == 0 && lastPosMsgId == 0) return;
QByteArray cid = m_currentChannelId.toUtf8();
@ -326,6 +358,11 @@ void MessageList::updateReadPosition() {
newReadMsgId = msgId;
}
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG,
"MessageList::updateReadPosition ch=%s oldRead=%lld newRead=%lld lastVisRow=%d/%d",
qPrintable(m_currentChannelId), (long long)m_lastReadMsgId,
(long long)newReadMsgId, lastFullyVisibleRow, m_model->rowCount());
if (newReadMsgId > m_lastReadMsgId) {
m_lastReadMsgId = newReadMsgId;

2
tools/chatgui/src/messagelist.h

@ -35,6 +35,8 @@ private:
QHash<quint64, QColor> m_avatarCache;
qint64 m_lastReadMsgId = 0;
QTimer* m_readDebounce;
qint64 m_savedTopMsgId = 0;
bool m_wasAtBottom = false;
void saveChannelState();
void restoreScrollPosition(const QString& channelId);

Loading…
Cancel
Save