Centralize owned attachment downloads and key auto-play by channel and row

This commit is contained in:
evgeny committed 2026-10-28 00:59:00 +01:00
1 parent 0d6fd63e8f
commit 6adfe5cf13
3 files changed
+34 -6

No files matched your search

+8 -6
View File
@@ -30,12 +30,12 @@ class CallAudioEngine;
class MemberFileBrowser;
class MessageNotification;
class QMessageBox;
struct MessageRow;
struct AutoPlayItem {
QString channelId;
qint64 msgId = 0;
bool downloadStarted = false;
float durationSec = 0.0f;
QString channelId; // Канал снимка; msgId уникален только внутри него.
qint64 msgId = 0; // Локальный rowid сообщения.
bool downloadStarted = false; // Команда загрузки принята очередью; false допускает первую попытку.
};
class MainWindow : public QMainWindow {
@@ -108,8 +108,9 @@ private:
void setupBridgeCallbacks();
void setupConnects();
void onShutdownCheck();
void autoPlayCheckNewMessage(const QString& channelId);
void autoPlayCheckNewMessage(const QString& channelId, qint64 msgId = 0);
QString autoPlayMediaDir() const;
QString autoPlayFilePath(const QString& channelId, const MessageRow& message) const;
void showMemberFiles(const QString& channel, quint64 owner = 0);
void showStreamPublisher(quint64 group, StreamGridWindow* returnTo = nullptr); // Управление; закрытие возвращает фокус сетке.
@@ -145,7 +146,8 @@ private:
QTimer* m_cpuLoadTimer = nullptr;
bool m_cpuLoadPending = false;
QTimer* m_shutdownTimer = nullptr;
QSet<int64_t> m_autoPlayDownloading; /* msgIds with download in progress */
QSet<QPair<QString, qint64>> m_autoPlayDownloading; // (channel,rowid) ожидающей загрузки.
QHash<QString, qint64> m_lastAutoPlayId; // Подавляет повторное добавление последнего сообщения канала.
QHash<quint64, CallWindow*> m_activeCalls; /* call_id → окно звонка */
QPointer<QMessageBox> m_radioCallWindow;
+3
View File
@@ -98,6 +98,9 @@ int gui_bridge_post_uasync_owned_fn(void (*fn)(void*), void* arg);
* 0 передаёт владение: fn освобождает arg после исполнения, мост — при отмене.
* -1 оставляет блок вызывающему для u_free; вложенные ресурсы этим API не поддерживаются. */
int gui_bridge_post_bound_fn(void (*fn)(void*), void* arg, struct UTUN_INSTANCE** binding);
/* Скачать вложение канала: десятичный непустой channel (до 63 байт), msg_id>0.
* Копия/привязка/владение принадлежат мосту. 0 — запрос принят, -1 — отказ с логом без heap-обязательств GUI. */
int gui_bridge_download_attachment(const char* channel, int64_t msg_id);
/* Команды обычного звонка: GUI не передаёт instance или heap-аргументы.
* Под mutex моста копируют данные, привязываются к живому running-ядру и передают владение очереди.
@@ -789,6 +789,29 @@ int gui_bridge_post_bound_fn(void (*fn)(void*), void* arg, struct UTUN_INSTANCE*
return 0;
}
/* Общий путь загрузки для delegate, контекстного меню и auto-play. */
int gui_bridge_download_attachment(const char* channel, int64_t msg_id) {
const size_t length = channel ? strnlen(channel, sizeof(attachment_dl_req::channel_id)) : 0;
if (!length || length == sizeof(attachment_dl_req::channel_id) || strspn(channel, "0123456789") != length || msg_id <= 0) {
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment download rejected: invalid channel/id length=%zu id=%lld", length, (long long)msg_id);
return -1;
}
std::lock_guard<std::mutex> guard(bridge_mutex);
if (!g_inst || !g_ua || !uasync_is_running(g_ua)) {
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "attachment download rejected: core unavailable channel=%s id=%lld", channel, (long long)msg_id);
return -1;
}
auto* request = static_cast<attachment_dl_req*>(u_calloc(1, sizeof(attachment_dl_req)));
if (!request) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment download allocation failed"); return -1; }
request->inst = g_inst; request->msg_id = msg_id; memcpy(request->channel_id, channel, length + 1);
if (post_command(chat_core_attachment_download_trampoline, request, true) < 0) {
u_free(request); DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment download queue failed channel=%s id=%lld", channel, (long long)msg_id);
return -1;
}
DEBUG_DEBUG(DEBUG_CATEGORY_MEDIA, "attachment download queued channel=%s id=%lld", channel, (long long)msg_id);
return 0;
}
/* Создание payload и enqueue атомарны относительно detach; GUI не читает заимствованный instance. */
int gui_bridge_call_start(const char* channel, uint64_t peer, uint64_t call_id) {
const size_t length = channel ? strnlen(channel, sizeof(call_start_arg::ch_id)) : 0;