Preserve failed composer drafts and cancel PM submissions with a result
This commit is contained in:
1 parent
9d48821af2
commit
f87ee63a1d
3 files changed
+41
-10
No files matched your search
@@ -279,7 +279,7 @@ bool InputBar::submissionPending() const {
|
||||
/* Канальный текст и каждая часть ответа имеют собственное подтверждение и снимок черновика. */
|
||||
quint64 InputBar::beginSubmission(const QByteArray& reply, quint64 generation, const QString& target,
|
||||
const QString& text, const QString& source) {
|
||||
if (reply.isEmpty() && (m_dmMode || text.isEmpty())) return 0;
|
||||
if (reply.isEmpty() && text.isEmpty()) return 0;
|
||||
const quint64 request = ++s_submissionSequence;
|
||||
m_pendingSubmissions.insert(request, {generation, target, text, source, m_input->document()->revision(), m_attachmentRevision});
|
||||
GUI_DEBUG("send: pending ch=%s reply=%s request=%llu", qPrintable(target), reply.toHex().constData(), (unsigned long long)request);
|
||||
@@ -287,6 +287,11 @@ quint64 InputBar::beginSubmission(const QByteArray& reply, quint64 generation, c
|
||||
}
|
||||
|
||||
void InputBar::submissionResult(quint64 request, bool success) {
|
||||
if (!request && !success) {
|
||||
m_submissionFailed = true;
|
||||
GUI_ERROR("send: untracked attachment rejected target=%s", qPrintable(m_channelIdForRecord));
|
||||
emit attachmentRejected(QCoreApplication::translate("ChatGui", "Could not send message. Please try again.")); return;
|
||||
}
|
||||
if (request && request == m_editRequest) {
|
||||
m_editRequest = 0; m_input->setReadOnly(false);
|
||||
if (success) cancelEdit();
|
||||
@@ -515,13 +520,14 @@ void InputBar::onSendClicked() {
|
||||
emit sendFileAttachment(target, attachmentSource, attachmentDestination, attachmentName, reply, requestId);
|
||||
}
|
||||
if (!alive || context != m_attachmentContext) return;
|
||||
if (m_submissionFailed) return;
|
||||
if (reply.isEmpty()) clearPendingAttachment();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
const quint64 request = beginSubmission(reply, m_replyGeneration, m_channelIdForRecord, text);
|
||||
emit sendMessage(text, reply, request);
|
||||
if (!alive || context != m_attachmentContext) return;
|
||||
if (!request) m_input->clear();
|
||||
if (!request && !m_submissionFailed) m_input->clear();
|
||||
if (m_emojiPanel) m_emojiPanel->hide();
|
||||
m_input->setFocus();
|
||||
}
|
||||
|
||||
@@ -135,6 +135,9 @@ int gui_bridge_update_name(const char* name);
|
||||
* При -1 результата нет: вызывающий освобождает req и сам сообщает об отказе своему composer. */
|
||||
struct chat_msg_submit;
|
||||
int gui_bridge_submit_message(struct chat_msg_submit* req);
|
||||
/* PM-текст с request_id: привязка/владение/отмена и MSG_SUBMITTED как у канального composer. */
|
||||
struct dm_send_req;
|
||||
int gui_bridge_submit_dm_message(struct dm_send_req* req);
|
||||
/* Подготовка вложения: тот же контракт результата, но отмена также освобождает PCM/compressor/временный source
|
||||
* и сообщает MSG_SUBMITTED(false). При -1 caller вызывает attachment_send_discard(req). */
|
||||
struct attachment_send_req;
|
||||
|
||||
@@ -1019,14 +1019,19 @@ int gui_bridge_update_name(const char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Общий codec composer: ID little-endian и success=0, без вызова GUI под mutex. */
|
||||
static void post_submission_failure(uint64_t id) {
|
||||
if (!id) return;
|
||||
uint8_t result[9] = {0};
|
||||
for (unsigned i = 0; i < 8; ++i) result[i] = (uint8_t)(id >> (8 * i));
|
||||
gui_bridge_post(CHAT_EVT_MSG_SUBMITTED, result, sizeof(result));
|
||||
}
|
||||
|
||||
/* Отмена выполняется в uasync, но не вызывает обработчик ядра под bridge_mutex; результат копируется в Qt-очередь. */
|
||||
static void cancel_message_submit(void* arg) {
|
||||
auto* request = static_cast<chat_msg_submit*>(arg);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "composer submission cancelled: request=%llu", (unsigned long long)request->request_id);
|
||||
if (!request->request_id) return;
|
||||
uint8_t result[9] = {0};
|
||||
for (unsigned i = 0; i < 8; ++i) result[i] = (uint8_t)(request->request_id >> (8 * i));
|
||||
gui_bridge_post(CHAT_EVT_MSG_SUBMITTED, result, sizeof(result));
|
||||
post_submission_failure(request->request_id);
|
||||
}
|
||||
|
||||
int gui_bridge_submit_message(struct chat_msg_submit* req) {
|
||||
@@ -1038,13 +1043,30 @@ int gui_bridge_submit_message(struct chat_msg_submit* req) {
|
||||
return post_command(chat_core_submit_trampoline, req, true, cancel_message_submit);
|
||||
}
|
||||
|
||||
/* PM composer получает отказ также при detach до исполнения native trampoline. */
|
||||
static void cancel_dm_submit(void* arg) {
|
||||
auto* request = static_cast<dm_send_req*>(arg);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DM, "PM submission cancelled: request=%llu", (unsigned long long)request->request_id);
|
||||
post_submission_failure(request->request_id);
|
||||
}
|
||||
|
||||
int gui_bridge_submit_dm_message(struct dm_send_req* req) {
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
if (!req || !g_inst || !g_ua || !uasync_is_running(g_ua)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_DM, "PM submission: core/request unavailable"); return -1;
|
||||
}
|
||||
req->inst = g_inst;
|
||||
if (post_command(dm_send_trampoline, req, true, cancel_dm_submit) < 0) {
|
||||
req->inst = nullptr; DEBUG_ERROR(DEBUG_CATEGORY_DM, "PM submission: queue allocation failed"); return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DM, "PM text queued: conversation=%s request=%llu", req->conv_id, (unsigned long long)req->request_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Отмена до native trampoline не требует живого media owner; callback освобождает весь запрос сам. */
|
||||
static void cancel_attachment_submit(void* arg) {
|
||||
auto* request = static_cast<attachment_send_req*>(arg);
|
||||
if (request->request_id) {
|
||||
uint8_t result[9] = {0};
|
||||
memcpy(result, &request->request_id, 8); gui_bridge_post(CHAT_EVT_MSG_SUBMITTED, result, sizeof(result));
|
||||
}
|
||||
post_submission_failure(request->request_id);
|
||||
attachment_send_discard(request);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user