Complete desktop PM deletion after the core transaction result

This commit is contained in:
evgeny committed 2026-10-26 22:11:39 +01:00
1 parent 4089944673
commit 6382c794ea
2 files changed
+76 -5

No files matched your search

+71 -4
View File
@@ -236,6 +236,10 @@ MainWindow::~MainWindow() {
m_autoPlayTimer->stop();
gui_bridge_set_network_changed_cb(nullptr);
gui_bridge_set_dm_call_route_cb(nullptr);
gui_bridge_set_dm_conv_updated_cb(nullptr);
gui_bridge_set_dm_msg_received_cb(nullptr);
gui_bridge_set_dm_messages_cb(nullptr);
gui_bridge_set_dm_delete_result_cb(nullptr);
gui_bridge_set_msg_received_cb(nullptr);
gui_bridge_set_channel_updated_cb(nullptr);
gui_bridge_set_member_list_cb(nullptr);
@@ -620,9 +624,15 @@ void MainWindow::setupBridgeCallbacks() {
});
/* ── DM (p2p чат) ── */
gui_bridge_set_dm_conv_updated_cb([](const char* conv_id, int conv_id_len) {
gui_bridge_set_dm_conv_updated_cb([](const char* conv_id, int conv_id_len, uint64_t generation) {
if (s_mainWindow)
s_mainWindow->onDmConvUpdated(QString::fromUtf8(conv_id, conv_id_len));
s_mainWindow->onDmConvUpdated(QString::fromUtf8(conv_id, conv_id_len), generation);
});
gui_bridge_set_dm_delete_result_cb([](const uint8_t* data, int len) {
if (!s_mainWindow || len != 25) return;
quint64 request, conv, generation;
memcpy(&request, data, 8); memcpy(&conv, data + 8, 8); memcpy(&generation, data + 16, 8);
s_mainWindow->onDmDeleteResult(request, QString::number(conv), generation, data[24] != 0);
});
gui_bridge_set_dm_msg_received_cb([](const char* conv_id, int conv_id_len, uint64_t author) {
if (s_mainWindow)
@@ -631,6 +641,9 @@ void MainWindow::setupBridgeCallbacks() {
gui_bridge_set_network_changed_cb([](int type) {
if (!s_mainWindow) return;
if (type == 13) {
const auto pending = s_mainWindow->m_dmDeleteRequests;
for (auto it = pending.cbegin(); it != pending.cend(); ++it)
s_mainWindow->onDmDeleteResult(it.key(), it.value().first, it.value().second, false);
s_mainWindow->m_cpuLoadPending = false;
s_mainWindow->m_channelList->setCpuLoad(0);
s_mainWindow->m_accountList->setChannel(QString());
@@ -756,6 +769,7 @@ void MainWindow::setupConnects() {
connect(m_channelList, &ChannelList::createGroupRequested, this, &MainWindow::onCreateGroupRequested);
connect(m_channelList, &ChannelList::settingsRequested, this, &MainWindow::showSettings);
connect(m_channelList, &ChannelList::connMonitorRequested, this, &MainWindow::showConnMonitor);
connect(m_channelList, &ChannelList::dmDeleteRequested, this, &MainWindow::onDmDeleteRequested);
connect(m_messageList, &MessageList::channelSettingsRequested, this, &MainWindow::showChannelSettings);
connect(m_accountList, &AccountList::memberRenamed,
m_messageList, &MessageList::reloadLocalNicks);
@@ -1045,14 +1059,63 @@ void MainWindow::onPmRequested(const QString& chId, quint64 nodeId, const QStrin
/* открытие беседы произойдёт по CHAT_EVT_DM_CONV_UPDATED (onDmConvUpdated) */
}
void MainWindow::onDmConvUpdated(const QString& convId) {
if (!m_channelList) return;
void MainWindow::onDmConvUpdated(const QString& convId, quint64 generation) {
if (!m_channelList || !m_db) return;
bool visible = false;
for (const auto& conv : m_db->getDmConversations()) if (conv.convId == convId && conv.generation == generation) visible = true;
if (!visible) {
GUI_INFO("PM update ignored: hidden/stale conv=%s generation=%llu", qPrintable(convId), (unsigned long long)generation); return;
}
QString key = QStringLiteral("dm:") + convId;
m_channelList->loadChannels();
if (m_currentChannelId == key) { m_messageList->loadChannel(key); return; }
if (qobject_cast<DmInviteDialog*>(QApplication::activeModalWidget())) return;
m_channelList->selectChannel(key);
}
/* Диалог фиксирует поколение строки до вложенного Qt event loop; окончательную проверку выполняет ядро. */
void MainWindow::onDmDeleteRequested(const QString& convId, quint64 generation, const QString& name) {
for (const auto& pending : m_dmDeleteRequests) if (pending.first == convId) return;
QMessageBox box(QMessageBox::Warning, QCoreApplication::translate("ChatGui", "Delete conversation"),
QCoreApplication::translate("ChatGui", "Delete the conversation with %1 and its local files? The other person keeps their history.")
.arg(name), QMessageBox::NoButton, this);
auto* remove = box.addButton(QCoreApplication::translate("ChatGui", "Delete"), QMessageBox::DestructiveRole);
auto* cancel = box.addButton(QCoreApplication::translate("ChatGui", "Cancel"), QMessageBox::RejectRole);
box.setDefaultButton(cancel); box.setEscapeButton(cancel); box.exec();
if (box.clickedButton() != remove) return;
const quint64 request = ++m_dmDeleteSequence;
m_dmDeleteRequests.insert(request, {convId, generation});
m_channelList->setDmDeleting(convId, generation, true);
m_messageList->setDmDeleting(convId, generation, true);
if (gui_bridge_delete_dm(qPrintable(convId), generation, request)) onDmDeleteResult(request, convId, generation, false);
}
/* Только подтверждённый commit очищает беседу. Старый результат не закрывает PM нового поколения. */
void MainWindow::onDmDeleteResult(quint64 request, const QString& convId, quint64 generation, bool success) {
auto expected = m_dmDeleteRequests.constFind(request);
if (expected == m_dmDeleteRequests.cend()) {
GUI_INFO("PM delete: ignored obsolete result request=%llu", (unsigned long long)request); return;
}
if (expected->first != convId || expected->second != generation) {
GUI_ERROR("PM delete: result target mismatch request=%llu conv=%s generation=%llu", (unsigned long long)request,
qPrintable(convId), (unsigned long long)generation); return;
}
m_dmDeleteRequests.remove(request);
GUI_INFO("PM delete completed: request=%llu conv=%s generation=%llu success=%d", (unsigned long long)request,
qPrintable(convId), (unsigned long long)generation, success);
if (success && m_messageList->forgetDmHistory(convId, generation)) {
m_currentChannelId.clear(); saveLastChannelId(QString()); m_accountList->setChannel(QString());
}
m_channelList->setDmDeleting(convId, generation, false);
m_messageList->setDmDeleting(convId, generation, false);
m_channelList->loadChannels();
if (!success) {
auto* error = new QMessageBox(QMessageBox::Warning, QCoreApplication::translate("ChatGui", "Delete conversation"),
QCoreApplication::translate("ChatGui", "Could not delete the conversation. Please try again."), QMessageBox::Ok, this);
error->setAttribute(Qt::WA_DeleteOnClose); error->open();
}
}
void MainWindow::onInviteToPmRequested(const QString& source, quint64 peer, const QString& name) {
if (!m_db || !m_db->isOpen() || !m_node || !m_node->isRunning()) {
GUI_ERROR("invite PM: node unavailable");
@@ -1114,6 +1177,10 @@ void MainWindow::onMessageLinkActivated(const QString& link) {
}
void MainWindow::onDmMsgReceived(const QString& convId, quint64 author) {
if (!m_db) return;
bool visible = false;
for (const auto& conv : m_db->getDmConversations()) if (conv.convId == convId) visible = true;
if (!visible) { GUI_DEBUG("PM message event ignored: hidden conv=%s", qPrintable(convId)); return; }
QString key = QStringLiteral("dm:") + convId;
showIncomingMessageNotification(key, author);
if (m_currentChannelId == key) {
+5 -1
View File
@@ -93,8 +93,10 @@ public:
void onPmRequested(const QString& chId, quint64 nodeId, const QString& name);
void onInviteToPmRequested(const QString& source, quint64 peer, const QString& name);
void onMessageLinkActivated(const QString& link);
void onDmConvUpdated(const QString& convId);
void onDmConvUpdated(const QString& convId, quint64 generation);
void onDmMsgReceived(const QString& convId, quint64 author);
void onDmDeleteRequested(const QString& convId, quint64 generation, const QString& name);
void onDmDeleteResult(quint64 request, const QString& convId, quint64 generation, bool success);
private:
void setupUi();
@@ -129,6 +131,8 @@ private:
QString m_cfgDebugCategories;
QString m_pendingChannelSelect;
QString m_currentChannelId;
quint64 m_dmDeleteSequence = 0;
QHash<quint64, QPair<QString, quint64>> m_dmDeleteRequests; /* request_id → conv_id и удаляемое поколение */
AudioRecorder *m_recorder = nullptr;
ConnMonitorWindow *m_connMonitor = nullptr;
VideoPlayerWindow *m_videoPlayer = nullptr;