diff --git a/tools/chatgui-android/jni_bridge/android_jni_bridge.c b/tools/chatgui-android/jni_bridge/android_jni_bridge.c index b9ba5d52..7872c595 100644 --- a/tools/chatgui-android/jni_bridge/android_jni_bridge.c +++ b/tools/chatgui-android/jni_bridge/android_jni_bridge.c @@ -664,13 +664,14 @@ void utun_bridge_dm_send_file(const char* conv_id, const char* path, const char* if (!conv_id || !path || !name || !uasync_is_running(ua)) { bridge_log(BLEV_WARN, "DM file: invalid request/core stopped"); return; } struct dm_file_req* req = u_calloc(1, sizeof(*req)); if (!req) { bridge_log(BLEV_ERROR, "DM file: OOM"); return; } - if (strlen(conv_id) >= sizeof(req->conv) || strlen(path) >= sizeof(req->path) || strlen(name) >= sizeof(req->name)) { + if (strlen(conv_id) >= sizeof(req->conv) || strlen(path) >= sizeof(req->path) || strlen(name) >= sizeof(req->info.name)) { bridge_log(BLEV_ERROR, "DM file: path, conversation or name too long"); u_free(req); return; } req->inst = instance_lite_get_instance(); snprintf(req->conv, sizeof(req->conv), "%s", conv_id); snprintf(req->path, sizeof(req->path), "%s", path); - snprintf(req->name, sizeof(req->name), "%s", name); + req->info.kind = ATTACHMENT_FILE; + snprintf(req->info.name, sizeof(req->info.name), "%s", name); uasync_post(ua, dm_send_file_trampoline, req); } diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index b61f3f3d..bd8cc11e 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/tools/chatgui/src/messagelist.cpp @@ -385,6 +385,17 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent msgDelegate->setImageOpenCallback([this](const QString& path) { emit openImageRequested(path); }); + msgDelegate->setDownloadCallback([](const QModelIndex& index) { + QString target = index.data(MsgChannelIdRole).toString(); + qint64 id = index.data(MsgIdRole).toLongLong(); + if (target.isEmpty() || target.startsWith("dm:") || id <= 0) return false; + auto* req = (struct attachment_dl_req*)u_calloc(1, sizeof(struct attachment_dl_req)); + if (!req) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "attachment: download request allocation failed"); return false; } + req->inst = gui_bridge_get_inst(); req->msg_id = id; + snprintf(req->channel_id, sizeof(req->channel_id), "%s", target.toUtf8().constData()); + gui_bridge_post_uasync_fn(chat_core_attachment_download_trampoline, req); + return true; + }); m_view->setItemDelegate(msgDelegate); m_view->setEditTriggers(QAbstractItemView::NoEditTriggers); m_view->setSelectionMode(QAbstractItemView::NoSelection); @@ -1097,7 +1108,8 @@ void MessageList::onDmMessages(const uint8_t* data, int len) { item->setData(QVariant::fromValue(author), MsgAuthorNodeIdRole); item->setData(dir == 1 ? 1 : 0, MsgIsOutgoingRole); item->setData(m_currentChannelId, MsgChannelIdRole); - item->setData(file ? QStringLiteral("application/octet-stream") : QStringLiteral("text/plain"), MsgContentTypeRole); + QString type = message.value("content_type").toString(QStringLiteral("text/plain")); + item->setData(type, MsgContentTypeRole); if (file) { QString path = message.value("media_path").toString(); item->setData(path, MsgVoiceFileRole); @@ -1105,6 +1117,19 @@ void MessageList::onDmMessages(const uint8_t* data, int len) { item->setData((qint64)message.value("media_size").toDouble(), MsgFileSizeRole); item->setData(path.isEmpty() ? (state == "expired" ? 0 : 1) : 2, MsgFileDownloadStateRole); item->setData(status, MsgDeliveryStateRole); + int duration = message.value("duration_ms").toInt(); + if (type == "audio/opus") { + item->setData(QString::number(duration / 1000.0, 'f', 1) + "s", MsgVoiceDurationRole); + item->setData((qint64)message.value("media_size").toDouble(), MsgVoiceFileSizeRole); + QVariantList waveform; + const QString levels = QStringLiteral("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); + for (QChar level : message.value("waveform").toString()) waveform.append(qMax(0, levels.indexOf(level)) / 63.0); + item->setData(waveform, MsgVoiceWaveformRole); + } else if (type == "video/mp4") { + item->setData(duration, MsgVideoDurationMsRole); + item->setData(message.value("width").toInt(), MsgVideoWidthRole); + item->setData(message.value("height").toInt(), MsgVideoHeightRole); + } } m_model->appendRow(item); }