diff --git a/tools/chatgui/src/mainwindow.cpp b/tools/chatgui/src/mainwindow.cpp index 058f4e84..d15811b1 100644 --- a/tools/chatgui/src/mainwindow.cpp +++ b/tools/chatgui/src/mainwindow.cpp @@ -31,10 +31,10 @@ extern "C" { static MainWindow* s_mainWindow = nullptr; -static void onMsgReceivedCallback(const char* ch_id, int ch_id_len) { +static void onMsgReceivedCallback(const char* ch_id, int ch_id_len, uint64_t author) { Q_UNUSED(ch_id_len); if (s_mainWindow) - s_mainWindow->onMessageReceived(ch_id); + s_mainWindow->onMessageReceived(ch_id, author); } static void onChannelUpdatedCallback(const char* ch_id, int ch_id_len) { @@ -326,11 +326,12 @@ void MainWindow::showSettings() { dlg.exec(); } -void MainWindow::onMessageReceived(const char* ch_id) { +void MainWindow::onMessageReceived(const char* ch_id, uint64_t author) { 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"); + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "MainWindow::onMessageReceived ch=%s author=%llu cur=%s", + qPrintable(cid), (unsigned long long)author, qPrintable(m_currentChannelId)); + if (m_db && author != m_db->myNodeId()) + SoundManager::instance()->play("msg_incoming"); if (m_messageList) { if (cid == m_currentChannelId) { m_messageList->refresh(); diff --git a/tools/chatgui/src/mainwindow.h b/tools/chatgui/src/mainwindow.h index 859107fe..3b7ee783 100644 --- a/tools/chatgui/src/mainwindow.h +++ b/tools/chatgui/src/mainwindow.h @@ -31,7 +31,7 @@ private slots: void showSettings(); public: - void onMessageReceived(const char* ch_id); + void onMessageReceived(const char* ch_id, uint64_t author); void onMembersChanged(const char* ch_id); void onAutoConnectStatus(uint8_t status, uint16_t total, uint16_t totalNodes, uint16_t connected); void onChannelPeersOnline(const char* ch_id, int ch_id_len, uint16_t online); diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index 514e5d97..d63384d0 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/tools/chatgui/src/messagelist.cpp @@ -197,12 +197,6 @@ void MessageList::loadChannel(const QString& channelId) { m_readDebounce->stop(); 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); for (const auto& m : msgs) { @@ -227,22 +221,28 @@ void MessageList::loadChannel(const QString& 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; + bool wasBottom = m_wasAtBottom; + qint64 savedTop = m_savedTopMsgId; + QTimer::singleShot(0, this, [this, wasBottom, savedTop]() { + if (wasBottom || savedTop == 0) { + m_view->scrollToBottom(); + } else { + for (int row = 0; row < m_model->rowCount(); row++) { + if (m_model->item(row)->data(MsgIdRole).toLongLong() == savedTop) { + m_view->scrollTo(m_model->index(row, 0), QAbstractItemView::PositionAtTop); + break; + } } + } + m_readDebounce->start(); + }); } else { m_lastReadMsgId = m_db->getUiStateInt64( QStringLiteral("ch_%1_last_read").arg(channelId), 0); restoreScrollPosition(channelId); + m_readDebounce->start(); } - m_readDebounce->start(); - if (prevFocus) prevFocus->setFocus(); else diff --git a/tools/chatgui/transport/chat_msg.c b/tools/chatgui/transport/chat_msg.c index e697b499..b7f0d489 100644 --- a/tools/chatgui/transport/chat_msg.c +++ b/tools/chatgui/transport/chat_msg.c @@ -59,8 +59,9 @@ void chat_core_submit_message(struct chat_msg_submit* req) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: db_sync_insert_signed failed ret=%d", CC_ID, ret); return; } - { uint8_t evt[65]; uint8_t cl=(uint8_t)strlen(req->channel_id); evt[0]=cl; memcpy(evt+1,req->channel_id,cl); - gui_bridge_post(GUI_EVT_MSG_RECEIVED, evt, 1+cl); } + { uint8_t evt[73]; uint8_t cl=(uint8_t)strlen(req->channel_id); evt[0]=cl; memcpy(evt+1,req->channel_id,cl); + memcpy(evt+1+cl, &g_cc.my_node_id, 8); + gui_bridge_post(GUI_EVT_MSG_RECEIVED, evt, 1+cl+8); } } void chat_core_submit_trampoline(void* arg) { chat_core_submit_message((struct chat_msg_submit*)arg); u_free(arg); } @@ -218,6 +219,7 @@ int chat_core_load_nodeinfo(uint64_t node_id, uint8_t* buf, size_t buf_size, void on_msg_inserted(struct DB_SYNC_INSTANCE* si, uint64_t record_ts, const char* data, size_t len, uint64_t author, void* arg) { (void)si; (void)record_ts; (void)data; (void)len; (void)author; const char* ch_id = (const char*)arg; - uint8_t evt[65]; uint8_t cl = (uint8_t)strlen(ch_id); evt[0] = cl; memcpy(evt + 1, ch_id, cl); - gui_bridge_post(GUI_EVT_MSG_RECEIVED, evt, 1 + cl); + uint8_t evt[73]; uint8_t cl = (uint8_t)strlen(ch_id); evt[0] = cl; memcpy(evt + 1, ch_id, cl); + memcpy(evt + 1 + cl, &author, 8); + gui_bridge_post(GUI_EVT_MSG_RECEIVED, evt, 1 + cl + 8); } diff --git a/tools/chatgui/transport/gui_bridge.h b/tools/chatgui/transport/gui_bridge.h index 5aff3f7d..1ceca439 100644 --- a/tools/chatgui/transport/gui_bridge.h +++ b/tools/chatgui/transport/gui_bridge.h @@ -12,7 +12,7 @@ struct UASYNC; /* ── Типы уведомлений uasync→GUI (fire-and-forget) ── */ -#define GUI_EVT_MSG_RECEIVED 1 /* data: [ch_id_len:1][ch_id:var] */ +#define GUI_EVT_MSG_RECEIVED 1 /* data: [ch_id_len:1][ch_id:var][author_node_id:8] */ #define GUI_EVT_CONNECT_RESULT 2 /* data: [node_id:8][result:4][channel_id:8] */ #define GUI_EVT_NEW_PEER 3 /* data: [node_id:8] */ #define GUI_EVT_CHANNEL_UPDATED 4 /* data: [ch_id_len:1][ch_id:var] */ @@ -46,7 +46,7 @@ typedef void (*gui_connect_result_fn)(uint64_t node_id, uint64_t channel_id, int void gui_bridge_set_connect_result_cb(gui_connect_result_fn cb); /* Callback для входящих сообщений (вызывается из GUI-потока) */ -typedef void (*gui_msg_received_fn)(const char* ch_id, int ch_id_len); +typedef void (*gui_msg_received_fn)(const char* ch_id, int ch_id_len, uint64_t author); void gui_bridge_set_msg_received_cb(gui_msg_received_fn cb); /* Callback для обновления канала (вызывается из GUI-потока) */ diff --git a/tools/chatgui/transport/gui_bridge_impl.cpp b/tools/chatgui/transport/gui_bridge_impl.cpp index a36974c1..8f5f6be7 100644 --- a/tools/chatgui/transport/gui_bridge_impl.cpp +++ b/tools/chatgui/transport/gui_bridge_impl.cpp @@ -45,10 +45,13 @@ void GuiBridgeReceiver::processPost(int eventType, QByteArray data) { case GUI_EVT_MSG_RECEIVED: if (dlen >= 2) { uint8_t chLen = d[0]; - if (dlen >= 1 + chLen) { + if (dlen >= 1 + chLen + 8) { + uint64_t author = 0; + memcpy(&author, d + 1 + chLen, 8); QString chId = QString::fromUtf8((const char*)d + 1, chLen); - DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "gui_bridge: MSG_RECEIVED ch=%s", qPrintable(chId)); - if (g_msg_received_cb) g_msg_received_cb((const char*)d + 1, chLen); + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "gui_bridge: MSG_RECEIVED ch=%s author=%llu", + qPrintable(chId), (unsigned long long)author); + if (g_msg_received_cb) g_msg_received_cb((const char*)d + 1, chLen, author); } else { DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: MSG_RECEIVED invalid data length %d", dlen); }