158 lines
7.8 KiB
C++
158 lines
7.8 KiB
C++
#include <QCoreApplication>
|
|
#include "channelsettingsdialog.h"
|
|
#include "avatars/groupavatarmanager.h"
|
|
#include "../db/db_manager.h"
|
|
#include "../transport/gui_bridge.h"
|
|
#include "../../lib/mem.h"
|
|
extern "C" {
|
|
#include "chat/chat_core.h"
|
|
}
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QPushButton>
|
|
#include <QLabel>
|
|
#include <QFileDialog>
|
|
#include <cstring>
|
|
|
|
ChannelSettingsDialog::ChannelSettingsDialog(const QString& channelId, DbManager* db, QWidget* parent)
|
|
: QDialog(parent)
|
|
, m_channelId(channelId)
|
|
, m_db(db)
|
|
{
|
|
setWindowTitle(QCoreApplication::translate("ChatGui", "Channel Settings"));
|
|
setMinimumWidth(340);
|
|
setModal(true);
|
|
|
|
auto* layout = new QVBoxLayout(this);
|
|
layout->setContentsMargins(20, 16, 20, 16);
|
|
layout->setSpacing(12);
|
|
|
|
auto* titleLabel = new QLabel(QCoreApplication::translate("ChatGui", "Settings for channel"), this);
|
|
titleLabel->setStyleSheet("font-weight: bold; font-size: 14px;");
|
|
layout->addWidget(titleLabel);
|
|
|
|
auto* chIdLabel = new QLabel(channelId, this);
|
|
chIdLabel->setStyleSheet("color: gray; font-size: 11px;");
|
|
chIdLabel->setWordWrap(true);
|
|
layout->addWidget(chIdLabel);
|
|
|
|
if (auto* avatars = GroupAvatarManager::instance()) {
|
|
auto* preview = new QLabel(this); preview->setFixedSize(64, 64); layout->addWidget(preview);
|
|
auto* buttons = new QHBoxLayout;
|
|
auto* upload = new QPushButton(QCoreApplication::translate("ChatGui", "Upload group avatar"), this);
|
|
auto* remove = new QPushButton(QCoreApplication::translate("ChatGui", "Remove group avatar"), this);
|
|
upload->setObjectName("uploadGroupAvatar"); remove->setObjectName("removeGroupAvatar");
|
|
bool hasKey = false;
|
|
if (db && db->isOpen()) for (const auto& row : db->getChannels())
|
|
if (row.channelId == channelId) hasKey = row.ed25519_privkey.size() == 32;
|
|
upload->setEnabled(hasKey); remove->setEnabled(hasKey);
|
|
auto* info = new QLabel(QCoreApplication::translate("ChatGui", "Group avatar: up to 16 KiB. Changes apply immediately and require the group key."), this);
|
|
info->setWordWrap(true); auto* result = new QLabel(this); result->setWordWrap(true);
|
|
buttons->addWidget(upload); buttons->addWidget(remove); layout->addLayout(buttons); layout->addWidget(info); layout->addWidget(result);
|
|
auto refresh = [avatars, preview, channelId] {
|
|
const QImage image = avatars->image(channelId);
|
|
if (image.isNull()) { preview->setPixmap(QPixmap()); preview->setText(QCoreApplication::translate("ChatGui", "No avatar")); }
|
|
else preview->setPixmap(QPixmap::fromImage(image).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
|
};
|
|
connect(avatars, &GroupAvatarManager::changed, this, [channelId, refresh](const QString& channel) { if (channel == channelId) refresh(); });
|
|
connect(avatars, &GroupAvatarManager::status, this, [channelId, result, refresh](const QString& channel, const QString& message) {
|
|
if (channel == channelId) { result->setText(message); refresh(); }
|
|
});
|
|
connect(upload, &QPushButton::clicked, this, [this, avatars, channelId] {
|
|
const QString file = QFileDialog::getOpenFileName(this, QCoreApplication::translate("ChatGui", "Choose avatar"), {},
|
|
QCoreApplication::translate("ChatGui", "Images (*.png *.jpg *.jpeg *.webp)"));
|
|
if (!file.isEmpty()) avatars->upload(channelId, file);
|
|
});
|
|
connect(remove, &QPushButton::clicked, this, [avatars, channelId] { avatars->remove(channelId); }); refresh();
|
|
}
|
|
|
|
layout->addSpacing(8);
|
|
|
|
m_autoPlayVoice = new QCheckBox(QCoreApplication::translate("ChatGui", "Auto-play voice messages on receive"), this);
|
|
m_autoPlayVoice->setToolTip(QCoreApplication::translate("ChatGui",
|
|
"Voice messages will play automatically when received. Multiple messages queue up and play "
|
|
"sequentially without interrupting current playback."));
|
|
layout->addWidget(m_autoPlayVoice);
|
|
|
|
m_soundOnMessage = new QCheckBox(QCoreApplication::translate("ChatGui", "Play sound on incoming message"), this);
|
|
m_soundOnMessage->setToolTip(QCoreApplication::translate("ChatGui", "Play a notification sound when a message arrives in this channel."));
|
|
layout->addWidget(m_soundOnMessage);
|
|
|
|
m_pttMode = new QCheckBox(QCoreApplication::translate("ChatGui", "Push-To-Talk (PTT) mode"), this);
|
|
m_pttMode->setToolTip(QCoreApplication::translate("ChatGui", "Record voice messages with push-to-talk. (Coming soon)"));
|
|
m_pttMode->setEnabled(false);
|
|
layout->addWidget(m_pttMode);
|
|
|
|
layout->addStretch();
|
|
|
|
auto* btnLayout = new QHBoxLayout();
|
|
btnLayout->setSpacing(8);
|
|
btnLayout->addStretch();
|
|
|
|
auto* cancelBtn = new QPushButton(QCoreApplication::translate("ChatGui", "Cancel"), this);
|
|
cancelBtn->setMinimumWidth(90);
|
|
cancelBtn->setStyleSheet(
|
|
"QPushButton { border: 1px solid palette(mid); border-radius: 4px;"
|
|
" padding: 6px 16px; font-size: 13px; background: palette(button); }"
|
|
"QPushButton:hover { background: palette(light); }");
|
|
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
|
btnLayout->addWidget(cancelBtn);
|
|
|
|
auto* saveBtn = new QPushButton(QCoreApplication::translate("ChatGui", "Save"), this);
|
|
saveBtn->setMinimumWidth(90);
|
|
saveBtn->setDefault(true);
|
|
saveBtn->setStyleSheet(
|
|
"QPushButton { border: none; border-radius: 4px;"
|
|
" padding: 6px 16px; font-size: 13px; font-weight: bold;"
|
|
" background: #3390EC; color: white; }"
|
|
"QPushButton:hover { background: #2B7ED4; }");
|
|
connect(saveBtn, &QPushButton::clicked, this, &ChannelSettingsDialog::onSave);
|
|
btnLayout->addWidget(saveBtn);
|
|
|
|
layout->addLayout(btnLayout);
|
|
|
|
if (m_db && m_db->isOpen()) {
|
|
QString autoPlayKey = QStringLiteral("ch_%1_auto_play_voice").arg(channelId);
|
|
m_autoPlayVoice->setChecked(m_db->getUiStateInt(autoPlayKey, 0) != 0);
|
|
QString soundKey = QStringLiteral("ch_%1_sound_on_message").arg(channelId);
|
|
m_soundOnMessage->setChecked(m_db->getUiStateInt(soundKey, 1) != 0);
|
|
QString pttKey = QStringLiteral("ch_%1_ptt_mode").arg(channelId);
|
|
m_pttMode->setChecked(m_db->getUiStateInt(pttKey, 0) != 0);
|
|
}
|
|
}
|
|
|
|
void ChannelSettingsDialog::onSave() {
|
|
auto saveKey = [&](const char* suffix, int val) {
|
|
QString key = QStringLiteral("ch_%1_%2").arg(m_channelId, QString::fromUtf8(suffix));
|
|
QByteArray keyBA = key.toUtf8();
|
|
QByteArray valBA = QByteArray::number(val);
|
|
size_t klen = (size_t)keyBA.size(), vlen = (size_t)valBA.size();
|
|
size_t total = klen + 1 + vlen + 1;
|
|
if (total <= 256) {
|
|
struct save_ui_state_arg* arg = (struct save_ui_state_arg*)u_malloc(sizeof(struct save_ui_state_arg));
|
|
if (!arg) return;
|
|
arg->inst = gui_bridge_get_inst();
|
|
memcpy(arg->data, keyBA.constData(), klen + 1);
|
|
memcpy(arg->data + klen + 1, valBA.constData(), vlen + 1);
|
|
gui_bridge_post_uasync_fn(chat_core_save_ui_state_trampoline, arg);
|
|
}
|
|
};
|
|
saveKey("auto_play_voice", m_autoPlayVoice->isChecked() ? 1 : 0);
|
|
saveKey("ptt_mode", m_pttMode->isChecked() ? 1 : 0);
|
|
|
|
/* sound_on_message: сохранить + разослать пирам (троттлинг db_sync на сервере) */
|
|
{
|
|
int on = m_soundOnMessage->isChecked() ? 1 : 0;
|
|
QByteArray chIdBA = m_channelId.toUtf8();
|
|
struct chat_sound_arg* arg = (struct chat_sound_arg*)u_malloc(sizeof(struct chat_sound_arg));
|
|
if (arg) {
|
|
memset(arg, 0, sizeof(*arg));
|
|
arg->inst = gui_bridge_get_inst();
|
|
strncpy(arg->ch_id, chIdBA.constData(), sizeof(arg->ch_id) - 1);
|
|
arg->on = on;
|
|
gui_bridge_post_uasync_fn(chat_core_set_sound_on_message_trampoline, arg);
|
|
}
|
|
}
|
|
accept();
|
|
}
|