Move device linking into an eligible member context action with confirmation
This commit is contained in:
1 parent
10e7eeee3f
commit
18ae58a3d2
3 files changed
+47
-6
No files matched your search
@@ -613,6 +613,42 @@ void AccountList::onMemberDoubleClicked(const QModelIndex& index) {
|
||||
editMember(index.data(MemberListModel::NodeIdRole).toULongLong(), true);
|
||||
}
|
||||
|
||||
bool AccountList::canLinkMyDevice(quint64 nodeId) const {
|
||||
const auto member = m_model->member(nodeId);
|
||||
static const uint8_t noGroup[32] = {};
|
||||
return member && !member->is_self && member->online && (member->conn_up & NCONN_BGP)
|
||||
&& !(member->flags & CHAT_MEMBER_FLAG_DELETED) && !memcmp(member->devgroup, noGroup, sizeof(noGroup));
|
||||
}
|
||||
|
||||
void AccountList::confirmMyDeviceLink(quint64 nodeId) {
|
||||
const auto member = m_model->member(nodeId);
|
||||
if (!canLinkMyDevice(nodeId) || !gui_bridge_is_uasync_ready()) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT, "device link: target unavailable channel=%s node=%016llx", qPrintable(m_channelId),
|
||||
(unsigned long long)nodeId); return;
|
||||
}
|
||||
const QString channel = m_channelId; QPointer<AccountList> alive(this);
|
||||
QPointer<QMessageBox> dialog = new QMessageBox(QMessageBox::Information,
|
||||
QCoreApplication::translate("ChatGui", "This is my device"),
|
||||
QCoreApplication::translate("ChatGui", "Link %1 to your device subgroup. The device will receive the subgroup's shared keys.\n\n"
|
||||
"After you start linking, a PIN will appear here. Enter it on the selected device within two minutes.")
|
||||
.arg(QString::fromUtf8(member->name)), QMessageBox::Cancel, this);
|
||||
const auto release = qScopeGuard([dialog] { if (dialog) delete dialog.data(); });
|
||||
dialog->setObjectName("linkMyDeviceConfirmation"); dialog->setTextFormat(Qt::PlainText);
|
||||
auto* link = dialog->addButton(QCoreApplication::translate("ChatGui", "Start linking"), QMessageBox::AcceptRole);
|
||||
dialog->setDefaultButton(QMessageBox::Cancel);
|
||||
connect(m_model, &MemberListModel::snapshotChanged, dialog, [this, channel, nodeId, link] {
|
||||
link->setEnabled(channel == m_channelId && canLinkMyDevice(nodeId) && gui_bridge_is_uasync_ready());
|
||||
});
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT, "device link: explanation opened channel=%s node=%016llx", qPrintable(channel),
|
||||
(unsigned long long)nodeId);
|
||||
dialog->exec();
|
||||
if (!alive || !dialog || dialog->clickedButton() != link) return;
|
||||
if (channel != m_channelId || !canLinkMyDevice(nodeId) || !gui_bridge_is_uasync_ready()) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT, "device link: cancelled after target changed node=%016llx", (unsigned long long)nodeId); return;
|
||||
}
|
||||
inviteMyDevice(this, channel, nodeId);
|
||||
}
|
||||
|
||||
/* Вложенный event loop меню допускает смену канала, снимка и уничтожение панели. */
|
||||
void AccountList::onMemberContextMenu(const QPoint& pos) {
|
||||
auto* view = qobject_cast<QListView*>(sender()); if (!view) view = m_listView;
|
||||
@@ -657,6 +693,8 @@ void AccountList::onMemberContextMenu(const QPoint& pos) {
|
||||
QAction* editAction = menu.addAction(QCoreApplication::translate("ChatGui", "Edit"));
|
||||
editAction->setEnabled(editable);
|
||||
QAction* filesAction = menu.addAction(QCoreApplication::translate("ChatGui", "Member files"));
|
||||
QAction* myDeviceAction = canLinkMyDevice(nodeId) ? menu.addAction(QCoreApplication::translate("ChatGui", "This is my device")) : nullptr;
|
||||
if (myDeviceAction) myDeviceAction->setEnabled(gui_bridge_is_uasync_ready());
|
||||
QAction* chosen = menu.exec(view->viewport()->mapToGlobal(pos));
|
||||
if (!alive || !chosen) return;
|
||||
const auto current = m_model->member(nodeId);
|
||||
@@ -674,6 +712,7 @@ void AccountList::onMemberContextMenu(const QPoint& pos) {
|
||||
return;
|
||||
}
|
||||
const QString name = QString::fromUtf8(current->name);
|
||||
if (myDeviceAction && chosen == myDeviceAction) { confirmMyDeviceLink(nodeId); return; }
|
||||
if (chosen == inviteAction) { emit inviteRequested(channel, nodeId, name); return; }
|
||||
if (chosen == radioCallAction) { emit radioCallRequested(channel, nodeId); return; }
|
||||
if (chosen == filesAction) { emit filesRequested(channel, nodeId); return; }
|
||||
|
||||
@@ -103,6 +103,8 @@ private:
|
||||
void updateGroupDetail(); // актуализировать список после изменения общего снимка
|
||||
void renameGroup(QString group); // только своя devgroup; повторная проверка после диалога
|
||||
quint64 ownGroupNode(const QString& group) const; // self текущей группы, 0 для чужой/удалённой
|
||||
bool canLinkMyDevice(quint64 nodeId) const; // Чужой неудалённый узел с живым BGP-маршрутом и без devgroup.
|
||||
void confirmMyDeviceLink(quint64 nodeId); // Объяснение, затем явный старт с повторной проверкой выбранного канала/узла.
|
||||
static QString relativeTimeStr(qint64 timestamp);
|
||||
static QString addrStr(const QByteArray& addr, int family);
|
||||
|
||||
|
||||
@@ -124,12 +124,12 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
||||
layout->addWidget(hint);
|
||||
}
|
||||
|
||||
auto* addDevice = new QPushButton(QCoreApplication::translate("ChatGui", isOwn ? "Disconnect from my devices" : "Add device"), this);
|
||||
addDevice->setObjectName("memberAddMyDevice"); addDevice->setEnabled(loaded && !curDeleted && (!isOwn || inDeviceGroup));
|
||||
connect(addDevice, &QPushButton::clicked, this, [this, addDevice] {
|
||||
if (m_isOwn) disconnectMyDevice(addDevice); else inviteMyDevice(this, m_channelId, m_nodeId);
|
||||
});
|
||||
layout->addWidget(addDevice);
|
||||
if (isOwn) {
|
||||
auto* disconnect = new QPushButton(QCoreApplication::translate("ChatGui", "Disconnect from my devices"), this);
|
||||
disconnect->setObjectName("memberAddMyDevice"); disconnect->setEnabled(loaded && !curDeleted && inDeviceGroup);
|
||||
connect(disconnect, &QPushButton::clicked, this, [disconnect] { disconnectMyDevice(disconnect); });
|
||||
layout->addWidget(disconnect);
|
||||
}
|
||||
|
||||
m_transferBtn = new QPushButton(QCoreApplication::translate("ChatGui", "Transfer admin rights"), this);
|
||||
m_transferBtn->setEnabled(haveKey && !isOwn);
|
||||
|
||||
Reference in new issue
Block a user