Add caller decision controls and colored phone presence on desktop

This commit is contained in:
evgeny committed 2026-10-19 14:54:01 +02:00
1 parent b68116eedf
commit 37cf6089e7
3 files changed
+52 -5

No files matched your search

+8 -1
View File
@@ -148,7 +148,9 @@ void AccountDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
const QRect radio = actionRect(option.rect, Action::RadioCall);
const QColor radioColor = flags & CHAT_MEMBER_FLAG_RADIO ? QColor("#4CAF50") : color;
FlagPainter::drawRadio(painter, radio.center().x() - 12, radio.center().y() - 12, 24, radioColor);
drawCallButton(painter, actionRect(option.rect, Action::Call), color);
const bool known = index.data(MemberListModel::OnlineRole).toBool() && (flags & CHAT_MEMBER_FLAG_PHONE_KNOWN);
const QColor phoneColor = known ? QColor(flags & CHAT_MEMBER_FLAG_PHONE_BUSY ? "#E53935" : "#4CAF50") : color;
drawCallButton(painter, actionRect(option.rect, Action::Call), phoneColor);
}
painter->restore();
}
@@ -200,6 +202,11 @@ bool AccountDelegate::helpEvent(QHelpEvent* event, QAbstractItemView* view, cons
QString text = QCoreApplication::translate("ChatGui", action == Action::RadioCall ? "Call by radio" : "Call peer");
if (action == Action::RadioCall && (index.data(Qt::UserRole + 3).toInt() & CHAT_MEMBER_FLAG_RADIO))
text += QCoreApplication::translate("ChatGui", " · Radio enabled");
if (action == Action::Call && index.data(MemberListModel::OnlineRole).toBool()) {
const int flags = index.data(Qt::UserRole + 3).toInt();
text += " · " + QCoreApplication::translate("ChatGui", !(flags & CHAT_MEMBER_FLAG_PHONE_KNOWN) ? "Phone status unknown" :
(flags & CHAT_MEMBER_FLAG_PHONE_BUSY) ? "Busy on a call" : "Phone is free");
}
if (!index.data(MemberListModel::OnlineRole).toBool()) text += " · " + QCoreApplication::translate("ChatGui", "offline");
QToolTip::showText(event->globalPos(), text, view);
return true;
+16 -2
View File
@@ -257,6 +257,15 @@ CallWindow::CallWindow(QWidget* parent)
lay->addWidget(m_avatarLabel, 0, Qt::AlignHCenter);
lay->addWidget(m_peerLabel);
lay->addWidget(m_statusLabel);
m_continueBtn = new QPushButton(callText("Call anyway"), this);
lay->addWidget(m_continueBtn);
connect(m_continueBtn, &QPushButton::clicked, this, [this] {
if (m_state != WaitDecision) return;
DEBUG_INFO(DEBUG_CATEGORY_CALL, "desktop caller overrides phone busy id=%016llx", (unsigned long long)m_callId);
postCallFn(call_continue_trampoline, m_callId);
setState(Outgoing);
SoundManager::instance()->playLoop("call_connecting");
});
lay->addWidget(m_durationLabel);
lay->addWidget(m_connectionLabel);
lay->addWidget(m_bgpPathLabel);
@@ -389,6 +398,10 @@ void CallWindow::setConnectionType(uint8_t type, quint64 nextHop) {
void CallWindow::setState(State s) {
m_state = s;
switch (s) {
case WaitDecision:
m_statusLabel->setText(callText("Subscriber is on a phone call"));
m_durationLabel->hide();
break;
case Outgoing:
m_statusLabel->setText(QCoreApplication::translate("ChatGui", "Connecting…"));
m_durationLabel->hide();
@@ -439,9 +452,10 @@ void CallWindow::populateDeviceCombo() {
}
void CallWindow::updateButtons() {
m_continueBtn->setVisible(m_state == WaitDecision);
m_acceptCell->setVisible(m_state == Incoming);
m_declineCell->setVisible(m_state == Incoming);
m_hangupCell->setVisible(m_state == Outgoing || m_state == Ringing || m_state == Active);
m_hangupCell->setVisible(m_state == Outgoing || m_state == Ringing || m_state == Active || m_state == WaitDecision);
m_muteCell->setVisible(m_state == Active);
updateVideoPresentation();
}
@@ -509,7 +523,7 @@ void CallWindow::onDeviceChanged(int index) {
void CallWindow::closeEvent(QCloseEvent* event) {
m_video->stop(); m_videoCall = 0;
if (m_state == Outgoing || m_state == Ringing || m_state == Active)
if (m_state == Outgoing || m_state == Ringing || m_state == Active || m_state == WaitDecision)
postCallFn(call_hangup_trampoline, m_callId);
emit closed(m_callId);
event->accept();
+28 -2
View File
@@ -571,6 +571,14 @@ void MainWindow::setupBridgeCallbacks() {
gui_bridge_set_call_ringing_cb([](uint64_t call_id) {
if (s_mainWindow) s_mainWindow->onCallRinging(call_id);
});
gui_bridge_set_call_phone_busy_cb([](uint64_t call_id) {
if (!s_mainWindow) return;
auto* window = s_mainWindow->m_activeCalls.value(call_id, nullptr);
if (!window || window->state() != CallWindow::Outgoing) return;
SoundManager::instance()->stopLoop();
window->setState(CallWindow::WaitDecision);
window->show(); window->raise();
});
gui_bridge_set_call_accepted_cb([](uint64_t call_id) {
if (s_mainWindow) s_mainWindow->onCallAccepted(call_id);
});
@@ -767,7 +775,7 @@ void MainWindow::onRadioCallRequested(const QString& channel, quint64 peer) {
/* Один диалог на незавершённое приглашение; принятая рация живёт своим обычным циклом. */
void MainWindow::onRadioCallEvent(const uint8_t* data, int len) {
if (!data || len != 27 || data[24] < RADIO_CALL_OUTGOING || data[24] > RADIO_CALL_FINISHED ||
if (!data || len != 27 || data[24] < RADIO_CALL_OUTGOING || data[24] > RADIO_CALL_WAIT_DECISION ||
data[25] > RADIO_CALL_AUDIO_ERROR || data[26] > 1) {
DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "desktop invalid radio call event bytes=%d", len); return;
}
@@ -807,6 +815,13 @@ void MainWindow::onRadioCallEvent(const uint8_t* data, int len) {
}
return;
}
if (state == RADIO_CALL_WAIT_DECISION && incoming) return;
if (state == RADIO_CALL_WAIT_DECISION && m_radioCallId == id) {
m_radioCallId = 0;
SoundManager::instance()->stopLoop();
if (m_radioCallWindow) m_radioCallWindow->close();
m_radioCallWindow = nullptr;
}
if (m_radioCallId == id) return;
if (m_radioCallId || !m_activeCalls.isEmpty()) { postRadioCall(id, RADIO_CALL_REJECT_BUSY); return; }
QString name = m_db->getDisplayName(peer);
@@ -830,6 +845,17 @@ void MainWindow::onRadioCallEvent(const uint8_t* data, int len) {
bool ready = m_currentChannelId == channel && m_messageList->enableRadio();
postRadioCall(id, ready ? RADIO_CALL_ACCEPT : RADIO_CALL_FAIL);
});
} else if (state == RADIO_CALL_WAIT_DECISION) {
box->setInformativeText(QCoreApplication::translate("ChatGui", "Subscriber is on a phone call"));
auto* proceed = box->addButton(QCoreApplication::translate("ChatGui", "Call anyway"), QMessageBox::AcceptRole);
box->addButton(QCoreApplication::translate("ChatGui", "End call"), QMessageBox::RejectRole);
connect(box, &QMessageBox::buttonClicked, this, [this, id, proceed](QAbstractButton* button) {
if (m_radioCallId != id || button != proceed) return;
m_radioCallAnswered = true;
m_radioCallId = 0;
DEBUG_INFO(DEBUG_CATEGORY_RADIO, "desktop caller overrides phone busy id=%016llx", (unsigned long long)id);
postRadioCall(id, RADIO_CALL_CONTINUE);
});
} else {
box->addButton(QMessageBox::Cancel);
box->setInformativeText(QCoreApplication::translate("ChatGui", "Checking subscriber availability…"));
@@ -842,7 +868,7 @@ void MainWindow::onRadioCallEvent(const uint8_t* data, int len) {
}
});
box->show(); box->raise(); box->activateWindow();
SoundManager::instance()->playLoop(incoming ? "radio_incoming" : "call_connecting");
if (state != RADIO_CALL_WAIT_DECISION) SoundManager::instance()->playLoop(incoming ? "radio_incoming" : "call_connecting");
if (incoming) {
if (m_trayIcon && (!isVisible() || isMinimized()))
m_trayIcon->showMessage(QCoreApplication::translate("ChatGui", "Radio call"), box->text());