From ab01c6dc48112057f013f58c1cff90be1b68ffcf Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 14 Oct 2026 02:53:22 +0200 Subject: [PATCH] Expose broadcast setup even when a channel has no live sources --- tools/chatgui/src/mainwindow.h | 4 ++++ tools/chatgui/src/messagelist.cpp | 12 +++++++++--- tools/chatgui/src/messagelist.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/chatgui/src/mainwindow.h b/tools/chatgui/src/mainwindow.h index dda791d8..d830a4f7 100644 --- a/tools/chatgui/src/mainwindow.h +++ b/tools/chatgui/src/mainwindow.h @@ -22,6 +22,8 @@ class AudioRecorder; class ConnMonitorWindow; class VideoPlayerWindow; class StreamPlayerWindow; +class StreamPublishEngine; +class StreamPublishWindow; class ImageViewerWindow; class CallWindow; class CallAudioEngine; @@ -126,6 +128,8 @@ private: ConnMonitorWindow *m_connMonitor = nullptr; VideoPlayerWindow *m_videoPlayer = nullptr; QPointer m_streamPlayer; + StreamPublishEngine* m_streamPublisher = nullptr; + QPointer m_streamPublishWindow; ImageViewerWindow *m_imageViewer = nullptr; QPointer m_fileBrowser; diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index e9f35119..032be66a 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/tools/chatgui/src/messagelist.cpp @@ -441,8 +441,10 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent qPrintable(m_currentChannelId), (unsigned long long)source.id, (unsigned long long)source.epoch); emit streamRequested(m_currentChannelId.toULongLong(), source.id, source.epoch, source.name); }; - if (m_streamSources.size() == 1) { watch(m_streamSources.front()); return; } QMenu menu(this); + auto* publish = menu.addAction(QCoreApplication::translate("ChatGui", "Broadcast stream")); + connect(publish, &QAction::triggered, this, [this] { emit streamPublishRequested(m_currentChannelId.toULongLong()); }); + if (!m_streamSources.isEmpty()) menu.addSeparator(); for (const auto& source : m_streamSources) { auto* action = menu.addAction(QStringLiteral("%1 · %2").arg(source.name).arg(source.id)); connect(action, &QAction::triggered, this, [watch, source] { watch(source); }); @@ -1482,7 +1484,11 @@ void MessageList::watchStreams() { gui_stream_watch(isDmChannel(m_currentChannelId) ? 0 : m_currentChannelId.toULongLong()); } -void MessageList::clearStreams() { m_streamSources.clear(); m_streamBtn->hide(); } +void MessageList::clearStreams() { + m_streamSources.clear(); m_streamBtn->setText(QString()); + m_streamBtn->setVisible(!m_currentChannelId.isEmpty() && !isDmChannel(m_currentChannelId)); + m_streamBtn->setToolTip(QCoreApplication::translate("ChatGui", "Live streams")); +} /* Полный снимок применяется атомарно; ответы предыдущего канала не меняют текущую шапку. */ void MessageList::onStreamSources(const uint8_t* data, int len) { @@ -1508,7 +1514,7 @@ void MessageList::onStreamSources(const uint8_t* data, int len) { QString name = member.value("name").toString(); if (name.isEmpty()) name = QString::number(id); sources.push_back({id, epoch, name}); } - m_streamSources = std::move(sources); m_streamBtn->setVisible(!m_streamSources.isEmpty()); + m_streamSources = std::move(sources); m_streamBtn->setVisible(true); m_streamBtn->setText(m_streamSources.size() > 1 ? QString::number(m_streamSources.size()) : QString()); m_streamBtn->setToolTip(QCoreApplication::translate("ChatGui", "Live streams: %1").arg(m_streamSources.size())); DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop stream header group=%llx sources=%d", (unsigned long long)group, (int)m_streamSources.size()); diff --git a/tools/chatgui/src/messagelist.h b/tools/chatgui/src/messagelist.h index 110e5a12..32ca4dbe 100644 --- a/tools/chatgui/src/messagelist.h +++ b/tools/chatgui/src/messagelist.h @@ -55,6 +55,7 @@ signals: void callRequested(const QString& target, quint64 peer, const QString& name); void openVideoRequested(const QString& filePath); void streamRequested(quint64 group, quint64 source, quint64 epoch, const QString& name); + void streamPublishRequested(quint64 group); void openImageRequested(const QString& filePath); void inviteRequested(const QString& sourceChannel, quint64 peer, const QString& name); void ownFilesRequested(const QString& channelId);