|
|
|
|
@ -26,6 +26,7 @@
|
|
|
|
|
#include <QDragEnterEvent> |
|
|
|
|
#include <QDropEvent> |
|
|
|
|
#include <QMimeData> |
|
|
|
|
#include <QMimeDatabase> |
|
|
|
|
#include <QUrl> |
|
|
|
|
#include <QToolTip> |
|
|
|
|
#include <cmath> |
|
|
|
|
@ -132,6 +133,13 @@ InputBar::InputBar(EmojiPanel *emojiPanel, AudioRecorder *recorder, QWidget *par
|
|
|
|
|
QCoreApplication::translate("ChatGui", "Attach"), this); |
|
|
|
|
connect(m_attachBtn, &QPushButton::clicked, this, &InputBar::onAttachClicked); |
|
|
|
|
layout->addWidget(wrapBottomBtn(m_attachBtn, 3), 0, Qt::AlignBottom); |
|
|
|
|
m_encryptBtn = new QPushButton(QString::fromUtf8("🔒"), this); |
|
|
|
|
m_encryptBtn->setObjectName("encryptAttachmentButton"); |
|
|
|
|
m_encryptBtn->setCheckable(true); |
|
|
|
|
m_encryptBtn->setFixedSize(32, 32); |
|
|
|
|
m_encryptBtn->setToolTip(QCoreApplication::translate("ChatGui", "Encrypt attachment; approve each recipient's key request")); |
|
|
|
|
m_encryptBtn->setAccessibleName(QCoreApplication::translate("ChatGui", "Encrypt attachment")); |
|
|
|
|
layout->addWidget(wrapBottomBtn(m_encryptBtn, 3), 0, Qt::AlignBottom); |
|
|
|
|
|
|
|
|
|
m_input->setAcceptRichText(false); |
|
|
|
|
m_input->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
|
|
|
@ -405,7 +413,29 @@ void InputBar::onSendClicked() {
|
|
|
|
|
|
|
|
|
|
if (hasAttach) { |
|
|
|
|
const quint64 requestId = beginReplySend(reply, m_replyGeneration, m_channelIdForRecord, {}, m_pendingAttachSrc); |
|
|
|
|
if (m_pendingAttachAsImage) { |
|
|
|
|
const bool encrypted = !m_dmMode && m_encryptBtn->isChecked(); |
|
|
|
|
if (encrypted) { |
|
|
|
|
auto* request = (struct attachment_send_req*)u_calloc(1, sizeof(struct attachment_send_req)); |
|
|
|
|
QByteArray source = m_pendingAttachSrc.toUtf8(), name = m_pendingAttachName.toUtf8(); |
|
|
|
|
if (!request || source.size() >= (int)sizeof(request->source) || name.size() >= (int)sizeof(request->info.name)) { |
|
|
|
|
GUI_ERROR("encrypted attachment: invalid path/name or allocation failed"); |
|
|
|
|
u_free(request); submissionResult(requestId, false); return; |
|
|
|
|
} |
|
|
|
|
request->encrypted = 1; |
|
|
|
|
request->info.kind = m_pendingAttachAsVideo ? ATTACHMENT_VIDEO : ATTACHMENT_FILE; |
|
|
|
|
request->transcode = m_pendingAttachAsVideo; |
|
|
|
|
if (request->transcode) name = (QFileInfo(m_pendingAttachName).completeBaseName() + ".mp4").toUtf8(); |
|
|
|
|
if (m_pendingAttachAsImage) { |
|
|
|
|
const QByteArray type = QMimeDatabase().mimeTypeForFile(m_pendingAttachSrc, QMimeDatabase::MatchExtension).name().toUtf8(); |
|
|
|
|
if (type.size() < (int)sizeof(request->content_type)) snprintf(request->content_type, sizeof(request->content_type), "%s", type.constData()); |
|
|
|
|
} |
|
|
|
|
snprintf(request->source, sizeof(request->source), "%s", source.constData()); |
|
|
|
|
snprintf(request->info.name, sizeof(request->info.name), "%s", name.constData()); |
|
|
|
|
if (reply.size() == 32) memcpy(request->reply_to, reply.constData(), 32); |
|
|
|
|
request->request_id = requestId; |
|
|
|
|
emit submitAttachment(m_channelIdForRecord, request); |
|
|
|
|
m_encryptBtn->setChecked(false); |
|
|
|
|
} else if (m_pendingAttachAsImage) { |
|
|
|
|
GUI_INFO("send: image=%s name=%s", qPrintable(m_pendingAttachSrc), qPrintable(m_pendingAttachName)); |
|
|
|
|
emit sendImageAttachment(m_channelIdForRecord, m_pendingAttachSrc, m_pendingAttachDest, m_pendingAttachName, reply, requestId); |
|
|
|
|
} else if (m_pendingAttachAsVideo) { |
|
|
|
|
@ -451,11 +481,14 @@ void InputBar::setRecordingContext(const QString& mediaDirBase, const QString& c
|
|
|
|
|
|
|
|
|
|
void InputBar::setDmMode(bool enabled) { |
|
|
|
|
m_dmMode = enabled; |
|
|
|
|
m_encryptBtn->setVisible(!enabled); |
|
|
|
|
if (enabled) m_encryptBtn->setChecked(false); |
|
|
|
|
m_pttBtn->setEnabled(true); |
|
|
|
|
m_attachBtn->setEnabled(true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void InputBar::setMediaEnabled(bool enabled) { |
|
|
|
|
if (m_encryptBtn) m_encryptBtn->setEnabled(enabled); |
|
|
|
|
if (m_pttBtn) m_pttBtn->setEnabled(enabled); |
|
|
|
|
if (m_attachBtn) m_attachBtn->setEnabled(enabled); |
|
|
|
|
if (!enabled && m_dropHint) m_dropHint->hide(); |
|
|
|
|
@ -468,6 +501,7 @@ void InputBar::onPttPressed() {
|
|
|
|
|
m_pttActive = m_recorder->isRecording(); |
|
|
|
|
if (!m_pttActive) { DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "voice recording did not start; composer remains idle"); return; } |
|
|
|
|
m_recordTarget = m_channelIdForRecord; |
|
|
|
|
m_recordEncrypted = !m_dmMode && m_encryptBtn->isChecked(); |
|
|
|
|
m_recordReply = m_replyTo; m_recordReplyGeneration = m_replyGeneration; m_replyFailed = false; |
|
|
|
|
m_pttBtn->setStyleSheet(m_pttBtn->styleSheet() + |
|
|
|
|
"QPushButton { background: #e74c3c; border-radius: 4px; }"); |
|
|
|
|
@ -490,10 +524,12 @@ void InputBar::onPttReleased() {
|
|
|
|
|
auto* request = (struct attachment_send_req*)u_calloc(1, sizeof(struct attachment_send_req)); |
|
|
|
|
if (!request) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "InputBar: voice request allocation failed"); return; } |
|
|
|
|
request->info.kind = ATTACHMENT_VOICE; request->preset = VoiceEncoder::preset(); |
|
|
|
|
request->encrypted = m_recordEncrypted; |
|
|
|
|
if (!m_recorder->takeRecording(request)) { u_free(request); return; } |
|
|
|
|
if (m_recordReply.size() == 32) memcpy(request->reply_to, m_recordReply.constData(), 32); |
|
|
|
|
request->request_id = beginReplySend(m_recordReply, m_recordReplyGeneration, m_recordTarget); |
|
|
|
|
emit submitAttachment(m_recordTarget, request); |
|
|
|
|
if (m_recordTarget == m_channelIdForRecord) m_encryptBtn->setChecked(false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void InputBar::onAttachClicked() { |
|
|
|
|
|