This commit is contained in:
evgeny committed 2026-08-04 15:29:25 +03:00
1 parent 26f4da1b7c
commit 712d1b53df
29 files changed
+1029 -1138

No files matched your search

+120 -3
View File
@@ -1,5 +1,14 @@
#include "invitedialog.h"
#include "invite_link.h"
#include "qrcode_utils.h"
#include "debug_ui.h"
#include "../transport/utun_node.h"
#include "../transport/gui_bridge.h"
#include "../db/db_manager.h"
extern "C" {
#include "chat/chat_sync.h"
#include "transport_layer/secure_channel.h"
}
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
@@ -8,9 +17,11 @@
#include <QClipboard>
#include <QApplication>
#include <QTimer>
#include <QFrame>
InviteDialog::InviteDialog(const QString& link, QWidget* parent)
: QDialog(parent), m_link(link)
InviteDialog::InviteDialog(const QString& link, const QString& channelId,
UtunNode* node, QWidget* parent)
: QDialog(parent), m_link(link), m_channelId(channelId), m_node(node)
{
setWindowTitle("Пригласительная ссылка");
setMinimumWidth(420);
@@ -25,7 +36,7 @@ InviteDialog::InviteDialog(const QString& link, QWidget* parent)
layout->addWidget(linkEdit);
auto *btnLayout = new QHBoxLayout();
auto *copyBtn = new QPushButton("Скопировать", this);
auto *copyBtn = new QPushButton("Копировать", this);
connect(copyBtn, &QPushButton::clicked, this, [this, linkEdit]() {
QClipboard* cb = QApplication::clipboard();
cb->clear(QClipboard::Clipboard);
@@ -48,6 +59,44 @@ InviteDialog::InviteDialog(const QString& link, QWidget* parent)
qrLabel->setAlignment(Qt::AlignCenter);
layout->addWidget(qrLabel, 0, Qt::AlignCenter);
/* ── Разделитель ── */
auto *sep = new QFrame(this);
sep->setFrameShape(QFrame::HLine);
sep->setStyleSheet("QFrame { color: palette(mid); }");
layout->addWidget(sep);
/* ── Пригласить по чужой ссылке ── */
auto *inviteTitle = new QLabel("Пригласить в эту группу:", this);
inviteTitle->setStyleSheet("font-weight: bold; font-size: 12px;");
layout->addWidget(inviteTitle);
m_inviteLinkEdit = new QLineEdit(this);
m_inviteLinkEdit->setPlaceholderText("utun://...");
m_inviteLinkEdit->setStyleSheet(
"QLineEdit { border: 1px solid palette(mid); border-radius: 4px;"
" padding: 6px 8px; font-size: 12px; background: palette(base); }");
layout->addWidget(m_inviteLinkEdit);
m_inviteStatusLabel = new QLabel(this);
m_inviteStatusLabel->setWordWrap(true);
m_inviteStatusLabel->setStyleSheet("color: gray; font-size: 11px; padding: 2px 0;");
layout->addWidget(m_inviteStatusLabel);
auto *invBtnLayout = new QHBoxLayout();
invBtnLayout->addStretch();
m_inviteSendBtn = new QPushButton("Пригласить", this);
m_inviteSendBtn->setStyleSheet(
"QPushButton { border: none; border-radius: 4px;"
" padding: 5px 14px; font-size: 12px; font-weight: bold;"
" background: #3390EC; color: white; }"
"QPushButton:hover { background: #2B7ED4; }"
"QPushButton:disabled { background: palette(mid); color: palette(midlight); }");
connect(m_inviteSendBtn, &QPushButton::clicked, this, &InviteDialog::onSendInvite);
invBtnLayout->addWidget(m_inviteSendBtn);
layout->addLayout(invBtnLayout);
connect(m_inviteLinkEdit, &QLineEdit::returnPressed, this, &InviteDialog::onSendInvite);
auto *closeBtn = new QPushButton("OK", this);
connect(closeBtn, &QPushButton::clicked, this, &QDialog::accept);
layout->addWidget(closeBtn, 0, Qt::AlignRight);
@@ -62,3 +111,71 @@ InviteDialog::InviteDialog(const QString& link, QWidget* parent)
}
});
}
void InviteDialog::onInviteByLink() {
/* Toggle visibility of invite-by-link section (handled in constructor now) */
}
void InviteDialog::onInviteLinkTextChanged() {
}
void InviteDialog::setInviteStatus(const QString& text, bool isError) {
if (isError)
m_inviteStatusLabel->setStyleSheet("color: #D0021B; font-size: 11px; padding: 2px 0;");
else
m_inviteStatusLabel->setStyleSheet("color: gray; font-size: 11px; padding: 2px 0;");
m_inviteStatusLabel->setText(text);
}
void InviteDialog::onSendInvite() {
if (m_inviteSending) return;
QString link = m_inviteLinkEdit->text().trimmed();
if (link.isEmpty()) {
setInviteStatus("Вставьте utun:// ссылку узла.", true);
return;
}
InviteData d = decodeInviteLink(link);
if (!d.error.isEmpty()) {
setInviteStatus("Неверная ссылка: " + d.error, true);
return;
}
if (d.pubkey.size() != 32) {
setInviteStatus("Pubkey не 32 байта.", true);
return;
}
if (d.addrs.isEmpty()) {
setInviteStatus("Нет адресов.", true);
return;
}
uint64_t targetNodeId = sc_derive_node_id_from_pubkey((const uint8_t*)d.pubkey.constData());
m_inviteSending = true;
m_inviteTargetNodeId = targetNodeId;
m_inviteSendBtn->setEnabled(false);
setInviteStatus("Приглашаем узел 0x" + QString::number(targetNodeId, 16) + "...");
/* Save addresses to DB */
QByteArray addrsBuf;
for (const auto& a : d.addrs) {
addrsBuf.append(static_cast<char>(a.family));
addrsBuf.append(static_cast<char>(a.socketId));
addrsBuf.append(static_cast<char>(a.proto));
addrsBuf.append(a.address);
addrsBuf.append(static_cast<char>((a.port >> 8) & 0xFF));
addrsBuf.append(static_cast<char>(a.port & 0xFF));
}
GUI_INFO("invite_by_link: channel=%s target=0x%016llx addrs=%d",
m_channelId.toUtf8().constData(), targetNodeId, d.addrs.size());
/* Post to uasync thread */
chat_sync_invite_to_channel(
chat_core_get_inst(), m_channelId.toUtf8().constData(), targetNodeId);
setInviteStatus("Приглашение отправлено. OK");
QTimer::singleShot(2000, this, [this]() {
m_inviteSending = false;
m_inviteSendBtn->setEnabled(true);
});
}