Follow new messages near the bottom and always follow accepted sends
This commit is contained in:
1 parent
39a9fe01a3
commit
0da3c3a677
2 files changed
+42
-12
No files matched your search
@@ -1311,7 +1311,7 @@ void MainWindow::onDmMsgReceived(const QString& convId, quint64 author) {
|
||||
QString key = QStringLiteral("dm:") + convId;
|
||||
showIncomingMessageNotification(key, author);
|
||||
if (m_currentChannelId == key) {
|
||||
m_messageList->refresh();
|
||||
m_messageList->refresh(author == m_db->myNodeId());
|
||||
return;
|
||||
}
|
||||
if (author == m_db->myNodeId()) return;
|
||||
@@ -1539,7 +1539,7 @@ void MainWindow::onMessageReceived(const char* ch_id, int ch_id_len, uint64_t au
|
||||
SoundManager::instance()->play("msg_incoming");
|
||||
if (m_messageList) {
|
||||
if (cid == m_currentChannelId) {
|
||||
m_messageList->refresh();
|
||||
m_messageList->refresh(!initialSync && m_db && author == m_db->myNodeId());
|
||||
} else if (m_channelList && !initialSync && m_db && author != m_db->myNodeId()) {
|
||||
int unread = m_channelList->getChannelUnreadCount(cid) + 1;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT, "MainWindow::onMessageReceived increment unread ch=%s %d->%d",
|
||||
|
||||
@@ -617,11 +617,7 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent
|
||||
connect(msgDelegate, &MessageDelegate::reactionRequested, this, &MessageList::requestReaction);
|
||||
connect(msgDelegate, &MessageDelegate::pollRequested, this, &MessageList::showPoll);
|
||||
connect(msgDelegate, &MessageDelegate::replyRequested, this, &MessageList::jumpToMessage);
|
||||
connect(m_view, &ChatView::latestRequested, this, [this]() {
|
||||
if (m_historyAnchor.isEmpty()) return;
|
||||
m_historyAnchor.clear(); loadChannel(m_currentChannelId);
|
||||
QTimer::singleShot(0, m_view, &QListView::scrollToBottom);
|
||||
});
|
||||
connect(m_view, &ChatView::latestRequested, this, &MessageList::showLatestMessages);
|
||||
msgDelegate->setDownloadCallback([](const QModelIndex& index) {
|
||||
QString target = index.data(MsgChannelIdRole).toString();
|
||||
qint64 id = index.data(MsgIdRole).toLongLong();
|
||||
@@ -662,6 +658,7 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent
|
||||
layout->addWidget(m_emojiPanel);
|
||||
|
||||
m_inputBar = new InputBar(m_emojiPanel, recorder, this);
|
||||
connect(m_inputBar, &InputBar::messageAccepted, this, &MessageList::showLatestMessages);
|
||||
setFocusProxy(m_inputBar);
|
||||
layout->addWidget(m_inputBar);
|
||||
m_inputBar->installFileDropTarget(m_view->viewport());
|
||||
@@ -1019,8 +1016,34 @@ void MessageList::loadChannel(const QString& channelId) {
|
||||
m_inputBar->setFocus();
|
||||
}
|
||||
|
||||
void MessageList::refresh() {
|
||||
bool MessageList::nearHistoryBottom() const {
|
||||
const auto* scrollbar = m_view->verticalScrollBar();
|
||||
const int gap = scrollbar->maximum() - scrollbar->value();
|
||||
const int threshold = 10 * m_view->fontMetrics().lineSpacing();
|
||||
GUI_DEBUG("history follow: ch=%s gap=%d threshold=%d near=%d", qPrintable(m_currentChannelId), gap, threshold, gap <= threshold);
|
||||
return gap <= threshold;
|
||||
}
|
||||
|
||||
void MessageList::scrollHistoryToBottom() {
|
||||
m_view->doItemsLayout(); m_view->scrollToBottom();
|
||||
GUI_DEBUG("history bottom: ch=%s rows=%d position=%d maximum=%d", qPrintable(m_currentChannelId), m_model->rowCount(),
|
||||
m_view->verticalScrollBar()->value(), m_view->verticalScrollBar()->maximum());
|
||||
QTimer::singleShot(0, this, [this, channel = m_currentChannelId, generation = m_currentDmGeneration, anchor = m_historyAnchor] {
|
||||
if (channel != m_currentChannelId || generation != m_currentDmGeneration || anchor != m_historyAnchor) return;
|
||||
m_view->doItemsLayout(); m_view->scrollToBottom();
|
||||
GUI_DEBUG("history bottom after layout: ch=%s position=%d maximum=%d", qPrintable(channel),
|
||||
m_view->verticalScrollBar()->value(), m_view->verticalScrollBar()->maximum());
|
||||
});
|
||||
}
|
||||
|
||||
void MessageList::showLatestMessages() {
|
||||
if (!m_historyAnchor.isEmpty()) { m_historyAnchor.clear(); loadChannel(m_currentChannelId); }
|
||||
scrollHistoryToBottom();
|
||||
}
|
||||
|
||||
void MessageList::refresh(bool outgoing) {
|
||||
if (m_currentChannelId.isEmpty()) return;
|
||||
if (outgoing) showLatestMessages();
|
||||
|
||||
if (isDmChannel(m_currentChannelId)) {
|
||||
requestDmMessages(m_currentChannelId);
|
||||
@@ -1039,10 +1062,12 @@ void MessageList::refresh() {
|
||||
m_localNicks = m_db->getLocalNicknames(m_currentChannelId);
|
||||
|
||||
QScrollBar* sb = m_view->verticalScrollBar();
|
||||
bool wasAtBottom = sb && (sb->value() >= sb->maximum());
|
||||
const bool wasAtBottom = nearHistoryBottom();
|
||||
bool added = false;
|
||||
|
||||
for (const auto& m : newMsgs) {
|
||||
if (present.contains(QString::fromLatin1(m.messageId.toHex()))) continue;
|
||||
added = true;
|
||||
AccountRow acc = m_db->getAccount(m.authorNodeId);
|
||||
QString author = authorName(m.authorNodeId);
|
||||
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
||||
@@ -1071,7 +1096,7 @@ void MessageList::refresh() {
|
||||
}
|
||||
|
||||
m_model->setSortRole(MsgRawTimestampRole); m_model->sort(0);
|
||||
if (wasAtBottom) m_view->scrollToBottom();
|
||||
if (added && wasAtBottom) scrollHistoryToBottom();
|
||||
m_readDebounce->start();
|
||||
}
|
||||
|
||||
@@ -1586,6 +1611,10 @@ void MessageList::onDmMessages(const uint8_t* data, int len) {
|
||||
}
|
||||
auto* scrollbar = m_view->verticalScrollBar();
|
||||
bool atBottom = m_model->rowCount() == 0 || scrollbar->value() >= scrollbar->maximum();
|
||||
const bool nearBottom = nearHistoryBottom();
|
||||
qint64 previousLatest = 0;
|
||||
for (int row = 0; row < m_model->rowCount(); ++row) previousLatest = qMax(previousLatest, m_model->item(row)->data(MsgIdRole).toLongLong());
|
||||
bool newMessage = false, outgoingMessage = false;
|
||||
int previousScroll = scrollbar->value();
|
||||
m_model->clear();
|
||||
m_avatarCache.clear();
|
||||
@@ -1594,6 +1623,7 @@ void MessageList::onDmMessages(const uint8_t* data, int len) {
|
||||
auto message = entry.toObject();
|
||||
int dir = message.value("dir").toInt();
|
||||
qint64 seq = (qint64)message.value("seq").toDouble();
|
||||
if (seq > previousLatest) { newMessage = true; if (dir == 1) outgoingMessage = true; }
|
||||
qint64 ts = (qint64)message.value("ts").toDouble();
|
||||
quint64 author = message.value("author").toString().toULongLong();
|
||||
QString text = message.value("data").toString();
|
||||
@@ -1669,8 +1699,8 @@ void MessageList::onDmMessages(const uint8_t* data, int len) {
|
||||
m_model->appendRow(item);
|
||||
}
|
||||
|
||||
if (atBottom) m_view->scrollToBottom();
|
||||
else scrollbar->setValue(previousScroll);
|
||||
if (atBottom || outgoingMessage || (newMessage && nearBottom)) scrollHistoryToBottom();
|
||||
else { m_view->doItemsLayout(); scrollbar->setValue(previousScroll); }
|
||||
}
|
||||
|
||||
/* ── рация ── */
|
||||
|
||||
Reference in new issue
Block a user