From 188b98b4d8a8ecd0bcbf93ab9ecdbaa75bafd2d0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 27 Jul 2020 09:28:12 +0400 Subject: [PATCH 001/142] Update cmake_helpers submodule. --- cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake b/cmake index 3f73163b0..28ff83971 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 3f73163b0692f34136b4c5fd0d748a2ac91922cd +Subproject commit 28ff839711926438018da162c4bb9591e1559015 From 4f3f1e18a2309146812c4e08ff480e6e9325bebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Gro=C3=9F?= Date: Sun, 26 Jul 2020 14:01:33 +0200 Subject: [PATCH 002/142] Export chats with ISO 8601 dates Fixes #6020 --- .../SourceFiles/export/output/export_output_abstract.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/export/output/export_output_abstract.cpp b/Telegram/SourceFiles/export/output/export_output_abstract.cpp index e39468b12..11020b42d 100644 --- a/Telegram/SourceFiles/export/output/export_output_abstract.cpp +++ b/Telegram/SourceFiles/export/output/export_output_abstract.cpp @@ -33,11 +33,9 @@ QString NormalizePath(const Settings &settings) { } const auto date = QDate::currentDate(); const auto base = QString(settings.onlySinglePeer() - ? "ChatExport_%1_%2_%3" - : "DataExport_%1_%2_%3" - ).arg(date.day(), 2, 10, QChar('0') - ).arg(date.month(), 2, 10, QChar('0') - ).arg(date.year()); + ? "ChatExport_%1" + : "DataExport_%1" + ).arg(date.toString(Qt::ISODate)); const auto add = [&](int i) { return base + (i ? " (" + QString::number(i) + ')' : QString()); }; From e293a2602914dfc410ea5b195f3a0e1f44807a5f Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 27 Jul 2020 10:34:59 +0400 Subject: [PATCH 003/142] Fix crash in incorrect passcode input. --- Telegram/SourceFiles/window/window_lock_widgets.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index ff409bed1..0e471a702 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -154,8 +154,7 @@ void PasscodeLockWidget::submit() { auto &domain = Core::App().domain(); const auto correct = domain.started() ? domain.local().checkPasscode(passcode) - : (domain.start(passcode) - != Storage::StartResult::IncorrectPasscode); + : (domain.start(passcode) == Storage::StartResult::Success); if (!correct) { cSetPasscodeBadTries(cPasscodeBadTries() + 1); cSetPasscodeLastTry(crl::now()); From 361b99b0c9c9f69bc8479a4413dbe62113405734 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 27 Jul 2020 18:19:26 +0400 Subject: [PATCH 004/142] Use threaded decoding in ffmpeg streaming. --- Telegram/SourceFiles/core/utils.cpp | 4 ---- Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp | 1 + Telegram/SourceFiles/stdafx.h | 8 ++++++++ Telegram/lib_base | 2 +- Telegram/lib_crl | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/core/utils.cpp b/Telegram/SourceFiles/core/utils.cpp index 8066bc67d..d989ff25e 100644 --- a/Telegram/SourceFiles/core/utils.cpp +++ b/Telegram/SourceFiles/core/utils.cpp @@ -32,10 +32,6 @@ extern "C" { #include -#ifdef small -#undef small -#endif // small - uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 }; // Base types compile-time check diff --git a/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp b/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp index 6cb988a28..5221c92da 100644 --- a/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp +++ b/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp @@ -175,6 +175,7 @@ CodecPointer MakeCodecPointer(not_null stream) { return {}; } av_codec_set_pkt_timebase(context, stream->time_base); + av_opt_set(context, "threads", "auto", 0); av_opt_set_int(context, "refcounted_frames", 1, 0); const auto codec = avcodec_find_decoder(context->codec_id); diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index ca0f0098d..563fb11a5 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -83,6 +83,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #define __STDC_FORMAT_MACROS #endif // Q_OS_UNIX +// Remove 'small' macro definition. +#ifdef Q_OS_WIN +#include +#ifdef small +#undef small +#endif // small +#endif // Q_OS_WIN + #include #include #include diff --git a/Telegram/lib_base b/Telegram/lib_base index 6a78e454e..623439a33 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 6a78e454e5bd61133b3d6c9f8d64fbad00f17618 +Subproject commit 623439a33a4c3e70251d62566f064c812e545980 diff --git a/Telegram/lib_crl b/Telegram/lib_crl index 661ac4f6b..bb8547bba 160000 --- a/Telegram/lib_crl +++ b/Telegram/lib_crl @@ -1 +1 @@ -Subproject commit 661ac4f6bdf8991e7d6cac176d32338ac025b637 +Subproject commit bb8547bba703e53ab46cd6cd009c48adabaa1823 From 252bdd2353c145feaed7e1d237b516815d7f316b Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 8 Aug 2020 16:07:13 +0400 Subject: [PATCH 005/142] TDESKTOP_DISABLE_DBUS_INTEGRATION -> DESKTOP_APP_DISABLE_DBUS_INTEGRATION --- .../platform/linux/main_window_linux.cpp | 58 +++++++++---------- .../platform/linux/main_window_linux.h | 10 ++-- .../linux/notifications_manager_linux.cpp | 26 ++++----- .../linux/notifications_manager_linux.h | 12 ++-- .../platform/linux/specific_linux.cpp | 30 +++++----- Telegram/SourceFiles/qt_static_plugins.cpp | 12 ++-- Telegram/cmake/telegram_options.cmake | 4 -- 7 files changed, 74 insertions(+), 78 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index fbf7b6ef0..db9a32190 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -33,7 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include #include #include @@ -42,7 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION namespace Platform { namespace { @@ -236,7 +236,7 @@ QIcon TrayIconGen(int counter, bool muted) { return result; } -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION bool IsIndicatorApplication() { // Hack for indicator-application, which doesn't handle icons sent across D-Bus: // save the icon to a temp file and set the icon name to that filename. @@ -305,10 +305,10 @@ bool UseUnityCounter() { return Result; } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION bool IsSNIAvailable() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION auto message = QDBusMessage::createMethodCall( kSNIWatcherService.utf16(), qsl("/StatusNotifierWatcher"), @@ -328,7 +328,7 @@ bool IsSNIAvailable() { } else if (reply.error().type() != QDBusError::ServiceUnknown) { LOG(("SNI Error: %1").arg(reply.error().message())); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION return false; } @@ -342,7 +342,7 @@ quint32 djbStringHash(QString string) { return hash; } -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION bool IsAppMenuSupported() { const auto interface = QDBusConnection::sessionBus().interface(); @@ -406,7 +406,7 @@ void ForceDisabled(QAction *action, bool disabled) { action->setDisabled(false); } } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } // namespace @@ -428,7 +428,7 @@ void MainWindow::initHook() { LOG(("System tray available: %1").arg(Logs::b(trayAvailable))); Platform::SetTrayIconSupported(trayAvailable); -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION auto sniWatcher = new QDBusServiceWatcher( kSNIWatcherService.utf16(), QDBusConnection::sessionBus(), @@ -472,7 +472,7 @@ void MainWindow::initHook() { } else { LOG(("Not using Unity launcher counter.")); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION updateWaylandDecorationColors(); @@ -483,11 +483,11 @@ void MainWindow::initHook() { } bool MainWindow::hasTrayIcon() const { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION return trayIcon || (SNIAvailable && _sniTrayIcon); #else return trayIcon; -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } void MainWindow::psShowTrayMenu() { @@ -495,14 +495,14 @@ void MainWindow::psShowTrayMenu() { } void MainWindow::psTrayMenuUpdated() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (_sniTrayIcon && trayIconMenu) { _sniTrayIcon->setContextMenu(trayIconMenu); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION void MainWindow::setSNITrayIcon(int counter, bool muted) { const auto iconName = GetTrayIconName(counter, muted); @@ -618,14 +618,14 @@ void MainWindow::onAppMenuOwnerChanged( UnregisterAppMenu(winId()); } } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION void MainWindow::psSetupTrayIcon() { const auto counter = Core::App().unreadBadge(); const auto muted = Core::App().unreadBadgeMuted(); if (SNIAvailable) { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION LOG(("Using SNI tray icon.")); if (!_sniTrayIcon) { _sniTrayIcon = new StatusNotifierItem( @@ -638,7 +638,7 @@ void MainWindow::psSetupTrayIcon() { attachToSNITrayIcon(); } updateIconCounters(); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } else { LOG(("Using Qt tray icon.")); if (!trayIcon) { @@ -657,13 +657,13 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { if (!Platform::TrayIconSupported()) { return; } else if (mode == dbiwmWindowOnly) { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (_sniTrayIcon) { _sniTrayIcon->setContextMenu(0); _sniTrayIcon->deleteLater(); } _sniTrayIcon = nullptr; -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (trayIcon) { trayIcon->setContextMenu(0); @@ -686,7 +686,7 @@ void MainWindow::updateIconCounters() { updateWindowIcon(); -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (UseUnityCounter()) { const auto launcherUrl = "application://" + GetLauncherFilename(); QVariantMap dbusUnityProperties; @@ -714,7 +714,7 @@ void MainWindow::updateIconCounters() { if (_sniTrayIcon) { setSNITrayIcon(counter, muted); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (trayIcon && IsIconRegenerationNeeded(counter, muted)) { trayIcon->setIcon(TrayIconGen(counter, muted)); @@ -732,11 +732,11 @@ void MainWindow::updateWaylandDecorationColors() { } void MainWindow::LibsLoaded() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } void MainWindow::initTrayMenuHook() { @@ -744,7 +744,7 @@ void MainWindow::initTrayMenuHook() { _trayIconMenuXEmbed->deleteOnHide(false); } -#ifdef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifdef DESKTOP_APP_DISABLE_DBUS_INTEGRATION void MainWindow::createGlobalMenu() { } @@ -752,7 +752,7 @@ void MainWindow::createGlobalMenu() { void MainWindow::updateGlobalMenuHook() { } -#else // TDESKTOP_DISABLE_DBUS_INTEGRATION +#else // DESKTOP_APP_DISABLE_DBUS_INTEGRATION void MainWindow::createGlobalMenu() { psMainMenu = new QMenu(this); @@ -1063,10 +1063,10 @@ void MainWindow::onVisibleChanged(bool visible) { } } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION MainWindow::~MainWindow() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION delete _sniTrayIcon; if (AppMenuSupported) { @@ -1075,7 +1075,7 @@ MainWindow::~MainWindow() { delete _mainMenuExporter; delete psMainMenu; -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION delete _trayIconMenuXEmbed; } diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index de74c3ef8..f4370542d 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/popup_menu.h" -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include "statusnotifieritem.h" #include #include @@ -45,7 +45,7 @@ public: public slots: void psShowTrayMenu(); -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION void onSNIOwnerChanged( const QString &service, const QString &oldOwner, @@ -73,7 +73,7 @@ public slots: void onVisibleChanged(bool visible); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_GTK_INTEGRATION GtkClipboard *gtkClipboard() { @@ -112,7 +112,7 @@ private: void updateIconCounters(); void updateWaylandDecorationColors(); -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION StatusNotifierItem *_sniTrayIcon = nullptr; std::unique_ptr _trayIconFile = nullptr; @@ -142,7 +142,7 @@ private: void setSNITrayIcon(int counter, bool muted); void attachToSNITrayIcon(); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_GTK_INTEGRATION GtkClipboard *_gtkClipboard = nullptr; diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 62463eb7a..996dec475 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -17,18 +17,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "lang/lang_keys.h" -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include #include #include #include #include -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION namespace Platform { namespace Notifications { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION namespace { constexpr auto kService = "org.freedesktop.Notifications"_cs; @@ -446,16 +446,16 @@ const QDBusArgument &operator>>( argument.endStructure(); return argument; } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION bool SkipAudio() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (Supported() && GetCapabilities().contains(qsl("inhibitions")) && !InhibitedNotSupported) { return Inhibited(); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION return false; } @@ -469,18 +469,18 @@ bool SkipFlashBounce() { } bool Supported() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION return NotificationsSupported; -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION return false; } std::unique_ptr Create( Window::Notifications::System *system) { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION GetSupported(); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION if ((Core::App().settings().nativeNotifications() && Supported()) || Platform::IsWayland()) { @@ -490,7 +490,7 @@ std::unique_ptr Create( return nullptr; } -#ifdef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifdef DESKTOP_APP_DISABLE_DBUS_INTEGRATION class Manager::Private { public: using Type = Window::Notifications::CachedUserpics::Type; @@ -510,7 +510,7 @@ public: void clearFromSession(not_null session) {} void clearNotification(NotificationId id) {} }; -#else // TDESKTOP_DISABLE_DBUS_INTEGRATION +#else // DESKTOP_APP_DISABLE_DBUS_INTEGRATION class Manager::Private { public: using Type = Window::Notifications::CachedUserpics::Type; @@ -699,7 +699,7 @@ void Manager::Private::clearNotification(NotificationId id) { Manager::Private::~Private() { clearAll(); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION Manager::Manager(not_null system) : NativeManager(system) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index b82abb8ac..a3a1c0ab5 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -10,15 +10,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/platform_notifications_manager.h" #include "base/weak_ptr.h" -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include #include -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION namespace Platform { namespace Notifications { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION class NotificationData : public QObject { Q_OBJECT @@ -78,7 +78,7 @@ QDBusArgument &operator<<( const QDBusArgument &operator>>( const QDBusArgument &argument, NotificationData::ImageData &imageData); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION class Manager : public Window::Notifications::NativeManager @@ -111,6 +111,6 @@ private: } // namespace Notifications } // namespace Platform -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION Q_DECLARE_METATYPE(Platform::Notifications::NotificationData::ImageData) -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 6fd2edc52..1ebf5e3ca 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -31,13 +31,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include #include #include #include #include -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include #include @@ -74,7 +74,7 @@ QStringList PlatformThemes; bool IsTrayIconSupported = true; -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION void PortalAutostart(bool autostart, bool silent = false) { QVariantMap options; options["reason"] = tr::lng_settings_auto_start(tr::now); @@ -135,7 +135,7 @@ uint FileChooserPortalVersion() { return Result; } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION QString FlatpakID() { static const auto Result = [] { @@ -356,7 +356,7 @@ std::optional XCBLastUserInputTime() { return std::nullopt; } -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION std::optional FreedesktopDBusLastUserInputTime() { static auto NotSupported = false; @@ -443,7 +443,7 @@ std::optional MutterDBusLastUserInputTime() { return std::nullopt; } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION uint XCBMoveResizeFromEdges(Qt::Edges edges) { if (edges == (Qt::TopEdge | Qt::LeftEdge)) @@ -667,13 +667,13 @@ bool IsQtPluginsBundled() { } bool IsXDGDesktopPortalPresent() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION static const auto Result = QDBusInterface( kXDGDesktopPortalService.utf16(), kXDGDesktopPortalObjectPath.utf16()).isValid(); return Result; -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION return false; } @@ -693,11 +693,11 @@ bool UseXDGDesktopPortal() { } bool CanOpenDirectoryWithPortal() { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED) && !defined TDESKTOP_DISABLE_DBUS_INTEGRATION +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED) && !defined DESKTOP_APP_DISABLE_DBUS_INTEGRATION return FileChooserPortalVersion() >= 3; -#else // (Qt >= 5.15 || DESKTOP_APP_QT_PATCHED) && !TDESKTOP_DISABLE_DBUS_INTEGRATION +#else // (Qt >= 5.15 || DESKTOP_APP_QT_PATCHED) && !DESKTOP_APP_DISABLE_DBUS_INTEGRATION return false; -#endif // (Qt < 5.15 && !DESKTOP_APP_QT_PATCHED) || TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // (Qt < 5.15 && !DESKTOP_APP_QT_PATCHED) || DESKTOP_APP_DISABLE_DBUS_INTEGRATION } QString CurrentExecutablePath(int argc, char *argv[]) { @@ -873,7 +873,7 @@ std::optional LastUserInputTime() { return XCBLastUserInputTime(); } -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION const auto freedesktopResult = FreedesktopDBusLastUserInputTime(); if (freedesktopResult.has_value()) { return freedesktopResult; @@ -883,7 +883,7 @@ std::optional LastUserInputTime() { if (mutterResult.has_value()) { return mutterResult; } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION return std::nullopt; } @@ -1293,9 +1293,9 @@ void psAutoStart(bool start, bool silent) { return; if (InFlatpak()) { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION PortalAutostart(start, silent); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION } else { const auto autostart = [&] { if (InSnap()) { diff --git a/Telegram/SourceFiles/qt_static_plugins.cpp b/Telegram/SourceFiles/qt_static_plugins.cpp index 82a4cdb6b..c5f7473ce 100644 --- a/Telegram/SourceFiles/qt_static_plugins.cpp +++ b/Telegram/SourceFiles/qt_static_plugins.cpp @@ -38,12 +38,12 @@ Q_IMPORT_PLUGIN(QGenericEnginePlugin) Q_IMPORT_PLUGIN(QComposePlatformInputContextPlugin) Q_IMPORT_PLUGIN(QSvgPlugin) Q_IMPORT_PLUGIN(QSvgIconPlugin) -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION Q_IMPORT_PLUGIN(QConnmanEnginePlugin) Q_IMPORT_PLUGIN(QNetworkManagerEnginePlugin) Q_IMPORT_PLUGIN(QIbusPlatformInputContextPlugin) Q_IMPORT_PLUGIN(QXdgDesktopPortalThemePlugin) -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #endif // Q_OS_WIN | Q_OS_MAC | Q_OS_UNIX #endif // !DESKTOP_APP_USE_PACKAGED @@ -51,11 +51,11 @@ Q_IMPORT_PLUGIN(QXdgDesktopPortalThemePlugin) #if !defined DESKTOP_APP_USE_PACKAGED || defined DESKTOP_APP_USE_PACKAGED_LAZY Q_IMPORT_PLUGIN(QWaylandMaterialDecorationPlugin) Q_IMPORT_PLUGIN(NimfInputContextPlugin) -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION Q_IMPORT_PLUGIN(QFcitxPlatformInputContextPlugin) Q_IMPORT_PLUGIN(QFcitx5PlatformInputContextPlugin) Q_IMPORT_PLUGIN(QHimePlatformInputContextPlugin) -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #endif // !DESKTOP_APP_USE_PACKAGED || DESKTOP_APP_USE_PACKAGED_LAZY #if !defined DESKTOP_APP_USE_PACKAGED || defined DESKTOP_APP_USE_PACKAGED_LAZY_PLATFORMTHEMES @@ -65,8 +65,8 @@ Q_IMPORT_PLUGIN(Qt5CTStylePlugin) // conflicts with Qt static link #ifdef DESKTOP_APP_USE_PACKAGED_LAZY_PLATFORMTHEMES -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION Q_IMPORT_PLUGIN(LXQtPlatformThemePlugin) -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #endif // DESKTOP_APP_USE_PACKAGED_LAZY_PLATFORMTHEMES #endif // Q_OS_UNIX && !Q_OS_MAC diff --git a/Telegram/cmake/telegram_options.cmake b/Telegram/cmake/telegram_options.cmake index 9895b5c30..c3fad735f 100644 --- a/Telegram/cmake/telegram_options.cmake +++ b/Telegram/cmake/telegram_options.cmake @@ -85,10 +85,6 @@ if (TDESKTOP_DISABLE_GTK_INTEGRATION) target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_GTK_INTEGRATION) endif() -if (DESKTOP_APP_DISABLE_DBUS_INTEGRATION) - target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_DBUS_INTEGRATION) -endif() - if (NOT TDESKTOP_LAUNCHER_BASENAME) set(TDESKTOP_LAUNCHER_BASENAME "telegramdesktop") endif() From 26bedd95d790a90bbf2a01321ae46c6b60c357cc Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 8 Aug 2020 16:07:55 +0400 Subject: [PATCH 006/142] DESKTOP_APP_USE_PACKAGED_FONTS respects DESKTOP_APP_USE_PACKAGED_LAZY now --- snap/snapcraft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 6a00e3c86..cb2dae458 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -103,7 +103,6 @@ parts: - -DTDESKTOP_API_ID=611335 - -DTDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c - -DDESKTOP_APP_USE_PACKAGED_LAZY=ON - - -DDESKTOP_APP_USE_PACKAGED_FONTS=OFF - -DTDESKTOP_USE_GTK_FILE_DIALOG=ON - -DDESKTOP_APP_QTWAYLANDCLIENT_PRIVATE_HEADERS=$SNAPCRAFT_STAGE/usr/include/$SNAPCRAFT_ARCH_TRIPLET/qt5/QtWaylandClient/5.12.8 override-pull: | From cbeaee24c98f147acd788ba58d95ccef836307dc Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 10 Aug 2020 16:13:11 +0400 Subject: [PATCH 007/142] Update submodules & patches commit --- Telegram/lib_base | 2 +- Telegram/lib_crl | 2 +- cmake | 2 +- docs/building-cmake.md | 2 +- docs/building-msvc.md | 2 +- docs/building-xcode.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Telegram/lib_base b/Telegram/lib_base index 623439a33..e94515700 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 623439a33a4c3e70251d62566f064c812e545980 +Subproject commit e94515700a622c2424f58d32e670581e9185f7e7 diff --git a/Telegram/lib_crl b/Telegram/lib_crl index bb8547bba..16150bf71 160000 --- a/Telegram/lib_crl +++ b/Telegram/lib_crl @@ -1 +1 @@ -Subproject commit bb8547bba703e53ab46cd6cd009c48adabaa1823 +Subproject commit 16150bf71d79382738114b913f137ec1a1a7630c diff --git a/cmake b/cmake index 28ff83971..f05e28c8d 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 28ff839711926438018da162c4bb9591e1559015 +Subproject commit f05e28c8da6751a3eee3eba1736736a6ac91c95f diff --git a/docs/building-cmake.md b/docs/building-cmake.md index 34b7c17fc..c3475c3fe 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -54,7 +54,7 @@ Go to ***BuildPath*** and run git clone https://github.com/desktop-app/patches.git cd patches - git checkout 7df6fdd + git checkout b2ee1fb cd ../ git clone https://github.com/xiph/opus diff --git a/docs/building-msvc.md b/docs/building-msvc.md index 1d59cbec6..67b204a8b 100644 --- a/docs/building-msvc.md +++ b/docs/building-msvc.md @@ -33,7 +33,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath*** cd ThirdParty git clone https://github.com/desktop-app/patches.git cd patches - git checkout 7df6fdd + git checkout b2ee1fb cd ../ git clone https://chromium.googlesource.com/external/gyp cd gyp diff --git a/docs/building-xcode.md b/docs/building-xcode.md index eab327933..c29939328 100644 --- a/docs/building-xcode.md +++ b/docs/building-xcode.md @@ -29,7 +29,7 @@ Go to ***BuildPath*** and run git clone https://github.com/desktop-app/patches.git cd patches - git checkout 7df6fdd + git checkout b2ee1fb cd ../ git clone https://chromium.googlesource.com/external/gyp git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git From 4e5e30a8ddd611de6aebbbe807b27e8e3eece446 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 1 Aug 2020 13:09:56 +0000 Subject: [PATCH 008/142] Update fcitx5-qt --- .github/workflows/linux.yml | 4 ++-- Telegram/ThirdParty/fcitx5-qt | 2 +- docs/building-cmake.md | 4 ++-- snap/snapcraft.yaml | 2 -- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 7dfbce9a0..931a88c29 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -423,8 +423,8 @@ jobs: git clone -b v5.12.8 --depth=1 git://code.qt.io/qt/qt5.git qt_${QT} cd qt_${QT} - perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg,qtx11extras - git submodule update qtbase qtwayland qtimageformats qtsvg qtx11extras + perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg + git submodule update qtbase qtwayland qtimageformats qtsvg cd qtbase find ../../patches/qtbase_${QT} -type f -print0 | sort -z | xargs -r0 git apply cd .. diff --git a/Telegram/ThirdParty/fcitx5-qt b/Telegram/ThirdParty/fcitx5-qt index b7bdd8aec..47628ac9f 160000 --- a/Telegram/ThirdParty/fcitx5-qt +++ b/Telegram/ThirdParty/fcitx5-qt @@ -1 +1 @@ -Subproject commit b7bdd8aec2dcb44dc792fedec89d67be0c527ca1 +Subproject commit 47628ac9f81b589d8e69f82b121d08773b06e813 diff --git a/docs/building-cmake.md b/docs/building-cmake.md index c3475c3fe..7cd86d029 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -236,9 +236,9 @@ Go to ***BuildPath*** and run git clone git://code.qt.io/qt/qt5.git qt_5_12_8 cd qt_5_12_8 - perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg,qtx11extras + perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg git checkout v5.12.8 - git submodule update qtbase qtwayland qtimageformats qtsvg qtx11extras + git submodule update qtbase qtwayland qtimageformats qtsvg cd qtbase find ../../patches/qtbase_5_12_8 -type f -print0 | sort -z | xargs -r0 git apply cd .. diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index cb2dae458..69682630b 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -77,7 +77,6 @@ parts: - libpulse-dev - libqt5svg5-dev - libqt5waylandclient5-dev - - libqt5x11extras5-dev - libssl-dev - libxcb1-dev - libxcb-screensaver0-dev @@ -92,7 +91,6 @@ parts: - libpulse0 - libqt5svg5 - libqt5waylandclient5 - - libqt5x11extras5 - libssl1.1 - libxcb1 - libxcb-screensaver0 From 08b67e383e388c5ac17b139e01d666a388642333 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 10 Aug 2020 18:10:42 +0400 Subject: [PATCH 009/142] Add -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF to docs & actions --- .github/workflows/linux.yml | 1 + .github/workflows/mac.yml | 6 +++++- .github/workflows/win.yml | 1 + docs/building-cmake.md | 2 +- docs/building-msvc.md | 2 +- docs/building-osx.md | 2 +- 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 931a88c29..18e05c02d 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -530,6 +530,7 @@ jobs: -D CMAKE_CXX_FLAGS="-s" \ -D TDESKTOP_API_TEST=ON \ -D DESKTOP_APP_USE_PACKAGED=OFF \ + -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \ $DEFINE cd ../out/Debug diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index ea6c9bd04..ebce645fa 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -462,7 +462,11 @@ jobs: echo ::set-env name=ARTIFACT_NAME::Telegram fi - ./configure.sh -D TDESKTOP_API_TEST=ON -D DESKTOP_APP_USE_PACKAGED=OFF $DEFINE + ./configure.sh \ + -D TDESKTOP_API_TEST=ON \ + -D DESKTOP_APP_USE_PACKAGED=OFF \ + -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \ + $DEFINE cd ../out diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 922b115cc..aaf1ba4a4 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -365,6 +365,7 @@ jobs: call configure.bat ^ -D TDESKTOP_API_TEST=ON ^ -D DESKTOP_APP_USE_PACKAGED=OFF ^ + -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^ %TDESKTOP_BUILD_DEFINE% ^ -DCMAKE_SYSTEM_VERSION=%SDK% diff --git a/docs/building-cmake.md b/docs/building-cmake.md index 7cd86d029..27bf7d047 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -301,7 +301,7 @@ Go to ***BuildPath*** and run Go to ***BuildPath*/tdesktop/Telegram** and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials)) - ./configure.sh -D TDESKTOP_API_ID=YOUR_API_ID -D TDESKTOP_API_HASH=YOUR_API_HASH -D DESKTOP_APP_USE_PACKAGED=OFF + ./configure.sh -D TDESKTOP_API_ID=YOUR_API_ID -D TDESKTOP_API_HASH=YOUR_API_HASH -D DESKTOP_APP_USE_PACKAGED=OFF -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF To make Debug version go to ***BuildPath*/tdesktop/out/Debug** and run diff --git a/docs/building-msvc.md b/docs/building-msvc.md index 67b204a8b..4b80dfe90 100644 --- a/docs/building-msvc.md +++ b/docs/building-msvc.md @@ -167,7 +167,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath*** Go to ***BuildPath*\\tdesktop\\Telegram** and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials)) - configure.bat -D TDESKTOP_API_ID=YOUR_API_ID -D TDESKTOP_API_HASH=YOUR_API_HASH -D DESKTOP_APP_USE_PACKAGED=OFF + configure.bat -D TDESKTOP_API_ID=YOUR_API_ID -D TDESKTOP_API_HASH=YOUR_API_HASH -D DESKTOP_APP_USE_PACKAGED=OFF -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF * Open ***BuildPath*\\tdesktop\\out\\Telegram.sln** in Visual Studio 2019 * Select Telegram project and press Build > Build Telegram (Debug and Release configurations) diff --git a/docs/building-osx.md b/docs/building-osx.md index 09e6ae4d3..f47c7de91 100644 --- a/docs/building-osx.md +++ b/docs/building-osx.md @@ -250,7 +250,7 @@ Go to ***BuildPath*** and run Go to ***BuildPath*/tdesktop/Telegram** and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials)) - ./configure.sh -D TDESKTOP_API_ID=YOUR_API_ID -D TDESKTOP_API_HASH=YOUR_API_HASH -D DESKTOP_APP_USE_PACKAGED=OFF + ./configure.sh -D TDESKTOP_API_ID=YOUR_API_ID -D TDESKTOP_API_HASH=YOUR_API_HASH -D DESKTOP_APP_USE_PACKAGED=OFF -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF Then launch Xcode, open ***BuildPath*/tdesktop/out/Telegram.xcodeproj** and build for Debug / Release. From dc9d0aae5433bfff6de2e5b0d6d9df84b6a1b26a Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 8 Aug 2020 01:59:45 +0400 Subject: [PATCH 010/142] Add support for showing window menu on Wayland --- .../platform/linux/specific_linux.cpp | 23 +++++++++++++++++++ .../SourceFiles/platform/mac/specific_mac.h | 4 ++++ .../SourceFiles/platform/platform_specific.h | 1 + .../SourceFiles/platform/win/specific_win.cpp | 12 ++++++++++ .../SourceFiles/window/window_title_qt.cpp | 8 +++---- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 1ebf5e3ca..6cc1295f5 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -585,6 +585,21 @@ bool StartWaylandResize(QWindow *window, Qt::Edges edges) { return false; } +bool ShowWaylandWindowMenu(QWindow *window) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) || defined DESKTOP_APP_QT_PATCHED + if (const auto waylandWindow = static_cast( + window->handle())) { + if (const auto seat = waylandWindow->display()->lastInputDevice()) { + if (const auto shellSurface = waylandWindow->shellSurface()) { + return shellSurface->showWindowMenu(seat); + } + } + } +#endif // Qt >= 5.13 || DESKTOP_APP_QT_PATCHED + + return false; +} + Window::Control GtkKeywordToWindowControl(const QString &keyword) { if (keyword == qstr("minimize")) { return Window::Control::Minimize; @@ -956,6 +971,14 @@ bool StartSystemResize(QWindow *window, Qt::Edges edges) { } } +bool ShowWindowMenu(QWindow *window) { + if (IsWayland()) { + return ShowWaylandWindowMenu(window); + } + + return false; +} + Window::ControlsLayout WindowControlsLayout() { #ifndef TDESKTOP_DISABLE_GTK_INTEGRATION if (Libs::GtkSettingSupported() diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index 3260b183e..f74ad82e6 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -38,6 +38,10 @@ inline bool StartSystemResize(QWindow *window, Qt::Edges edges) { return false; } +inline bool ShowWindowMenu(QWindow *window) { + return false; +} + inline bool AutostartSupported() { return false; } diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index efd75cd63..1939738e0 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -54,6 +54,7 @@ bool TrayIconSupported(); QImage GetImageFromClipboard(); bool StartSystemMove(QWindow *window); bool StartSystemResize(QWindow *window, Qt::Edges edges); +bool ShowWindowMenu(QWindow *window); Window::ControlsLayout WindowControlsLayout(); namespace ThirdParty { diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp index df6d316e5..6481defde 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.cpp +++ b/Telegram/SourceFiles/platform/win/specific_win.cpp @@ -418,6 +418,18 @@ bool AutostartSupported() { return !IsWindowsStoreBuild(); } +bool ShowWindowMenu(QWindow *window) { + const auto pos = QCursor::pos(); + + SendMessage( + window->winId(), + WM_SYSCOMMAND, + SC_MOUSEMENU, + MAKELPARAM(pos.x(), pos.y())); + + return true; +} + Window::ControlsLayout WindowControlsLayout() { Window::ControlsLayout controls; controls.right = { diff --git a/Telegram/SourceFiles/window/window_title_qt.cpp b/Telegram/SourceFiles/window/window_title_qt.cpp index 02cd57498..891484681 100644 --- a/Telegram/SourceFiles/window/window_title_qt.cpp +++ b/Telegram/SourceFiles/window/window_title_qt.cpp @@ -189,11 +189,11 @@ void TitleWidgetQt::resizeEvent(QResizeEvent *e) { } void TitleWidgetQt::mousePressEvent(QMouseEvent *e) { - if (e->button() != Qt::LeftButton) { - return; + if (e->button() == Qt::LeftButton) { + startMove(); + } else if (e->button() == Qt::RightButton) { + Platform::ShowWindowMenu(window()->windowHandle()); } - - startMove(); } void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) { From 449fa0ef2c61c0b1c9c554e0bdfdabf9681065e8 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 29 Jul 2020 19:28:02 +0400 Subject: [PATCH 011/142] Don't focus parent window after opening file dialog --- .../platform/linux/file_utilities_linux.cpp | 16 +++++++--------- .../platform/linux/file_utilities_linux.h | 9 +++------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp index 4ae87497c..a05155bfe 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp @@ -11,18 +11,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/linux_gdk_helper.h" #include "platform/linux/linux_desktop_environment.h" #include "platform/linux/specific_linux.h" -#include "core/application.h" -#include "mainwindow.h" #include "boxes/abstract_box.h" #include "storage/localstorage.h" #include "base/platform/base_platform_file_utilities.h" -#include "base/call_delayed.h" #include #include #ifndef TDESKTOP_DISABLE_GTK_INTEGRATION #include + +extern "C" { +#undef signals +#include +#include +#define signals public +} // extern "C" #endif // !TDESKTOP_DISABLE_GTK_INTEGRATION namespace Platform { @@ -461,12 +465,6 @@ int GtkFileDialog::exec() { show(); - if (const auto parent = parentWidget()) { - base::call_delayed(200, parent, [=] { - parent->activateWindow(); - }); - } - QPointer guard = this; d->exec(); if (guard.isNull()) diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.h b/Telegram/SourceFiles/platform/linux/file_utilities_linux.h index 08de04aae..13fe85301 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.h +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.h @@ -12,14 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -extern "C" { -#undef signals #ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -#include -#include +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkDialog GtkDialog; +typedef struct _GtkFileFilter GtkFileFilter; #endif // !TDESKTOP_DISABLE_GTK_INTEGRATION -#define signals public -} // extern "C" namespace Platform { namespace File { From bbe2adc44fe9d404621d54efd3edef0c7fe493cf Mon Sep 17 00:00:00 2001 From: ilya-fedin Date: Tue, 26 May 2020 16:13:38 +0400 Subject: [PATCH 012/142] Fix AppImage overwrite by updater --- Telegram/SourceFiles/_other/updater_linux.cpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Telegram/SourceFiles/_other/updater_linux.cpp b/Telegram/SourceFiles/_other/updater_linux.cpp index d56478ba2..5d4d742e2 100644 --- a/Telegram/SourceFiles/_other/updater_linux.cpp +++ b/Telegram/SourceFiles/_other/updater_linux.cpp @@ -298,6 +298,28 @@ bool update() { for (size_t i = 0; i < from.size(); ++i) { string fname = from[i], tofname = to[i]; + + // it is necessary to remove the old file to not to get an error if appimage file is used by fuse + struct stat statbuf; + writeLog("Trying to get stat() for '%s'", tofname.c_str()); + if (!stat(tofname.c_str(), &statbuf)) { + if (S_ISDIR(statbuf.st_mode)) { + writeLog("Fully clearing path '%s'..", tofname.c_str()); + if (!remove_directory(tofname.c_str())) { + writeLog("Error: failed to clear path '%s'", tofname.c_str()); + delFolder(); + return false; + } + } else { + writeLog("Unlinking file '%s'", tofname.c_str()); + if (unlink(tofname.c_str())) { + writeLog("Error: failed to unlink '%s'", tofname.c_str()); + delFolder(); + return false; + } + } + } + writeLog("Copying file '%s' to '%s'..", fname.c_str(), tofname.c_str()); int copyTries = 0, triesLimit = 30; do { From 65e2bbee3efbbfb3448e68db65b4e817cdcd7c8b Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 31 Jul 2020 02:38:21 +0000 Subject: [PATCH 013/142] Override cursor only if no buttons pressed --- Telegram/SourceFiles/window/window_title_qt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/window/window_title_qt.cpp b/Telegram/SourceFiles/window/window_title_qt.cpp index 891484681..a8a02de5b 100644 --- a/Telegram/SourceFiles/window/window_title_qt.cpp +++ b/Telegram/SourceFiles/window/window_title_qt.cpp @@ -211,7 +211,8 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { const auto mouseEvent = static_cast(e); const auto edges = edgesFromPos(mouseEvent->windowPos().toPoint()); - if (e->type() == QEvent::MouseMove) { + if (e->type() == QEvent::MouseMove + && mouseEvent->buttons() == Qt::NoButton) { updateCursor(edges); } From 972bbbce6a6b6cf2544b2ab00a58febeb7a32b3f Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 15 Jul 2020 18:37:25 +0300 Subject: [PATCH 014/142] Fixed online status stuck when switching between accounts one more time. The first attempt to fix this bug is here: 8171ed6c12. It caused crash so it was reverted here: 2ef47222f4. --- Telegram/SourceFiles/main/main_session.cpp | 1 + .../SourceFiles/window/window_controller.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp index 4f9873ea0..fcb1b1064 100644 --- a/Telegram/SourceFiles/main/main_session.cpp +++ b/Telegram/SourceFiles/main/main_session.cpp @@ -157,6 +157,7 @@ Session::Session( // Can be called only right before ~Session. void Session::finishLogout() { + updates().updateOnline(); unlockTerms(); data().clear(); data().clearLocalStorage(); diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index a9da6ff2a..41eaf073b 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -51,9 +51,26 @@ Controller::~Controller() { } void Controller::showAccount(not_null account) { + const auto prevSessionUniqueId = (_account && _account->sessionExists()) + ? _account->session().uniqueId() + : 0; _accountLifetime.destroy(); _account = account; + const auto updateOnlineOfPrevSesssion = crl::guard(_account, [=] { + if (!prevSessionUniqueId) { + return; + } + for (auto &[index, account] : _account->domain().accounts()) { + if (const auto anotherSession = account->maybeSession()) { + if (anotherSession->uniqueId() == prevSessionUniqueId) { + anotherSession->updates().updateOnline(); + return; + } + } + } + }); + _account->sessionValue( ) | rpl::start_with_next([=](Main::Session *session) { const auto was = base::take(_sessionController); @@ -84,6 +101,8 @@ void Controller::showAccount(not_null account) { setupIntro(); _widget.updateGlobalMenu(); } + + crl::on_main(updateOnlineOfPrevSesssion); }, _accountLifetime); } From 2576312cd41469536135bcf106870ee61f014dec Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 28 Jul 2020 10:28:56 +0300 Subject: [PATCH 015/142] Fixed autodownloading of dictionaries at logout. --- .../chat_helpers/spellchecker_common.cpp | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp index 100f08599..8f2a8025a 100644 --- a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp +++ b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp @@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "lang/lang_instance.h" #include "lang/lang_keys.h" +#include "main/main_account.h" +#include "main/main_domain.h" #include "main/main_session.h" #include "mainwidget.h" #include "spellcheck/platform/platform_spellcheck.h" @@ -377,6 +379,7 @@ void Start(not_null session) { { &ph::lng_spellchecker_ignore, tr::lng_spellchecker_ignore() }, } }); const auto settings = &Core::App().settings(); + auto &lifetime = session->lifetime(); const auto onEnabled = [=](auto enabled) { Platform::Spellchecker::UpdateLanguages( @@ -390,31 +393,25 @@ void Start(not_null session) { }); if (Platform::Spellchecker::IsSystemSpellchecker()) { - - const auto scriptsLifetime = - session->lifetime().make_state(); - - Spellchecker::SupportedScriptsChanged( - ) | rpl::start_with_next([=] { - AddExceptions(); - scriptsLifetime->destroy(); - }, *scriptsLifetime); + Spellchecker::SupportedScriptsChanged() + | rpl::take(1) + | rpl::start_with_next(AddExceptions, lifetime); return; } Spellchecker::SupportedScriptsChanged( - ) | rpl::start_with_next(AddExceptions, session->lifetime()); + ) | rpl::start_with_next(AddExceptions, lifetime); Spellchecker::SetWorkingDirPath(DictionariesPath()); settings->dictionariesEnabledChanges( ) | rpl::start_with_next([](auto dictionaries) { Platform::Spellchecker::UpdateLanguages(dictionaries); - }, session->lifetime()); + }, lifetime); settings->spellcheckerEnabledChanges( - ) | rpl::start_with_next(onEnabled, session->lifetime()); + ) | rpl::start_with_next(onEnabled, lifetime); const auto method = QGuiApplication::inputMethod(); @@ -448,11 +445,30 @@ void Start(not_null session) { } DownloadDictionaryInBackground(session, 0, DefaultLanguages()); - }, session->lifetime()); + }, lifetime); connectInput(); } + const auto disconnect = [=] { + QObject::disconnect( + method, + &QInputMethod::localeChanged, + nullptr, + nullptr); + }; + lifetime.add([=] { + disconnect(); + for (auto &[index, account] : session->domain().accounts()) { + if (const auto anotherSession = account->maybeSession()) { + if (anotherSession->uniqueId() != session->uniqueId()) { + Spellchecker::Start(anotherSession); + return; + } + } + } + }); + rpl::combine( settings->spellcheckerEnabledValue(), settings->autoDownloadDictionariesValue() @@ -461,12 +477,8 @@ void Start(not_null session) { connectInput(); return; } - QObject::disconnect( - method, - &QInputMethod::localeChanged, - nullptr, - nullptr); - }, session->lifetime()); + disconnect(); + }, lifetime); } From b71062561aa871b35dc0a5e3c61629dda0d04248 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 30 Jul 2020 10:50:12 +0300 Subject: [PATCH 016/142] Added ability to drag'n'drop videos in SendFilesBox. --- .../SourceFiles/boxes/edit_caption_box.cpp | 25 +++---------------- Telegram/SourceFiles/boxes/send_files_box.cpp | 11 ++++---- .../storage/storage_media_prepare.cpp | 19 ++++++++++++++ .../storage/storage_media_prepare.h | 1 + 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 3aec102e9..32f00f56b 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -91,25 +91,6 @@ auto ListFromMimeData(not_null data) { return result; } -auto CheckMimeData(not_null data, bool isAlbum) { - if (data->urls().size() > 1) { - return false; - } else if (data->hasImage()) { - return true; - } - - if (isAlbum && data->hasUrls()) { - const auto url = data->urls().front(); - if (url.isLocalFile()) { - using namespace Core; - const auto info = QFileInfo(Platform::File::UrlToLocal(url)); - return IsMimeAcceptedForAlbum(MimeTypeForFile(info).name()); - } - } - - return true; -} - } // namespace EditCaptionBox::EditCaptionBox( @@ -663,7 +644,7 @@ void EditCaptionBox::prepare() { if (action == Ui::InputField::MimeAction::Check) { if (!data->hasText() && !_isAllowedEditMedia) { return false; - } else if (CheckMimeData(data, _isAlbum)) { + } else if (Storage::ValidateDragData(data, _isAlbum)) { return true; } return data->hasText(); @@ -766,7 +747,9 @@ void EditCaptionBox::setupEmojiPanel() { void EditCaptionBox::setupDragArea() { auto enterFilter = [=](not_null data) { - return !_isAllowedEditMedia ? false : CheckMimeData(data, _isAlbum); + return !_isAllowedEditMedia + ? false + : Storage::ValidateDragData(data, _isAlbum); }; // Avoid both drag areas appearing at one time. auto computeState = [=](const QMimeData *data) { diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 32ff2af77..73b05d706 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -1865,12 +1865,13 @@ void SendFilesBox::prepare() { void SendFilesBox::setupDragArea() { // Avoid both drag areas appearing at one time. auto computeState = [=](const QMimeData *data) { + using DragState = Storage::MimeDataState; const auto state = Storage::ComputeMimeDataState(data); - return (state == Storage::MimeDataState::PhotoFiles) - ? Storage::MimeDataState::Image - : (state == Storage::MimeDataState::Files) - // Temporary enable drag'n'drop only for images. TODO. - ? Storage::MimeDataState::None + return (state == DragState::PhotoFiles) + ? DragState::Image + : (state == DragState::Files + && !Storage::ValidateDragData(data, true)) + ? DragState::None : state; }; const auto areas = DragArea::SetupDragAreaToContainer( diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index 2b0fef409..d8ff21784 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -140,6 +140,25 @@ void PrepareAlbum(PreparedList &result, int previewWidth) { } // namespace +bool ValidateDragData(not_null data, bool isAlbum) { + if (data->urls().size() > 1) { + return false; + } else if (data->hasImage()) { + return true; + } + + if (isAlbum && data->hasUrls()) { + const auto url = data->urls().front(); + if (url.isLocalFile()) { + using namespace Core; + const auto info = QFileInfo(Platform::File::UrlToLocal(url)); + return IsMimeAcceptedForAlbum(MimeTypeForFile(info).name()); + } + } + + return true; +} + bool ValidateThumbDimensions(int width, int height) { return (width > 0) && (height > 0) diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.h b/Telegram/SourceFiles/storage/storage_media_prepare.h index 5ed80d445..1cdfa3082 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.h +++ b/Telegram/SourceFiles/storage/storage_media_prepare.h @@ -79,6 +79,7 @@ struct PreparedList { }; +bool ValidateDragData(not_null data, bool isAlbum); bool ValidateThumbDimensions(int width, int height); PreparedList PrepareMediaList(const QList &files, int previewWidth); PreparedList PrepareMediaList(const QStringList &files, int previewWidth); From 759e802ebaf4049601ee8af73979841064421792 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 24 Jul 2020 11:22:45 +0300 Subject: [PATCH 017/142] Added ability to pass Api::SendOptions from TabbedSelector. --- .../SourceFiles/chat_helpers/gifs_list_widget.cpp | 4 ++-- Telegram/SourceFiles/chat_helpers/gifs_list_widget.h | 4 ++-- .../SourceFiles/chat_helpers/stickers_list_widget.cpp | 4 ++-- .../SourceFiles/chat_helpers/stickers_list_widget.h | 4 ++-- Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp | 4 ++-- Telegram/SourceFiles/chat_helpers/tabbed_selector.h | 7 ++++++- Telegram/SourceFiles/history/history_widget.cpp | 11 +++++++---- Telegram/SourceFiles/history/history_widget.h | 4 +++- .../history/view/history_view_compose_controls.cpp | 3 ++- .../history/view/history_view_compose_controls.h | 5 +++-- .../history/view/history_view_scheduled_section.cpp | 5 +++-- Telegram/SourceFiles/mainwidget.cpp | 2 +- 12 files changed, 35 insertions(+), 22 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 6f21db7db..4909768bb 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -165,7 +165,7 @@ GifsListWidget::GifsListWidget( }); } -rpl::producer> GifsListWidget::fileChosen() const { +rpl::producer GifsListWidget::fileChosen() const { return _fileChosen.events(); } @@ -391,7 +391,7 @@ void GifsListWidget::selectInlineResult(int row, int column) { const auto media = document->activeMediaView(); const auto preview = Data::VideoPreviewState(media.get()); if (ctrl || (media && preview.loaded())) { - _fileChosen.fire_copy(document); + _fileChosen.fire_copy({ .document = document }); } else if (!preview.usingThumbnail()) { if (preview.loading()) { document->cancel(); diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 7a67388b3..84925eb1c 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -40,7 +40,7 @@ public: GifsListWidget(QWidget *parent, not_null controller); - rpl::producer> fileChosen() const; + rpl::producer fileChosen() const; rpl::producer> photoChosen() const; rpl::producer inlineResultChosen() const; @@ -177,7 +177,7 @@ private: QString _inlineQuery, _inlineNextQuery, _inlineNextOffset; mtpRequestId _inlineRequestId = 0; - rpl::event_stream> _fileChosen; + rpl::event_stream _fileChosen; rpl::event_stream> _photoChosen; rpl::event_stream _inlineResultChosen; rpl::event_stream<> _cancelled; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index bcd7c2d2a..ef0ba93f0 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -913,7 +913,7 @@ Main::Session &StickersListWidget::session() const { return controller()->session(); } -rpl::producer> StickersListWidget::chosen() const { +rpl::producer StickersListWidget::chosen() const { return _chosen.events(); } @@ -2087,7 +2087,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { document)); } } else { - _chosen.fire_copy(document); + _chosen.fire_copy({ .document = document }); } } else if (auto set = base::get_if(&pressed)) { Assert(set->section >= 0 && set->section < sets.size()); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 8ac39583a..9238cfe32 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -51,7 +51,7 @@ public: Main::Session &session() const; - rpl::producer> chosen() const; + rpl::producer chosen() const; rpl::producer<> scrollUpdated() const; rpl::producer<> checkForHide() const; @@ -358,7 +358,7 @@ private: QString _searchQuery, _searchNextQuery; mtpRequestId _searchRequestId = 0; - rpl::event_stream> _chosen; + rpl::event_stream _chosen; rpl::event_stream<> _scrollUpdated; rpl::event_stream<> _checkForHide; diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index a4c7a805a..132f8ba70 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -409,10 +409,10 @@ rpl::producer TabbedSelector::emojiChosen() const { return emoji()->chosen(); } -rpl::producer> TabbedSelector::fileChosen() const { +rpl::producer TabbedSelector::fileChosen() const { return full() ? rpl::merge(stickers()->chosen(), gifs()->fileChosen()) - : rpl::never>() | rpl::type_erased(); + : rpl::never() | rpl::type_erased(); } rpl::producer> TabbedSelector::photoChosen() const { diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index 6f78129e4..eec1e74fa 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "api/api_common.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" #include "ui/effects/panel_animation.h" @@ -46,6 +47,10 @@ class GifsListWidget; class TabbedSelector : public Ui::RpWidget, private base::Subscriber { public: + struct FileChosen { + not_null document; + Api::SendOptions options; + }; struct InlineChosen { not_null result; not_null bot; @@ -64,7 +69,7 @@ public: Main::Session &session() const; rpl::producer emojiChosen() const; - rpl::producer> fileChosen() const; + rpl::producer fileChosen() const; rpl::producer> photoChosen() const; rpl::producer inlineResultChosen() const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index a36a76b37..2e7a67e91 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -387,7 +387,7 @@ HistoryWidget::HistoryWidget( connect(_fieldAutocomplete, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod))); connect(_fieldAutocomplete, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod))); connect(_fieldAutocomplete, &FieldAutocomplete::stickerChosen, this, [=](not_null document) { - sendExistingDocument(document); + sendExistingDocument(document, Api::SendOptions()); }); connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*))); if (_supportAutocomplete) { @@ -818,8 +818,8 @@ void HistoryWidget::initTabbedSelector() { selector->fileChosen( ) | rpl::filter([=] { return !isHidden(); - }) | rpl::start_with_next([=](not_null document) { - sendExistingDocument(document); + }) | rpl::start_with_next([=](TabbedSelector::FileChosen data) { + sendExistingDocument(data.document, data.options); }, lifetime()); selector->photoChosen( @@ -5368,7 +5368,9 @@ void HistoryWidget::destroyPinnedBar() { _inPinnedMsg = false; } -bool HistoryWidget::sendExistingDocument(not_null document) { +bool HistoryWidget::sendExistingDocument( + not_null document, + Api::SendOptions options) { const auto error = _peer ? Data::RestrictionError(_peer, ChatRestriction::f_send_stickers) : std::nullopt; @@ -5382,6 +5384,7 @@ bool HistoryWidget::sendExistingDocument(not_null document) { } auto message = Api::MessageToSend(_history); + message.action.options = std::move(options); message.action.replyTo = replyToId(); Api::SendExistingDocument(std::move(message), document); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 9c5e7e644..28e9b506d 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -248,7 +248,9 @@ public: void confirmDeleteSelected(); void clearSelected(); - bool sendExistingDocument(not_null document); + bool sendExistingDocument( + not_null document, + Api::SendOptions options); bool sendExistingPhoto(not_null photo); void showInfoTooltip( diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp index 7edb1a78e..a4ac23c37 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp @@ -39,6 +39,7 @@ namespace HistoryView { namespace { +using FileChosen = ComposeControls::FileChosen; using MessageToEdit = ComposeControls::MessageToEdit; constexpr auto kMouseEvent = { @@ -502,7 +503,7 @@ void ComposeControls::setMimeDataHook(MimeDataHook hook) { _field->setMimeDataHook(std::move(hook)); } -rpl::producer> ComposeControls::fileChosen() const { +rpl::producer ComposeControls::fileChosen() const { return _fileChosen.events(); } diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/history_view_compose_controls.h index 32b8fd80d..7e9bd2c3f 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.h @@ -54,6 +54,7 @@ class FieldHeader; class ComposeControls final { public: + using FileChosen = ChatHelpers::TabbedSelector::FileChosen; enum class Mode { Normal, Scheduled, @@ -85,7 +86,7 @@ public: [[nodiscard]] rpl::producer<> sendRequests() const; [[nodiscard]] rpl::producer editRequests() const; [[nodiscard]] rpl::producer<> attachRequests() const; - [[nodiscard]] rpl::producer> fileChosen() const; + [[nodiscard]] rpl::producer fileChosen() const; [[nodiscard]] rpl::producer> photoChosen() const; [[nodiscard]] rpl::producer scrollRequests() const; [[nodiscard]] rpl::producer> keyEvents() const; @@ -154,7 +155,7 @@ private: const std::unique_ptr _header; rpl::event_stream<> _cancelRequests; - rpl::event_stream> _fileChosen; + rpl::event_stream _fileChosen; rpl::event_stream> _photoChosen; rpl::event_stream _inlineResultChosen; diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 06bfcdb60..021a3d516 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -199,8 +199,9 @@ void ScheduledWidget::setupComposeControls() { }, lifetime()); _composeControls->fileChosen( - ) | rpl::start_with_next([=](not_null document) { - sendExistingDocument(document); + ) | rpl::start_with_next([=]( + ChatHelpers::TabbedSelector::FileChosen chosen) { + sendExistingDocument(chosen.document); }, lifetime()); _composeControls->photoChosen( diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 89cfa644e..603557c22 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1081,7 +1081,7 @@ void MainWidget::inlineResultLoadFailed(FileLoader *loader, bool started) { } bool MainWidget::sendExistingDocument(not_null document) { - return _history->sendExistingDocument(document); + return _history->sendExistingDocument(document, Api::SendOptions()); } void MainWidget::dialogsCancelled() { From a95a32440151fad7a859853f151349151d49f7db Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 24 Jul 2020 11:23:08 +0300 Subject: [PATCH 018/142] Separated send menu filling to another method. --- .../chat_helpers/message_field.cpp | 48 ++++++++++++------- .../SourceFiles/chat_helpers/message_field.h | 10 ++++ 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index 9c6db61ba..d48addd0d 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -686,6 +686,33 @@ void MessageLinksParser::apply( _list = std::move(parsed); } +bool FillSendMenu( + not_null menu, + Fn type, + Fn silent, + Fn schedule) { + if (!silent && !schedule) { + return false; + } + const auto now = type(); + if (now == SendMenuType::Disabled + || (!silent && now == SendMenuType::SilentOnly)) { + return false; + } + + if (silent && now != SendMenuType::Reminder) { + menu->addAction(tr::lng_send_silent_message(tr::now), silent); + } + if (schedule && now != SendMenuType::SilentOnly) { + menu->addAction( + (now == SendMenuType::Reminder + ? tr::lng_reminder_message(tr::now) + : tr::lng_schedule_message(tr::now)), + schedule); + } + return true; +} + void SetupSendMenuAndShortcuts( not_null button, Fn type, @@ -696,25 +723,12 @@ void SetupSendMenuAndShortcuts( } const auto menu = std::make_shared>(); const auto showMenu = [=] { - const auto now = type(); - if (now == SendMenuType::Disabled - || (!silent && now == SendMenuType::SilentOnly)) { - return false; - } - *menu = base::make_unique_q(button); - if (silent && now != SendMenuType::Reminder) { - (*menu)->addAction(tr::lng_send_silent_message(tr::now), silent); + const auto success = FillSendMenu(*menu, type, silent, schedule); + if (success) { + (*menu)->popup(QCursor::pos()); } - if (schedule && now != SendMenuType::SilentOnly) { - (*menu)->addAction( - (now == SendMenuType::Reminder - ? tr::lng_reminder_message(tr::now) - : tr::lng_schedule_message(tr::now)), - schedule); - } - (*menu)->popup(QCursor::pos()); - return true; + return success; }; base::install_event_filter(button, [=](not_null e) { if (e->type() == QEvent::ContextMenu && showMenu()) { diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h index b67bff668..035d3709e 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.h +++ b/Telegram/SourceFiles/chat_helpers/message_field.h @@ -26,6 +26,10 @@ namespace Window { class SessionController; } // namespace Window +namespace Ui { +class PopupMenu; +} // namespace Ui + QString PrepareMentionTag(not_null user); TextWithTags PrepareEditText(not_null item); @@ -106,6 +110,12 @@ enum class SendMenuType { Reminder, }; +bool FillSendMenu( + not_null menu, + Fn type, + Fn silent, + Fn schedule); + void SetupSendMenuAndShortcuts( not_null button, Fn type, From 7db9843543f936158d34f353af940415c5768ad5 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 25 Jul 2020 18:07:14 +0300 Subject: [PATCH 019/142] Added initial context menu to TabbedPanel. Added ability to schedule and send silently stickers and GIFs. --- .../chat_helpers/gifs_list_widget.cpp | 48 +++++++++++++++++-- .../chat_helpers/gifs_list_widget.h | 12 +++++ .../chat_helpers/stickers_list_widget.cpp | 37 ++++++++++++++ .../chat_helpers/stickers_list_widget.h | 3 ++ .../SourceFiles/chat_helpers/tabbed_panel.cpp | 8 ++++ .../SourceFiles/chat_helpers/tabbed_panel.h | 2 + .../chat_helpers/tabbed_selector.cpp | 18 ++++++- .../chat_helpers/tabbed_selector.h | 7 +++ 8 files changed, 130 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 4909768bb..ded6f8b6f 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "chat_helpers/gifs_list_widget.h" +#include "api/api_common.h" #include "base/const_string.h" #include "data/data_photo.h" #include "data/data_document.h" @@ -16,8 +17,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "data/stickers/data_stickers.h" +#include "chat_helpers/message_field.h" // FillSendMenu #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" +#include "ui/widgets/popup_menu.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image.h" #include "boxes/stickers_box.h" @@ -28,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "window/window_session_controller.h" #include "history/view/history_view_cursor_state.h" +#include "history/view/history_view_schedule_box.h" #include "app.h" #include "styles/style_chat_helpers.h" @@ -343,6 +347,32 @@ void GifsListWidget::mousePressEvent(QMouseEvent *e) { _previewTimer.callOnce(QApplication::startDragTime()); } +void GifsListWidget::fillContextMenu(not_null menu) { + if (_selected < 0 || _pressed >= 0) { + return; + } + const auto row = _selected / MatrixRowShift; + const auto column = _selected % MatrixRowShift; + + const auto send = [=](Api::SendOptions options) { + selectInlineResult(row, column, options, true); + }; + const auto silent = [=] { send({ .silent = true }); }; + const auto schedule = [=] { + Ui::show( + HistoryView::PrepareScheduleBox( + this, + SendMenuType::Scheduled, + [=](Api::SendOptions options) { send(options); }), + Ui::LayerOption::KeepOther); + }; + FillSendMenu( + menu, + [] { return SendMenuType::Scheduled; }, + silent, + schedule); +} + void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) { _previewTimer.cancel(); @@ -370,17 +400,25 @@ void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) { } void GifsListWidget::selectInlineResult(int row, int column) { + selectInlineResult(row, column, Api::SendOptions()); +} + +void GifsListWidget::selectInlineResult( + int row, + int column, + Api::SendOptions options, + bool forceSend) { if (row >= _rows.size() || column >= _rows[row].items.size()) { return; } - const auto ctrl = (QGuiApplication::keyboardModifiers() + forceSend |= (QGuiApplication::keyboardModifiers() == Qt::ControlModifier); auto item = _rows[row].items[column]; if (const auto photo = item->getPhoto()) { using Data::PhotoSize; const auto media = photo->activeMediaView(); - if (ctrl + if (forceSend || (media && media->image(PhotoSize::Thumbnail)) || (media && media->image(PhotoSize::Large))) { _photoChosen.fire_copy(photo); @@ -390,8 +428,10 @@ void GifsListWidget::selectInlineResult(int row, int column) { } else if (const auto document = item->getDocument()) { const auto media = document->activeMediaView(); const auto preview = Data::VideoPreviewState(media.get()); - if (ctrl || (media && preview.loaded())) { - _fileChosen.fire_copy({ .document = document }); + if (forceSend || (media && preview.loaded())) { + _fileChosen.fire_copy({ + .document = document, + .options = options }); } else if (!preview.usingThumbnail()) { if (preview.loading()) { document->cancel(); diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 84925eb1c..366e1279c 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include +namespace Api { +struct SendOptions; +} // namespace Api + namespace InlineBots { namespace Layout { class ItemBase; @@ -22,6 +26,7 @@ class Result; } // namespace InlineBots namespace Ui { +class PopupMenu; class RoundButton; } // namespace Ui @@ -66,6 +71,8 @@ public: void cancelled(); rpl::producer<> cancelRequests() const; + void fillContextMenu(not_null menu) override; + ~GifsListWidget(); protected: @@ -158,6 +165,11 @@ private: int validateExistingInlineRows(const InlineResults &results); void selectInlineResult(int row, int column); + void selectInlineResult( + int row, + int column, + Api::SendOptions options, + bool forceSend = false); Footer *_footer = nullptr; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index ef0ba93f0..896949164 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -14,8 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_cloud_file.h" #include "data/data_changes.h" +#include "chat_helpers/message_field.h" // FillSendMenu #include "chat_helpers/stickers_lottie.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/popup_menu.h" #include "ui/effects/animations.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image.h" @@ -24,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lottie/lottie_animation.h" #include "boxes/stickers_box.h" #include "inline_bots/inline_bot_result.h" +#include "history/view/history_view_schedule_box.h" #include "storage/storage_account.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -2043,6 +2046,40 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const { return myrtlrect(removeButtonRect(section)).topLeft() + st::stickerPanRemoveSet.rippleAreaPosition; } +void StickersListWidget::fillContextMenu(not_null menu) { + auto selected = _selected; + auto &sets = shownSets(); + if (!selected || _pressed) { + return; + } + if (auto sticker = base::get_if(&selected)) { + Assert(sticker->section >= 0 && sticker->section < sets.size()); + auto &set = sets[sticker->section]; + Assert(sticker->index >= 0 && sticker->index < set.stickers.size()); + + const auto document = set.stickers[sticker->index].document; + const auto send = [=](Api::SendOptions options) { + _chosen.fire_copy({ + .document = document, + .options = options }); + }; + const auto silent = [=] { send({ .silent = true }); }; + const auto schedule = [=] { + checkHideWithBox(Ui::show( + HistoryView::PrepareScheduleBox( + this, + SendMenuType::Scheduled, + [=](Api::SendOptions options) { send(options); }), + Ui::LayerOption::KeepOther).data()); + }; + FillSendMenu( + menu, + [] { return SendMenuType::Scheduled; }, + silent, + schedule); + } +} + void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { _previewTimer.cancel(); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 9238cfe32..2e7adc729 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -22,6 +22,7 @@ class SessionController; namespace Ui { class LinkButton; +class PopupMenu; class RippleAnimation; class BoxContent; } // namespace Ui @@ -82,6 +83,8 @@ public: std::shared_ptr getLottieRenderer(); + void fillContextMenu(not_null menu) override; + ~StickersListWidget(); protected: diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp index 8fba46c57..86c5e97ec 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp @@ -364,6 +364,10 @@ void TabbedPanel::hideAnimated() { } else { startOpacityAnimation(true); } + + // There is no reason to worry about the message scheduling box + // while it moves the user to the separate scheduled section. + _shouldFinishHide = _selector->hasMenu(); } void TabbedPanel::toggleAnimated() { @@ -380,6 +384,7 @@ void TabbedPanel::hideFinished() { _showAnimation.reset(); _cache = QPixmap(); _hiding = false; + _shouldFinishHide = false; _selector->hideFinished(); } @@ -390,6 +395,9 @@ void TabbedPanel::showAnimated() { } void TabbedPanel::showStarted() { + if (_shouldFinishHide) { + return; + } if (isHidden()) { _selector->showStarted(); moveByBottom(); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h index b05966792..edaa45fa0 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h @@ -110,6 +110,8 @@ private: std::unique_ptr _showAnimation; Ui::Animations::Simple _a_show; + bool _shouldFinishHide = false; + bool _hiding = false; bool _hideAfterSlide = false; QPixmap _cache; diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 132f8ba70..03daa863f 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/shadow.h" #include "ui/widgets/discrete_sliders.h" +#include "ui/widgets/popup_menu.h" #include "ui/widgets/scroll_area.h" #include "ui/image/image_prepare.h" #include "window/window_session_controller.h" @@ -584,7 +585,13 @@ void TabbedSelector::refreshStickers() { } bool TabbedSelector::preventAutoHide() const { - return full() ? stickers()->preventAutoHide() : false; + return full() + ? (stickers()->preventAutoHide() || hasMenu()) + : false; +} + +bool TabbedSelector::hasMenu() const { + return (_menu && !_menu->actions().empty()); } QImage TabbedSelector::grabForAnimation() { @@ -867,6 +874,15 @@ void TabbedSelector::scrollToY(int y) { } } +void TabbedSelector::contextMenuEvent(QContextMenuEvent *e) { + _menu = base::make_unique_q(this); + currentTab()->widget()->fillContextMenu(_menu); + + if (!_menu->actions().empty()) { + _menu->popup(QCursor::pos()); + } +} + TabbedSelector::Inner::Inner( QWidget *parent, not_null controller) diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index eec1e74fa..eb719b6f2 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -24,6 +24,7 @@ class Session; namespace Ui { class PlainShadow; +class PopupMenu; class ScrollArea; class SettingsSlider; class FlatLabel; @@ -94,6 +95,7 @@ public: bool isSliding() const { return _a_slide.animating(); } + bool hasMenu() const; void setAfterShownCallback(Fn callback) { _afterShownCallback = std::move(callback); @@ -116,6 +118,7 @@ public: protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void contextMenuEvent(QContextMenuEvent *e) override; private: class Tab { @@ -211,6 +214,8 @@ private: std::array _tabs; SelectorTab _currentTabType = SelectorTab::Emoji; + base::unique_qptr _menu; + Fn _afterShownCallback; Fn _beforeHidingCallback; @@ -246,6 +251,8 @@ public: } virtual void beforeHiding() { } + virtual void fillContextMenu(not_null menu) { + } rpl::producer scrollToRequests() const; rpl::producer disableScrollRequests() const; From 43056107fdf0c90c21fa512fb13e3d9b874231f8 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 25 Jul 2020 19:50:19 +0300 Subject: [PATCH 020/142] Added ability to pass SendMenuType to TabbedSelector. --- .../SourceFiles/chat_helpers/gifs_list_widget.cpp | 8 +++++--- Telegram/SourceFiles/chat_helpers/gifs_list_widget.h | 6 +++++- .../chat_helpers/stickers_list_widget.cpp | 8 +++++--- .../SourceFiles/chat_helpers/stickers_list_widget.h | 4 +++- .../SourceFiles/chat_helpers/tabbed_selector.cpp | 6 +++++- Telegram/SourceFiles/chat_helpers/tabbed_selector.h | 12 +++++++++++- Telegram/SourceFiles/history/history_widget.cpp | 2 ++ 7 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index ded6f8b6f..10544a6ab 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -347,7 +347,9 @@ void GifsListWidget::mousePressEvent(QMouseEvent *e) { _previewTimer.callOnce(QApplication::startDragTime()); } -void GifsListWidget::fillContextMenu(not_null menu) { +void GifsListWidget::fillContextMenu( + not_null menu, + SendMenuType type) { if (_selected < 0 || _pressed >= 0) { return; } @@ -362,13 +364,13 @@ void GifsListWidget::fillContextMenu(not_null menu) { Ui::show( HistoryView::PrepareScheduleBox( this, - SendMenuType::Scheduled, + type, [=](Api::SendOptions options) { send(options); }), Ui::LayerOption::KeepOther); }; FillSendMenu( menu, - [] { return SendMenuType::Scheduled; }, + [&] { return type; }, silent, schedule); } diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 366e1279c..8772cf2a0 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -34,6 +34,8 @@ namespace Window { class SessionController; } // namespace Window +enum class SendMenuType; + namespace ChatHelpers { class GifsListWidget @@ -71,7 +73,9 @@ public: void cancelled(); rpl::producer<> cancelRequests() const; - void fillContextMenu(not_null menu) override; + void fillContextMenu( + not_null menu, + SendMenuType type) override; ~GifsListWidget(); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 896949164..62ebe98d9 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -2046,7 +2046,9 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const { return myrtlrect(removeButtonRect(section)).topLeft() + st::stickerPanRemoveSet.rippleAreaPosition; } -void StickersListWidget::fillContextMenu(not_null menu) { +void StickersListWidget::fillContextMenu( + not_null menu, + SendMenuType type) { auto selected = _selected; auto &sets = shownSets(); if (!selected || _pressed) { @@ -2068,13 +2070,13 @@ void StickersListWidget::fillContextMenu(not_null menu) { checkHideWithBox(Ui::show( HistoryView::PrepareScheduleBox( this, - SendMenuType::Scheduled, + type, [=](Api::SendOptions options) { send(options); }), Ui::LayerOption::KeepOther).data()); }; FillSendMenu( menu, - [] { return SendMenuType::Scheduled; }, + [&] { return type; }, silent, schedule); } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 2e7adc729..e2c46a6a6 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -83,7 +83,9 @@ public: std::shared_ptr getLottieRenderer(); - void fillContextMenu(not_null menu) override; + void fillContextMenu( + not_null menu, + SendMenuType type) override; ~StickersListWidget(); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 03daa863f..fbb46532b 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "chat_helpers/tabbed_selector.h" +#include "chat_helpers/message_field.h" #include "chat_helpers/emoji_list_widget.h" #include "chat_helpers/stickers_list_widget.h" #include "chat_helpers/gifs_list_widget.h" @@ -876,7 +877,10 @@ void TabbedSelector::scrollToY(int y) { void TabbedSelector::contextMenuEvent(QContextMenuEvent *e) { _menu = base::make_unique_q(this); - currentTab()->widget()->fillContextMenu(_menu); + const auto type = _sendMenuType + ? _sendMenuType() + : SendMenuType::Disabled; + currentTab()->widget()->fillContextMenu(_menu, type); if (!_menu->actions().empty()) { _menu->popup(QCursor::pos()); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index eb719b6f2..1ec902e27 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -34,6 +34,8 @@ namespace Window { class SessionController; } // namespace Window +enum class SendMenuType; + namespace ChatHelpers { enum class SelectorTab { @@ -104,6 +106,10 @@ public: _beforeHidingCallback = std::move(callback); } + void setSendMenuType(Fn callback) { + _sendMenuType = std::move(callback); + } + // Float player interface. bool floatPlayerHandleWheelEvent(QEvent *e); QRect floatPlayerAvailableRect() const; @@ -219,6 +225,8 @@ private: Fn _afterShownCallback; Fn _beforeHidingCallback; + Fn _sendMenuType; + rpl::event_stream<> _showRequests; rpl::event_stream<> _slideFinished; @@ -251,7 +259,9 @@ public: } virtual void beforeHiding() { } - virtual void fillContextMenu(not_null menu) { + virtual void fillContextMenu( + not_null menu, + SendMenuType type) { } rpl::producer scrollToRequests() const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 2e7a67e91..b7137c620 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -835,6 +835,8 @@ void HistoryWidget::initTabbedSelector() { }) | rpl::start_with_next([=](TabbedSelector::InlineChosen data) { sendInlineResult(data.result, data.bot); }, lifetime()); + + selector->setSendMenuType([=] { return sendMenuType(); }); } void HistoryWidget::supportInitAutocomplete() { From 5b95585725df8945bbc3fcc600d78a364e144faf Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 25 Jul 2020 22:03:29 +0300 Subject: [PATCH 021/142] Added other items to TabbedPanel's context menu. --- Telegram/Resources/langs/lang.strings | 1 + .../chat_helpers/gifs_list_widget.cpp | 36 ++++++++++++++++++- .../chat_helpers/gifs_list_widget.h | 2 ++ .../chat_helpers/stickers_list_widget.cpp | 32 +++++++++++++---- .../chat_helpers/stickers_list_widget.h | 2 ++ .../inline_bot_layout_internal.cpp | 15 ++------ 6 files changed, 67 insertions(+), 21 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 351fe5256..17797e785 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1468,6 +1468,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_copy_text" = "Copy Text"; "lng_context_open_gif" = "Open GIF"; "lng_context_save_gif" = "Save GIF"; +"lng_context_delete_gif" = "Delete GIF"; "lng_context_attached_stickers" = "Attached Stickers"; "lng_context_to_msg" = "Go To Message"; "lng_context_reply_msg" = "Reply"; diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 10544a6ab..aacd3ddf0 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "chat_helpers/gifs_list_widget.h" -#include "api/api_common.h" +#include "apiwrap.h" // ApiWrap::toggleSavedGif #include "base/const_string.h" #include "data/data_photo.h" #include "data/data_document.h" @@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_schedule_box.h" #include "app.h" +#include "storage/storage_account.h" // Account::writeSavedGifs #include "styles/style_chat_helpers.h" #include @@ -46,6 +47,21 @@ constexpr auto kSearchBotUsername = "gif"_cs; } // namespace +void DeleteSavedGif(not_null document) { + auto &data = document->owner(); + document->session().api().toggleSavedGif( + document, + Data::FileOriginSavedGifs(), + false); + + const auto index = data.stickers().savedGifs().indexOf(document); + if (index >= 0) { + data.stickers().savedGifsRef().remove(index); + document->session().local().writeSavedGifs(); + } + data.stickers().notifySavedGifsUpdated(); +} + class GifsListWidget::Footer : public TabbedSelector::InnerFooter { public: Footer(not_null parent); @@ -373,6 +389,24 @@ void GifsListWidget::fillContextMenu( [&] { return type; }, silent, schedule); + + [&] { + const auto row = _selected / MatrixRowShift; + const auto column = _selected % MatrixRowShift; + if (row >= _rows.size() || column >= _rows[row].items.size()) { + return; + } + const auto item = _rows[row].items[column]; + if (const auto document = item->getDocument()) { + auto &data = document->owner(); + if (data.stickers().savedGifs().indexOf(document) < 0) { + return; + } + menu->addAction(tr::lng_context_delete_gif(tr::now), [=] { + ChatHelpers::DeleteSavedGif(document); + }); + } + }(); } void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) { diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 8772cf2a0..9b16ff71c 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -38,6 +38,8 @@ enum class SendMenuType; namespace ChatHelpers { +void DeleteSavedGif(not_null document); + class GifsListWidget : public TabbedSelector::Inner , public InlineBots::Layout::Context diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 62ebe98d9..29fcce2e5 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -2046,6 +2046,14 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const { return myrtlrect(removeButtonRect(section)).topLeft() + st::stickerPanRemoveSet.rippleAreaPosition; } +void StickersListWidget::showStickerSetBox(not_null document) { + if (document->sticker() + && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) { + _displayingSet = true; + checkHideWithBox(StickerSetBox::Show(controller(), document)); + } +} + void StickersListWidget::fillContextMenu( not_null menu, SendMenuType type) { @@ -2079,6 +2087,22 @@ void StickersListWidget::fillContextMenu( [&] { return type; }, silent, schedule); + + const auto toggleFavedSticker = [=] { + document->session().api().toggleFavedSticker( + document, + Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0), + !document->owner().stickers().isFaved(document)); + }; + menu->addAction( + (document->owner().stickers().isFaved(document) + ? tr::lng_faved_stickers_remove + : tr::lng_faved_stickers_add)(tr::now), + toggleFavedSticker); + + menu->addAction(tr::lng_context_pack_info(tr::now), [=] { + showStickerSetBox(document); + }); } } @@ -2118,13 +2142,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { } const auto document = set.stickers[sticker->index].document; if (e->modifiers() & Qt::ControlModifier) { - if (document->sticker() - && document->sticker()->set.type() != mtpc_inputStickerSetEmpty) { - _displayingSet = true; - checkHideWithBox(StickerSetBox::Show( - controller(), - document)); - } + showStickerSetBox(document); } else { _chosen.fire_copy({ .document = document }); } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index e2c46a6a6..a0e6bf21e 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -303,6 +303,8 @@ private: void setColumnCount(int count); void refreshFooterIcons(); + void showStickerSetBox(not_null document); + void cancelSetsSearch(); void showSearchResults(); void searchResultsDone(const MTPmessages_FoundStickerSets &result); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index f485b0285..9b871b3b1 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "data/stickers/data_stickers.h" +#include "chat_helpers/gifs_list_widget.h" // ChatHelpers::DeleteSavedGif #include "chat_helpers/stickers_lottie.h" #include "inline_bots/inline_bot_result.h" #include "lottie/lottie_single_player.h" @@ -22,10 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/player/media_player_instance.h" #include "history/history_location_manager.h" #include "history/view/history_view_cursor_state.h" -#include "storage/storage_account.h" #include "ui/image/image.h" #include "main/main_session.h" -#include "apiwrap.h" #include "lang/lang_keys.h" #include "app.h" #include "styles/style_overview.h" @@ -126,17 +125,7 @@ void Gif::setPosition(int32 position) { } void DeleteSavedGifClickHandler::onClickImpl() const { - _data->session().api().toggleSavedGif( - _data, - Data::FileOriginSavedGifs(), - false); - - const auto index = _data->owner().stickers().savedGifs().indexOf(_data); - if (index >= 0) { - _data->owner().stickers().savedGifsRef().remove(index); - _data->session().local().writeSavedGifs(); - } - _data->owner().stickers().notifySavedGifsUpdated(); + ChatHelpers::DeleteSavedGif(_data); } int Gif::resizeGetHeight(int width) { From d1d153e8865ec9babc516ddd8d69bb2593da5406 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 7 Aug 2020 19:13:47 +0300 Subject: [PATCH 022/142] Added Api::SendOptions passing from TabbedSelector for inline results. --- .../chat_helpers/gifs_list_widget.cpp | 9 ++++++--- .../SourceFiles/chat_helpers/gifs_list_widget.h | 4 ++-- .../chat_helpers/tabbed_selector.cpp | 3 ++- .../SourceFiles/chat_helpers/tabbed_selector.h | 7 ++++++- Telegram/SourceFiles/history/history_widget.cpp | 17 +++++++++++------ Telegram/SourceFiles/history/history_widget.h | 7 +++++-- .../view/history_view_compose_controls.cpp | 3 ++- .../view/history_view_compose_controls.h | 5 +++-- .../view/history_view_scheduled_section.cpp | 12 ++++++------ 9 files changed, 43 insertions(+), 24 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index aacd3ddf0..3d32f233c 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -189,7 +189,8 @@ rpl::producer GifsListWidget::fileChosen() const { return _fileChosen.events(); } -rpl::producer> GifsListWidget::photoChosen() const { +auto GifsListWidget::photoChosen() const +-> rpl::producer { return _photoChosen.events(); } @@ -457,7 +458,9 @@ void GifsListWidget::selectInlineResult( if (forceSend || (media && media->image(PhotoSize::Thumbnail)) || (media && media->image(PhotoSize::Large))) { - _photoChosen.fire_copy(photo); + _photoChosen.fire_copy({ + .photo = photo, + .options = options }); } else if (!photo->loading(PhotoSize::Thumbnail)) { photo->load(PhotoSize::Thumbnail, Data::FileOrigin()); } @@ -479,7 +482,7 @@ void GifsListWidget::selectInlineResult( } } else if (const auto inlineResult = item->getResult()) { if (inlineResult->onChoose(item)) { - _inlineResultChosen.fire({ inlineResult, _searchBot }); + _inlineResultChosen.fire({ inlineResult, _searchBot, options }); } } } diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 9b16ff71c..4a78c147a 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -50,7 +50,7 @@ public: GifsListWidget(QWidget *parent, not_null controller); rpl::producer fileChosen() const; - rpl::producer> photoChosen() const; + rpl::producer photoChosen() const; rpl::producer inlineResultChosen() const; void refreshRecent() override; @@ -196,7 +196,7 @@ private: mtpRequestId _inlineRequestId = 0; rpl::event_stream _fileChosen; - rpl::event_stream> _photoChosen; + rpl::event_stream _photoChosen; rpl::event_stream _inlineResultChosen; rpl::event_stream<> _cancelled; diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index fbb46532b..0802ace53 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -417,7 +417,8 @@ rpl::producer TabbedSelector::fileChosen() const { : rpl::never() | rpl::type_erased(); } -rpl::producer> TabbedSelector::photoChosen() const { +auto TabbedSelector::photoChosen() const +-> rpl::producer{ return full() ? gifs()->photoChosen() : nullptr; } diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index 1ec902e27..4b9e61987 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -54,9 +54,14 @@ public: not_null document; Api::SendOptions options; }; + struct PhotoChosen { + not_null photo; + Api::SendOptions options; + }; struct InlineChosen { not_null result; not_null bot; + Api::SendOptions options; }; enum class Mode { Full, @@ -73,7 +78,7 @@ public: rpl::producer emojiChosen() const; rpl::producer fileChosen() const; - rpl::producer> photoChosen() const; + rpl::producer photoChosen() const; rpl::producer inlineResultChosen() const; rpl::producer<> cancelled() const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index b7137c620..34540cb9f 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -825,15 +825,15 @@ void HistoryWidget::initTabbedSelector() { selector->photoChosen( ) | rpl::filter([=] { return !isHidden(); - }) | rpl::start_with_next([=](not_null photo) { - sendExistingPhoto(photo); + }) | rpl::start_with_next([=](TabbedSelector::PhotoChosen data) { + sendExistingPhoto(data.photo, data.options); }, lifetime()); selector->inlineResultChosen( ) | rpl::filter([=] { return !isHidden(); }) | rpl::start_with_next([=](TabbedSelector::InlineChosen data) { - sendInlineResult(data.result, data.bot); + sendInlineResult(data.result, data.bot, data.options); }, lifetime()); selector->setSendMenuType([=] { return sendMenuType(); }); @@ -1200,7 +1200,7 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) { _inlineResults->setResultSelectedCallback([=]( InlineBots::Result *result, UserData *bot) { - sendInlineResult(result, bot); + sendInlineResult(result, bot, Api::SendOptions()); }); _inlineResults->requesting( ) | rpl::start_with_next([=](bool requesting) { @@ -5218,7 +5218,8 @@ void HistoryWidget::onFieldTabbed() { void HistoryWidget::sendInlineResult( not_null result, - not_null bot) { + not_null bot, + Api::SendOptions options) { if (!_peer || !_peer->canWrite()) { return; } else if (showSlowmodeError()) { @@ -5233,6 +5234,7 @@ void HistoryWidget::sendInlineResult( auto action = Api::SendAction(_history); action.replyTo = replyToId(); + action.options = std::move(options); action.generateLocal = true; session().api().sendInlineResult(bot, result, action); @@ -5404,7 +5406,9 @@ bool HistoryWidget::sendExistingDocument( return true; } -bool HistoryWidget::sendExistingPhoto(not_null photo) { +bool HistoryWidget::sendExistingPhoto( + not_null photo, + Api::SendOptions options) { const auto error = _peer ? Data::RestrictionError(_peer, ChatRestriction::f_send_media) : std::nullopt; @@ -5419,6 +5423,7 @@ bool HistoryWidget::sendExistingPhoto(not_null photo) { auto message = Api::MessageToSend(_history); message.action.replyTo = replyToId(); + message.action.options = std::move(options); Api::SendExistingPhoto(std::move(message), photo); hideSelectorControlsAnimated(); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 28e9b506d..c73ec6cb7 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -251,7 +251,9 @@ public: bool sendExistingDocument( not_null document, Api::SendOptions options); - bool sendExistingPhoto(not_null photo); + bool sendExistingPhoto( + not_null photo, + Api::SendOptions options); void showInfoTooltip( const TextWithEntities &text, @@ -501,7 +503,8 @@ private: void sendInlineResult( not_null result, - not_null bot); + not_null bot, + Api::SendOptions options); void drawField(Painter &p, const QRect &rect); void paintEditHeader( diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp index a4ac23c37..c43d26298 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp @@ -40,6 +40,7 @@ namespace HistoryView { namespace { using FileChosen = ComposeControls::FileChosen; +using PhotoChosen = ComposeControls::PhotoChosen; using MessageToEdit = ComposeControls::MessageToEdit; constexpr auto kMouseEvent = { @@ -507,7 +508,7 @@ rpl::producer ComposeControls::fileChosen() const { return _fileChosen.events(); } -rpl::producer> ComposeControls::photoChosen() const { +rpl::producer ComposeControls::photoChosen() const { return _photoChosen.events(); } diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/history_view_compose_controls.h index 7e9bd2c3f..13179d945 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.h @@ -55,6 +55,7 @@ class FieldHeader; class ComposeControls final { public: using FileChosen = ChatHelpers::TabbedSelector::FileChosen; + using PhotoChosen = ChatHelpers::TabbedSelector::PhotoChosen; enum class Mode { Normal, Scheduled, @@ -87,7 +88,7 @@ public: [[nodiscard]] rpl::producer editRequests() const; [[nodiscard]] rpl::producer<> attachRequests() const; [[nodiscard]] rpl::producer fileChosen() const; - [[nodiscard]] rpl::producer> photoChosen() const; + [[nodiscard]] rpl::producer photoChosen() const; [[nodiscard]] rpl::producer scrollRequests() const; [[nodiscard]] rpl::producer> keyEvents() const; [[nodiscard]] auto inlineResultChosen() const @@ -156,7 +157,7 @@ private: rpl::event_stream<> _cancelRequests; rpl::event_stream _fileChosen; - rpl::event_stream> _photoChosen; + rpl::event_stream _photoChosen; rpl::event_stream _inlineResultChosen; TextWithTags _localSavedText; diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 021a3d516..8d0a2fdc6 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -198,20 +198,20 @@ void ScheduledWidget::setupComposeControls() { [=] { _choosingAttach = false; chooseAttach(); }); }, lifetime()); + using Selector = ChatHelpers::TabbedSelector; + _composeControls->fileChosen( - ) | rpl::start_with_next([=]( - ChatHelpers::TabbedSelector::FileChosen chosen) { + ) | rpl::start_with_next([=](Selector::FileChosen chosen) { sendExistingDocument(chosen.document); }, lifetime()); _composeControls->photoChosen( - ) | rpl::start_with_next([=](not_null photo) { - sendExistingPhoto(photo); + ) | rpl::start_with_next([=](Selector::PhotoChosen chosen) { + sendExistingPhoto(chosen.photo); }, lifetime()); _composeControls->inlineResultChosen( - ) | rpl::start_with_next([=]( - ChatHelpers::TabbedSelector::InlineChosen chosen) { + ) | rpl::start_with_next([=](Selector::InlineChosen chosen) { sendInlineResult(chosen.result, chosen.bot); }, lifetime()); From 1fee7d1a4187ac8eebdc427dbced71d480b011e8 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 7 Aug 2020 19:43:00 +0300 Subject: [PATCH 023/142] Added ability to schedule and send silently media from inline bots. --- .../SourceFiles/history/history_widget.cpp | 5 +- .../inline_bots/inline_results_widget.cpp | 51 ++++++++++++++++++- .../inline_bots/inline_results_widget.h | 16 ++++-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 34540cb9f..2f3ac4ee7 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1199,8 +1199,9 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) { _inlineResults.create(this, controller()); _inlineResults->setResultSelectedCallback([=]( InlineBots::Result *result, - UserData *bot) { - sendInlineResult(result, bot, Api::SendOptions()); + UserData *bot, + Api::SendOptions options) { + sendInlineResult(result, bot, options); }); _inlineResults->requesting( ) | rpl::start_with_next([=](bool requesting) { diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 23aee7c0e..828f00e7d 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "inline_bots/inline_results_widget.h" +#include "api/api_common.h" +#include "chat_helpers/message_field.h" // FillSendMenu #include "data/data_photo.h" #include "data/data_document.h" #include "data/data_channel.h" @@ -15,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_changes.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/popup_menu.h" #include "ui/widgets/shadow.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image_prepare.h" @@ -31,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/scroll_area.h" #include "ui/widgets/labels.h" #include "history/view/history_view_cursor_state.h" +#include "history/view/history_view_schedule_box.h" #include "facades.h" #include "app.h" #include "styles/style_chat_helpers.h" @@ -254,14 +258,24 @@ void Inner::mouseReleaseEvent(QMouseEvent *e) { } void Inner::selectInlineResult(int row, int column) { + selectInlineResult(row, column, Api::SendOptions()); +} + +void Inner::selectInlineResult( + int row, + int column, + Api::SendOptions options) { if (row >= _rows.size() || column >= _rows.at(row).items.size()) { return; } auto item = _rows[row].items[column]; - if (auto inlineResult = item->getResult()) { + if (const auto inlineResult = item->getResult()) { if (inlineResult->onChoose(item)) { - _resultSelectedCallback(inlineResult, _inlineBot); + _resultSelectedCallback( + inlineResult, + _inlineBot, + std::move(options)); } } } @@ -285,6 +299,39 @@ void Inner::enterFromChildEvent(QEvent *e, QWidget *child) { updateSelected(); } +void Inner::contextMenuEvent(QContextMenuEvent *e) { + if (_selected < 0 || _pressed >= 0) { + return; + } + const auto row = _selected / MatrixRowShift; + const auto column = _selected % MatrixRowShift; + const auto type = SendMenuType::Scheduled; + + _menu = base::make_unique_q(this); + + const auto send = [=](Api::SendOptions options) { + selectInlineResult(row, column, options); + }; + const auto silent = [=] { send({ .silent = true }); }; + const auto schedule = [=] { + Ui::show( + HistoryView::PrepareScheduleBox( + this, + type, + [=](Api::SendOptions options) { send(options); }), + Ui::LayerOption::KeepOther); + }; + FillSendMenu( + _menu, + [&] { return type; }, + silent, + schedule); + + if (!_menu->actions().empty()) { + _menu->popup(QCursor::pos()); + } +} + void Inner::clearSelection() { if (_selected >= 0) { int srow = _selected / MatrixRowShift, scol = _selected % MatrixRowShift; diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.h b/Telegram/SourceFiles/inline_bots/inline_results_widget.h index a86cda86a..bec1ccb31 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.h +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.h @@ -18,6 +18,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include +namespace Api { +struct SendOptions; +} // namespace Api + namespace Ui { class ScrollArea; class IconButton; @@ -25,6 +29,7 @@ class LinkButton; class RoundButton; class FlatLabel; class RippleAnimation; +class PopupMenu; } // namespace Ui namespace Window { @@ -44,6 +49,7 @@ namespace internal { constexpr int kInlineItemsMaxPerRow = 5; using Results = std::vector>; +using ResultSelected = Fn; struct CacheEntry { QString nextOffset; @@ -79,7 +85,7 @@ public: int countHeight(); - void setResultSelectedCallback(Fn callback) { + void setResultSelectedCallback(ResultSelected callback) { _resultSelectedCallback = std::move(callback); } @@ -102,6 +108,7 @@ protected: void leaveEventHook(QEvent *e) override; void leaveToChildEvent(QEvent *e, QWidget *child) override; void enterFromChildEvent(QEvent *e, QWidget *child) override; + void contextMenuEvent(QContextMenuEvent *e) override; private slots: void onSwitchPm(); @@ -140,6 +147,7 @@ private: int validateExistingInlineRows(const Results &results); void selectInlineResult(int row, int column); + void selectInlineResult(int row, int column, Api::SendOptions options); not_null _controller; @@ -157,6 +165,8 @@ private: object_ptr _restrictedLabel = { nullptr }; + base::unique_qptr _menu; + QVector _rows; std::map> _inlineLayouts; @@ -168,7 +178,7 @@ private: base::Timer _previewTimer; bool _previewShown = false; - Fn _resultSelectedCallback; + ResultSelected _resultSelectedCallback; }; @@ -195,7 +205,7 @@ public: void showAnimated(); void hideAnimated(); - void setResultSelectedCallback(Fn callback) { + void setResultSelectedCallback(internal::ResultSelected callback) { _inner->setResultSelectedCallback(std::move(callback)); } From edceed28d71e9f1c2d011587e7ec95bda2a3d554 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 9 Aug 2020 14:28:39 +0300 Subject: [PATCH 024/142] Moved code for send context menu to separate file. --- Telegram/CMakeLists.txt | 2 + .../SourceFiles/boxes/create_poll_box.cpp | 1 + Telegram/SourceFiles/boxes/send_files_box.cpp | 1 + Telegram/SourceFiles/boxes/share_box.cpp | 1 + .../chat_helpers/gifs_list_widget.cpp | 2 +- .../chat_helpers/message_field.cpp | 94 --------------- .../SourceFiles/chat_helpers/message_field.h | 20 ---- .../chat_helpers/send_context_menu.cpp | 111 ++++++++++++++++++ .../chat_helpers/send_context_menu.h | 39 ++++++ .../chat_helpers/stickers_list_widget.cpp | 2 +- .../chat_helpers/tabbed_selector.cpp | 2 +- .../SourceFiles/history/history_widget.cpp | 1 + .../view/history_view_context_menu.cpp | 2 +- .../view/history_view_schedule_box.cpp | 2 +- .../view/history_view_scheduled_section.cpp | 2 +- .../inline_bots/inline_results_widget.cpp | 2 +- 16 files changed, 163 insertions(+), 121 deletions(-) create mode 100644 Telegram/SourceFiles/chat_helpers/send_context_menu.cpp create mode 100644 Telegram/SourceFiles/chat_helpers/send_context_menu.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index f0bafb1b1..a26881c4d 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -340,6 +340,8 @@ PRIVATE chat_helpers/gifs_list_widget.h chat_helpers/message_field.cpp chat_helpers/message_field.h + chat_helpers/send_context_menu.cpp + chat_helpers/send_context_menu.h chat_helpers/spellchecker_common.cpp chat_helpers/spellchecker_common.h chat_helpers/stickers_emoji_image_loader.cpp diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 97fb5d1ae..37d66216a 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/core_settings.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/message_field.h" +#include "chat_helpers/send_context_menu.h" #include "history/view/history_view_schedule_box.h" #include "settings/settings_common.h" #include "base/unique_qptr.h" diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 73b05d706..443d77d7e 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "mtproto/mtproto_config.h" #include "chat_helpers/message_field.h" +#include "chat_helpers/send_context_menu.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_selector.h" diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 006a8307d..1691502f7 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/slide_wrap.h" #include "ui/text_options.h" #include "chat_helpers/message_field.h" +#include "chat_helpers/send_context_menu.h" #include "history/history.h" #include "history/history_message.h" #include "history/view/history_view_schedule_box.h" diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 3d32f233c..f0971a362 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "data/stickers/data_stickers.h" -#include "chat_helpers/message_field.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // FillSendMenu #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/popup_menu.h" diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index d48addd0d..347cfb9a5 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -685,97 +685,3 @@ void MessageLinksParser::apply( } _list = std::move(parsed); } - -bool FillSendMenu( - not_null menu, - Fn type, - Fn silent, - Fn schedule) { - if (!silent && !schedule) { - return false; - } - const auto now = type(); - if (now == SendMenuType::Disabled - || (!silent && now == SendMenuType::SilentOnly)) { - return false; - } - - if (silent && now != SendMenuType::Reminder) { - menu->addAction(tr::lng_send_silent_message(tr::now), silent); - } - if (schedule && now != SendMenuType::SilentOnly) { - menu->addAction( - (now == SendMenuType::Reminder - ? tr::lng_reminder_message(tr::now) - : tr::lng_schedule_message(tr::now)), - schedule); - } - return true; -} - -void SetupSendMenuAndShortcuts( - not_null button, - Fn type, - Fn silent, - Fn schedule) { - if (!silent && !schedule) { - return; - } - const auto menu = std::make_shared>(); - const auto showMenu = [=] { - *menu = base::make_unique_q(button); - const auto success = FillSendMenu(*menu, type, silent, schedule); - if (success) { - (*menu)->popup(QCursor::pos()); - } - return success; - }; - base::install_event_filter(button, [=](not_null e) { - if (e->type() == QEvent::ContextMenu && showMenu()) { - return base::EventFilterResult::Cancel; - } - return base::EventFilterResult::Continue; - }); - - Shortcuts::Requests( - ) | rpl::start_with_next([=](not_null request) { - using Command = Shortcuts::Command; - - const auto now = type(); - if (now == SendMenuType::Disabled - || (!silent && now == SendMenuType::SilentOnly)) { - return; - } - (silent - && (now != SendMenuType::Reminder) - && request->check(Command::SendSilentMessage) - && request->handle([=] { - silent(); - return true; - })) - || - (schedule - && (now != SendMenuType::SilentOnly) - && request->check(Command::ScheduleMessage) - && request->handle([=] { - schedule(); - return true; - })) - || - (request->check(Command::JustSendMessage) && request->handle([=] { - const auto post = [&](QEvent::Type type) { - QApplication::postEvent( - button, - new QMouseEvent( - type, - QPointF(0, 0), - Qt::LeftButton, - Qt::LeftButton, - Qt::NoModifier)); - }; - post(QEvent::MouseButtonPress); - post(QEvent::MouseButtonRelease); - return true; - })); - }, button->lifetime()); -} diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h index 035d3709e..fd7e53aad 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.h +++ b/Telegram/SourceFiles/chat_helpers/message_field.h @@ -101,23 +101,3 @@ private: base::qt_connection _connection; }; - -enum class SendMenuType { - Disabled, - SilentOnly, - Scheduled, - ScheduledToUser, // For "Send when online". - Reminder, -}; - -bool FillSendMenu( - not_null menu, - Fn type, - Fn silent, - Fn schedule); - -void SetupSendMenuAndShortcuts( - not_null button, - Fn type, - Fn silent, - Fn schedule); diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp new file mode 100644 index 000000000..4add9f213 --- /dev/null +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp @@ -0,0 +1,111 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "chat_helpers/send_context_menu.h" + +#include "api/api_common.h" +#include "base/event_filter.h" +#include "core/shortcuts.h" +#include "lang/lang_keys.h" +#include "ui/widgets/popup_menu.h" + +#include + +FillMenuResult FillSendMenu( + not_null menu, + Fn type, + Fn silent, + Fn schedule) { + if (!silent && !schedule) { + return FillMenuResult::None; + } + const auto now = type(); + if (now == SendMenuType::Disabled + || (!silent && now == SendMenuType::SilentOnly)) { + return FillMenuResult::None; + } + + if (silent && now != SendMenuType::Reminder) { + menu->addAction(tr::lng_send_silent_message(tr::now), silent); + } + if (schedule && now != SendMenuType::SilentOnly) { + menu->addAction( + (now == SendMenuType::Reminder + ? tr::lng_reminder_message(tr::now) + : tr::lng_schedule_message(tr::now)), + schedule); + } + return FillMenuResult::Success; +} + +void SetupSendMenuAndShortcuts( + not_null button, + Fn type, + Fn silent, + Fn schedule) { + if (!silent && !schedule) { + return; + } + const auto menu = std::make_shared>(); + const auto showMenu = [=] { + *menu = base::make_unique_q(button); + const auto result = FillSendMenu(*menu, type, silent, schedule); + const auto success = (result == FillMenuResult::Success); + if (success) { + (*menu)->popup(QCursor::pos()); + } + return success; + }; + base::install_event_filter(button, [=](not_null e) { + if (e->type() == QEvent::ContextMenu && showMenu()) { + return base::EventFilterResult::Cancel; + } + return base::EventFilterResult::Continue; + }); + + Shortcuts::Requests( + ) | rpl::start_with_next([=](not_null request) { + using Command = Shortcuts::Command; + + const auto now = type(); + if (now == SendMenuType::Disabled + || (!silent && now == SendMenuType::SilentOnly)) { + return; + } + (silent + && (now != SendMenuType::Reminder) + && request->check(Command::SendSilentMessage) + && request->handle([=] { + silent(); + return true; + })) + || + (schedule + && (now != SendMenuType::SilentOnly) + && request->check(Command::ScheduleMessage) + && request->handle([=] { + schedule(); + return true; + })) + || + (request->check(Command::JustSendMessage) && request->handle([=] { + const auto post = [&](QEvent::Type type) { + QApplication::postEvent( + button, + new QMouseEvent( + type, + QPointF(0, 0), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier)); + }; + post(QEvent::MouseButtonPress); + post(QEvent::MouseButtonRelease); + return true; + })); + }, button->lifetime()); +} diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.h b/Telegram/SourceFiles/chat_helpers/send_context_menu.h new file mode 100644 index 000000000..cd221f1a3 --- /dev/null +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.h @@ -0,0 +1,39 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "ui/rp_widget.h" + +namespace Ui { +class PopupMenu; +} // namespace Ui + +enum class SendMenuType { + Disabled, + SilentOnly, + Scheduled, + ScheduledToUser, // For "Send when online". + Reminder, +}; + +enum class FillMenuResult { + Success, + None, +}; + +FillMenuResult FillSendMenu( + not_null menu, + Fn type, + Fn silent, + Fn schedule); + +void SetupSendMenuAndShortcuts( + not_null button, + Fn type, + Fn silent, + Fn schedule); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 29fcce2e5..92bb0b1b1 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_cloud_file.h" #include "data/data_changes.h" -#include "chat_helpers/message_field.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // FillSendMenu #include "chat_helpers/stickers_lottie.h" #include "ui/widgets/buttons.h" #include "ui/widgets/popup_menu.h" diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 0802ace53..92323c9ca 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -7,10 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "chat_helpers/tabbed_selector.h" -#include "chat_helpers/message_field.h" #include "chat_helpers/emoji_list_widget.h" #include "chat_helpers/stickers_list_widget.h" #include "chat_helpers/gifs_list_widget.h" +#include "chat_helpers/send_context_menu.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/shadow.h" diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 2f3ac4ee7..13df5ea95 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -69,6 +69,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/tabbed_section.h" #include "chat_helpers/bot_keyboard.h" #include "chat_helpers/message_field.h" +#include "chat_helpers/send_context_menu.h" #include "platform/platform_specific.h" #include "mtproto/mtproto_config.h" #include "lang/lang_keys.h" diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 1a4585ecd..140a06593 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/toast/toast.h" #include "ui/ui_utility.h" -#include "chat_helpers/message_field.h" +#include "chat_helpers/send_context_menu.h" #include "boxes/confirm_box.h" #include "boxes/sticker_set_box.h" #include "data/data_photo.h" diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index 075e8be29..1b27cdee2 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/widgets/popup_menu.h" #include "ui/wrap/padding_wrap.h" -#include "chat_helpers/message_field.h" +#include "chat_helpers/send_context_menu.h" #include "styles/style_info.h" #include "styles/style_layers.h" #include "styles/style_history.h" diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 8d0a2fdc6..850d89b05 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/history_drag_area.h" #include "history/history_item.h" -#include "chat_helpers/message_field.h" // SendMenuType. +#include "chat_helpers/send_context_menu.h" // SendMenuType. #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" #include "ui/layers/generic_box.h" diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 828f00e7d..6fb589b80 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "inline_bots/inline_results_widget.h" #include "api/api_common.h" -#include "chat_helpers/message_field.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // FillSendMenu #include "data/data_photo.h" #include "data/data_document.h" #include "data/data_channel.h" From 2ac425f35055c90cba8ae2bed041d38bcfdeb7ba Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 9 Aug 2020 14:50:32 +0300 Subject: [PATCH 025/142] Moved default send callbacks to separate functions. --- .../chat_helpers/gifs_list_widget.cpp | 14 ++----------- .../chat_helpers/send_context_menu.cpp | 21 +++++++++++++++++++ .../chat_helpers/send_context_menu.h | 10 +++++++++ .../chat_helpers/stickers_list_widget.cpp | 14 ++----------- .../inline_bots/inline_results_widget.cpp | 14 ++----------- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index f0971a362..471b273fa 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -31,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "window/window_session_controller.h" #include "history/view/history_view_cursor_state.h" -#include "history/view/history_view_schedule_box.h" #include "app.h" #include "storage/storage_account.h" // Account::writeSavedGifs #include "styles/style_chat_helpers.h" @@ -376,20 +375,11 @@ void GifsListWidget::fillContextMenu( const auto send = [=](Api::SendOptions options) { selectInlineResult(row, column, options, true); }; - const auto silent = [=] { send({ .silent = true }); }; - const auto schedule = [=] { - Ui::show( - HistoryView::PrepareScheduleBox( - this, - type, - [=](Api::SendOptions options) { send(options); }), - Ui::LayerOption::KeepOther); - }; FillSendMenu( menu, [&] { return type; }, - silent, - schedule); + DefaultSilentCallback(send), + DefaultScheduleCallback(this, type, send)); [&] { const auto row = _selected / MatrixRowShift; diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp index 4add9f213..f0a60ddb0 100644 --- a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp @@ -9,12 +9,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_common.h" #include "base/event_filter.h" +#include "boxes/abstract_box.h" #include "core/shortcuts.h" +#include "history/view/history_view_schedule_box.h" #include "lang/lang_keys.h" #include "ui/widgets/popup_menu.h" #include +Fn DefaultSilentCallback(Fn send) { + return [=] { send({ .silent = true }); }; +} + +Fn DefaultScheduleCallback( + not_null parent, + SendMenuType type, + Fn send) { + const auto weak = Ui::MakeWeak(parent); + return [=] { + Ui::show( + HistoryView::PrepareScheduleBox( + weak, + type, + [=](Api::SendOptions options) { send(options); }), + Ui::LayerOption::KeepOther); + }; +} + FillMenuResult FillSendMenu( not_null menu, Fn type, diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.h b/Telegram/SourceFiles/chat_helpers/send_context_menu.h index cd221f1a3..382d5cafa 100644 --- a/Telegram/SourceFiles/chat_helpers/send_context_menu.h +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.h @@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" +namespace Api { +struct SendOptions; +} // namespace Api + namespace Ui { class PopupMenu; } // namespace Ui @@ -26,6 +30,12 @@ enum class FillMenuResult { None, }; +Fn DefaultSilentCallback(Fn send); +Fn DefaultScheduleCallback( + not_null parent, + SendMenuType type, + Fn send); + FillMenuResult FillSendMenu( not_null menu, Fn type, diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 92bb0b1b1..7fc2021cb 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -26,7 +26,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lottie/lottie_animation.h" #include "boxes/stickers_box.h" #include "inline_bots/inline_bot_result.h" -#include "history/view/history_view_schedule_box.h" #include "storage/storage_account.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -2073,20 +2072,11 @@ void StickersListWidget::fillContextMenu( .document = document, .options = options }); }; - const auto silent = [=] { send({ .silent = true }); }; - const auto schedule = [=] { - checkHideWithBox(Ui::show( - HistoryView::PrepareScheduleBox( - this, - type, - [=](Api::SendOptions options) { send(options); }), - Ui::LayerOption::KeepOther).data()); - }; FillSendMenu( menu, [&] { return type; }, - silent, - schedule); + DefaultSilentCallback(send), + DefaultScheduleCallback(this, type, send)); const auto toggleFavedSticker = [=] { document->session().api().toggleFavedSticker( diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 6fb589b80..157a5169e 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -34,7 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/scroll_area.h" #include "ui/widgets/labels.h" #include "history/view/history_view_cursor_state.h" -#include "history/view/history_view_schedule_box.h" #include "facades.h" #include "app.h" #include "styles/style_chat_helpers.h" @@ -312,20 +311,11 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { const auto send = [=](Api::SendOptions options) { selectInlineResult(row, column, options); }; - const auto silent = [=] { send({ .silent = true }); }; - const auto schedule = [=] { - Ui::show( - HistoryView::PrepareScheduleBox( - this, - type, - [=](Api::SendOptions options) { send(options); }), - Ui::LayerOption::KeepOther); - }; FillSendMenu( _menu, [&] { return type; }, - silent, - schedule); + DefaultSilentCallback(send), + DefaultScheduleCallback(this, type, send)); if (!_menu->actions().empty()) { _menu->popup(QCursor::pos()); From cf566586642f3d9c19f043da244e0da34aeb05fd Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 9 Aug 2020 17:13:24 +0300 Subject: [PATCH 026/142] Slightly refactored FieldAutocomplete. --- .../chat_helpers/field_autocomplete.cpp | 106 ++++++++++++++---- .../chat_helpers/field_autocomplete.h | 61 +++++++--- .../SourceFiles/history/history_widget.cpp | 38 +++++-- Telegram/SourceFiles/history/history_widget.h | 2 - 4 files changed, 155 insertions(+), 52 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index 1c9e792a5..847fb7135 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -45,8 +45,10 @@ FieldAutocomplete::FieldAutocomplete( , _scroll(this, st::mentionScroll) { _scroll->setGeometry(rect()); + using Inner = internal::FieldAutocompleteInner; + _inner = _scroll->setOwnedWidget( - object_ptr( + object_ptr( _controller, this, &_mrows, @@ -55,18 +57,41 @@ FieldAutocomplete::FieldAutocomplete( &_srows)); _inner->setGeometry(rect()); - connect(_inner, SIGNAL(mentionChosen(not_null,FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(not_null,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(stickerChosen(not_null,FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(not_null,FieldAutocomplete::ChooseMethod))); - connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int))); + _inner->scrollToRequested( + ) | rpl::start_with_next([=](Inner::ScrollTo data) { + _scroll->scrollToY(data.top, data.bottom); + }, lifetime()); _scroll->show(); _inner->show(); hide(); - connect(_scroll, SIGNAL(geometryChanged()), _inner, SLOT(onParentGeometryChanged())); + connect( + _scroll, + &Ui::ScrollArea::geometryChanged, + _inner, + &Inner::onParentGeometryChanged); +} + +auto FieldAutocomplete::mentionChosen() const +-> rpl::producer { + return _inner->mentionChosen(); +} + +auto FieldAutocomplete::hashtagChosen() const +-> rpl::producer { + return _inner->hashtagChosen(); +} + +auto FieldAutocomplete::botCommandChosen() const +-> rpl::producer { + return _inner->botCommandChosen(); +} + +auto FieldAutocomplete::stickerChosen() const +-> rpl::producer { + return _inner->stickerChosen(); } FieldAutocomplete::~FieldAutocomplete() = default; @@ -583,9 +608,10 @@ bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) { && ((key >= Qt::Key_1 && key <= Qt::Key_9) || key == Qt::Key_Q || key == Qt::Key_W)) { - bool handled = false; - emit moderateKeyActivate(key, &handled); - return handled; + + return _moderateKeyActivateCallback + ? _moderateKeyActivateCallback(key) + : false; } } } @@ -878,29 +904,37 @@ bool FieldAutocompleteInner::moveSel(int key) { bool FieldAutocompleteInner::chooseSelected(FieldAutocomplete::ChooseMethod method) const { if (!_srows->empty()) { if (_sel >= 0 && _sel < _srows->size()) { - emit stickerChosen((*_srows)[_sel].document, method); + _stickerChosen.fire({ (*_srows)[_sel].document, method }); return true; } } else if (!_mrows->empty()) { if (_sel >= 0 && _sel < _mrows->size()) { - emit mentionChosen(_mrows->at(_sel).user, method); + _mentionChosen.fire({ _mrows->at(_sel).user, method }); return true; } } else if (!_hrows->empty()) { if (_sel >= 0 && _sel < _hrows->size()) { - emit hashtagChosen('#' + _hrows->at(_sel), method); + _hashtagChosen.fire({ '#' + _hrows->at(_sel), method }); return true; } } else if (!_brows->empty()) { if (_sel >= 0 && _sel < _brows->size()) { const auto user = _brows->at(_sel).user; const auto command = _brows->at(_sel).command; - int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1); - if (botStatus == 0 || botStatus == 2 || _parent->filter().indexOf('@') > 0) { - emit botCommandChosen('/' + command->command + '@' + user->username, method); - } else { - emit botCommandChosen('/' + command->command, method); - } + const auto botStatus = _parent->chat() + ? _parent->chat()->botStatus + : ((_parent->channel() && _parent->channel()->isMegagroup()) + ? _parent->channel()->mgInfo->botStatus + : -1); + + const auto insertUsername = (botStatus == 0 + || botStatus == 2 + || _parent->filter().indexOf('@') > 0); + const auto commandString = QString("/%1%2") + .arg(command->command) + .arg(insertUsername ? ('@' + user->username) : QString()); + + _botCommandChosen.fire({ commandString, method }); return true; } } @@ -1000,10 +1034,15 @@ void FieldAutocompleteInner::setSel(int sel, bool scroll) { if (scroll && _sel >= 0) { if (_srows->empty()) { - emit mustScrollTo(_sel * st::mentionHeight, (_sel + 1) * st::mentionHeight); + _scrollToRequested.fire({ + _sel * st::mentionHeight, + (_sel + 1) * st::mentionHeight }); } else { int32 row = _sel / _stickersPerRow; - emit mustScrollTo(st::stickerPanPadding + row * st::stickerPanSize.height(), st::stickerPanPadding + (row + 1) * st::stickerPanSize.height()); + const auto padding = st::stickerPanPadding; + _scrollToRequested.fire({ + padding + row * st::stickerPanSize.height(), + padding + (row + 1) * st::stickerPanSize.height() }); } } } @@ -1131,4 +1170,29 @@ void FieldAutocompleteInner::showPreview() { } } +auto FieldAutocompleteInner::mentionChosen() const +-> rpl::producer { + return _mentionChosen.events(); +} + +auto FieldAutocompleteInner::hashtagChosen() const +-> rpl::producer { + return _hashtagChosen.events(); +} + +auto FieldAutocompleteInner::botCommandChosen() const +-> rpl::producer { + return _botCommandChosen.events(); +} + +auto FieldAutocompleteInner::stickerChosen() const +-> rpl::producer { + return _stickerChosen.events(); +} + +auto FieldAutocompleteInner::scrollToRequested() const +-> rpl::producer { + return _scrollToRequested.events(); +} + } // namespace internal diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h index 94a7578f4..5a0ea82b3 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h @@ -59,7 +59,6 @@ class FieldAutocompleteInner; } // namespace internal class FieldAutocomplete final : public Ui::RpWidget { - Q_OBJECT public: FieldAutocomplete( @@ -90,6 +89,23 @@ public: ByTab, ByClick, }; + struct MentionChosen { + not_null user; + ChooseMethod method; + }; + struct HashtagChosen { + QString hashtag; + ChooseMethod method; + }; + struct BotCommandChosen { + QString command; + ChooseMethod method; + }; + struct StickerChosen { + not_null sticker; + ChooseMethod method; + }; + bool chooseSelected(ChooseMethod method) const; bool stickersShown() const { @@ -102,15 +118,16 @@ public: return rect().contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); } + void setModerateKeyActivateCallback(Fn callback) { + _moderateKeyActivateCallback = std::move(callback); + } + void hideFast(); -signals: - void mentionChosen(not_null user, FieldAutocomplete::ChooseMethod method) const; - void hashtagChosen(QString hashtag, FieldAutocomplete::ChooseMethod method) const; - void botCommandChosen(QString command, FieldAutocomplete::ChooseMethod method) const; - void stickerChosen(not_null sticker, FieldAutocomplete::ChooseMethod method) const; - - void moderateKeyActivate(int key, bool *outHandled) const; + rpl::producer mentionChosen() const; + rpl::producer hashtagChosen() const; + rpl::producer botCommandChosen() const; + rpl::producer stickerChosen() const; public slots: void showAnimated(); @@ -160,11 +177,12 @@ private: QRect _boundings; bool _addInlineBots; - int32 _width, _height; bool _hiding = false; Ui::Animations::Simple _a_opacity; + Fn _moderateKeyActivateCallback; + friend class internal::FieldAutocompleteInner; }; @@ -174,9 +192,13 @@ namespace internal { class FieldAutocompleteInner final : public Ui::RpWidget , private base::Subscriber { - Q_OBJECT public: + struct ScrollTo { + int top; + int bottom; + }; + FieldAutocompleteInner( not_null controller, not_null parent, @@ -192,14 +214,13 @@ public: void setRecentInlineBotsInRows(int32 bots); void rowsUpdated(); -signals: - void mentionChosen(not_null user, FieldAutocomplete::ChooseMethod method) const; - void hashtagChosen(QString hashtag, FieldAutocomplete::ChooseMethod method) const; - void botCommandChosen(QString command, FieldAutocomplete::ChooseMethod method) const; - void stickerChosen(not_null sticker, FieldAutocomplete::ChooseMethod method) const; - void mustScrollTo(int scrollToTop, int scrollToBottom); + rpl::producer mentionChosen() const; + rpl::producer hashtagChosen() const; + rpl::producer + botCommandChosen() const; + rpl::producer stickerChosen() const; + rpl::producer scrollToRequested() const; -public slots: void onParentGeometryChanged(); private: @@ -242,6 +263,12 @@ private: bool _previewShown = false; + rpl::event_stream _mentionChosen; + rpl::event_stream _hashtagChosen; + rpl::event_stream _botCommandChosen; + rpl::event_stream _stickerChosen; + rpl::event_stream _scrollToRequested; + base::Timer _previewTimer; }; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 13df5ea95..07447e41f 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -382,15 +382,33 @@ HistoryWidget::HistoryWidget( InitMessageField(controller, _field); _fieldAutocomplete->hide(); - connect(_fieldAutocomplete, &FieldAutocomplete::mentionChosen, this, [=](not_null user) { - onMentionInsert(user); + + _fieldAutocomplete->mentionChosen( + ) | rpl::start_with_next([=](FieldAutocomplete::MentionChosen data) { + onMentionInsert(data.user); + }, lifetime()); + + _fieldAutocomplete->hashtagChosen( + ) | rpl::start_with_next([=](FieldAutocomplete::HashtagChosen data) { + onHashtagOrBotCommandInsert(data.hashtag, data.method); + }, lifetime()); + + _fieldAutocomplete->botCommandChosen( + ) | rpl::start_with_next([=](FieldAutocomplete::BotCommandChosen data) { + onHashtagOrBotCommandInsert(data.command, data.method); + }, lifetime()); + + _fieldAutocomplete->stickerChosen( + ) | rpl::start_with_next([=](FieldAutocomplete::StickerChosen data) { + sendExistingDocument(data.sticker, Api::SendOptions()); + }, lifetime()); + + _fieldAutocomplete->setModerateKeyActivateCallback([=](int key) { + return _keyboard->isHidden() + ? false + : _keyboard->moderateKeyActivate(key); }); - connect(_fieldAutocomplete, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod))); - connect(_fieldAutocomplete, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod))); - connect(_fieldAutocomplete, &FieldAutocomplete::stickerChosen, this, [=](not_null document) { - sendExistingDocument(document, Api::SendOptions()); - }); - connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*))); + if (_supportAutocomplete) { supportInitAutocomplete(); } @@ -3921,10 +3939,6 @@ void HistoryWidget::onMembersDropdownShow() { _membersDropdown->otherEnter(); } -void HistoryWidget::onModerateKeyActivate(int index, bool *outHandled) { - *outHandled = _keyboard->isHidden() ? false : _keyboard->moderateKeyActivate(index); -} - bool HistoryWidget::pushTabbedSelectorToThirdSection( not_null peer, const Window::SectionShow ¶ms) { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index c73ec6cb7..a2d4fd2b9 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -325,8 +325,6 @@ private slots: void onInlineBotCancel(); void onMembersDropdownShow(); - void onModerateKeyActivate(int index, bool *outHandled); - private: using TabbedPanel = ChatHelpers::TabbedPanel; using TabbedSelector = ChatHelpers::TabbedSelector; From 1eea07d88a9174e489fb907375f9052b0950560d Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 9 Aug 2020 17:52:51 +0300 Subject: [PATCH 027/142] Added ability to schedule and send silently stickers from autocomplete. --- .../chat_helpers/field_autocomplete.cpp | 57 +++++++++++++++---- .../chat_helpers/field_autocomplete.h | 9 +++ .../SourceFiles/history/history_widget.cpp | 2 +- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index 847fb7135..fe47fe47d 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_session.h" #include "data/stickers/data_stickers.h" +#include "chat_helpers/send_context_menu.h" // FillSendMenu #include "chat_helpers/stickers_lottie.h" #include "mainwindow.h" #include "apiwrap.h" @@ -24,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "core/core_settings.h" #include "lottie/lottie_single_player.h" +#include "ui/widgets/popup_menu.h" #include "ui/widgets/scroll_area.h" #include "ui/image/image.h" #include "ui/ui_utility.h" @@ -901,26 +903,38 @@ bool FieldAutocompleteInner::moveSel(int key) { return true; } -bool FieldAutocompleteInner::chooseSelected(FieldAutocomplete::ChooseMethod method) const { +bool FieldAutocompleteInner::chooseSelected( + FieldAutocomplete::ChooseMethod method) const { + return chooseAtIndex(method, _sel); +} + +bool FieldAutocompleteInner::chooseAtIndex( + FieldAutocomplete::ChooseMethod method, + int index, + Api::SendOptions options) const { + if (index < 0) { + return false; + } if (!_srows->empty()) { - if (_sel >= 0 && _sel < _srows->size()) { - _stickerChosen.fire({ (*_srows)[_sel].document, method }); + if (index < _srows->size()) { + const auto document = (*_srows)[index].document; + _stickerChosen.fire({ document, options, method }); return true; } } else if (!_mrows->empty()) { - if (_sel >= 0 && _sel < _mrows->size()) { - _mentionChosen.fire({ _mrows->at(_sel).user, method }); + if (index < _mrows->size()) { + _mentionChosen.fire({ _mrows->at(index).user, method }); return true; } } else if (!_hrows->empty()) { - if (_sel >= 0 && _sel < _hrows->size()) { - _hashtagChosen.fire({ '#' + _hrows->at(_sel), method }); + if (index < _hrows->size()) { + _hashtagChosen.fire({ '#' + _hrows->at(index), method }); return true; } } else if (!_brows->empty()) { - if (_sel >= 0 && _sel < _brows->size()) { - const auto user = _brows->at(_sel).user; - const auto command = _brows->at(_sel).command; + if (index < _brows->size()) { + const auto user = _brows->at(index).user; + const auto command = _brows->at(index).command; const auto botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) @@ -1003,6 +1017,29 @@ void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) { chooseSelected(FieldAutocomplete::ChooseMethod::ByClick); } +void FieldAutocompleteInner::contextMenuEvent(QContextMenuEvent *e) { + if (_sel < 0 || _srows->empty() || _down >= 0) { + return; + } + const auto index = _sel; + const auto type = SendMenuType::Scheduled; + const auto method = FieldAutocomplete::ChooseMethod::ByClick; + _menu = base::make_unique_q(this); + + const auto send = [=](Api::SendOptions options) { + chooseAtIndex(method, index, options); + }; + FillSendMenu( + _menu, + [&] { return type; }, + DefaultSilentCallback(send), + DefaultScheduleCallback(this, type, send)); + + if (!_menu->actions().empty()) { + _menu->popup(QCursor::pos()); + } +} + void FieldAutocompleteInner::enterEventHook(QEvent *e) { setMouseTracking(true); } diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h index 5a0ea82b3..e7d3f3205 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h @@ -7,12 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "api/api_common.h" #include "ui/effects/animations.h" #include "ui/rp_widget.h" #include "base/timer.h" #include "base/object_ptr.h" namespace Ui { +class PopupMenu; class ScrollArea; } // namespace Ui @@ -103,6 +105,7 @@ public: }; struct StickerChosen { not_null sticker; + Api::SendOptions options; ChooseMethod method; }; @@ -210,6 +213,10 @@ public: void clearSel(bool hidden = false); bool moveSel(int key); bool chooseSelected(FieldAutocomplete::ChooseMethod method) const; + bool chooseAtIndex( + FieldAutocomplete::ChooseMethod method, + int index, + Api::SendOptions options = Api::SendOptions()) const; void setRecentInlineBotsInRows(int32 bots); void rowsUpdated(); @@ -233,6 +240,7 @@ private: void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; + void contextMenuEvent(QContextMenuEvent *e) override; void updateSelectedRow(); void setSel(int sel, bool scroll = false); @@ -252,6 +260,7 @@ private: const not_null _srows; rpl::lifetime _stickersLifetime; std::weak_ptr _lottieRenderer; + base::unique_qptr _menu; int _stickersPerRow = 1; int _recentInlineBotsInRows = 0; int _sel = -1; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 07447e41f..81bad4bbe 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -400,7 +400,7 @@ HistoryWidget::HistoryWidget( _fieldAutocomplete->stickerChosen( ) | rpl::start_with_next([=](FieldAutocomplete::StickerChosen data) { - sendExistingDocument(data.sticker, Api::SendOptions()); + sendExistingDocument(data.sticker, data.options); }, lifetime()); _fieldAutocomplete->setModerateKeyActivateCallback([=](int key) { From af9440db382fca8150221f80376eea857d5086ab Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 9 Aug 2020 19:06:18 +0300 Subject: [PATCH 028/142] Slightly refactored InlineBots::Layout::Widget. --- .../inline_bots/inline_results_widget.cpp | 34 +++++++++++-------- .../inline_bots/inline_results_widget.h | 27 ++++++--------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 157a5169e..73cdca3df 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -159,6 +159,10 @@ bool Inner::tooltipWindowActive() const { return Ui::AppInFocus() && Ui::InFocusChain(window()); } +rpl::producer<> Inner::inlineRowsCleared() const { + return _inlineRowsCleared.events(); +} + Inner::~Inner() = default; void Inner::paintEvent(QPaintEvent *e) { @@ -517,7 +521,7 @@ int Inner::refreshInlineRows(PeerData *queryPeer, UserData *bot, const CacheEntr clearInlineRows(true); deleteUnusedInlineLayouts(); } - emit emptyInlineRows(); + _inlineRowsCleared.fire({}); return 0; } @@ -788,7 +792,8 @@ Widget::Widget( , _api(&_controller->session().mtp()) , _contentMaxHeight(st::emojiPanMaxHeight) , _contentHeight(_contentMaxHeight) -, _scroll(this, st::inlineBotsScroll) { +, _scroll(this, st::inlineBotsScroll) +, _inlineRequestTimer([=] { onInlineRequest(); }) { resize(QRect(0, 0, st::emojiPanWidth, _contentHeight).marginsAdded(innerPadding()).size()); _width = width(); _height = height(); @@ -800,13 +805,17 @@ Widget::Widget( _inner->moveToLeft(0, 0, _scroll->width()); - connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); + connect( + _scroll, + &Ui::ScrollArea::scrolled, + this, + &InlineBots::Layout::Widget::onScroll); - connect(_inner, SIGNAL(emptyInlineRows()), this, SLOT(onEmptyInlineRows())); - - // inline bots - _inlineRequestTimer.setSingleShot(true); - connect(&_inlineRequestTimer, SIGNAL(timeout()), this, SLOT(onInlineRequest())); + _inner->inlineRowsCleared( + ) | rpl::start_with_next([=] { + hideAnimated(); + _inner->clearInlineRowsPanel(); + }, lifetime()); macWindowDeactivateEvents( ) | rpl::filter([=] { @@ -1149,12 +1158,12 @@ void Widget::queryInlineBot(UserData *bot, PeerData *peer, QString query) { _requesting.fire(false); } if (_inlineCache.find(query) != _inlineCache.cend()) { - _inlineRequestTimer.stop(); + _inlineRequestTimer.cancel(); _inlineQuery = _inlineNextQuery = query; showInlineRows(true); } else { _inlineNextQuery = query; - _inlineRequestTimer.start(internal::kInlineBotRequestDelay); + _inlineRequestTimer.callOnce(internal::kInlineBotRequestDelay); } } } @@ -1188,11 +1197,6 @@ void Widget::onInlineRequest() { }).handleAllErrors().send(); } -void Widget::onEmptyInlineRows() { - hideAnimated(); - _inner->clearInlineRowsPanel(); -} - bool Widget::refreshInlineRows(int *added) { auto it = _inlineCache.find(_inlineQuery); const internal::CacheEntry *entry = nullptr; diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.h b/Telegram/SourceFiles/inline_bots/inline_results_widget.h index bec1ccb31..e7369759e 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.h +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.h @@ -16,8 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" #include "inline_bots/inline_bot_layout_item.h" -#include - namespace Api { struct SendOptions; } // namespace Api @@ -62,7 +60,6 @@ class Inner , public Ui::AbstractTooltipShower , public Context , private base::Subscriber { - Q_OBJECT public: Inner(QWidget *parent, not_null controller); @@ -94,6 +91,8 @@ public: QPoint tooltipPos() const override; bool tooltipWindowActive() const override; + rpl::producer<> inlineRowsCleared() const; + ~Inner(); protected: @@ -110,12 +109,6 @@ protected: void enterFromChildEvent(QEvent *e, QWidget *child) override; void contextMenuEvent(QContextMenuEvent *e) override; -private slots: - void onSwitchPm(); - -signals: - void emptyInlineRows(); - private: static constexpr bool kRefreshIconsScrollAnimation = true; static constexpr bool kRefreshIconsNoAnimation = false; @@ -125,6 +118,8 @@ private: QVector items; }; + void onSwitchPm(); + void updateSelected(); void checkRestrictedPeer(); bool isRestrictedView(); @@ -171,6 +166,8 @@ private: std::map> _inlineLayouts; + rpl::event_stream<> _inlineRowsCleared; + int _selected = -1; int _pressed = -1; QPoint _lastMousePos; @@ -185,7 +182,6 @@ private: } // namespace internal class Widget : public Ui::RpWidget { - Q_OBJECT public: Widget(QWidget *parent, not_null controller); @@ -218,18 +214,15 @@ public: protected: void paintEvent(QPaintEvent *e) override; -private slots: - void onScroll(); - - void onInlineRequest(); - void onEmptyInlineRows(); - private: void moveByBottom(); void paintContent(Painter &p); style::margins innerPadding() const; + void onScroll(); + void onInlineRequest(); + // Rounded rect which has shadow around it. QRect innerRect() const; @@ -283,7 +276,7 @@ private: QPointer _inner; std::map> _inlineCache; - QTimer _inlineRequestTimer; + base::Timer _inlineRequestTimer; UserData *_inlineBot = nullptr; PeerData *_inlineQueryPeer = nullptr; From 14cda49db264c01ad0a614a79cc10c3f2f75ed7d Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 10 Aug 2020 15:22:54 +0300 Subject: [PATCH 029/142] Moved code for send context menu to namespace. --- .../SourceFiles/boxes/create_poll_box.cpp | 8 +++-- Telegram/SourceFiles/boxes/send_files_box.cpp | 6 ++-- Telegram/SourceFiles/boxes/send_files_box.h | 8 +++-- Telegram/SourceFiles/boxes/share_box.cpp | 10 +++---- Telegram/SourceFiles/boxes/share_box.h | 6 ++-- .../chat_helpers/field_autocomplete.cpp | 10 +++---- .../chat_helpers/gifs_list_widget.cpp | 10 +++---- .../chat_helpers/gifs_list_widget.h | 6 ++-- .../chat_helpers/send_context_menu.cpp | 30 +++++++++++-------- .../chat_helpers/send_context_menu.h | 14 +++++---- .../chat_helpers/stickers_list_widget.cpp | 10 +++---- .../chat_helpers/stickers_list_widget.h | 2 +- .../chat_helpers/tabbed_selector.cpp | 2 +- .../chat_helpers/tabbed_selector.h | 10 ++++--- .../SourceFiles/history/history_widget.cpp | 16 +++++----- Telegram/SourceFiles/history/history_widget.h | 9 ++++-- .../view/history_view_context_menu.cpp | 8 ++--- .../view/history_view_schedule_box.cpp | 10 +++---- .../history/view/history_view_schedule_box.h | 8 +++-- .../view/history_view_scheduled_section.cpp | 12 ++++---- .../view/history_view_scheduled_section.h | 7 +++-- .../inline_bots/inline_results_widget.cpp | 10 +++---- 22 files changed, 119 insertions(+), 93 deletions(-) diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 37d66216a..1f5137ebf 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -1087,7 +1087,7 @@ object_ptr CreatePollBox::setupContent() { Ui::show( HistoryView::PrepareScheduleBox( this, - SendMenuType::Scheduled, + SendMenu::Type::Scheduled, send), Ui::LayerOption::KeepOther); }; @@ -1108,9 +1108,11 @@ object_ptr CreatePollBox::setupContent() { if (_sendType == Api::SendType::Normal) { const auto sendMenuType = [=] { collectError(); - return *error ? SendMenuType::Disabled : SendMenuType::Scheduled; + return *error + ? SendMenu::Type::Disabled + : SendMenu::Type::Scheduled; }; - SetupSendMenuAndShortcuts( + SendMenu::SetupMenuAndShortcuts( submit.data(), sendMenuType, sendSilent, diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 443d77d7e..ab8c9d721 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -1667,7 +1667,7 @@ SendFilesBox::SendFilesBox( CompressConfirm compressed, SendLimit limit, Api::SendType sendType, - SendMenuType sendMenuType) + SendMenu::Type sendMenuType) : _controller(controller) , _sendType(sendType) , _list(std::move(list)) @@ -1837,7 +1837,7 @@ void SendFilesBox::setupShadows( void SendFilesBox::prepare() { _send = addButton(tr::lng_send_button(), [=] { send({}); }); if (_sendType == Api::SendType::Normal) { - SetupSendMenuAndShortcuts( + SendMenu::SetupMenuAndShortcuts( _send, [=] { return _sendMenuType; }, [=] { sendSilent(); }, @@ -2418,7 +2418,7 @@ void SendFilesBox::sendSilent() { void SendFilesBox::sendScheduled() { const auto type = (_sendType == Api::SendType::ScheduledToUser) - ? SendMenuType::ScheduledToUser + ? SendMenu::Type::ScheduledToUser : _sendMenuType; const auto callback = [=](Api::SendOptions options) { send(options); }; Ui::show( diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 84fe80ad8..e7b013071 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -40,7 +40,9 @@ namespace Window { class SessionController; } // namespace Window -enum class SendMenuType; +namespace SendMenu { +enum class Type; +} // namespace SendMenu enum class SendFilesWay { Album, @@ -62,7 +64,7 @@ public: CompressConfirm compressed, SendLimit limit, Api::SendType sendType, - SendMenuType sendMenuType); + SendMenu::Type sendMenuType); void setConfirmedCallback( Fnselected(); return ranges::all_of(selected, HistoryView::CanScheduleUntilOnline) - ? SendMenuType::ScheduledToUser + ? SendMenu::Type::ScheduledToUser : (selected.size() == 1 && selected.front()->isSelf()) - ? SendMenuType::Reminder - : SendMenuType::Scheduled; + ? SendMenu::Type::Reminder + : SendMenu::Type::Scheduled; } void ShareBox::createButtons() { @@ -424,7 +424,7 @@ void ShareBox::createButtons() { const auto send = addButton(tr::lng_share_confirm(), [=] { submit({}); }); - SetupSendMenuAndShortcuts( + SendMenu::SetupMenuAndShortcuts( send, [=] { return sendMenuType(); }, [=] { submitSilent(); }, diff --git a/Telegram/SourceFiles/boxes/share_box.h b/Telegram/SourceFiles/boxes/share_box.h index 605b68f63..67e19bff6 100644 --- a/Telegram/SourceFiles/boxes/share_box.h +++ b/Telegram/SourceFiles/boxes/share_box.h @@ -14,7 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/round_checkbox.h" #include "mtproto/sender.h" -enum class SendMenuType; +namespace SendMenu { +enum class Type; +} // namespace SendMenu namespace Window { class SessionNavigation; @@ -82,7 +84,7 @@ private: void copyLink(); bool searchByUsername(bool useCache = false); - SendMenuType sendMenuType() const; + SendMenu::Type sendMenuType() const; void scrollTo(Ui::ScrollToRequest request); void needSearchByUsername(); diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index fe47fe47d..a290af8cc 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_session.h" #include "data/stickers/data_stickers.h" -#include "chat_helpers/send_context_menu.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu #include "chat_helpers/stickers_lottie.h" #include "mainwindow.h" #include "apiwrap.h" @@ -1022,18 +1022,18 @@ void FieldAutocompleteInner::contextMenuEvent(QContextMenuEvent *e) { return; } const auto index = _sel; - const auto type = SendMenuType::Scheduled; + const auto type = SendMenu::Type::Scheduled; const auto method = FieldAutocomplete::ChooseMethod::ByClick; _menu = base::make_unique_q(this); const auto send = [=](Api::SendOptions options) { chooseAtIndex(method, index, options); }; - FillSendMenu( + SendMenu::FillSendMenu( _menu, [&] { return type; }, - DefaultSilentCallback(send), - DefaultScheduleCallback(this, type, send)); + SendMenu::DefaultSilentCallback(send), + SendMenu::DefaultScheduleCallback(this, type, send)); if (!_menu->actions().empty()) { _menu->popup(QCursor::pos()); diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 471b273fa..1fe231f52 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "data/stickers/data_stickers.h" -#include "chat_helpers/send_context_menu.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/popup_menu.h" @@ -365,7 +365,7 @@ void GifsListWidget::mousePressEvent(QMouseEvent *e) { void GifsListWidget::fillContextMenu( not_null menu, - SendMenuType type) { + SendMenu::Type type) { if (_selected < 0 || _pressed >= 0) { return; } @@ -375,11 +375,11 @@ void GifsListWidget::fillContextMenu( const auto send = [=](Api::SendOptions options) { selectInlineResult(row, column, options, true); }; - FillSendMenu( + SendMenu::FillSendMenu( menu, [&] { return type; }, - DefaultSilentCallback(send), - DefaultScheduleCallback(this, type, send)); + SendMenu::DefaultSilentCallback(send), + SendMenu::DefaultScheduleCallback(this, type, send)); [&] { const auto row = _selected / MatrixRowShift; diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 4a78c147a..f1235213f 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -34,7 +34,9 @@ namespace Window { class SessionController; } // namespace Window -enum class SendMenuType; +namespace SendMenu { +enum class Type; +} // namespace SendMenu namespace ChatHelpers { @@ -77,7 +79,7 @@ public: void fillContextMenu( not_null menu, - SendMenuType type) override; + SendMenu::Type type) override; ~GifsListWidget(); diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp index f0a60ddb0..0f5666dd9 100644 --- a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp @@ -17,13 +17,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include +namespace SendMenu { + Fn DefaultSilentCallback(Fn send) { return [=] { send({ .silent = true }); }; } Fn DefaultScheduleCallback( not_null parent, - SendMenuType type, + Type type, Fn send) { const auto weak = Ui::MakeWeak(parent); return [=] { @@ -38,24 +40,24 @@ Fn DefaultScheduleCallback( FillMenuResult FillSendMenu( not_null menu, - Fn type, + Fn type, Fn silent, Fn schedule) { if (!silent && !schedule) { return FillMenuResult::None; } const auto now = type(); - if (now == SendMenuType::Disabled - || (!silent && now == SendMenuType::SilentOnly)) { + if (now == Type::Disabled + || (!silent && now == Type::SilentOnly)) { return FillMenuResult::None; } - if (silent && now != SendMenuType::Reminder) { + if (silent && now != Type::Reminder) { menu->addAction(tr::lng_send_silent_message(tr::now), silent); } - if (schedule && now != SendMenuType::SilentOnly) { + if (schedule && now != Type::SilentOnly) { menu->addAction( - (now == SendMenuType::Reminder + (now == Type::Reminder ? tr::lng_reminder_message(tr::now) : tr::lng_schedule_message(tr::now)), schedule); @@ -63,9 +65,9 @@ FillMenuResult FillSendMenu( return FillMenuResult::Success; } -void SetupSendMenuAndShortcuts( +void SetupMenuAndShortcuts( not_null button, - Fn type, + Fn type, Fn silent, Fn schedule) { if (!silent && !schedule) { @@ -93,12 +95,12 @@ void SetupSendMenuAndShortcuts( using Command = Shortcuts::Command; const auto now = type(); - if (now == SendMenuType::Disabled - || (!silent && now == SendMenuType::SilentOnly)) { + if (now == Type::Disabled + || (!silent && now == Type::SilentOnly)) { return; } (silent - && (now != SendMenuType::Reminder) + && (now != Type::Reminder) && request->check(Command::SendSilentMessage) && request->handle([=] { silent(); @@ -106,7 +108,7 @@ void SetupSendMenuAndShortcuts( })) || (schedule - && (now != SendMenuType::SilentOnly) + && (now != Type::SilentOnly) && request->check(Command::ScheduleMessage) && request->handle([=] { schedule(); @@ -130,3 +132,5 @@ void SetupSendMenuAndShortcuts( })); }, button->lifetime()); } + +} // namespace SendMenu diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.h b/Telegram/SourceFiles/chat_helpers/send_context_menu.h index 382d5cafa..ec810545e 100644 --- a/Telegram/SourceFiles/chat_helpers/send_context_menu.h +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.h @@ -17,7 +17,9 @@ namespace Ui { class PopupMenu; } // namespace Ui -enum class SendMenuType { +namespace SendMenu { + +enum class Type { Disabled, SilentOnly, Scheduled, @@ -33,17 +35,19 @@ enum class FillMenuResult { Fn DefaultSilentCallback(Fn send); Fn DefaultScheduleCallback( not_null parent, - SendMenuType type, + Type type, Fn send); FillMenuResult FillSendMenu( not_null menu, - Fn type, + Fn type, Fn silent, Fn schedule); -void SetupSendMenuAndShortcuts( +void SetupMenuAndShortcuts( not_null button, - Fn type, + Fn type, Fn silent, Fn schedule); + +} // namespace SendMenu diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 7fc2021cb..6015a7ff5 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_cloud_file.h" #include "data/data_changes.h" -#include "chat_helpers/send_context_menu.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu #include "chat_helpers/stickers_lottie.h" #include "ui/widgets/buttons.h" #include "ui/widgets/popup_menu.h" @@ -2055,7 +2055,7 @@ void StickersListWidget::showStickerSetBox(not_null document) { void StickersListWidget::fillContextMenu( not_null menu, - SendMenuType type) { + SendMenu::Type type) { auto selected = _selected; auto &sets = shownSets(); if (!selected || _pressed) { @@ -2072,11 +2072,11 @@ void StickersListWidget::fillContextMenu( .document = document, .options = options }); }; - FillSendMenu( + SendMenu::FillSendMenu( menu, [&] { return type; }, - DefaultSilentCallback(send), - DefaultScheduleCallback(this, type, send)); + SendMenu::DefaultSilentCallback(send), + SendMenu::DefaultScheduleCallback(this, type, send)); const auto toggleFavedSticker = [=] { document->session().api().toggleFavedSticker( diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index a0e6bf21e..d9d6378cf 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -85,7 +85,7 @@ public: void fillContextMenu( not_null menu, - SendMenuType type) override; + SendMenu::Type type) override; ~StickersListWidget(); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 92323c9ca..b60304b46 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -880,7 +880,7 @@ void TabbedSelector::contextMenuEvent(QContextMenuEvent *e) { _menu = base::make_unique_q(this); const auto type = _sendMenuType ? _sendMenuType() - : SendMenuType::Disabled; + : SendMenu::Type::Disabled; currentTab()->widget()->fillContextMenu(_menu, type); if (!_menu->actions().empty()) { diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index 4b9e61987..2c1fa9f96 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -34,7 +34,9 @@ namespace Window { class SessionController; } // namespace Window -enum class SendMenuType; +namespace SendMenu { +enum class Type; +} // namespace SendMenu namespace ChatHelpers { @@ -111,7 +113,7 @@ public: _beforeHidingCallback = std::move(callback); } - void setSendMenuType(Fn callback) { + void setSendMenuType(Fn callback) { _sendMenuType = std::move(callback); } @@ -230,7 +232,7 @@ private: Fn _afterShownCallback; Fn _beforeHidingCallback; - Fn _sendMenuType; + Fn _sendMenuType; rpl::event_stream<> _showRequests; rpl::event_stream<> _slideFinished; @@ -266,7 +268,7 @@ public: } virtual void fillContextMenu( not_null menu, - SendMenuType type) { + SendMenu::Type type) { } rpl::producer scrollToRequests() const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 81bad4bbe..fb1463234 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -308,7 +308,7 @@ HistoryWidget::HistoryWidget( _fieldBarCancel->addClickHandler([=] { cancelFieldAreaState(); }); _send->addClickHandler([=] { sendButtonClicked(); }); - SetupSendMenuAndShortcuts( + SendMenu::SetupMenuAndShortcuts( _send, [=] { return sendButtonMenuType(); }, [=] { sendSilent(); }, @@ -3169,14 +3169,14 @@ void HistoryWidget::sendScheduled() { Ui::LayerOption::KeepOther); } -SendMenuType HistoryWidget::sendMenuType() const { +SendMenu::Type HistoryWidget::sendMenuType() const { return !_peer - ? SendMenuType::Disabled + ? SendMenu::Type::Disabled : _peer->isSelf() - ? SendMenuType::Reminder + ? SendMenu::Type::Reminder : HistoryView::CanScheduleUntilOnline(_peer) - ? SendMenuType::ScheduledToUser - : SendMenuType::Scheduled; + ? SendMenu::Type::ScheduledToUser + : SendMenu::Type::Scheduled; } auto HistoryWidget::computeSendButtonType() const { @@ -3192,10 +3192,10 @@ auto HistoryWidget::computeSendButtonType() const { return Type::Send; } -SendMenuType HistoryWidget::sendButtonMenuType() const { +SendMenu::Type HistoryWidget::sendButtonMenuType() const { return (computeSendButtonType() == Ui::SendButton::Type::Send) ? sendMenuType() - : SendMenuType::Disabled; + : SendMenu::Type::Disabled; } void HistoryWidget::unblockUser() { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index a2d4fd2b9..e945bf72b 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -26,7 +26,10 @@ struct SendingAlbum; enum class SendMediaType; enum class CompressConfirm; class MessageLinksParser; -enum class SendMenuType; + +namespace SendMenu { +enum class Type; +} // namespace SendMenu namespace Api { struct SendOptions; @@ -371,8 +374,8 @@ private: void sendWithModifiers(Qt::KeyboardModifiers modifiers); void sendSilent(); void sendScheduled(); - [[nodiscard]] SendMenuType sendMenuType() const; - [[nodiscard]] SendMenuType sendButtonMenuType() const; + [[nodiscard]] SendMenu::Type sendMenuType() const; + [[nodiscard]] SendMenu::Type sendButtonMenuType() const; void handlePendingHistoryUpdate(); void fullPeerUpdated(PeerData *peer); void toggleTabbedSelectorMode(); diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 140a06593..14c2fba92 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -435,12 +435,12 @@ bool AddRescheduleMessageAction( const auto peer = item->history()->peer; const auto sendMenuType = !peer - ? SendMenuType::Disabled + ? SendMenu::Type::Disabled : peer->isSelf() - ? SendMenuType::Reminder + ? SendMenu::Type::Reminder : HistoryView::CanScheduleUntilOnline(peer) - ? SendMenuType::ScheduledToUser - : SendMenuType::Scheduled; + ? SendMenu::Type::ScheduledToUser + : SendMenu::Type::Scheduled; using S = Data::ScheduledMessages; const auto date = (item->date() == S::kScheduledUntilOnlineTimestamp) diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index 1b27cdee2..73960991b 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -603,10 +603,10 @@ bool CanScheduleUntilOnline(not_null peer) { void ScheduleBox( not_null box, - SendMenuType type, + SendMenu::Type type, Fn done, TimeId time) { - box->setTitle((type == SendMenuType::Reminder) + box->setTitle((type == SendMenu::Type::Reminder) ? tr::lng_remind_title() : tr::lng_schedule_title()); box->setWidth(st::boxWideWidth); @@ -742,14 +742,14 @@ void ScheduleBox( const auto submit = box->addButton(tr::lng_schedule_button(), [=] { save(false); }); - SetupSendMenuAndShortcuts( + SendMenu::SetupMenuAndShortcuts( submit.data(), - [=] { return SendMenuType::SilentOnly; }, + [=] { return SendMenu::Type::SilentOnly; }, [=] { save(true); }, nullptr); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); - if (type == SendMenuType::ScheduledToUser) { + if (type == SendMenu::Type::ScheduledToUser) { const auto sendUntilOnline = box->addTopButton(st::infoTopBarMenu); FillSendUntilOnlineMenu( sendUntilOnline.data(), diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.h b/Telegram/SourceFiles/history/view/history_view_schedule_box.h index 772507639..da640faaa 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.h +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.h @@ -13,7 +13,9 @@ namespace Api { struct SendOptions; } // namespace Api -enum class SendMenuType; +namespace SendMenu { +enum class Type; +} // namespace SendMenu namespace HistoryView { @@ -21,14 +23,14 @@ namespace HistoryView { [[nodiscard]] bool CanScheduleUntilOnline(not_null peer); void ScheduleBox( not_null box, - SendMenuType type, + SendMenu::Type type, Fn done, TimeId time); template [[nodiscard]] object_ptr PrepareScheduleBox( Guard &&guard, - SendMenuType type, + SendMenu::Type type, Submit &&submit, TimeId scheduleTime = DefaultScheduleTime()) { return Box( diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 850d89b05..d922e7bac 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/history_drag_area.h" #include "history/history_item.h" -#include "chat_helpers/send_context_menu.h" // SendMenuType. +#include "chat_helpers/send_context_menu.h" // SendMenu::Type. #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" #include "ui/layers/generic_box.h" @@ -371,7 +371,7 @@ bool ScheduledWidget::confirmSendingFiles( CanScheduleUntilOnline(_history->peer) ? Api::SendType::ScheduledToUser : Api::SendType::Scheduled, - SendMenuType::Disabled); + SendMenu::Type::Disabled); //_field->setTextWithTags({}); box->setConfirmedCallback(crl::guard(this, [=]( @@ -745,12 +745,12 @@ void ScheduledWidget::sendInlineResult( _composeControls->focus(); } -SendMenuType ScheduledWidget::sendMenuType() const { +SendMenu::Type ScheduledWidget::sendMenuType() const { return _history->peer->isSelf() - ? SendMenuType::Reminder + ? SendMenu::Type::Reminder : HistoryView::CanScheduleUntilOnline(_history->peer) - ? SendMenuType::ScheduledToUser - : SendMenuType::Scheduled; + ? SendMenu::Type::ScheduledToUser + : SendMenu::Type::Scheduled; } void ScheduledWidget::setupScrollDownButton() { diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h index 57353c9c8..3429d2a6b 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h @@ -16,7 +16,10 @@ class History; enum class CompressConfirm; enum class SendMediaType; struct SendingAlbum; -enum class SendMenuType; + +namespace SendMenu { +enum class Type; +} // namespace SendMenu namespace Api { struct SendOptions; @@ -149,7 +152,7 @@ private: mtpRequestId *const saveEditMsgRequestId); void highlightSingleNewMessage(const Data::MessagesSlice &slice); void chooseAttach(); - [[nodiscard]] SendMenuType sendMenuType() const; + [[nodiscard]] SendMenu::Type sendMenuType() const; void uploadFile(const QByteArray &fileContent, SendMediaType type); bool confirmSendingFiles( diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 73cdca3df..335ca6cd5 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "inline_bots/inline_results_widget.h" #include "api/api_common.h" -#include "chat_helpers/send_context_menu.h" // FillSendMenu +#include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu #include "data/data_photo.h" #include "data/data_document.h" #include "data/data_channel.h" @@ -308,18 +308,18 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { } const auto row = _selected / MatrixRowShift; const auto column = _selected % MatrixRowShift; - const auto type = SendMenuType::Scheduled; + const auto type = SendMenu::Type::Scheduled; _menu = base::make_unique_q(this); const auto send = [=](Api::SendOptions options) { selectInlineResult(row, column, options); }; - FillSendMenu( + SendMenu::FillSendMenu( _menu, [&] { return type; }, - DefaultSilentCallback(send), - DefaultScheduleCallback(this, type, send)); + SendMenu::DefaultSilentCallback(send), + SendMenu::DefaultScheduleCallback(this, type, send)); if (!_menu->actions().empty()) { _menu->popup(QCursor::pos()); From b12256f1ee5963a2c58d6781c60f996c66918955 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 3 Aug 2020 12:02:41 +0300 Subject: [PATCH 030/142] Added ability to schedule polls from section of scheduled messages. Fixed #7433. --- .../SourceFiles/boxes/create_poll_box.cpp | 27 ++++++----- .../view/history_view_top_bar_widget.cpp | 10 ++++- .../SourceFiles/window/window_peer_menu.cpp | 45 +++++++++++-------- .../SourceFiles/window/window_peer_menu.h | 5 ++- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 1f5137ebf..2ac6a8fb7 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -1059,19 +1059,19 @@ object_ptr CreatePollBox::setupContent() { *error &= ~Error::Solution; } }; - const auto showError = [=](const QString &text) { - Ui::Toast::Show(text); + const auto showError = [](tr::phrase<> text) { + Ui::Toast::Show(text(tr::now)); }; const auto send = [=](Api::SendOptions sendOptions) { collectError(); if (*error & Error::Question) { - showError(tr::lng_polls_choose_question(tr::now)); + showError(tr::lng_polls_choose_question); question->setFocus(); } else if (*error & Error::Options) { - showError(tr::lng_polls_choose_answers(tr::now)); + showError(tr::lng_polls_choose_answers); options->focusFirst(); } else if (*error & Error::Correct) { - showError(tr::lng_polls_choose_correct(tr::now)); + showError(tr::lng_polls_choose_correct); } else if (*error & Error::Solution) { solution->showError(); } else if (!*error) { @@ -1079,9 +1079,7 @@ object_ptr CreatePollBox::setupContent() { } }; const auto sendSilent = [=] { - auto options = Api::SendOptions(); - options.silent = true; - send(options); + send({ .silent = true }); }; const auto sendScheduled = [=] { Ui::show( @@ -1102,13 +1100,18 @@ object_ptr CreatePollBox::setupContent() { FocusAtEnd(question); }, lifetime()); + const auto isNormal = (_sendType == Api::SendType::Normal); + const auto isScheduled = (_sendType == Api::SendType::Scheduled); + const auto submit = addButton( - tr::lng_polls_create_button(), - [=] { send({}); }); - if (_sendType == Api::SendType::Normal) { + isNormal + ? tr::lng_polls_create_button() + : tr::lng_schedule_button(), + [=] { isNormal ? send({}) : sendScheduled(); }); + if (isNormal || isScheduled) { const auto sendMenuType = [=] { collectError(); - return *error + return (*error || isScheduled) ? SendMenu::Type::Disabled : SendMenu::Type::Scheduled; }; diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index c08579410..464b7e418 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -233,7 +233,9 @@ void TopBarWidget::showMenu() { peer, FilterId(), addAction, - Window::PeerMenuSource::History); + (_section == Section::Scheduled) + ? Window::PeerMenuSource::ScheduledSection + : Window::PeerMenuSource::History); } else if (const auto folder = _activeChat.folder()) { Window::FillFolderMenu( _controller, @@ -640,8 +642,12 @@ void TopBarWidget::updateControlsVisibility() { _unreadBadge->show(); } const auto historyMode = (_section == Section::History); + const auto scheduledMode = (_section == Section::Scheduled); + const auto showInScheduledMode = (_activeChat.peer() + && _activeChat.peer()->canSendPolls()); updateSearchVisibility(); - _menuToggle->setVisible(historyMode && !_activeChat.folder()); + _menuToggle->setVisible(!_activeChat.folder() + && (scheduledMode ? showInScheduledMode : historyMode)); _infoToggle->setVisible(historyMode && !_activeChat.folder() && !Adaptive::OneColumn() diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index cc736bc86..d4aff3db6 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -25,7 +25,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "mainwidget.h" #include "mainwindow.h" -#include "api/api_common.h" #include "api/api_chat_filters.h" #include "mtproto/mtproto_config.h" #include "history/history.h" @@ -92,6 +91,8 @@ private: void addChatActions(not_null chat); void addChannelActions(not_null channel); + void addPollAction(not_null peer); + not_null _controller; not_null _peer; FilterId _filterId = 0; @@ -484,11 +485,7 @@ void Filler::addUserActions(not_null user) { tr::lng_profile_invite_to_group(tr::now), [=] { AddBotToGroup::Start(controller, user); }); } - if (user->canSendPolls()) { - _addAction( - tr::lng_polls_create(tr::now), - [=] { PeerMenuCreatePoll(controller, user); }); - } + addPollAction(user); if (user->canExportChatHistory()) { _addAction( tr::lng_profile_export_chat(tr::now), @@ -522,11 +519,7 @@ void Filler::addChatActions(not_null chat) { tr::lng_profile_add_participant(tr::now), [=] { AddChatMembers(controller, chat); }); } - if (chat->canSendPolls()) { - _addAction( - tr::lng_polls_create(tr::now), - [=] { PeerMenuCreatePoll(controller, chat); }); - } + addPollAction(chat); if (chat->canExportChatHistory()) { _addAction( tr::lng_profile_export_chat(tr::now), @@ -568,11 +561,7 @@ void Filler::addChannelActions(not_null channel) { tr::lng_channel_add_members(tr::now), [=] { PeerMenuAddChannelMembers(navigation, channel); }); } - if (channel->canSendPolls()) { - _addAction( - tr::lng_polls_create(tr::now), - [=] { PeerMenuCreatePoll(navigation, channel); }); - } + addPollAction(channel); if (channel->canExportChatHistory()) { _addAction( (isGroup @@ -610,7 +599,26 @@ void Filler::addChannelActions(not_null channel) { } } +void Filler::addPollAction(not_null peer) { + if (!peer->canSendPolls()) { + return; + } + const auto controller = _controller; + const auto source = (_source == PeerMenuSource::ScheduledSection) + ? Api::SendType::Scheduled + : Api::SendType::Normal; + const auto flag = PollData::Flags(); + auto callback = [=] { + PeerMenuCreatePoll(controller, peer, flag, flag, source); + }; + _addAction(tr::lng_polls_create(tr::now), std::move(callback)); +} + void Filler::fill() { + if (_source == PeerMenuSource::ScheduledSection) { + addPollAction(_peer); + return; + } if (showHidePromotion()) { addHidePromotion(); } @@ -791,7 +799,8 @@ void PeerMenuCreatePoll( not_null controller, not_null peer, PollData::Flags chosen, - PollData::Flags disabled) { + PollData::Flags disabled, + Api::SendType sendType) { if (peer->isChannel() && !peer->isMegagroup()) { chosen &= ~PollData::Flag::PublicVotes; disabled |= PollData::Flag::PublicVotes; @@ -800,7 +809,7 @@ void PeerMenuCreatePoll( controller, chosen, disabled, - Api::SendType::Normal)); + sendType)); const auto lock = box->lifetime().make_state(false); box->submitRequests( ) | rpl::start_with_next([=](const CreatePollBox::Result &result) { diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index e68bdb138..3268ffcbf 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "api/api_common.h" #include "data/data_poll.h" class History; @@ -30,6 +31,7 @@ enum class PeerMenuSource { ChatsList, History, Profile, + ScheduledSection, }; using PeerMenuCallback = Fn controller, not_null peer, PollData::Flags chosen = PollData::Flags(), - PollData::Flags disabled = PollData::Flags()); + PollData::Flags disabled = PollData::Flags(), + Api::SendType sendType = Api::SendType::Normal); void PeerMenuBlockUserBox( not_null box, not_null window, From b6c70572a94e7c23983647ba461a32716b30a638 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 11 Aug 2020 15:45:30 +0300 Subject: [PATCH 031/142] Fixed Github CI macOS build. --- .github/workflows/mac.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index ebce645fa..7036ac978 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -79,6 +79,7 @@ jobs: - name: First set up. run: | + sudo chown -R `whoami`:admin /usr/local/share brew install automake fdk-aac lame libass libtool libvorbis libvpx \ ninja opus sdl shtool texi2html theora x264 xvid yasm pkg-config From 4ba7de8df1e1278448d4140f76e8f2c93674f000 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 11 Aug 2020 17:30:12 +0400 Subject: [PATCH 032/142] Fix build on Windows. --- Telegram/SourceFiles/platform/win/specific_win.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp index 6481defde..1600396ca 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.cpp +++ b/Telegram/SourceFiles/platform/win/specific_win.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include #include #include @@ -422,7 +423,7 @@ bool ShowWindowMenu(QWindow *window) { const auto pos = QCursor::pos(); SendMessage( - window->winId(), + HWND(window->winId()), WM_SYSCOMMAND, SC_MOUSEMENU, MAKELPARAM(pos.x(), pos.y())); From 145ace2fa032796b68a3cd5bdf78692cef08390f Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 13 May 2020 16:59:39 +0400 Subject: [PATCH 033/142] Use external_webrtc in libtgvoip. --- Telegram/ThirdParty/libtgvoip | 2 +- Telegram/cmake/lib_tgvoip.cmake | 627 +------------------------------- cmake | 2 +- 3 files changed, 3 insertions(+), 628 deletions(-) diff --git a/Telegram/ThirdParty/libtgvoip b/Telegram/ThirdParty/libtgvoip index 8682c5c22..6e82b6e45 160000 --- a/Telegram/ThirdParty/libtgvoip +++ b/Telegram/ThirdParty/libtgvoip @@ -1 +1 @@ -Subproject commit 8682c5c22e9c3a28ee3aacfd1d529db07ea914bf +Subproject commit 6e82b6e45664c1f80b9039256c99bebc76d34672 diff --git a/Telegram/cmake/lib_tgvoip.cmake b/Telegram/cmake/lib_tgvoip.cmake index 05ad50bd1..ecf773f4d 100644 --- a/Telegram/cmake/lib_tgvoip.cmake +++ b/Telegram/cmake/lib_tgvoip.cmake @@ -125,622 +125,9 @@ else() os/posix/NetworkSocketPosix.h ) - if (NOT WIN32 OR CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # Doesn't build with mingw for now - nice_target_sources(lib_tgvoip ${tgvoip_loc} - PRIVATE - # WebRTC APM - webrtc_dsp/system_wrappers/include/field_trial.h - webrtc_dsp/system_wrappers/include/cpu_features_wrapper.h - webrtc_dsp/system_wrappers/include/asm_defines.h - webrtc_dsp/system_wrappers/include/metrics.h - webrtc_dsp/system_wrappers/include/compile_assert_c.h - webrtc_dsp/system_wrappers/source/field_trial.cc - webrtc_dsp/system_wrappers/source/metrics.cc - webrtc_dsp/system_wrappers/source/cpu_features.cc - webrtc_dsp/typedefs.h - webrtc_dsp/absl/strings/internal/memutil.h - webrtc_dsp/absl/strings/internal/memutil.cc - webrtc_dsp/absl/strings/string_view.cc - webrtc_dsp/absl/strings/ascii.h - webrtc_dsp/absl/strings/ascii.cc - webrtc_dsp/absl/strings/string_view.h - webrtc_dsp/absl/types/optional.h - webrtc_dsp/absl/types/bad_optional_access.h - webrtc_dsp/absl/types/bad_optional_access.cc - webrtc_dsp/absl/types/optional.cc - webrtc_dsp/absl/memory/memory.h - webrtc_dsp/absl/meta/type_traits.h - webrtc_dsp/absl/algorithm/algorithm.h - webrtc_dsp/absl/container/inlined_vector.h - webrtc_dsp/absl/base/policy_checks.h - webrtc_dsp/absl/base/port.h - webrtc_dsp/absl/base/config.h - webrtc_dsp/absl/base/internal/raw_logging.cc - webrtc_dsp/absl/base/internal/throw_delegate.cc - webrtc_dsp/absl/base/internal/invoke.h - webrtc_dsp/absl/base/internal/inline_variable.h - webrtc_dsp/absl/base/internal/atomic_hook.h - webrtc_dsp/absl/base/internal/identity.h - webrtc_dsp/absl/base/internal/raw_logging.h - webrtc_dsp/absl/base/internal/throw_delegate.h - webrtc_dsp/absl/base/attributes.h - webrtc_dsp/absl/base/macros.h - webrtc_dsp/absl/base/optimization.h - webrtc_dsp/absl/base/log_severity.h - webrtc_dsp/absl/utility/utility.h - webrtc_dsp/rtc_base/string_to_number.h - webrtc_dsp/rtc_base/constructormagic.h - webrtc_dsp/rtc_base/race_checker.cc - webrtc_dsp/rtc_base/strings/string_builder.h - webrtc_dsp/rtc_base/strings/string_builder.cc - webrtc_dsp/rtc_base/event_tracer.h - webrtc_dsp/rtc_base/stringencode.h - webrtc_dsp/rtc_base/memory/aligned_malloc.cc - webrtc_dsp/rtc_base/memory/aligned_malloc.h - webrtc_dsp/rtc_base/timeutils.cc - webrtc_dsp/rtc_base/event.h - webrtc_dsp/rtc_base/ignore_wundef.h - webrtc_dsp/rtc_base/stringutils.h - webrtc_dsp/rtc_base/arraysize.h - webrtc_dsp/rtc_base/platform_file.cc - webrtc_dsp/rtc_base/swap_queue.h - webrtc_dsp/rtc_base/string_to_number.cc - webrtc_dsp/rtc_base/trace_event.h - webrtc_dsp/rtc_base/checks.h - webrtc_dsp/rtc_base/deprecation.h - webrtc_dsp/rtc_base/thread_checker_impl.cc - webrtc_dsp/rtc_base/sanitizer.h - webrtc_dsp/rtc_base/scoped_ref_ptr.h - webrtc_dsp/rtc_base/logging.h - webrtc_dsp/rtc_base/logging_mac.h - webrtc_dsp/rtc_base/logging_mac.mm - webrtc_dsp/rtc_base/timeutils.h - webrtc_dsp/rtc_base/atomicops.h - webrtc_dsp/rtc_base/stringencode.cc - webrtc_dsp/rtc_base/stringutils.cc - webrtc_dsp/rtc_base/checks.cc - webrtc_dsp/rtc_base/numerics/safe_minmax.h - webrtc_dsp/rtc_base/numerics/safe_conversions.h - webrtc_dsp/rtc_base/numerics/safe_conversions_impl.h - webrtc_dsp/rtc_base/numerics/safe_compare.h - webrtc_dsp/rtc_base/system/unused.h - webrtc_dsp/rtc_base/system/inline.h - webrtc_dsp/rtc_base/system/ignore_warnings.h - webrtc_dsp/rtc_base/system/asm_defines.h - webrtc_dsp/rtc_base/system/rtc_export.h - webrtc_dsp/rtc_base/system/arch.h - webrtc_dsp/rtc_base/platform_thread.cc - webrtc_dsp/rtc_base/platform_thread.h - webrtc_dsp/rtc_base/platform_thread_types.h - webrtc_dsp/rtc_base/protobuf_utils.h - webrtc_dsp/rtc_base/thread_annotations.h - webrtc_dsp/rtc_base/gtest_prod_util.h - webrtc_dsp/rtc_base/function_view.h - webrtc_dsp/rtc_base/criticalsection.h - webrtc_dsp/rtc_base/criticalsection.cc - webrtc_dsp/rtc_base/platform_thread_types.cc - webrtc_dsp/rtc_base/refcount.h - webrtc_dsp/rtc_base/event.cc - webrtc_dsp/rtc_base/thread_checker_impl.h - webrtc_dsp/rtc_base/event_tracer.cc - webrtc_dsp/rtc_base/compile_assert_c.h - webrtc_dsp/rtc_base/logging_webrtc.cc - webrtc_dsp/rtc_base/type_traits.h - webrtc_dsp/rtc_base/platform_file.h - webrtc_dsp/rtc_base/refcounter.h - webrtc_dsp/rtc_base/logging_mac.h - webrtc_dsp/rtc_base/thread_checker.h - webrtc_dsp/rtc_base/race_checker.h - webrtc_dsp/rtc_base/refcountedobject.h - webrtc_dsp/third_party/rnnoise/src/rnn_vad_weights.cc - webrtc_dsp/third_party/rnnoise/src/rnn_activations.h - webrtc_dsp/third_party/rnnoise/src/kiss_fft.h - webrtc_dsp/third_party/rnnoise/src/kiss_fft.cc - webrtc_dsp/third_party/rnnoise/src/rnn_vad_weights.h - webrtc_dsp/api/audio/audio_frame.cc - webrtc_dsp/api/audio/echo_canceller3_config.h - webrtc_dsp/api/audio/echo_control.h - webrtc_dsp/api/audio/audio_frame.h - webrtc_dsp/api/audio/echo_canceller3_config.cc - webrtc_dsp/api/audio/echo_canceller3_factory.h - webrtc_dsp/api/audio/echo_canceller3_factory.cc - webrtc_dsp/api/array_view.h - webrtc_dsp/modules/third_party/fft/fft.h - webrtc_dsp/modules/third_party/fft/fft.c - webrtc_dsp/modules/audio_coding/codecs/isac/bandwidth_info.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/include/isac.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_estimator.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines_logist.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filterbanks.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/entropy_coding.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_vad.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/settings.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/transform.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/crc.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_filter.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filter_functions.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/decode.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lattice.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/intialize.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_float_type.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_analysis.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines_hist.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/codec.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_estimator.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/entropy_coding.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac_vad.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/structs.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/filter_functions.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_filter.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/arith_routines.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/crc.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_analysis.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/decode_bwe.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/bandwidth_estimator.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/isac.c - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h - webrtc_dsp/modules/audio_coding/codecs/isac/main/source/lpc_tables.h - webrtc_dsp/modules/audio_processing/rms_level.cc - webrtc_dsp/modules/audio_processing/echo_detector/moving_max.h - webrtc_dsp/modules/audio_processing/echo_detector/circular_buffer.h - webrtc_dsp/modules/audio_processing/echo_detector/normalized_covariance_estimator.h - webrtc_dsp/modules/audio_processing/echo_detector/normalized_covariance_estimator.cc - webrtc_dsp/modules/audio_processing/echo_detector/moving_max.cc - webrtc_dsp/modules/audio_processing/echo_detector/circular_buffer.cc - webrtc_dsp/modules/audio_processing/echo_detector/mean_variance_estimator.cc - webrtc_dsp/modules/audio_processing/echo_detector/mean_variance_estimator.h - webrtc_dsp/modules/audio_processing/gain_control_for_experimental_agc.h - webrtc_dsp/modules/audio_processing/splitting_filter.cc - webrtc_dsp/modules/audio_processing/gain_control_impl.cc - webrtc_dsp/modules/audio_processing/rms_level.h - webrtc_dsp/modules/audio_processing/ns/ns_core.h - webrtc_dsp/modules/audio_processing/ns/nsx_core.c - webrtc_dsp/modules/audio_processing/ns/noise_suppression_x.c - webrtc_dsp/modules/audio_processing/ns/nsx_core_c.c - webrtc_dsp/modules/audio_processing/ns/defines.h - webrtc_dsp/modules/audio_processing/ns/noise_suppression.h - webrtc_dsp/modules/audio_processing/ns/ns_core.c - webrtc_dsp/modules/audio_processing/ns/nsx_core.h - webrtc_dsp/modules/audio_processing/ns/windows_private.h - webrtc_dsp/modules/audio_processing/ns/noise_suppression_x.h - webrtc_dsp/modules/audio_processing/ns/noise_suppression.c - webrtc_dsp/modules/audio_processing/ns/nsx_defines.h - webrtc_dsp/modules/audio_processing/residual_echo_detector.h - webrtc_dsp/modules/audio_processing/audio_processing_impl.h - webrtc_dsp/modules/audio_processing/audio_buffer.cc - webrtc_dsp/modules/audio_processing/typing_detection.cc - webrtc_dsp/modules/audio_processing/render_queue_item_verifier.h - webrtc_dsp/modules/audio_processing/include/audio_generator.h - webrtc_dsp/modules/audio_processing/include/config.h - webrtc_dsp/modules/audio_processing/include/audio_frame_view.h - webrtc_dsp/modules/audio_processing/include/mock_audio_processing.h - webrtc_dsp/modules/audio_processing/include/gain_control.h - webrtc_dsp/modules/audio_processing/include/audio_generator_factory.h - webrtc_dsp/modules/audio_processing/include/audio_processing_statistics.cc - webrtc_dsp/modules/audio_processing/include/audio_generator_factory.cc - webrtc_dsp/modules/audio_processing/include/aec_dump.cc - webrtc_dsp/modules/audio_processing/include/aec_dump.h - webrtc_dsp/modules/audio_processing/include/audio_processing_statistics.h - webrtc_dsp/modules/audio_processing/include/audio_processing.h - webrtc_dsp/modules/audio_processing/include/audio_processing.cc - webrtc_dsp/modules/audio_processing/include/config.cc - webrtc_dsp/modules/audio_processing/agc2/interpolated_gain_curve.h - webrtc_dsp/modules/audio_processing/agc2/biquad_filter.h - webrtc_dsp/modules/audio_processing/agc2/interpolated_gain_curve.cc - webrtc_dsp/modules/audio_processing/agc2/agc2_common.cc - webrtc_dsp/modules/audio_processing/agc2/agc2_testing_common.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator.h - webrtc_dsp/modules/audio_processing/agc2/gain_applier.cc - webrtc_dsp/modules/audio_processing/agc2/signal_classifier.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_agc.cc - webrtc_dsp/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc - webrtc_dsp/modules/audio_processing/agc2/limiter.cc - webrtc_dsp/modules/audio_processing/agc2/saturation_protector.cc - webrtc_dsp/modules/audio_processing/agc2/vector_float_frame.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features_internal.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/sequence_buffer.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/rnn.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/rnn.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/test_utils.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_info.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/lp_residual.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/ring_buffer.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/symmetric_matrix_buffer.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/features_extraction.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/common.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features_internal.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/fft_util.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/spectral_features.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/pitch_search.h - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/features_extraction.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/fft_util.cc - webrtc_dsp/modules/audio_processing/agc2/rnn_vad/lp_residual.cc - webrtc_dsp/modules/audio_processing/agc2/fixed_gain_controller.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator_agc.cc - webrtc_dsp/modules/audio_processing/agc2/vector_float_frame.cc - webrtc_dsp/modules/audio_processing/agc2/down_sampler.h - webrtc_dsp/modules/audio_processing/agc2/noise_level_estimator.cc - webrtc_dsp/modules/audio_processing/agc2/agc2_testing_common.cc - webrtc_dsp/modules/audio_processing/agc2/fixed_digital_level_estimator.cc - webrtc_dsp/modules/audio_processing/agc2/fixed_gain_controller.cc - webrtc_dsp/modules/audio_processing/agc2/saturation_protector.h - webrtc_dsp/modules/audio_processing/agc2/vad_with_level.cc - webrtc_dsp/modules/audio_processing/agc2/limiter_db_gain_curve.cc - webrtc_dsp/modules/audio_processing/agc2/agc2_common.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator_agc.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_digital_gain_applier.h - webrtc_dsp/modules/audio_processing/agc2/vad_with_level.h - webrtc_dsp/modules/audio_processing/agc2/limiter_db_gain_curve.h - webrtc_dsp/modules/audio_processing/agc2/fixed_digital_level_estimator.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_agc.h - webrtc_dsp/modules/audio_processing/agc2/gain_applier.h - webrtc_dsp/modules/audio_processing/agc2/down_sampler.cc - webrtc_dsp/modules/audio_processing/agc2/noise_level_estimator.h - webrtc_dsp/modules/audio_processing/agc2/signal_classifier.cc - webrtc_dsp/modules/audio_processing/agc2/noise_spectrum_estimator.cc - webrtc_dsp/modules/audio_processing/agc2/compute_interpolated_gain_curve.cc - webrtc_dsp/modules/audio_processing/agc2/compute_interpolated_gain_curve.h - webrtc_dsp/modules/audio_processing/agc2/biquad_filter.cc - webrtc_dsp/modules/audio_processing/agc2/noise_spectrum_estimator.h - webrtc_dsp/modules/audio_processing/agc2/limiter.h - webrtc_dsp/modules/audio_processing/agc2/adaptive_mode_level_estimator.cc - webrtc_dsp/modules/audio_processing/transient/moving_moments.cc - webrtc_dsp/modules/audio_processing/transient/transient_detector.h - webrtc_dsp/modules/audio_processing/transient/wpd_tree.cc - webrtc_dsp/modules/audio_processing/transient/transient_suppressor.h - webrtc_dsp/modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h - webrtc_dsp/modules/audio_processing/transient/common.h - webrtc_dsp/modules/audio_processing/transient/wpd_node.h - webrtc_dsp/modules/audio_processing/transient/moving_moments.h - webrtc_dsp/modules/audio_processing/transient/wpd_tree.h - webrtc_dsp/modules/audio_processing/transient/wpd_node.cc - webrtc_dsp/modules/audio_processing/transient/transient_suppressor.cc - webrtc_dsp/modules/audio_processing/transient/transient_detector.cc - webrtc_dsp/modules/audio_processing/transient/dyadic_decimator.h - webrtc_dsp/modules/audio_processing/low_cut_filter.cc - webrtc_dsp/modules/audio_processing/noise_suppression_impl.h - webrtc_dsp/modules/audio_processing/level_estimator_impl.cc - webrtc_dsp/modules/audio_processing/three_band_filter_bank.cc - webrtc_dsp/modules/audio_processing/aec/echo_cancellation.cc - webrtc_dsp/modules/audio_processing/aec/aec_resampler.h - webrtc_dsp/modules/audio_processing/aec/aec_resampler.cc - webrtc_dsp/modules/audio_processing/aec/echo_cancellation.h - webrtc_dsp/modules/audio_processing/aec/aec_core.cc - webrtc_dsp/modules/audio_processing/aec/aec_core.h - webrtc_dsp/modules/audio_processing/aec/aec_core_optimized_methods.h - webrtc_dsp/modules/audio_processing/aec/aec_core_sse2.cc - webrtc_dsp/modules/audio_processing/aec/aec_common.h - webrtc_dsp/modules/audio_processing/voice_detection_impl.h - webrtc_dsp/modules/audio_processing/voice_detection_impl.cc - webrtc_dsp/modules/audio_processing/echo_cancellation_impl.cc - webrtc_dsp/modules/audio_processing/gain_control_for_experimental_agc.cc - webrtc_dsp/modules/audio_processing/agc/agc.cc - webrtc_dsp/modules/audio_processing/agc/loudness_histogram.cc - webrtc_dsp/modules/audio_processing/agc/agc_manager_direct.cc - webrtc_dsp/modules/audio_processing/agc/legacy/analog_agc.h - webrtc_dsp/modules/audio_processing/agc/legacy/gain_control.h - webrtc_dsp/modules/audio_processing/agc/legacy/digital_agc.h - webrtc_dsp/modules/audio_processing/agc/legacy/analog_agc.c - webrtc_dsp/modules/audio_processing/agc/legacy/digital_agc.c - webrtc_dsp/modules/audio_processing/agc/utility.cc - webrtc_dsp/modules/audio_processing/agc/mock_agc.h - webrtc_dsp/modules/audio_processing/agc/loudness_histogram.h - webrtc_dsp/modules/audio_processing/agc/gain_map_internal.h - webrtc_dsp/modules/audio_processing/agc/utility.h - webrtc_dsp/modules/audio_processing/agc/agc_manager_direct.h - webrtc_dsp/modules/audio_processing/agc/agc.h - webrtc_dsp/modules/audio_processing/common.h - webrtc_dsp/modules/audio_processing/audio_processing_impl.cc - webrtc_dsp/modules/audio_processing/audio_buffer.h - webrtc_dsp/modules/audio_processing/echo_control_mobile_impl.h - webrtc_dsp/modules/audio_processing/splitting_filter.h - webrtc_dsp/modules/audio_processing/low_cut_filter.h - webrtc_dsp/modules/audio_processing/audio_generator/file_audio_generator.h - webrtc_dsp/modules/audio_processing/audio_generator/file_audio_generator.cc - webrtc_dsp/modules/audio_processing/gain_controller2.cc - webrtc_dsp/modules/audio_processing/three_band_filter_bank.h - webrtc_dsp/modules/audio_processing/residual_echo_detector.cc - webrtc_dsp/modules/audio_processing/echo_cancellation_impl.h - webrtc_dsp/modules/audio_processing/noise_suppression_impl.cc - webrtc_dsp/modules/audio_processing/level_estimator_impl.h - webrtc_dsp/modules/audio_processing/gain_controller2.h - webrtc_dsp/modules/audio_processing/aecm/aecm_core.h - webrtc_dsp/modules/audio_processing/aecm/aecm_defines.h - webrtc_dsp/modules/audio_processing/aecm/aecm_core.cc - webrtc_dsp/modules/audio_processing/aecm/aecm_core_c.cc - webrtc_dsp/modules/audio_processing/aecm/echo_control_mobile.h - webrtc_dsp/modules/audio_processing/aecm/echo_control_mobile.cc - webrtc_dsp/modules/audio_processing/aec3/render_reverb_model.cc - webrtc_dsp/modules/audio_processing/aec3/downsampled_render_buffer.h - webrtc_dsp/modules/audio_processing/aec3/subtractor_output_analyzer.h - webrtc_dsp/modules/audio_processing/aec3/reverb_model_fallback.cc - webrtc_dsp/modules/audio_processing/aec3/residual_echo_estimator.h - webrtc_dsp/modules/audio_processing/aec3/shadow_filter_update_gain.h - webrtc_dsp/modules/audio_processing/aec3/echo_remover_metrics.cc - webrtc_dsp/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer2.cc - webrtc_dsp/modules/audio_processing/aec3/aec_state.h - webrtc_dsp/modules/audio_processing/aec3/suppression_filter.h - webrtc_dsp/modules/audio_processing/aec3/echo_path_variability.cc - webrtc_dsp/modules/audio_processing/aec3/frame_blocker.cc - webrtc_dsp/modules/audio_processing/aec3/subtractor.cc - webrtc_dsp/modules/audio_processing/aec3/block_delay_buffer.h - webrtc_dsp/modules/audio_processing/aec3/adaptive_fir_filter.h - webrtc_dsp/modules/audio_processing/aec3/cascaded_biquad_filter.h - webrtc_dsp/modules/audio_processing/aec3/matched_filter.h - webrtc_dsp/modules/audio_processing/aec3/subtractor_output.h - webrtc_dsp/modules/audio_processing/aec3/render_signal_analyzer.h - webrtc_dsp/modules/audio_processing/aec3/aec3_fft.cc - webrtc_dsp/modules/audio_processing/aec3/aec3_fft.h - webrtc_dsp/modules/audio_processing/aec3/echo_remover_metrics.h - webrtc_dsp/modules/audio_processing/aec3/fullband_erle_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/suppression_filter.cc - webrtc_dsp/modules/audio_processing/aec3/block_processor.cc - webrtc_dsp/modules/audio_processing/aec3/filter_analyzer.h - webrtc_dsp/modules/audio_processing/aec3/subtractor.h - webrtc_dsp/modules/audio_processing/aec3/echo_path_delay_estimator.h - webrtc_dsp/modules/audio_processing/aec3/subband_erle_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_controller_metrics.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/block_processor_metrics.h - webrtc_dsp/modules/audio_processing/aec3/vector_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/erl_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/aec_state.cc - webrtc_dsp/modules/audio_processing/aec3/adaptive_fir_filter.cc - webrtc_dsp/modules/audio_processing/aec3/fft_data.h - webrtc_dsp/modules/audio_processing/aec3/render_delay_controller.cc - webrtc_dsp/modules/audio_processing/aec3/skew_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_controller_metrics.h - webrtc_dsp/modules/audio_processing/aec3/comfort_noise_generator.h - webrtc_dsp/modules/audio_processing/aec3/echo_path_delay_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/erl_estimator.h - webrtc_dsp/modules/audio_processing/aec3/echo_remover.h - webrtc_dsp/modules/audio_processing/aec3/block_framer.cc - webrtc_dsp/modules/audio_processing/aec3/erle_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/reverb_model.cc - webrtc_dsp/modules/audio_processing/aec3/cascaded_biquad_filter.cc - webrtc_dsp/modules/audio_processing/aec3/matrix_buffer.h - webrtc_dsp/modules/audio_processing/aec3/render_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/reverb_model_estimator.h - webrtc_dsp/modules/audio_processing/aec3/subtractor_output.cc - webrtc_dsp/modules/audio_processing/aec3/stationarity_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/render_signal_analyzer.cc - webrtc_dsp/modules/audio_processing/aec3/echo_path_variability.h - webrtc_dsp/modules/audio_processing/aec3/moving_average.h - webrtc_dsp/modules/audio_processing/aec3/render_reverb_model.h - webrtc_dsp/modules/audio_processing/aec3/subtractor_output_analyzer.cc - webrtc_dsp/modules/audio_processing/aec3/suppression_gain.cc - webrtc_dsp/modules/audio_processing/aec3/echo_audibility.cc - webrtc_dsp/modules/audio_processing/aec3/block_processor_metrics.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_controller.h - webrtc_dsp/modules/audio_processing/aec3/suppression_gain.h - webrtc_dsp/modules/audio_processing/aec3/moving_average.cc - webrtc_dsp/modules/audio_processing/aec3/erle_estimator.h - webrtc_dsp/modules/audio_processing/aec3/subband_erle_estimator.h - webrtc_dsp/modules/audio_processing/aec3/reverb_model_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/aec3_common.cc - webrtc_dsp/modules/audio_processing/aec3/residual_echo_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/block_processor.h - webrtc_dsp/modules/audio_processing/aec3/fullband_erle_estimator.h - webrtc_dsp/modules/audio_processing/aec3/matched_filter.cc - webrtc_dsp/modules/audio_processing/aec3/stationarity_estimator.h - webrtc_dsp/modules/audio_processing/aec3/echo_canceller3.h - webrtc_dsp/modules/audio_processing/aec3/skew_estimator.h - webrtc_dsp/modules/audio_processing/aec3/reverb_decay_estimator.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_controller2.cc - webrtc_dsp/modules/audio_processing/aec3/render_buffer.h - webrtc_dsp/modules/audio_processing/aec3/suppression_gain_limiter.cc - webrtc_dsp/modules/audio_processing/aec3/main_filter_update_gain.cc - webrtc_dsp/modules/audio_processing/aec3/echo_remover.cc - webrtc_dsp/modules/audio_processing/aec3/reverb_model_fallback.h - webrtc_dsp/modules/audio_processing/aec3/downsampled_render_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/vector_buffer.h - webrtc_dsp/modules/audio_processing/aec3/matrix_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/reverb_frequency_response.h - webrtc_dsp/modules/audio_processing/aec3/echo_audibility.h - webrtc_dsp/modules/audio_processing/aec3/fft_buffer.h - webrtc_dsp/modules/audio_processing/aec3/block_processor2.cc - webrtc_dsp/modules/audio_processing/aec3/echo_canceller3.cc - webrtc_dsp/modules/audio_processing/aec3/block_delay_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/aec3_common.h - webrtc_dsp/modules/audio_processing/aec3/fft_buffer.cc - webrtc_dsp/modules/audio_processing/aec3/vector_math.h - webrtc_dsp/modules/audio_processing/aec3/decimator.h - webrtc_dsp/modules/audio_processing/aec3/frame_blocker.h - webrtc_dsp/modules/audio_processing/aec3/block_framer.h - webrtc_dsp/modules/audio_processing/aec3/suppression_gain_limiter.h - webrtc_dsp/modules/audio_processing/aec3/delay_estimate.h - webrtc_dsp/modules/audio_processing/aec3/comfort_noise_generator.cc - webrtc_dsp/modules/audio_processing/aec3/reverb_model.h - webrtc_dsp/modules/audio_processing/aec3/main_filter_update_gain.h - webrtc_dsp/modules/audio_processing/aec3/matched_filter_lag_aggregator.h - webrtc_dsp/modules/audio_processing/aec3/shadow_filter_update_gain.cc - webrtc_dsp/modules/audio_processing/aec3/filter_analyzer.cc - webrtc_dsp/modules/audio_processing/aec3/reverb_decay_estimator.h - webrtc_dsp/modules/audio_processing/aec3/reverb_frequency_response.cc - webrtc_dsp/modules/audio_processing/aec3/decimator.cc - webrtc_dsp/modules/audio_processing/aec3/render_delay_buffer.h - webrtc_dsp/modules/audio_processing/echo_control_mobile_impl.cc - webrtc_dsp/modules/audio_processing/gain_control_impl.h - webrtc_dsp/modules/audio_processing/typing_detection.h - webrtc_dsp/modules/audio_processing/logging/apm_data_dumper.cc - webrtc_dsp/modules/audio_processing/logging/apm_data_dumper.h - webrtc_dsp/modules/audio_processing/vad/voice_activity_detector.cc - webrtc_dsp/modules/audio_processing/vad/standalone_vad.cc - webrtc_dsp/modules/audio_processing/vad/vad_audio_proc_internal.h - webrtc_dsp/modules/audio_processing/vad/pitch_internal.cc - webrtc_dsp/modules/audio_processing/vad/vad_circular_buffer.cc - webrtc_dsp/modules/audio_processing/vad/vad_circular_buffer.h - webrtc_dsp/modules/audio_processing/vad/pitch_based_vad.h - webrtc_dsp/modules/audio_processing/vad/vad_audio_proc.cc - webrtc_dsp/modules/audio_processing/vad/pole_zero_filter.cc - webrtc_dsp/modules/audio_processing/vad/pole_zero_filter.h - webrtc_dsp/modules/audio_processing/vad/pitch_based_vad.cc - webrtc_dsp/modules/audio_processing/vad/gmm.h - webrtc_dsp/modules/audio_processing/vad/common.h - webrtc_dsp/modules/audio_processing/vad/vad_audio_proc.h - webrtc_dsp/modules/audio_processing/vad/voice_gmm_tables.h - webrtc_dsp/modules/audio_processing/vad/noise_gmm_tables.h - webrtc_dsp/modules/audio_processing/vad/pitch_internal.h - webrtc_dsp/modules/audio_processing/vad/gmm.cc - webrtc_dsp/modules/audio_processing/vad/standalone_vad.h - webrtc_dsp/modules/audio_processing/vad/voice_activity_detector.h - webrtc_dsp/modules/audio_processing/utility/delay_estimator_internal.h - webrtc_dsp/modules/audio_processing/utility/ooura_fft.cc - webrtc_dsp/modules/audio_processing/utility/ooura_fft.h - webrtc_dsp/modules/audio_processing/utility/delay_estimator_wrapper.cc - webrtc_dsp/modules/audio_processing/utility/ooura_fft_sse2.cc - webrtc_dsp/modules/audio_processing/utility/delay_estimator.cc - webrtc_dsp/modules/audio_processing/utility/block_mean_calculator.h - webrtc_dsp/modules/audio_processing/utility/block_mean_calculator.cc - webrtc_dsp/modules/audio_processing/utility/delay_estimator.h - webrtc_dsp/modules/audio_processing/utility/ooura_fft_tables_common.h - webrtc_dsp/modules/audio_processing/utility/delay_estimator_wrapper.h - webrtc_dsp/common_audio/mocks/mock_smoothing_filter.h - webrtc_dsp/common_audio/wav_file.h - webrtc_dsp/common_audio/window_generator.cc - webrtc_dsp/common_audio/channel_buffer.cc - webrtc_dsp/common_audio/fir_filter_factory.cc - webrtc_dsp/common_audio/sparse_fir_filter.h - webrtc_dsp/common_audio/fir_filter_sse.h - webrtc_dsp/common_audio/window_generator.h - webrtc_dsp/common_audio/ring_buffer.h - webrtc_dsp/common_audio/fir_filter.h - webrtc_dsp/common_audio/include/audio_util.h - webrtc_dsp/common_audio/wav_header.cc - webrtc_dsp/common_audio/real_fourier_ooura.cc - webrtc_dsp/common_audio/audio_util.cc - webrtc_dsp/common_audio/real_fourier_ooura.h - webrtc_dsp/common_audio/fir_filter_sse.cc - webrtc_dsp/common_audio/smoothing_filter.h - webrtc_dsp/common_audio/resampler/push_sinc_resampler.cc - webrtc_dsp/common_audio/resampler/sinc_resampler.h - webrtc_dsp/common_audio/resampler/resampler.cc - webrtc_dsp/common_audio/resampler/sinc_resampler_sse.cc - webrtc_dsp/common_audio/resampler/include/push_resampler.h - webrtc_dsp/common_audio/resampler/include/resampler.h - webrtc_dsp/common_audio/resampler/push_sinc_resampler.h - webrtc_dsp/common_audio/resampler/push_resampler.cc - webrtc_dsp/common_audio/resampler/sinusoidal_linear_chirp_source.h - webrtc_dsp/common_audio/resampler/sinc_resampler.cc - webrtc_dsp/common_audio/resampler/sinusoidal_linear_chirp_source.cc - webrtc_dsp/common_audio/fir_filter_factory.h - webrtc_dsp/common_audio/audio_converter.h - webrtc_dsp/common_audio/wav_file.cc - webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c - webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h - webrtc_dsp/common_audio/third_party/fft4g/fft4g.c - webrtc_dsp/common_audio/third_party/fft4g/fft4g.h - webrtc_dsp/common_audio/audio_converter.cc - webrtc_dsp/common_audio/real_fourier.cc - webrtc_dsp/common_audio/channel_buffer.h - webrtc_dsp/common_audio/real_fourier.h - webrtc_dsp/common_audio/sparse_fir_filter.cc - webrtc_dsp/common_audio/smoothing_filter.cc - webrtc_dsp/common_audio/fir_filter_c.cc - webrtc_dsp/common_audio/ring_buffer.c - webrtc_dsp/common_audio/fir_filter_c.h - webrtc_dsp/common_audio/signal_processing/complex_fft_tables.h - webrtc_dsp/common_audio/signal_processing/complex_fft.c - webrtc_dsp/common_audio/signal_processing/filter_ma_fast_q12.c - webrtc_dsp/common_audio/signal_processing/levinson_durbin.c - webrtc_dsp/common_audio/signal_processing/dot_product_with_scale.cc - webrtc_dsp/common_audio/signal_processing/auto_corr_to_refl_coef.c - webrtc_dsp/common_audio/signal_processing/resample_by_2_internal.c - webrtc_dsp/common_audio/signal_processing/energy.c - webrtc_dsp/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c - webrtc_dsp/common_audio/signal_processing/downsample_fast.c - webrtc_dsp/common_audio/signal_processing/splitting_filter1.c - webrtc_dsp/common_audio/signal_processing/filter_ar_fast_q12.c - webrtc_dsp/common_audio/signal_processing/spl_init.c - webrtc_dsp/common_audio/signal_processing/lpc_to_refl_coef.c - webrtc_dsp/common_audio/signal_processing/cross_correlation.c - webrtc_dsp/common_audio/signal_processing/include/signal_processing_library.h - webrtc_dsp/common_audio/signal_processing/include/real_fft.h - webrtc_dsp/common_audio/signal_processing/include/spl_inl.h - webrtc_dsp/common_audio/signal_processing/division_operations.c - webrtc_dsp/common_audio/signal_processing/auto_correlation.c - webrtc_dsp/common_audio/signal_processing/get_scaling_square.c - webrtc_dsp/common_audio/signal_processing/dot_product_with_scale.h - webrtc_dsp/common_audio/signal_processing/resample_by_2_internal.h - webrtc_dsp/common_audio/signal_processing/resample.c - webrtc_dsp/common_audio/signal_processing/min_max_operations.c - webrtc_dsp/common_audio/signal_processing/refl_coef_to_lpc.c - webrtc_dsp/common_audio/signal_processing/filter_ar.c - webrtc_dsp/common_audio/signal_processing/vector_scaling_operations.c - webrtc_dsp/common_audio/signal_processing/resample_fractional.c - webrtc_dsp/common_audio/signal_processing/real_fft.c - webrtc_dsp/common_audio/signal_processing/ilbc_specific_functions.c - webrtc_dsp/common_audio/signal_processing/complex_bit_reverse.c - webrtc_dsp/common_audio/signal_processing/randomization_functions.c - webrtc_dsp/common_audio/signal_processing/copy_set_operations.c - webrtc_dsp/common_audio/signal_processing/resample_by_2.c - webrtc_dsp/common_audio/signal_processing/get_hanning_window.c - webrtc_dsp/common_audio/signal_processing/resample_48khz.c - webrtc_dsp/common_audio/signal_processing/spl_inl.c - webrtc_dsp/common_audio/signal_processing/spl_sqrt.c - webrtc_dsp/common_audio/wav_header.h - webrtc_dsp/common_audio/vad/vad_sp.c - webrtc_dsp/common_audio/vad/vad.cc - webrtc_dsp/common_audio/vad/webrtc_vad.c - webrtc_dsp/common_audio/vad/vad_core.h - webrtc_dsp/common_audio/vad/include/vad.h - webrtc_dsp/common_audio/vad/include/webrtc_vad.h - webrtc_dsp/common_audio/vad/vad_gmm.h - webrtc_dsp/common_audio/vad/vad_filterbank.c - webrtc_dsp/common_audio/vad/vad_core.c - webrtc_dsp/common_audio/vad/vad_sp.h - webrtc_dsp/common_audio/vad/vad_filterbank.h - webrtc_dsp/common_audio/vad/vad_gmm.c - - # ARM/NEON sources - # TODO check if there's a good way to make these compile with ARM ports of TDesktop - # webrtc_dsp/modules/audio_processing/ns/nsx_core_neon.c - # webrtc_dsp/modules/audio_processing/aec/aec_core_neon.cc - # webrtc_dsp/modules/audio_processing/aecm/aecm_core_neon.cc - # webrtc_dsp/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h - # webrtc_dsp/modules/audio_processing/utility/ooura_fft_neon.cc - # webrtc_dsp/common_audio/fir_filter_neon.cc - # webrtc_dsp/common_audio/resampler/sinc_resampler_neon.cc - # webrtc_dsp/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_arm.S - # webrtc_dsp/common_audio/fir_filter_neon.h - # webrtc_dsp/common_audio/signal_processing/downsample_fast_neon.c - # webrtc_dsp/common_audio/signal_processing/complex_bit_reverse_arm.S - # webrtc_dsp/common_audio/signal_processing/include/spl_inl_armv7.h - # webrtc_dsp/common_audio/signal_processing/min_max_operations_neon.c - # webrtc_dsp/common_audio/signal_processing/cross_correlation_neon.c - # webrtc_dsp/common_audio/signal_processing/filter_ar_fast_q12_armv7.S - ) - endif() - target_compile_definitions(lib_tgvoip PUBLIC - WEBRTC_APM_DEBUG_DUMP=0 TGVOIP_USE_DESKTOP_DSP - WEBRTC_NS_FLOAT ) if (WIN32) @@ -751,10 +138,6 @@ else() /wd4244 # conversion from 'int' to 'float', possible loss of data (several in webrtc) /wd5055 # operator '>' deprecated between enumerations and floating-point types ) - target_compile_definitions(lib_tgvoip - PUBLIC - WEBRTC_WIN - ) else() target_compile_definitions(lib_tgvoip PUBLIC @@ -765,8 +148,6 @@ else() elseif (APPLE) target_compile_definitions(lib_tgvoip PUBLIC - WEBRTC_POSIX - WEBRTC_MAC TARGET_OS_OSX TARGET_OSX ) @@ -786,24 +167,18 @@ else() if (build_linux32 AND CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*") target_compile_options(lib_tgvoip PRIVATE -msse2) endif() - target_compile_definitions(lib_tgvoip - PUBLIC - WEBRTC_POSIX - WEBRTC_LINUX - ) endif() target_include_directories(lib_tgvoip PUBLIC ${tgvoip_loc} - PRIVATE - ${tgvoip_loc}/webrtc_dsp ) target_link_libraries(lib_tgvoip PRIVATE desktop-app::external_openssl desktop-app::external_opus + desktop-app::external_webrtc ) if (LINUX) diff --git a/cmake b/cmake index f05e28c8d..8414d2aa3 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit f05e28c8da6751a3eee3eba1736736a6ac91c95f +Subproject commit 8414d2aa3a51511076de41e65fc10f4821cc67b3 From 438a560a796b15bb03f2c6b67c8561c9f9216e08 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 13 May 2020 17:04:35 +0400 Subject: [PATCH 034/142] Link tdesktop with external_webrtc. --- .gitmodules | 3 +++ Telegram/CMakeLists.txt | 2 ++ Telegram/lib_webrtc | 1 + 3 files changed, 6 insertions(+) create mode 160000 Telegram/lib_webrtc diff --git a/.gitmodules b/.gitmodules index 77e210b6d..e0dcccaa9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -94,3 +94,6 @@ [submodule "Telegram/ThirdParty/fcitx5-qt"] path = Telegram/ThirdParty/fcitx5-qt url = https://github.com/fcitx/fcitx5-qt.git +[submodule "Telegram/lib_webrtc"] + path = Telegram/lib_webrtc + url = https://github.com/desktop-app/lib_webrtc.git diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index a26881c4d..0fbb39e44 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -18,6 +18,7 @@ endif() add_subdirectory(lib_storage) add_subdirectory(lib_lottie) add_subdirectory(lib_qr) +add_subdirectory(lib_webrtc) add_subdirectory(codegen) include(CheckCXXSourceCompiles) @@ -111,6 +112,7 @@ PRIVATE desktop-app::lib_tl desktop-app::lib_storage desktop-app::lib_lottie + desktop-app::lib_webrtc desktop-app::lib_qr desktop-app::lib_ffmpeg desktop-app::external_lz4 diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc new file mode 160000 index 000000000..2b1cd3b5b --- /dev/null +++ b/Telegram/lib_webrtc @@ -0,0 +1 @@ +Subproject commit 2b1cd3b5b0c909834aea00e0590435a63d318468 From 6d36176a8d8257d5db6a272c10cec789e8a89eec Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 19 May 2020 10:33:57 +0400 Subject: [PATCH 035/142] Add test implementation of webrtc calls. --- Telegram/CMakeLists.txt | 2 + Telegram/Patches/build_ffmpeg_win.sh | 2 + Telegram/SourceFiles/api/api_updates.cpp | 5 +- Telegram/SourceFiles/calls/calls_call.cpp | 56 ++++-- Telegram/SourceFiles/calls/calls_call.h | 10 +- .../SourceFiles/calls/calls_controller.cpp | 24 ++- Telegram/SourceFiles/calls/calls_controller.h | 8 +- .../calls/calls_controller_tgvoip.h | 8 +- .../calls/calls_controller_webrtc.cpp | 175 ++++++++++++++++++ .../calls/calls_controller_webrtc.h | 60 ++++++ Telegram/SourceFiles/calls/calls_instance.cpp | 20 +- Telegram/SourceFiles/calls/calls_instance.h | 4 +- Telegram/SourceFiles/calls/calls_panel.cpp | 16 ++ Telegram/SourceFiles/calls/calls_panel.h | 2 + Telegram/lib_webrtc | 2 +- 15 files changed, 367 insertions(+), 27 deletions(-) create mode 100644 Telegram/SourceFiles/calls/calls_controller_webrtc.cpp create mode 100644 Telegram/SourceFiles/calls/calls_controller_webrtc.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 0fbb39e44..920e4483c 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -318,6 +318,8 @@ PRIVATE calls/calls_controller.cpp calls/calls_controller.h calls/calls_controller_tgvoip.h + calls/calls_controller_webrtc.cpp + calls/calls_controller_webrtc.h calls/calls_emoji_fingerprint.cpp calls/calls_emoji_fingerprint.h calls/calls_instance.cpp diff --git a/Telegram/Patches/build_ffmpeg_win.sh b/Telegram/Patches/build_ffmpeg_win.sh index 05a6db0ec..1b24980ee 100644 --- a/Telegram/Patches/build_ffmpeg_win.sh +++ b/Telegram/Patches/build_ffmpeg_win.sh @@ -13,6 +13,8 @@ pacman --noconfirm -S pkg-config PKG_CONFIG_PATH="/mingw64/lib/pkgconfig:$PKG_CONFIG_PATH" ./configure --toolchain=msvc \ +--extra-cflags="-DCONFIG_SAFE_BITSTREAM_READER=1" \ +--extra-cxxflags="-DCONFIG_SAFE_BITSTREAM_READER=1" \ --extra-ldflags="-libpath:$FullExecPath/../opus/win32/VS2015/Win32/Release" \ --disable-programs \ --disable-doc \ diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index f6caa032d..596c2c0f0 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -1726,8 +1726,9 @@ void Updates::feedUpdate(const MTPUpdate &update) { auto &d = update.c_updateEncryptedMessagesRead(); } break; - case mtpc_updatePhoneCall: { - Core::App().calls().handleUpdate(&session(), update.c_updatePhoneCall()); + case mtpc_updatePhoneCall: + case mtpc_updatePhoneCallSignalingData: { + Core::App().calls().handleUpdate(&session(), update); } break; case mtpc_updateUserBlocked: { diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 0a7286728..41ef4b96d 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -32,6 +32,7 @@ namespace { constexpr auto kMinLayer = 65; constexpr auto kHangupTimeoutMs = 5000; constexpr auto kSha256Size = 32; +const auto kDefaultVersion = "2.4.4"_q; void AppendEndpoint( std::vector &list, @@ -71,10 +72,6 @@ uint64 ComputeFingerprint(bytes::const_span authKey) { | (gsl::to_integer(hash[12])); } -[[nodiscard]] std::vector CollectVersions() { - return { TgVoip::getVersion() }; -} - [[nodiscard]] QVector WrapVersions( const std::vector &data) { auto result = QVector(); @@ -86,13 +83,11 @@ uint64 ComputeFingerprint(bytes::const_span authKey) { } [[nodiscard]] QVector CollectVersionsForApi() { - return WrapVersions(CollectVersions()); + return WrapVersions(CollectControllerVersions()); } } // namespace -Call::Delegate::~Delegate() = default; - Call::Call( not_null delegate, not_null user, @@ -170,7 +165,7 @@ void Call::startOutgoing() { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(TgVoip::getConnectionMaxLayer()), + MTP_int(ControllerMaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -251,7 +246,7 @@ void Call::actuallyAnswer() { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(TgVoip::getConnectionMaxLayer()), + MTP_int(ControllerMaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -322,6 +317,25 @@ void Call::startWaitingTrack() { _waitingTrack->playInLoop(); } +void Call::sendSignalingData(const QByteArray &data) { + _api.request(MTPphone_SendSignalingData( + MTP_inputPhoneCall( + MTP_long(_id), + MTP_long(_accessHash)), + MTP_bytes(data) + )).done([=](const MTPBool &result) { + if (!mtpIsTrue(result)) { + finish(FinishType::Failed); + } + }).fail([=](const RPCError &error) { + handleRequestError(error); + }).send(); +} + +void Call::displayNextFrame(QImage frame) { + _frames.fire(std::move(frame)); +} + float64 Call::getWaitingSoundPeakValue() const { if (_waitingTrack) { auto when = crl::now() + kSoundSampleMs / 4; @@ -462,6 +476,14 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { Unexpected("phoneCall type inside an existing call handleUpdate()"); } +bool Call::handleSignalingData( + const MTPDupdatePhoneCallSignalingData &data) { + if (data.vphone_call_id().v != _id || !_controller) { + return false; + } + return _controller->receiveSignalingData(data.vdata().v); +} + void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { Expects(_type == Type::Outgoing); @@ -494,9 +516,9 @@ void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(TgVoip::getConnectionMaxLayer()), + MTP_int(ControllerMaxLayer()), MTP_vector(CollectVersionsForApi())) - )).done([this](const MTPphone_PhoneCall &result) { + )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); auto &call = result.c_phone_phoneCall(); @@ -508,7 +530,7 @@ void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { } createAndStartController(call.vphone_call().c_phoneCall()); - }).fail([this](const RPCError &error) { + }).fail([=](const RPCError &error) { handleRequestError(error); }).send(); } @@ -597,14 +619,20 @@ void Call::createAndStartController(const MTPDphoneCall &call) { return static_cast(byte); }) | ranges::to_vector; + const auto version = call.vprotocol().match([&]( + const MTPDphoneCallProtocol &data) { + return data.vlibrary_versions().v; + }).value(0, MTP_bytes(kDefaultVersion)).v; _controller = MakeController( - "2.4.4", + version.toStdString(), config, TgVoipPersistentState(), endpoints, proxy.host.empty() ? nullptr : &proxy, TgVoipNetworkType::Unknown, - encryptionKey); + encryptionKey, + [=](QByteArray data) { sendSignalingData(data); }, + [=](QImage frame) { displayNextFrame(frame); }); const auto raw = _controller.get(); raw->setOnStateUpdated([=](TgVoipState state) { diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index 265e74671..f82e4ed70 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -48,7 +48,7 @@ public: virtual void playSound(Sound sound) = 0; virtual void requestMicrophonePermissionOrFail(Fn result) = 0; - virtual ~Delegate(); + virtual ~Delegate() = default; }; @@ -70,6 +70,7 @@ public: void start(bytes::const_span random); bool handleUpdate(const MTPPhoneCall &call); + bool handleSignalingData(const MTPDupdatePhoneCallSignalingData &data); enum State { Starting, @@ -110,6 +111,10 @@ public: return _muteChanged; } + rpl::producer frames() const { + return _frames.events(); + } + crl::time getDurationMs() const; float64 getWaitingSoundPeakValue() const; @@ -144,6 +149,8 @@ private: void startOutgoing(); void startIncoming(); void startWaitingTrack(); + void sendSignalingData(const QByteArray &data); + void displayNextFrame(QImage frame); void generateModExpFirst(bytes::const_span randomSeed); void handleControllerStateChange( @@ -181,6 +188,7 @@ private: bool _mute = false; base::Observable _muteChanged; + rpl::event_stream _frames; DhConfig _dhConfig; bytes::vector _ga; diff --git a/Telegram/SourceFiles/calls/calls_controller.cpp b/Telegram/SourceFiles/calls/calls_controller.cpp index d20f65e5d..9b82a8e6c 100644 --- a/Telegram/SourceFiles/calls/calls_controller.cpp +++ b/Telegram/SourceFiles/calls/calls_controller.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_controller.h" #include "calls/calls_controller_tgvoip.h" +#include "calls/calls_controller_webrtc.h" namespace Calls { @@ -18,7 +19,20 @@ namespace Calls { const std::vector &endpoints, const TgVoipProxy *proxy, TgVoipNetworkType initialNetworkType, - const TgVoipEncryptionKey &encryptionKey) { + const TgVoipEncryptionKey &encryptionKey, + Fn sendSignalingData, + Fn displayNextFrame) { + if (version == WebrtcController::Version()) { + return std::make_unique( + config, + persistentState, + endpoints, + proxy, + initialNetworkType, + encryptionKey, + std::move(sendSignalingData), + std::move(displayNextFrame)); + } return std::make_unique( config, persistentState, @@ -28,4 +42,12 @@ namespace Calls { encryptionKey); } +std::vector CollectControllerVersions() { + return { WebrtcController::Version(), TgVoipController::Version() }; +} + +int ControllerMaxLayer() { + return TgVoip::getConnectionMaxLayer(); +} + } // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_controller.h b/Telegram/SourceFiles/calls/calls_controller.h index 9c98d91be..cab175e25 100644 --- a/Telegram/SourceFiles/calls/calls_controller.h +++ b/Telegram/SourceFiles/calls/calls_controller.h @@ -26,6 +26,7 @@ public: virtual void setInputVolume(float level) = 0; virtual void setOutputVolume(float level) = 0; virtual void setAudioOutputDuckingEnabled(bool enabled) = 0; + virtual bool receiveSignalingData(const QByteArray &data) = 0; virtual std::string getLastError() = 0; virtual std::string getDebugInfo() = 0; @@ -48,6 +49,11 @@ public: const std::vector &endpoints, const TgVoipProxy *proxy, TgVoipNetworkType initialNetworkType, - const TgVoipEncryptionKey &encryptionKey); + const TgVoipEncryptionKey &encryptionKey, + Fn sendSignalingData, + Fn displayNextFrame); + +[[nodiscard]] std::vector CollectControllerVersions(); +[[nodiscard]] int ControllerMaxLayer(); } // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_controller_tgvoip.h b/Telegram/SourceFiles/calls/calls_controller_tgvoip.h index ebcb2bdd1..257660043 100644 --- a/Telegram/SourceFiles/calls/calls_controller_tgvoip.h +++ b/Telegram/SourceFiles/calls/calls_controller_tgvoip.h @@ -33,7 +33,7 @@ public: return TgVoip::getVersion(); } - [[nodiscard]] std::string version() override { + std::string version() override { return Version(); } void setNetworkType(TgVoipNetworkType networkType) override { @@ -63,6 +63,9 @@ public: void setAudioOutputDuckingEnabled(bool enabled) override { _impl->setAudioOutputDuckingEnabled(enabled); } + bool receiveSignalingData(const QByteArray &data) override { + return false; + } std::string getLastError() override { return _impl->getLastError(); } @@ -81,8 +84,7 @@ public: void setOnStateUpdated(Fn onStateUpdated) override { _impl->setOnStateUpdated(std::move(onStateUpdated)); } - void setOnSignalBarsUpdated( - Fn onSignalBarsUpdated) override { + void setOnSignalBarsUpdated(Fn onSignalBarsUpdated) override { _impl->setOnSignalBarsUpdated(std::move(onSignalBarsUpdated)); } TgVoipFinalState stop() override { diff --git a/Telegram/SourceFiles/calls/calls_controller_webrtc.cpp b/Telegram/SourceFiles/calls/calls_controller_webrtc.cpp new file mode 100644 index 000000000..f29b06853 --- /dev/null +++ b/Telegram/SourceFiles/calls/calls_controller_webrtc.cpp @@ -0,0 +1,175 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "calls/calls_controller_webrtc.h" + +#include "webrtc/webrtc_call_context.h" + +namespace Calls { +namespace { + +using namespace Webrtc; + +[[nodiscard]] CallConnectionDescription ConvertEndpoint(const TgVoipEndpoint &data) { + return CallConnectionDescription{ + .ip = QString::fromStdString(data.host.ipv4), + .ipv6 = QString::fromStdString(data.host.ipv6), + .peerTag = QByteArray( + reinterpret_cast(data.peerTag), + base::array_size(data.peerTag)), + .connectionId = data.endpointId, + .port = data.port, + }; +} + +[[nodiscard]] CallContext::Config MakeContextConfig( + const TgVoipConfig &config, + const TgVoipPersistentState &persistentState, + const std::vector &endpoints, + const TgVoipProxy *proxy, + TgVoipNetworkType initialNetworkType, + const TgVoipEncryptionKey &encryptionKey, + Fn sendSignalingData, + Fn displayNextFrame) { + Expects(!endpoints.empty()); + + auto result = CallContext::Config{ + .proxy = (proxy + ? ProxyServer{ + .host = QString::fromStdString(proxy->host), + .username = QString::fromStdString(proxy->login), + .password = QString::fromStdString(proxy->password), + .port = proxy->port } + : ProxyServer()), + .dataSaving = (config.dataSaving != TgVoipDataSaving::Never), + .key = QByteArray( + reinterpret_cast(encryptionKey.value.data()), + encryptionKey.value.size()), + .outgoing = encryptionKey.isOutgoing, + .primary = ConvertEndpoint(endpoints.front()), + .alternatives = endpoints | ranges::view::drop( + 1 + ) | ranges::view::transform(ConvertEndpoint) | ranges::to_vector, + .maxLayer = config.maxApiLayer, + .allowP2P = config.enableP2P, + .sendSignalingData = std::move(sendSignalingData), + .displayNextFrame = std::move(displayNextFrame), + }; + return result; +} + +} // namespace + +WebrtcController::WebrtcController( + const TgVoipConfig &config, + const TgVoipPersistentState &persistentState, + const std::vector &endpoints, + const TgVoipProxy *proxy, + TgVoipNetworkType initialNetworkType, + const TgVoipEncryptionKey &encryptionKey, + Fn sendSignalingData, + Fn displayNextFrame) +: _impl(std::make_unique(MakeContextConfig( + config, + persistentState, + endpoints, + proxy, + initialNetworkType, + encryptionKey, + std::move(sendSignalingData), + std::move(displayNextFrame)))) { +} + +WebrtcController::~WebrtcController() = default; + +std::string WebrtcController::Version() { + return CallContext::Version().toStdString(); +} + +std::string WebrtcController::version() { + return Version(); +} + +void WebrtcController::setNetworkType(TgVoipNetworkType networkType) { +} + +void WebrtcController::setMuteMicrophone(bool muteMicrophone) { + _impl->setIsMuted(muteMicrophone); +} + +void WebrtcController::setAudioOutputGainControlEnabled(bool enabled) { +} + +void WebrtcController::setEchoCancellationStrength(int strength) { +} + +void WebrtcController::setAudioInputDevice(std::string id) { +} + +void WebrtcController::setAudioOutputDevice(std::string id) { +} + +void WebrtcController::setInputVolume(float level) { +} + +void WebrtcController::setOutputVolume(float level) { +} + +void WebrtcController::setAudioOutputDuckingEnabled(bool enabled) { +} + +bool WebrtcController::receiveSignalingData(const QByteArray &data) { + return _impl->receiveSignalingData(data); +} + +std::string WebrtcController::getLastError() { + return {}; +} + +std::string WebrtcController::getDebugInfo() { + return _impl->getDebugInfo().toStdString(); +} + +int64_t WebrtcController::getPreferredRelayId() { + return 0; +} + +TgVoipTrafficStats WebrtcController::getTrafficStats() { + return {}; +} + +TgVoipPersistentState WebrtcController::getPersistentState() { + return TgVoipPersistentState{}; +} + +void WebrtcController::setOnStateUpdated( + Fn onStateUpdated) { + _stateUpdatedLifetime.destroy(); + _impl->state().changes( + ) | rpl::start_with_next([=](CallState state) { + onStateUpdated([&] { + switch (state) { + case CallState::Initializing: return TgVoipState::WaitInit; + case CallState::Reconnecting: return TgVoipState::Reconnecting; + case CallState::Connected: return TgVoipState::Established; + case CallState::Failed: return TgVoipState::Failed; + } + Unexpected("State value in Webrtc::CallContext::state."); + }()); + }, _stateUpdatedLifetime); +} + +void WebrtcController::setOnSignalBarsUpdated( + Fn onSignalBarsUpdated) { +} + +TgVoipFinalState WebrtcController::stop() { + _impl->stop(); + return TgVoipFinalState(); +} + +} // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_controller_webrtc.h b/Telegram/SourceFiles/calls/calls_controller_webrtc.h new file mode 100644 index 000000000..2cb99c669 --- /dev/null +++ b/Telegram/SourceFiles/calls/calls_controller_webrtc.h @@ -0,0 +1,60 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "calls/calls_controller.h" + +namespace Webrtc { +class CallContext; +} // namespace Webrtc + +namespace Calls { + +class WebrtcController final : public Controller { +public: + WebrtcController( + const TgVoipConfig &config, + const TgVoipPersistentState &persistentState, + const std::vector &endpoints, + const TgVoipProxy *proxy, + TgVoipNetworkType initialNetworkType, + const TgVoipEncryptionKey &encryptionKey, + Fn sendSignalingData, + Fn displayNextFrame); + ~WebrtcController(); + + [[nodiscard]] static std::string Version(); + + std::string version() override; + void setNetworkType(TgVoipNetworkType networkType) override; + void setMuteMicrophone(bool muteMicrophone) override; + void setAudioOutputGainControlEnabled(bool enabled) override; + void setEchoCancellationStrength(int strength) override; + void setAudioInputDevice(std::string id) override; + void setAudioOutputDevice(std::string id) override; + void setInputVolume(float level) override; + void setOutputVolume(float level) override; + void setAudioOutputDuckingEnabled(bool enabled) override; + bool receiveSignalingData(const QByteArray &data) override; + std::string getLastError() override; + std::string getDebugInfo() override; + int64_t getPreferredRelayId() override; + TgVoipTrafficStats getTrafficStats() override; + TgVoipPersistentState getPersistentState() override; + void setOnStateUpdated(Fn onStateUpdated) override; + void setOnSignalBarsUpdated(Fn onSignalBarsUpdated) override; + TgVoipFinalState stop() override; + +private: + const std::unique_ptr _impl; + + rpl::lifetime _stateUpdatedLifetime; + +}; + +} // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index 5c700db20..c1aab32fb 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -232,13 +232,19 @@ void Instance::refreshServerConfig(not_null session) { UpdateConfig(std::string(json.data(), json.size())); }).fail([=](const RPCError &error) { _serverConfigRequestSession = nullptr; - }).send(); + }).send(); } void Instance::handleUpdate( not_null session, - const MTPDupdatePhoneCall& update) { - handleCallUpdate(session, update.vphone_call()); + const MTPUpdate &update) { + update.match([&](const MTPDupdatePhoneCall &data) { + handleCallUpdate(session, data.vphone_call()); + }, [&](const MTPDupdatePhoneCallSignalingData &data) { + handleSignalingData(data); + }, [](const auto &) { + Unexpected("Update type in Calls::Instance::handleUpdate."); + }); } void Instance::showInfoPanel(not_null call) { @@ -291,6 +297,14 @@ void Instance::handleCallUpdate( } } +void Instance::handleSignalingData( + const MTPDupdatePhoneCallSignalingData &data) { + if (!_currentCall || !_currentCall->handleSignalingData(data)) { + DEBUG_LOG(("API Warning: unexpected call signaling data %1" + ).arg(data.vphone_call_id().v)); + } +} + bool Instance::alreadyInCall() { return (_currentCall && _currentCall->state() != Call::State::Busy); } diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index 92a6ad58a..41dac3400 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -35,7 +35,7 @@ public: void startOutgoingCall(not_null user); void handleUpdate( not_null session, - const MTPDupdatePhoneCall &update); + const MTPUpdate &update); void showInfoPanel(not_null call); [[nodiscard]] Call *currentCall() const; [[nodiscard]] rpl::producer currentCallValue() const; @@ -59,6 +59,8 @@ private: void destroyCurrentPanel(); void requestMicrophonePermissionOrFail(Fn onSuccess) override; + void handleSignalingData(const MTPDupdatePhoneCallSignalingData &data); + void refreshDhConfig(); void refreshServerConfig(not_null session); bytes::const_span updateDhConfig(const MTPmessages_DhConfig &data); diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index b44612e63..1bfdc9eba 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -400,6 +400,11 @@ void Panel::initControls() { _decline->finishAnimating(); _cancel->finishAnimating(); + + _call->frames() | rpl::start_with_next([=](QImage frame) { + _videoFrame = std::move(frame); + update(); + }, lifetime()); } void Panel::reinitControls() { @@ -742,6 +747,17 @@ void Panel::paintEvent(QPaintEvent *e) { p.fillRect(0, _contentTop, width(), height() - _contentTop, brush); } + if (!_videoFrame.isNull()) { + const auto to = rect().marginsRemoved(_padding); + p.save(); + p.setClipRect(to); + const auto big = _videoFrame.size().scaled(to.size(), Qt::KeepAspectRatioByExpanding); + const auto pos = QPoint((to.width() - big.width()) / 2, (to.height() - big.height()) / 2); + auto hq = PainterHighQualityEnabler(p); + p.drawImage(QRect(pos, big), _videoFrame); + p.restore(); + } + if (_signalBars->isDisplayed()) { paintSignalBarsBg(p); } diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index 697fe26a3..d518bb87d 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -158,6 +158,8 @@ private: QPixmap _bottomCache; QPixmap _cache; + QImage _videoFrame; + }; } // namespace Calls diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc index 2b1cd3b5b..eb5be1840 160000 --- a/Telegram/lib_webrtc +++ b/Telegram/lib_webrtc @@ -1 +1 @@ -Subproject commit 2b1cd3b5b0c909834aea00e0590435a63d318468 +Subproject commit eb5be18405d47a226f6a197280176f82b3e903bd From 71040464c53555fe66e6bdbbbb84ebe892b5b829 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 17 May 2020 13:12:27 +0400 Subject: [PATCH 036/142] Request camera permissions on macOS. --- Telegram/SourceFiles/calls/calls_call.cpp | 2 +- Telegram/SourceFiles/calls/calls_call.h | 2 +- Telegram/SourceFiles/calls/calls_instance.cpp | 28 ++++++--- Telegram/SourceFiles/calls/calls_instance.h | 7 ++- .../SourceFiles/platform/mac/specific_mac.mm | 59 +++++++++++-------- .../SourceFiles/platform/platform_specific.h | 1 + Telegram/Telegram.plist | 2 + Telegram/Telegram/Telegram.entitlements | 2 + Telegram/build/build.sh | 8 +-- 9 files changed, 71 insertions(+), 40 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 41ef4b96d..81e285735 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -217,7 +217,7 @@ void Call::startIncoming() { } void Call::answer() { - _delegate->requestMicrophonePermissionOrFail(crl::guard(this, [=] { + _delegate->requestPermissionsOrFail(crl::guard(this, [=] { actuallyAnswer(); })); } diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index f82e4ed70..582f72fa1 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -46,7 +46,7 @@ public: Ended, }; virtual void playSound(Sound sound) = 0; - virtual void requestMicrophonePermissionOrFail(Fn result) = 0; + virtual void requestPermissionsOrFail(Fn result) = 0; virtual ~Delegate() = default; diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index c1aab32fb..0ae72fc19 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -55,7 +55,7 @@ void Instance::startOutgoingCall(not_null user) { tr::lng_call_error_not_available(tr::now, lt_user, user->name))); return; } - requestMicrophonePermissionOrFail(crl::guard(this, [=] { + requestPermissionsOrFail(crl::guard(this, [=] { createCall(user, Call::Type::Outgoing); })); } @@ -317,13 +317,23 @@ rpl::producer Instance::currentCallValue() const { return _currentCallChanges.events_starting_with(currentCall()); } -void Instance::requestMicrophonePermissionOrFail(Fn onSuccess) { - Platform::PermissionStatus status=Platform::GetPermissionStatus(Platform::PermissionType::Microphone); - if (status==Platform::PermissionStatus::Granted) { +void Instance::requestPermissionsOrFail(Fn onSuccess) { + using Type = Platform::PermissionType; + requestPermissionOrFail(Type::Microphone, [=] { + requestPermissionOrFail(Type::Camera, [=] { + crl::on_main(onSuccess); + }); + }); +} + +void Instance::requestPermissionOrFail(Platform::PermissionType type, Fn onSuccess) { + using Status = Platform::PermissionStatus; + const auto status = Platform::GetPermissionStatus(type); + if (status == Status::Granted) { onSuccess(); - } else if(status==Platform::PermissionStatus::CanRequest) { - Platform::RequestPermission(Platform::PermissionType::Microphone, crl::guard(this, [=](Platform::PermissionStatus status) { - if (status==Platform::PermissionStatus::Granted) { + } else if (status == Status::CanRequest) { + Platform::RequestPermission(type, crl::guard(this, [=](Status status) { + if (status == Status::Granted) { crl::on_main(onSuccess); } else { if (_currentCall) { @@ -335,8 +345,8 @@ void Instance::requestMicrophonePermissionOrFail(Fn onSuccess) { if (alreadyInCall()) { _currentCall->hangup(); } - Ui::show(Box(tr::lng_no_mic_permission(tr::now), tr::lng_menu_settings(tr::now), crl::guard(this, [] { - Platform::OpenSystemSettingsForPermission(Platform::PermissionType::Microphone); + Ui::show(Box(tr::lng_no_mic_permission(tr::now), tr::lng_menu_settings(tr::now), crl::guard(this, [=] { + Platform::OpenSystemSettingsForPermission(type); Ui::hideLayer(); }))); } diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index 41dac3400..4bd159acd 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" #include "calls/calls_call.h" +namespace Platform { +enum class PermissionType; +} // namespace Platform + namespace Media { namespace Audio { class Track; @@ -57,7 +61,8 @@ private: void createCall(not_null user, Call::Type type); void destroyCall(not_null call); void destroyCurrentPanel(); - void requestMicrophonePermissionOrFail(Fn onSuccess) override; + void requestPermissionsOrFail(Fn onSuccess) override; + void requestPermissionOrFail(Platform::PermissionType type, Fn onSuccess); void handleSignalingData(const MTPDupdatePhoneCallSignalingData &data); diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.mm b/Telegram/SourceFiles/platform/mac/specific_mac.mm index 91f98ea9d..f2334247a 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac.mm @@ -170,19 +170,23 @@ void RegisterCustomScheme(bool force) { PermissionStatus GetPermissionStatus(PermissionType type) { #ifndef OS_MAC_OLD switch (type) { - case PermissionType::Microphone: - if([AVCaptureDevice respondsToSelector: @selector(authorizationStatusForMediaType:)]) { // Available starting with 10.14 - switch([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]) { - case AVAuthorizationStatusNotDetermined: - return PermissionStatus::CanRequest; - case AVAuthorizationStatusAuthorized: - return PermissionStatus::Granted; - case AVAuthorizationStatusDenied: - case AVAuthorizationStatusRestricted: - return PermissionStatus::Denied; - } + case PermissionType::Microphone: + case PermissionType::Camera: + const auto nativeType = (type == PermissionType::Microphone) + ? AVMediaTypeAudio + : AVMediaTypeVideo; + if ([AVCaptureDevice respondsToSelector: @selector(authorizationStatusForMediaType:)]) { // Available starting with 10.14 + switch ([AVCaptureDevice authorizationStatusForMediaType:nativeType]) { + case AVAuthorizationStatusNotDetermined: + return PermissionStatus::CanRequest; + case AVAuthorizationStatusAuthorized: + return PermissionStatus::Granted; + case AVAuthorizationStatusDenied: + case AVAuthorizationStatusRestricted: + return PermissionStatus::Denied; } - break; + } + break; } #endif // OS_MAC_OLD return PermissionStatus::Granted; @@ -191,15 +195,19 @@ PermissionStatus GetPermissionStatus(PermissionType type) { void RequestPermission(PermissionType type, Fn resultCallback) { #ifndef OS_MAC_OLD switch (type) { - case PermissionType::Microphone: - if ([AVCaptureDevice respondsToSelector: @selector(requestAccessForMediaType:completionHandler:)]) { // Available starting with 10.14 - [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { - crl::on_main([=] { - resultCallback(granted ? PermissionStatus::Granted : PermissionStatus::Denied); - }); - }]; - } - break; + case PermissionType::Microphone: + case PermissionType::Camera: + const auto nativeType = (type == PermissionType::Microphone) + ? AVMediaTypeAudio + : AVMediaTypeVideo; + if ([AVCaptureDevice respondsToSelector: @selector(requestAccessForMediaType:completionHandler:)]) { // Available starting with 10.14 + [AVCaptureDevice requestAccessForMediaType:nativeType completionHandler:^(BOOL granted) { + crl::on_main([=] { + resultCallback(granted ? PermissionStatus::Granted : PermissionStatus::Denied); + }); + }]; + } + break; } #endif // OS_MAC_OLD resultCallback(PermissionStatus::Granted); @@ -209,9 +217,12 @@ void RequestPermission(PermissionType type, Fn resultCal void OpenSystemSettingsForPermission(PermissionType type) { #ifndef OS_MAC_OLD switch (type) { - case PermissionType::Microphone: - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone"]]; - break; + case PermissionType::Microphone: + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone"]]; + break; + case PermissionType::Camera: + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Camera"]]; + break; } #endif // OS_MAC_OLD } diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 1939738e0..ec419bab7 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -22,6 +22,7 @@ enum class PermissionStatus { enum class PermissionType { Microphone, + Camera, }; enum class SystemSettingsType { diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index af4435e35..0506a8958 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -41,6 +41,8 @@ NSMicrophoneUsageDescription We need access to your microphone so that you can record voice messages and make calls. + NSCameraUsageDescription + We need access to your camera so that you can record video messages and make video calls. NSPrincipalClass NSApplication NSSupportsAutomaticGraphicsSwitching diff --git a/Telegram/Telegram/Telegram.entitlements b/Telegram/Telegram/Telegram.entitlements index b572d9c04..97c1f6d58 100644 --- a/Telegram/Telegram/Telegram.entitlements +++ b/Telegram/Telegram/Telegram.entitlements @@ -4,5 +4,7 @@ com.apple.security.device.audio-input + com.apple.security.device.camera + diff --git a/Telegram/build/build.sh b/Telegram/build/build.sh index 19da165c6..dd0183000 100755 --- a/Telegram/build/build.sh +++ b/Telegram/build/build.sh @@ -267,6 +267,10 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "osx" ] || [ "$BuildTarget fi if [ "$NotarizeRequestId" == "" ]; then + rm "$ReleasePath/$BinaryName.app/Contents/Info.plist" + rm "$ProjectPath/Telegram/CMakeFiles/Telegram.dir/Info.plist" + rm -rf "$ReleasePath/$BinaryName.app/Contents/_CodeSignature" + ./configure.sh cd $ProjectPath @@ -490,8 +494,6 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "osx" ] || [ "$BuildTarget mv "$ReleasePath/$BinaryName.app.dSYM" "$DeployPath/" rm "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName" rm "$ReleasePath/$BinaryName.app/Contents/Frameworks/Updater" - rm "$ReleasePath/$BinaryName.app/Contents/Info.plist" - rm -rf "$ReleasePath/$BinaryName.app/Contents/_CodeSignature" mv "$ReleasePath/$UpdateFile" "$DeployPath/" mv "$ReleasePath/$SetupFile" "$DeployPath/" @@ -518,8 +520,6 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "osx" ] || [ "$BuildTarget mv "$ReleasePath/$BinaryName.pkg" "$DeployPath/" mv "$ReleasePath/$BinaryName.app.dSYM" "$DeployPath/" rm "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName" - rm "$ReleasePath/$BinaryName.app/Contents/Info.plist" - rm -rf "$ReleasePath/$BinaryName.app/Contents/_CodeSignature" fi fi From b703f4e5557053d4cc320e42861db197c0ce7790 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 18 May 2020 18:24:20 +0400 Subject: [PATCH 037/142] Fix build on Linux. --- Telegram/CMakeLists.txt | 16 +++++- Telegram/SourceFiles/mainwindow.h | 2 +- .../platform/linux/main_window_linux.cpp | 50 +++++++++---------- Telegram/cmake/lib_tgvoip.cmake | 3 +- docs/building-cmake.md | 7 ++- 5 files changed, 46 insertions(+), 32 deletions(-) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 920e4483c..b2fd96b26 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -102,17 +102,17 @@ endif() target_link_libraries(Telegram PRIVATE + tdesktop::lib_tgvoip tdesktop::lib_mtproto tdesktop::lib_scheme tdesktop::lib_export - tdesktop::lib_tgvoip + desktop-app::lib_webrtc desktop-app::lib_base desktop-app::lib_crl desktop-app::lib_ui desktop-app::lib_tl desktop-app::lib_storage desktop-app::lib_lottie - desktop-app::lib_webrtc desktop-app::lib_qr desktop-app::lib_ffmpeg desktop-app::external_lz4 @@ -1226,6 +1226,18 @@ elseif (APPLE) ) endif() endif() +elseif (LINUX) + if (NOT TDESKTOP_DISABLE_GTK_INTEGRATION) + find_package(PkgConfig REQUIRED) + + pkg_search_module(GTK REQUIRED gtk+-2.0 gtk+-3.0) + target_include_directories(Telegram PRIVATE ${GTK_INCLUDE_DIRS}) + + if (DESKTOP_APP_USE_PACKAGED) + find_library(X11_LIBRARY X11) + target_link_libraries(Telegram PRIVATE ${X11_LIBRARY}) + endif() + endif() endif() if (build_macstore) diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index 4ca8e07f4..57a67eb50 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -66,6 +66,7 @@ public: void sendPaths(); QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override; + void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) override; bool contentOverlapped(const QRect &globalRect); bool contentOverlapped(QWidget *w, QPaintEvent *e) { @@ -139,7 +140,6 @@ private: QPixmap grabInner(); - void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) override; QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64; crl::time _lastTrayClickTime = 0; diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index db9a32190..87cc33e79 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -197,34 +197,34 @@ QIcon TrayIconGen(int counter, bool muted) { if (!qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) && counter > 0) { - QPainter p(&iconImage); - int32 layerSize = -16; - - if (iconSize >= 48) { - layerSize = -32; - } else if (iconSize >= 36) { - layerSize = -24; - } else if (iconSize >= 32) { - layerSize = -20; - } - - auto &bg = muted + const auto &bg = muted ? st::trayCounterBgMute : st::trayCounterBg; + const auto &fg = st::trayCounterFg; + if (iconSize >= 22) { + auto layerSize = -16; + if (iconSize >= 48) { + layerSize = -32; + } else if (iconSize >= 36) { + layerSize = -24; + } else if (iconSize >= 32) { + layerSize = -20; + } + const auto layer = App::wnd()->iconWithCounter( + layerSize, + counter, + bg, + fg, + false); - auto &fg = st::trayCounterFg; - - auto layer = App::wnd()->iconWithCounter( - layerSize, - counter, - bg, - fg, - false); - - p.drawImage( - iconImage.width() - layer.width() - 1, - iconImage.height() - layer.height() - 1, - layer); + QPainter p(&iconImage); + p.drawImage( + iconImage.width() - layer.width() - 1, + iconImage.height() - layer.height() - 1, + layer); + } else { + App::wnd()->placeSmallCounter(iconImage, 16, counter, bg, QPoint(), fg); + } } result.addPixmap(App::pixmapFromImageInPlace( diff --git a/Telegram/cmake/lib_tgvoip.cmake b/Telegram/cmake/lib_tgvoip.cmake index ecf773f4d..50748c324 100644 --- a/Telegram/cmake/lib_tgvoip.cmake +++ b/Telegram/cmake/lib_tgvoip.cmake @@ -176,9 +176,8 @@ else() target_link_libraries(lib_tgvoip PRIVATE - desktop-app::external_openssl - desktop-app::external_opus desktop-app::external_webrtc + desktop-app::external_opus ) if (LINUX) diff --git a/docs/building-cmake.md b/docs/building-cmake.md index 27bf7d047..81269c4ce 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -68,14 +68,14 @@ Go to ***BuildPath*** and run git clone https://github.com/01org/libva.git cd libva - ./autogen.sh --enable-static + CFLAGS=-fPIC CPPFLAGS=-fPIC LDFLAGS=-fPIC ./autogen.sh --enable-static make $MAKE_THREADS_CNT sudo make install cd .. git clone https://gitlab.freedesktop.org/vdpau/libvdpau.git --depth=1 -b libvdpau-1.2 cd libvdpau - ./autogen.sh --enable-static + CFLAGS=-fPIC CPPFLAGS=-fPIC LDFLAGS=-fPIC ./autogen.sh --enable-static make $MAKE_THREADS_CNT sudo make install cd .. @@ -85,6 +85,9 @@ Go to ***BuildPath*** and run git checkout release/3.4 ./configure \ + --extra-cflags="-fPIC" \ + --extra-cxxflags="-fPIC" \ + --extra-ldflags="-fPIC" \ --disable-programs \ --disable-doc \ --disable-network \ From 12e0399cf441f695f09f2b08e5092b7cafd62c95 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 9 Jul 2020 21:38:26 +0400 Subject: [PATCH 038/142] Add tgcalls library. --- .gitmodules | 3 + Telegram/CMakeLists.txt | 8 +- Telegram/SourceFiles/calls/calls_call.cpp | 263 ++++++++++++------ Telegram/SourceFiles/calls/calls_call.h | 13 +- Telegram/SourceFiles/main/main_app_config.cpp | 31 +++ Telegram/SourceFiles/main/main_app_config.h | 5 + Telegram/ThirdParty/tgcalls | 1 + Telegram/cmake/lib_tgcalls.cmake | 102 +++++++ Telegram/cmake/lib_tgvoip.cmake | 2 - Telegram/lib_webrtc | 2 +- docs/building-msvc.md | 10 + 11 files changed, 333 insertions(+), 107 deletions(-) create mode 160000 Telegram/ThirdParty/tgcalls create mode 100644 Telegram/cmake/lib_tgcalls.cmake diff --git a/.gitmodules b/.gitmodules index e0dcccaa9..48fe67ce6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,3 +97,6 @@ [submodule "Telegram/lib_webrtc"] path = Telegram/lib_webrtc url = https://github.com/desktop-app/lib_webrtc.git +[submodule "Telegram/ThirdParty/tgcalls"] + path = Telegram/ThirdParty/tgcalls + url = https://github.com/TelegramMessenger/tgcalls.git diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index b2fd96b26..14b902a46 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -35,6 +35,7 @@ include(cmake/lib_ffmpeg.cmake) include(cmake/lib_mtproto.cmake) include(cmake/lib_scheme.cmake) include(cmake/lib_tgvoip.cmake) +include(cmake/lib_tgcalls.cmake) set(style_files boxes/boxes.style @@ -102,6 +103,8 @@ endif() target_link_libraries(Telegram PRIVATE + tdesktop::lib_tgcalls_legacy + tdesktop::lib_tgcalls tdesktop::lib_tgvoip tdesktop::lib_mtproto tdesktop::lib_scheme @@ -315,11 +318,6 @@ PRIVATE calls/calls_box_controller.h calls/calls_call.cpp calls/calls_call.h - calls/calls_controller.cpp - calls/calls_controller.h - calls/calls_controller_tgvoip.h - calls/calls_controller_webrtc.cpp - calls/calls_controller_webrtc.h calls/calls_emoji_fingerprint.cpp calls/calls_emoji_fingerprint.h calls/calls_instance.cpp diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 81e285735..7746ab533 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_call.h" #include "main/main_session.h" +#include "main/main_account.h" +#include "main/main_app_config.h" #include "apiwrap.h" #include "lang/lang_keys.h" #include "boxes/confirm_box.h" @@ -21,11 +23,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/audio/media_audio_track.h" #include "base/platform/base_platform_info.h" #include "calls/calls_panel.h" -#include "calls/calls_controller.h" #include "data/data_user.h" #include "data/data_session.h" #include "facades.h" +#include "tgcalls/Instance.h" + +namespace tgcalls { +class InstanceImpl; +class InstanceImplLegacy; +void SetLegacyGlobalServerConfig(const std::string &serverConfig); +} // namespace tgcalls + namespace Calls { namespace { @@ -34,20 +43,23 @@ constexpr auto kHangupTimeoutMs = 5000; constexpr auto kSha256Size = 32; const auto kDefaultVersion = "2.4.4"_q; +const auto RegisterTag = tgcalls::Register(); +const auto RegisterTagLegacy = tgcalls::Register(); + void AppendEndpoint( - std::vector &list, + std::vector &list, const MTPPhoneConnection &connection) { connection.match([&](const MTPDphoneConnection &data) { if (data.vpeer_tag().v.length() != 16) { return; } - auto endpoint = TgVoipEndpoint{ + auto endpoint = tgcalls::Endpoint{ .endpointId = (int64_t)data.vid().v, - .host = TgVoipEdpointHost{ + .host = tgcalls::EndpointHost{ .ipv4 = data.vip().v.toStdString(), .ipv6 = data.vipv6().v.toStdString() }, .port = (uint16_t)data.vport().v, - .type = TgVoipEndpointType::UdpRelay + .type = tgcalls::EndpointType::UdpRelay }; const auto tag = data.vpeer_tag().v; if (tag.size() >= 16) { @@ -83,7 +95,48 @@ uint64 ComputeFingerprint(bytes::const_span authKey) { } [[nodiscard]] QVector CollectVersionsForApi() { - return WrapVersions(CollectControllerVersions()); + return WrapVersions(tgcalls::Meta::Versions() | ranges::action::reverse); +} + +[[nodiscard]] std::vector CollectRtcServers( + not_null user) { + using tgcalls::RtcServer; + using List = std::vector>; + + auto result = std::vector(); + const auto list = user->account().appConfig().get( + "rtc_servers", + List()); + result.reserve(list.size() * 2); + for (const auto &entry : list) { + const auto find = [&](const QString &key) { + const auto i = entry.find(key); + return (i != entry.end()) ? i->second : QString(); + }; + const auto host = find(u"host"_q).toStdString(); + const auto port = find(u"port"_q).toUShort(); + const auto username = find(u"username"_q).toStdString(); + const auto password = find(u"password"_q).toStdString(); + if (host.empty() || !port) { + continue; + } + result.push_back(RtcServer{ + .host = host, + .port = port, + .isTurn = false + }); + if (username.empty() || password.empty()) { + continue; + } + result.push_back(RtcServer{ + .host = host, + .port = port, + .login = username, + .password = password, + .isTurn = true, + }); + } + return result; } } // namespace @@ -165,7 +218,7 @@ void Call::startOutgoing() { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(ControllerMaxLayer()), + MTP_int(tgcalls::Meta::MaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -246,7 +299,7 @@ void Call::actuallyAnswer() { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(ControllerMaxLayer()), + MTP_int(tgcalls::Meta::MaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -267,8 +320,8 @@ void Call::actuallyAnswer() { void Call::setMute(bool mute) { _mute = mute; - if (_controller) { - _controller->setMuteMicrophone(_mute); + if (_instance) { + _instance->setMuteMicrophone(_mute); } _muteChanged.notify(_mute); } @@ -294,7 +347,7 @@ void Call::redial() { if (_state.current() != State::Busy) { return; } - Assert(_controller == nullptr); + Assert(_instance == nullptr); _type = Type::Outgoing; setState(State::Requesting); _answerAfterDhConfigReceived = false; @@ -303,7 +356,7 @@ void Call::redial() { } QString Call::getDebugLog() const { - return QString::fromStdString(_controller->getDebugInfo()); + return QString::fromStdString(_instance->getDebugInfo()); } void Call::startWaitingTrack() { @@ -418,7 +471,7 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { } if (_type == Type::Incoming && _state.current() == State::ExchangingKeys - && !_controller) { + && !_instance) { startConfirmedCall(data); } } return true; @@ -429,8 +482,8 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { return false; } if (data.is_need_debug()) { - auto debugLog = _controller - ? _controller->getDebugInfo() + auto debugLog = _instance + ? _instance->getDebugInfo() : std::string(); if (!debugLog.empty()) { user()->session().api().request(MTPphone_SaveCallDebug( @@ -478,17 +531,23 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { bool Call::handleSignalingData( const MTPDupdatePhoneCallSignalingData &data) { - if (data.vphone_call_id().v != _id || !_controller) { + if (data.vphone_call_id().v != _id || !_instance) { return false; } - return _controller->receiveSignalingData(data.vdata().v); + auto prepared = ranges::view::all( + data.vdata().v + ) | ranges::view::transform([](char byte) { + return static_cast(byte); + }) | ranges::to_vector; + _instance->receiveSignalingData(std::move(prepared)); + return true; } void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { Expects(_type == Type::Outgoing); if (_state.current() == State::ExchangingKeys - || _controller) { + || _instance) { LOG(("Call Warning: Unexpected confirmAcceptedCall.")); return; } @@ -516,7 +575,7 @@ void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(ControllerMaxLayer()), + MTP_int(tgcalls::Meta::MaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -568,52 +627,80 @@ void Call::createAndStartController(const MTPDphoneCall &call) { const auto &protocol = call.vprotocol().c_phoneCallProtocol(); const auto &serverConfig = _user->session().serverConfig(); - TgVoipConfig config; - config.dataSaving = TgVoipDataSaving::Never; - config.enableAEC = !Platform::IsMac10_7OrGreater(); - config.enableNS = true; - config.enableAGC = true; - config.enableVolumeControl = true; - config.initializationTimeout = serverConfig.callConnectTimeoutMs / 1000.; - config.receiveTimeout = serverConfig.callPacketTimeoutMs / 1000.; - config.enableP2P = call.is_p2p_allowed(); - config.maxApiLayer = protocol.vmax_layer().v; + const auto weak = base::make_weak(this); + auto descriptor = tgcalls::Descriptor{ + .config = tgcalls::Config{ + .initializationTimeout = serverConfig.callConnectTimeoutMs / 1000., + .receiveTimeout = serverConfig.callPacketTimeoutMs / 1000., + .dataSaving = tgcalls::DataSaving::Never, + .enableP2P = call.is_p2p_allowed(), + .enableAEC = !Platform::IsMac10_7OrGreater(), + .enableNS = true, + .enableAGC = true, + .enableVolumeControl = true, + .maxApiLayer = protocol.vmax_layer().v, + }, + .videoCapture = nullptr, + .stateUpdated = [=](tgcalls::State state) { + crl::on_main(weak, [=] { + handleControllerStateChange(state); + }); + }, + .videoStateUpdated = [=](bool state) { + + }, + .signalBarsUpdated = [=](int count) { + crl::on_main(weak, [=] { + handleControllerBarCountChange(count); + }); + }, + .remoteVideoIsActiveUpdated = [=](bool active) { + }, + .signalingDataEmitted = [=](const std::vector &data) { + const auto bytes = QByteArray( + reinterpret_cast(data.data()), + data.size()); + crl::on_main(weak, [=] { + sendSignalingData(bytes); + }); + }, + }; if (Logs::DebugEnabled()) { auto callLogFolder = cWorkingDir() + qsl("DebugLogs"); auto callLogPath = callLogFolder + qsl("/last_call_log.txt"); auto callLogNative = QDir::toNativeSeparators(callLogPath); #ifdef Q_OS_WIN - config.logPath = callLogNative.toStdWString(); + descriptor.config.logPath = callLogNative.toStdWString(); #else // Q_OS_WIN const auto callLogUtf = QFile::encodeName(callLogNative); - config.logPath.resize(callLogUtf.size()); + descriptor.config.logPath.resize(callLogUtf.size()); ranges::copy(callLogUtf, config.logPath.begin()); #endif // Q_OS_WIN QFile(callLogPath).remove(); QDir().mkpath(callLogFolder); } - auto endpoints = std::vector(); for (const auto &connection : call.vconnections().v) { - AppendEndpoint(endpoints, connection); + AppendEndpoint(descriptor.endpoints, connection); } - auto proxy = TgVoipProxy(); + descriptor.rtcServers = CollectRtcServers(_user); + if (Global::UseProxyForCalls() && (Global::ProxySettings() == MTP::ProxyData::Settings::Enabled)) { const auto &selected = Global::SelectedProxy(); - if (selected.supportsCalls()) { + if (selected.supportsCalls() && !selected.host.isEmpty()) { Assert(selected.type == MTP::ProxyData::Type::Socks5); - proxy.host = selected.host.toStdString(); - proxy.port = selected.port; - proxy.login = selected.user.toStdString(); - proxy.password = selected.password.toStdString(); + descriptor.proxy = std::make_unique(); + descriptor.proxy->host = selected.host.toStdString(); + descriptor.proxy->port = selected.port; + descriptor.proxy->login = selected.user.toStdString(); + descriptor.proxy->password = selected.password.toStdString(); } } - auto encryptionKey = TgVoipEncryptionKey(); - encryptionKey.isOutgoing = (_type == Type::Outgoing); - encryptionKey.value = ranges::view::all( + descriptor.encryptionKey.isOutgoing = (_type == Type::Outgoing); + descriptor.encryptionKey.value = ranges::view::all( _authKey ) | ranges::view::transform([](bytes::type byte) { return static_cast(byte); @@ -623,28 +710,26 @@ void Call::createAndStartController(const MTPDphoneCall &call) { const MTPDphoneCallProtocol &data) { return data.vlibrary_versions().v; }).value(0, MTP_bytes(kDefaultVersion)).v; - _controller = MakeController( - version.toStdString(), - config, - TgVoipPersistentState(), - endpoints, - proxy.host.empty() ? nullptr : &proxy, - TgVoipNetworkType::Unknown, - encryptionKey, - [=](QByteArray data) { sendSignalingData(data); }, - [=](QImage frame) { displayNextFrame(frame); }); - const auto raw = _controller.get(); - raw->setOnStateUpdated([=](TgVoipState state) { - handleControllerStateChange(raw, state); - }); - raw->setOnSignalBarsUpdated([=](int count) { - handleControllerBarCountChange(count); - }); + LOG(("Call Info: Creating instance with version '%1', allowP2P: %2" + ).arg(QString::fromUtf8(version) + ).arg(Logs::b(descriptor.config.enableP2P))); + _instance = tgcalls::Meta::Create( + version.toStdString(), + std::move(descriptor)); + if (!_instance) { + LOG(("Call Error: Wrong library version: %1." + ).arg(QString::fromUtf8(version))); + finish(FinishType::Failed); + return; + } + + const auto raw = _instance.get(); if (_mute) { raw->setMuteMicrophone(_mute); } const auto &settings = Core::App().settings(); + //raw->setIncomingVideoOutput(std::make_shared>()) raw->setAudioOutputDevice( settings.callOutputDeviceID().toStdString()); raw->setAudioInputDevice( @@ -654,32 +739,27 @@ void Call::createAndStartController(const MTPDphoneCall &call) { raw->setAudioOutputDuckingEnabled(settings.callAudioDuckingEnabled()); } -void Call::handleControllerStateChange( - not_null controller, - TgVoipState state) { - // NB! Can be called from an arbitrary thread! - // This can be called from ~VoIPController()! - +void Call::handleControllerStateChange(tgcalls::State state) { switch (state) { - case TgVoipState::WaitInit: { + case tgcalls::State::WaitInit: { DEBUG_LOG(("Call Info: State changed to WaitingInit.")); - setStateQueued(State::WaitingInit); + setState(State::WaitingInit); } break; - case TgVoipState::WaitInitAck: { + case tgcalls::State::WaitInitAck: { DEBUG_LOG(("Call Info: State changed to WaitingInitAck.")); - setStateQueued(State::WaitingInitAck); + setState(State::WaitingInitAck); } break; - case TgVoipState::Established: { + case tgcalls::State::Established: { DEBUG_LOG(("Call Info: State changed to Established.")); - setStateQueued(State::Established); + setState(State::Established); } break; - case TgVoipState::Failed: { - auto error = QString::fromStdString(controller->getLastError()); + case tgcalls::State::Failed: { + auto error = QString::fromStdString(_instance->getLastError()); LOG(("Call Info: State changed to Failed, error: %1.").arg(error)); - setFailedQueued(error); + handleControllerError(error); } break; default: LOG(("Call Error: Unexpected state in handleStateChange: %1" @@ -688,12 +768,7 @@ void Call::handleControllerStateChange( } void Call::handleControllerBarCountChange(int count) { - // NB! Can be called from an arbitrary thread! - // This can be called from ~VoIPController()! - - crl::on_main(this, [=] { - setSignalBarCount(count); - }); + setSignalBarCount(count); } void Call::setSignalBarCount(int count) { @@ -794,28 +869,28 @@ void Call::setState(State state) { } void Call::setCurrentAudioDevice(bool input, std::string deviceID) { - if (_controller) { + if (_instance) { if (input) { - _controller->setAudioInputDevice(deviceID); + _instance->setAudioInputDevice(deviceID); } else { - _controller->setAudioOutputDevice(deviceID); + _instance->setAudioOutputDevice(deviceID); } } } void Call::setAudioVolume(bool input, float level) { - if (_controller) { + if (_instance) { if (input) { - _controller->setInputVolume(level); + _instance->setInputVolume(level); } else { - _controller->setOutputVolume(level); + _instance->setOutputVolume(level); } } } void Call::setAudioDuckingEnabled(bool enabled) { - if (_controller) { - _controller->setAudioOutputDuckingEnabled(enabled); + if (_instance) { + _instance->setAudioOutputDuckingEnabled(enabled); } } @@ -846,7 +921,7 @@ void Call::finish(FinishType type, const MTPPhoneCallDiscardReason &reason) { setState(hangupState); auto duration = getDurationMs() / 1000; - auto connectionId = _controller ? _controller->getPreferredRelayId() : 0; + auto connectionId = _instance ? _instance->getPreferredRelayId() : 0; _finishByTimeoutTimer.call(kHangupTimeoutMs, [this, finalState] { setState(finalState); }); _api.request(MTPphone_DiscardCall( MTP_flags(0), @@ -902,9 +977,13 @@ void Call::handleControllerError(const QString &error) { } void Call::destroyController() { - if (_controller) { + if (_instance) { + AssertIsDebug(); + const auto state = _instance->stop(); + LOG(("CALL_LOG: %1").arg(QString::fromStdString(state.debugLog))); + DEBUG_LOG(("Call Info: Destroying call controller..")); - _controller.reset(); + _instance.reset(); DEBUG_LOG(("Call Info: Call controller destroyed.")); } setSignalBarCount(kSignalBarFinished); @@ -915,7 +994,7 @@ Call::~Call() { } void UpdateConfig(const std::string &data) { - TgVoip::setGlobalServerConfig(data); + tgcalls::SetLegacyGlobalServerConfig(data); } } // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index 582f72fa1..eb2eb8328 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -19,12 +19,13 @@ class Track; } // namespace Audio } // namespace Media -enum class TgVoipState; +namespace tgcalls { +class Instance; +enum class State; +} // namespace tgcalls namespace Calls { -class Controller; - struct DhConfig { int32 version = 0; int32 g = 0; @@ -153,9 +154,7 @@ private: void displayNextFrame(QImage frame); void generateModExpFirst(bytes::const_span randomSeed); - void handleControllerStateChange( - not_null controller, - TgVoipState state); + void handleControllerStateChange(tgcalls::State state); void handleControllerBarCountChange(int count); void createAndStartController(const MTPDphoneCall &call); @@ -202,7 +201,7 @@ private: uint64 _accessHash = 0; uint64 _keyFingerprint = 0; - std::unique_ptr _controller; + std::unique_ptr _instance; std::unique_ptr _waitingTrack; diff --git a/Telegram/SourceFiles/main/main_app_config.cpp b/Telegram/SourceFiles/main/main_app_config.cpp index bf6648a9a..9311eb6a0 100644 --- a/Telegram/SourceFiles/main/main_app_config.cpp +++ b/Telegram/SourceFiles/main/main_app_config.cpp @@ -117,6 +117,7 @@ std::vector AppConfig::getStringArray( return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonArray &data) { auto result = std::vector(); + result.reserve(data.vvalue().v.size()); for (const auto &entry : data.vvalue().v) { if (entry.type() != mtpc_jsonString) { return std::move(fallback); @@ -130,6 +131,36 @@ std::vector AppConfig::getStringArray( }); } +std::vector> AppConfig::getStringMapArray( + const QString &key, + std::vector> &&fallback) const { + return getValue(key, [&](const MTPJSONValue &value) { + return value.match([&](const MTPDjsonArray &data) { + auto result = std::vector>(); + result.reserve(data.vvalue().v.size()); + for (const auto &entry : data.vvalue().v) { + if (entry.type() != mtpc_jsonObject) { + return std::move(fallback); + } + auto element = std::map(); + for (const auto &field : entry.c_jsonObject().vvalue().v) { + const auto &data = field.c_jsonObjectValue(); + if (data.vvalue().type() != mtpc_jsonString) { + return std::move(fallback); + } + element.emplace( + qs(data.vkey()), + qs(data.vvalue().c_jsonString().vvalue())); + } + result.push_back(std::move(element)); + } + return result; + }, [&](const auto &data) { + return std::move(fallback); + }); + }); +} + bool AppConfig::suggestionCurrent(const QString &key) const { return !_dismissedSuggestions.contains(key) && ranges::contains( diff --git a/Telegram/SourceFiles/main/main_app_config.h b/Telegram/SourceFiles/main/main_app_config.h index 176d73c58..1235b7b40 100644 --- a/Telegram/SourceFiles/main/main_app_config.h +++ b/Telegram/SourceFiles/main/main_app_config.h @@ -25,6 +25,8 @@ public: return getString(key, fallback); } else if constexpr (std::is_same_v>) { return getStringArray(key, std::move(fallback)); + } else if constexpr (std::is_same_v>>) { + return getStringMapArray(key, std::move(fallback)); } else if constexpr (std::is_same_v) { return getBool(key, fallback); } @@ -60,6 +62,9 @@ private: [[nodiscard]] std::vector getStringArray( const QString &key, std::vector &&fallback) const; + [[nodiscard]] std::vector> getStringMapArray( + const QString &key, + std::vector> &&fallback) const; const not_null _account; std::optional _api; diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls new file mode 160000 index 000000000..ccba25880 --- /dev/null +++ b/Telegram/ThirdParty/tgcalls @@ -0,0 +1 @@ +Subproject commit ccba258805478783804cf273ff8c5edffd9f009a diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake new file mode 100644 index 000000000..3b6fc933d --- /dev/null +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -0,0 +1,102 @@ +# This file is part of Telegram Desktop, +# the official desktop application for the Telegram messaging service. +# +# For license and copyright information please follow this link: +# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL + +add_library(lib_tgcalls STATIC) +init_target(lib_tgcalls) +add_library(tdesktop::lib_tgcalls ALIAS lib_tgcalls) + +set(tgcalls_dir ${third_party_loc}/tgcalls) +set(tgcalls_loc ${tgcalls_dir}/tgcalls) + +nice_target_sources(lib_tgcalls ${tgcalls_loc} +PRIVATE + Manager.cpp + Manager.h + MediaManager.cpp + MediaManager.h + NetworkManager.cpp + NetworkManager.h + Instance.cpp + Instance.h + InstanceImpl.cpp + InstanceImpl.h + ThreadLocalObject.h + VideoCaptureInterface.cpp + VideoCaptureInterface.h + VideoCaptureInterfaceImpl.cpp + VideoCaptureInterfaceImpl.h + VideoCapturerInterface.h + platform/PlatformInterface.h + + # Windows + platform/windows/WindowsInterface.cpp + platform/windows/WindowsInterface.h + platform/windows/VideoCapturerInterfaceImpl.cpp + platform/windows/VideoCapturerInterfaceImpl.h + + # iOS / macOS + platform/darwin/DarwinInterface.h + platform/darwin/DarwinInterface.mm + platform/darwin/TGRTCDefaultVideoDecoderFactory.h + platform/darwin/TGRTCDefaultVideoDecoderFactory.mm + platform/darwin/TGRTCDefaultVideoEncoderFactory.h + platform/darwin/TGRTCDefaultVideoEncoderFactory.mm + platform/darwin/TGRTCVideoDecoderH265.h + platform/darwin/TGRTCVideoDecoderH265.mm + platform/darwin/TGRTCVideoEncoderH265.h + platform/darwin/TGRTCVideoEncoderH265.mm + platform/darwin/VideoCameraCapturer.h + platform/darwin/VideoCameraCapturer.mm + platform/darwin/VideoCapturerInterfaceImpl.h + platform/darwin/VideoCapturerInterfaceImpl.mm + platform/darwin/VideoMetalView.h + platform/darwin/VideoMetalView.mm + + # Linux + + # POSIX +) + +if (WIN32) + target_compile_definitions(lib_tgcalls + PRIVATE + TARGET_OS_WIN + ) +endif() + +target_include_directories(lib_tgcalls +PUBLIC + ${tgcalls_dir} +PRIVATE + ${tgcalls_loc} +) + +target_link_libraries(lib_tgcalls +PRIVATE + desktop-app::external_webrtc +) + +add_library(lib_tgcalls_legacy STATIC) +init_target(lib_tgcalls_legacy) +add_library(tdesktop::lib_tgcalls_legacy ALIAS lib_tgcalls_legacy) + +nice_target_sources(lib_tgcalls_legacy ${tgcalls_loc} +PRIVATE + legacy/InstanceImplLegacy.cpp + legacy/InstanceImplLegacy.h +) + +target_include_directories(lib_tgcalls_legacy +PRIVATE + ${tgcalls_loc} +) + +target_link_libraries(lib_tgcalls_legacy +PRIVATE + tdesktop::lib_tgcalls + tdesktop::lib_tgvoip + desktop-app::external_openssl +) diff --git a/Telegram/cmake/lib_tgvoip.cmake b/Telegram/cmake/lib_tgvoip.cmake index 50748c324..27e74d07a 100644 --- a/Telegram/cmake/lib_tgvoip.cmake +++ b/Telegram/cmake/lib_tgvoip.cmake @@ -48,8 +48,6 @@ else() OpusEncoder.cpp OpusEncoder.h threading.h - TgVoip.cpp - TgVoip.h VoIPController.cpp VoIPGroupController.cpp VoIPController.h diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc index eb5be1840..d3d96130b 160000 --- a/Telegram/lib_webrtc +++ b/Telegram/lib_webrtc @@ -1 +1 @@ -Subproject commit eb5be18405d47a226f6a197280176f82b3e903bd +Subproject commit d3d96130ba245e985c79c9040459b548416efdf8 diff --git a/docs/building-msvc.md b/docs/building-msvc.md index 4b80dfe90..d7beba696 100644 --- a/docs/building-msvc.md +++ b/docs/building-msvc.md @@ -163,6 +163,16 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath*** jom -j4 install cd .. + mkdir webrtc + cd webrtc + copy ..\patches\webrtc.gclient .gclient + git clone https://github.com/open-webrtc-toolkit/owt-deps-webrtc src + gclient sync + cd src + ..\..\..\tdesktop\Telegram\lib_webrtc\gn_build_webrtc.bat + ninja -C out/Debug webrtc test:platform_video_capturer test:video_test_common + cd .. + ## Build the project Go to ***BuildPath*\\tdesktop\\Telegram** and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials)) From 815300bffc3fa62a8d0971be7d61188e1bfaff3e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Jul 2020 17:55:46 +0400 Subject: [PATCH 039/142] Fix video between tdesktop instances. --- Telegram/SourceFiles/calls/calls_call.cpp | 11 +++++++++-- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 4 ++-- Telegram/cmake/lib_tgvoip.cmake | 10 +--------- Telegram/lib_webrtc | 2 +- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 7746ab533..9a9070ee3 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -23,11 +23,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/audio/media_audio_track.h" #include "base/platform/base_platform_info.h" #include "calls/calls_panel.h" +#include "webrtc/webrtc_video_sink.h" #include "data/data_user.h" #include "data/data_session.h" #include "facades.h" -#include "tgcalls/Instance.h" +#include namespace tgcalls { class InstanceImpl; @@ -706,6 +707,8 @@ void Call::createAndStartController(const MTPDphoneCall &call) { return static_cast(byte); }) | ranges::to_vector; + descriptor.videoCapture = tgcalls::CreateVideoCapture(); + const auto version = call.vprotocol().match([&]( const MTPDphoneCallProtocol &data) { return data.vlibrary_versions().v; @@ -729,7 +732,11 @@ void Call::createAndStartController(const MTPDphoneCall &call) { raw->setMuteMicrophone(_mute); } const auto &settings = Core::App().settings(); - //raw->setIncomingVideoOutput(std::make_shared>()) + raw->setIncomingVideoOutput(webrtc::CreateVideoSink([=](QImage frame) { + crl::on_main(weak, [=] { + _frames.fire_copy(frame); + }); + })); raw->setAudioOutputDevice( settings.callOutputDeviceID().toStdString()); raw->setAudioInputDevice( diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index ccba25880..f7b3ad47d 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit ccba258805478783804cf273ff8c5edffd9f009a +Subproject commit f7b3ad47df96bacf50bd958065d4d7d2901d9cfb diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index 3b6fc933d..50e7490d6 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -5,7 +5,7 @@ # https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL add_library(lib_tgcalls STATIC) -init_target(lib_tgcalls) +init_target(lib_tgcalls cxx_std_14) add_library(tdesktop::lib_tgcalls ALIAS lib_tgcalls) set(tgcalls_dir ${third_party_loc}/tgcalls) @@ -80,7 +80,7 @@ PRIVATE ) add_library(lib_tgcalls_legacy STATIC) -init_target(lib_tgcalls_legacy) +init_target(lib_tgcalls_legacy cxx_std_14) add_library(tdesktop::lib_tgcalls_legacy ALIAS lib_tgcalls_legacy) nice_target_sources(lib_tgcalls_legacy ${tgcalls_loc} diff --git a/Telegram/cmake/lib_tgvoip.cmake b/Telegram/cmake/lib_tgvoip.cmake index 27e74d07a..a5b1d0495 100644 --- a/Telegram/cmake/lib_tgvoip.cmake +++ b/Telegram/cmake/lib_tgvoip.cmake @@ -14,17 +14,9 @@ if (TDESKTOP_USE_PACKAGED_TGVOIP AND NOT DESKTOP_APP_USE_PACKAGED_LAZY) target_link_libraries(lib_tgvoip INTERFACE PkgConfig::TGVOIP) else() add_library(lib_tgvoip STATIC) - init_target(lib_tgvoip) + init_target(lib_tgvoip cxx_std_14) add_library(tdesktop::lib_tgvoip ALIAS lib_tgvoip) - if (NOT APPLE) - # On macOS if you build libtgvoip with C++17 it uses std::optional - # instead of absl::optional and when it uses optional::value, the - # build fails, because optional::value is available starting with - # macOS 10.14+. This way we force using absl::optional. - target_compile_features(lib_tgvoip PUBLIC cxx_std_17) - endif() - set(tgvoip_loc ${third_party_loc}/libtgvoip) nice_target_sources(lib_tgvoip ${tgvoip_loc} diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc index d3d96130b..078f6bf15 160000 --- a/Telegram/lib_webrtc +++ b/Telegram/lib_webrtc @@ -1 +1 @@ -Subproject commit d3d96130ba245e985c79c9040459b548416efdf8 +Subproject commit 078f6bf15d60c23f9907d91398bfd6bf201638be From 0a019411ee7c5197963f39b37e0260f86ee9df58 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Jul 2020 22:41:08 +0400 Subject: [PATCH 040/142] Use typed signaling messages. --- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index f7b3ad47d..c0d0e35c3 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit f7b3ad47df96bacf50bd958065d4d7d2901d9cfb +Subproject commit c0d0e35c3f42258dcbc24f1e0902c734bf311776 diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index 50e7490d6..29b1edad0 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -23,12 +23,15 @@ PRIVATE Instance.h InstanceImpl.cpp InstanceImpl.h + SignalingMessage.cpp + SignalingMessage.h ThreadLocalObject.h VideoCaptureInterface.cpp VideoCaptureInterface.h VideoCaptureInterfaceImpl.cpp VideoCaptureInterfaceImpl.h VideoCapturerInterface.h + platform/PlatformInterface.h # Windows From 6c272e38adc7c1dbd389ac5bb9fb2521cc4965d9 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Jul 2020 16:47:05 +0400 Subject: [PATCH 041/142] Update tgcalls to support codecs negotiation. --- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index c0d0e35c3..77f3411be 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit c0d0e35c3f42258dcbc24f1e0902c734bf311776 +Subproject commit 77f3411be90234a90cf0479d17e26bbad7106de3 diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index 29b1edad0..6518dc82e 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -13,16 +13,18 @@ set(tgcalls_loc ${tgcalls_dir}/tgcalls) nice_target_sources(lib_tgcalls ${tgcalls_loc} PRIVATE + CodecSelectHelper.cpp + CodecSelectHelper.h + Instance.cpp + Instance.h + InstanceImpl.cpp + InstanceImpl.h Manager.cpp Manager.h MediaManager.cpp MediaManager.h NetworkManager.cpp NetworkManager.h - Instance.cpp - Instance.h - InstanceImpl.cpp - InstanceImpl.h SignalingMessage.cpp SignalingMessage.h ThreadLocalObject.h From 46550381a4073938bd4ba2cfcbf55fd469983198 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Jul 2020 18:04:02 +0400 Subject: [PATCH 042/142] Fix build on macOS. --- Telegram/SourceFiles/calls/calls_call.cpp | 2 +- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 34 +++++++++++++++++------ Telegram/lib_webrtc | 2 +- cmake | 2 +- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 9a9070ee3..1615bb4b2 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -675,7 +675,7 @@ void Call::createAndStartController(const MTPDphoneCall &call) { #else // Q_OS_WIN const auto callLogUtf = QFile::encodeName(callLogNative); descriptor.config.logPath.resize(callLogUtf.size()); - ranges::copy(callLogUtf, config.logPath.begin()); + ranges::copy(callLogUtf, descriptor.config.logPath.begin()); #endif // Q_OS_WIN QFile(callLogPath).remove(); QDir().mkpath(callLogFolder); diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 77f3411be..dc2d21160 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 77f3411be90234a90cf0479d17e26bbad7106de3 +Subproject commit dc2d21160e5ff64ecd13f12afe7b34ad2cb1b0a1 diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index 6518dc82e..e45394a35 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -35,12 +35,12 @@ PRIVATE VideoCapturerInterface.h platform/PlatformInterface.h + platform/tdesktop/VideoCapturerInterfaceImpl.cpp + platform/tdesktop/VideoCapturerInterfaceImpl.h # Windows platform/windows/WindowsInterface.cpp platform/windows/WindowsInterface.h - platform/windows/VideoCapturerInterfaceImpl.cpp - platform/windows/VideoCapturerInterfaceImpl.h # iOS / macOS platform/darwin/DarwinInterface.h @@ -53,22 +53,38 @@ PRIVATE platform/darwin/TGRTCVideoDecoderH265.mm platform/darwin/TGRTCVideoEncoderH265.h platform/darwin/TGRTCVideoEncoderH265.mm - platform/darwin/VideoCameraCapturer.h - platform/darwin/VideoCameraCapturer.mm - platform/darwin/VideoCapturerInterfaceImpl.h - platform/darwin/VideoCapturerInterfaceImpl.mm - platform/darwin/VideoMetalView.h - platform/darwin/VideoMetalView.mm + # platform/darwin/VideoCameraCapturer.h + # platform/darwin/VideoCameraCapturer.mm + # platform/darwin/VideoCapturerInterfaceImpl.h + # platform/darwin/VideoCapturerInterfaceImpl.mm + # platform/darwin/VideoMetalView.h + # platform/darwin/VideoMetalView.mm # Linux # POSIX ) +target_compile_definitions(lib_tgcalls +PRIVATE + WEBRTC_APP_TDESKTOP + RTC_ENABLE_VP9 +) + if (WIN32) target_compile_definitions(lib_tgcalls PRIVATE - TARGET_OS_WIN + WEBRTC_WIN + ) +elseif (APPLE) + target_compile_definitions(lib_tgcalls + PRIVATE + WEBRTC_MAC + ) +else() + target_compile_definitions(lib_tgcalls + PRIVATE + WEBRTC_LINUX ) endif() diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc index 078f6bf15..6c349a974 160000 --- a/Telegram/lib_webrtc +++ b/Telegram/lib_webrtc @@ -1 +1 @@ -Subproject commit 078f6bf15d60c23f9907d91398bfd6bf201638be +Subproject commit 6c349a97466d3f38b7e7a4cb85a18a0b4e290b92 diff --git a/cmake b/cmake index 8414d2aa3..bff30ad53 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 8414d2aa3a51511076de41e65fc10f4821cc67b3 +Subproject commit bff30ad53b5097718b6151bd15ab4ad3a0ddf807 From 29d42a6936c857737ad9e0cfb2ec8ae594ec4679 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Jul 2020 19:04:24 +0400 Subject: [PATCH 043/142] Fix runtime errors in macOS. --- Telegram/ThirdParty/tgcalls | 2 +- cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index dc2d21160..42ff8037f 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit dc2d21160e5ff64ecd13f12afe7b34ad2cb1b0a1 +Subproject commit 42ff8037fd22513660cad29df52a6dfad868ec66 diff --git a/cmake b/cmake index bff30ad53..119b164e7 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit bff30ad53b5097718b6151bd15ab4ad3a0ddf807 +Subproject commit 119b164e7b151dc519b11c9de661b7af7b9c79e1 From 5c55f31972ff9341d45316b3d7301fecaab9c951 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 14 Jul 2020 13:11:17 +0400 Subject: [PATCH 044/142] Use test capture from webrtc on macOS. --- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 4 ++++ cmake | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 42ff8037f..fb4ad939e 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 42ff8037fd22513660cad29df52a6dfad868ec66 +Subproject commit fb4ad939e553161011506f90908405ac0bd364e1 diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index e45394a35..58231d5f0 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -35,8 +35,12 @@ PRIVATE VideoCapturerInterface.h platform/PlatformInterface.h + + # Teleram Desktop platform/tdesktop/VideoCapturerInterfaceImpl.cpp platform/tdesktop/VideoCapturerInterfaceImpl.h + platform/tdesktop/VideoCapturerTrackSource.cpp + platform/tdesktop/VideoCapturerTrackSource.h # Windows platform/windows/WindowsInterface.cpp diff --git a/cmake b/cmake index 119b164e7..ef2cfa49c 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 119b164e7b151dc519b11c9de661b7af7b9c79e1 +Subproject commit ef2cfa49cb93b8aa4f51d18791033f38ac4b683b From 662424319c7632585cd7ecfc60d132095177b936 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 14 Jul 2020 13:15:20 +0400 Subject: [PATCH 045/142] Fix build on Windows. --- Telegram/ThirdParty/tgcalls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index fb4ad939e..36566eda2 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit fb4ad939e553161011506f90908405ac0bd364e1 +Subproject commit 36566eda283ae3731ff2911965ee09efbf9ae361 From 78c9c1e7f8de279be30f4ddaf419e9fa5be2e065 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 14 Jul 2020 21:45:34 +0400 Subject: [PATCH 046/142] Update tgcalls library. --- Telegram/SourceFiles/calls/calls_call.cpp | 27 ++++++++++++----------- Telegram/SourceFiles/calls/calls_call.h | 3 ++- Telegram/ThirdParty/tgcalls | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 1615bb4b2..d8f0d23c6 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -628,6 +628,12 @@ void Call::createAndStartController(const MTPDphoneCall &call) { const auto &protocol = call.vprotocol().c_phoneCallProtocol(); const auto &serverConfig = _user->session().serverConfig(); + auto encryptionKeyValue = ranges::view::all( + _authKey + ) | ranges::view::transform([](bytes::type byte) { + return static_cast(byte); + }) | ranges::to_vector; + const auto weak = base::make_weak(this); auto descriptor = tgcalls::Descriptor{ .config = tgcalls::Config{ @@ -641,14 +647,14 @@ void Call::createAndStartController(const MTPDphoneCall &call) { .enableVolumeControl = true, .maxApiLayer = protocol.vmax_layer().v, }, + .encryptionKey = tgcalls::EncryptionKey( + std::move(encryptionKeyValue), + (_type == Type::Outgoing)), .videoCapture = nullptr, - .stateUpdated = [=](tgcalls::State state) { + .stateUpdated = [=](tgcalls::State state, tgcalls::VideoState videoState) { crl::on_main(weak, [=] { - handleControllerStateChange(state); + handleControllerStateChange(state, videoState); }); - }, - .videoStateUpdated = [=](bool state) { - }, .signalBarsUpdated = [=](int count) { crl::on_main(weak, [=] { @@ -700,13 +706,6 @@ void Call::createAndStartController(const MTPDphoneCall &call) { } } - descriptor.encryptionKey.isOutgoing = (_type == Type::Outgoing); - descriptor.encryptionKey.value = ranges::view::all( - _authKey - ) | ranges::view::transform([](bytes::type byte) { - return static_cast(byte); - }) | ranges::to_vector; - descriptor.videoCapture = tgcalls::CreateVideoCapture(); const auto version = call.vprotocol().match([&]( @@ -746,7 +745,9 @@ void Call::createAndStartController(const MTPDphoneCall &call) { raw->setAudioOutputDuckingEnabled(settings.callAudioDuckingEnabled()); } -void Call::handleControllerStateChange(tgcalls::State state) { +void Call::handleControllerStateChange( + tgcalls::State state, + tgcalls::VideoState videoState) { switch (state) { case tgcalls::State::WaitInit: { DEBUG_LOG(("Call Info: State changed to WaitingInit.")); diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index eb2eb8328..343a20a32 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -22,6 +22,7 @@ class Track; namespace tgcalls { class Instance; enum class State; +enum class VideoState; } // namespace tgcalls namespace Calls { @@ -154,7 +155,7 @@ private: void displayNextFrame(QImage frame); void generateModExpFirst(bytes::const_span randomSeed); - void handleControllerStateChange(tgcalls::State state); + void handleControllerStateChange(tgcalls::State state, tgcalls::VideoState videoState); void handleControllerBarCountChange(int count); void createAndStartController(const MTPDphoneCall &call); diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 36566eda2..80c2b48f3 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 36566eda283ae3731ff2911965ee09efbf9ae361 +Subproject commit 80c2b48f30b9ee21b75abf2afda09c5fc77b4145 From 7fec49a752bf7644645d3b3e05c7f71867850047 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 15 Jul 2020 22:01:32 +0400 Subject: [PATCH 047/142] Remove webrtc test code usage on macOS. --- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 30 ++++++++++++++++++++++++------ Telegram/lib_webrtc | 2 +- cmake | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 80c2b48f3..0b98641d4 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 80c2b48f30b9ee21b75abf2afda09c5fc77b4145 +Subproject commit 0b98641d4ccf2f2c7ea406e971ece81b229160ae diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index 58231d5f0..39049af3d 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -11,6 +11,8 @@ add_library(tdesktop::lib_tgcalls ALIAS lib_tgcalls) set(tgcalls_dir ${third_party_loc}/tgcalls) set(tgcalls_loc ${tgcalls_dir}/tgcalls) +target_compile_options(lib_tgcalls PRIVATE -fobjc-arc) + nice_target_sources(lib_tgcalls ${tgcalls_loc} PRIVATE CodecSelectHelper.cpp @@ -57,12 +59,16 @@ PRIVATE platform/darwin/TGRTCVideoDecoderH265.mm platform/darwin/TGRTCVideoEncoderH265.h platform/darwin/TGRTCVideoEncoderH265.mm - # platform/darwin/VideoCameraCapturer.h - # platform/darwin/VideoCameraCapturer.mm - # platform/darwin/VideoCapturerInterfaceImpl.h - # platform/darwin/VideoCapturerInterfaceImpl.mm - # platform/darwin/VideoMetalView.h - # platform/darwin/VideoMetalView.mm + platform/darwin/VideoCameraCapturer.h + platform/darwin/VideoCameraCapturer.mm + platform/darwin/VideoCameraCapturerMac.h + platform/darwin/VideoCameraCapturerMac.mm + platform/darwin/VideoCapturerInterfaceImpl.h + platform/darwin/VideoCapturerInterfaceImpl.mm + platform/darwin/VideoMetalView.h + platform/darwin/VideoMetalView.mm + platform/darwin/VideoMetalViewMac.h + platform/darwin/VideoMetalViewMac.mm # Linux @@ -85,6 +91,18 @@ elseif (APPLE) PRIVATE WEBRTC_MAC ) + remove_target_sources(lib_tgcalls ${tgcalls_loc} + platform/darwin/VideoCameraCapturer.h + platform/darwin/VideoCameraCapturer.mm + platform/darwin/VideoMetalView.h + platform/darwin/VideoMetalView.mm + platform/darwin/VideoMetalViewMac.h + platform/darwin/VideoMetalViewMac.mm + platform/tdesktop/VideoCapturerTrackSource.cpp + platform/tdesktop/VideoCapturerTrackSource.h + platform/tdesktop/VideoCapturerInterfaceImpl.cpp + platform/tdesktop/VideoCapturerInterfaceImpl.h + ) else() target_compile_definitions(lib_tgcalls PRIVATE diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc index 6c349a974..fa4c2e22d 160000 --- a/Telegram/lib_webrtc +++ b/Telegram/lib_webrtc @@ -1 +1 @@ -Subproject commit 6c349a97466d3f38b7e7a4cb85a18a0b4e290b92 +Subproject commit fa4c2e22d678d7a977b5f4572689e459be29b7e3 diff --git a/cmake b/cmake index ef2cfa49c..fde8a86d2 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit ef2cfa49cb93b8aa4f51d18791033f38ac4b683b +Subproject commit fde8a86d2bb2613ae493e8185c2dfc2f798191ca From a4ee90e8c6f4956b27350f1541e7b4ce3818dbf4 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 16 Jul 2020 16:05:04 +0400 Subject: [PATCH 048/142] Remove webrtc test code usage on Windows. --- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 8 ++++++-- cmake | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 0b98641d4..beb6eac85 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 0b98641d4ccf2f2c7ea406e971ece81b229160ae +Subproject commit beb6eac853c6f2caf037ab1c374c25cf81af7a95 diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index 39049af3d..a6e0dba2a 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -11,8 +11,6 @@ add_library(tdesktop::lib_tgcalls ALIAS lib_tgcalls) set(tgcalls_dir ${third_party_loc}/tgcalls) set(tgcalls_loc ${tgcalls_dir}/tgcalls) -target_compile_options(lib_tgcalls PRIVATE -fobjc-arc) - nice_target_sources(lib_tgcalls ${tgcalls_loc} PRIVATE CodecSelectHelper.cpp @@ -43,6 +41,8 @@ PRIVATE platform/tdesktop/VideoCapturerInterfaceImpl.h platform/tdesktop/VideoCapturerTrackSource.cpp platform/tdesktop/VideoCapturerTrackSource.h + platform/tdesktop/VideoCameraCapturer.cpp + platform/tdesktop/VideoCameraCapturer.h # Windows platform/windows/WindowsInterface.cpp @@ -87,6 +87,10 @@ if (WIN32) WEBRTC_WIN ) elseif (APPLE) + target_compile_options(lib_tgcalls + PRIVATE + -fobjc-arc + ) target_compile_definitions(lib_tgcalls PRIVATE WEBRTC_MAC diff --git a/cmake b/cmake index fde8a86d2..d7c7e92eb 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit fde8a86d2bb2613ae493e8185c2dfc2f798191ca +Subproject commit d7c7e92ebc68bb9b6c5187dc8476d9f62b00058c From da3bbba4979129cf103ccbf61297691409f41409 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 16 Jul 2020 20:23:55 +0400 Subject: [PATCH 049/142] Allow enable/disable video in a call. --- Telegram/Resources/icons/call_answer.png | Bin 456 -> 595 bytes Telegram/Resources/icons/call_answer@2x.png | Bin 1205 -> 1101 bytes Telegram/Resources/icons/call_answer@3x.png | Bin 1024 -> 1771 bytes .../Resources/icons/call_camera_active.png | Bin 0 -> 377 bytes .../Resources/icons/call_camera_active@2x.png | Bin 0 -> 733 bytes .../Resources/icons/call_camera_active@3x.png | Bin 0 -> 1177 bytes .../Resources/icons/call_camera_muted.png | Bin 0 -> 727 bytes .../Resources/icons/call_camera_muted@2x.png | Bin 0 -> 1400 bytes .../Resources/icons/call_camera_muted@3x.png | Bin 0 -> 2114 bytes Telegram/Resources/icons/call_discard.png | Bin 405 -> 460 bytes Telegram/Resources/icons/call_discard@2x.png | Bin 736 -> 970 bytes Telegram/Resources/icons/call_discard@3x.png | Bin 886 -> 1482 bytes .../Resources/icons/call_record_active.png | Bin 412 -> 489 bytes .../Resources/icons/call_record_active@2x.png | Bin 800 -> 1002 bytes .../Resources/icons/call_record_active@3x.png | Bin 945 -> 1545 bytes .../Resources/icons/call_record_muted.png | Bin 459 -> 744 bytes .../Resources/icons/call_record_muted@2x.png | Bin 843 -> 1543 bytes .../Resources/icons/call_record_muted@3x.png | Bin 1089 -> 2435 bytes Telegram/SourceFiles/calls/calls.style | 11 ++- Telegram/SourceFiles/calls/calls_call.cpp | 72 ++++++++++++++---- Telegram/SourceFiles/calls/calls_call.h | 52 +++++++++---- Telegram/SourceFiles/calls/calls_panel.cpp | 23 ++++-- Telegram/SourceFiles/calls/calls_panel.h | 8 +- Telegram/SourceFiles/calls/calls_top_bar.cpp | 10 +-- Telegram/SourceFiles/calls/calls_top_bar.h | 2 +- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 2 + 27 files changed, 133 insertions(+), 49 deletions(-) create mode 100644 Telegram/Resources/icons/call_camera_active.png create mode 100644 Telegram/Resources/icons/call_camera_active@2x.png create mode 100644 Telegram/Resources/icons/call_camera_active@3x.png create mode 100644 Telegram/Resources/icons/call_camera_muted.png create mode 100644 Telegram/Resources/icons/call_camera_muted@2x.png create mode 100644 Telegram/Resources/icons/call_camera_muted@3x.png diff --git a/Telegram/Resources/icons/call_answer.png b/Telegram/Resources/icons/call_answer.png index f5a9ceb7329b3844598e6db730463b754b85c8c9..0d79a1750d9451a644e2c6dc0e1c051519fe9396 100644 GIT binary patch literal 595 zcmV-Z0<8UsP)(&$@p`@Fd_I$2uSW)hfoisN#!hWG91aHzheLQ23I)kz z(r};1ua4aq1~-L5p+}bcbG2Hv97w8$=JPq_;w2ai^2#SQQb4=ij!dUhE>s{8;B?O_ zq<}EUXf)zt9S#Rh_pCx1sMTs|VqGp5QZAP@I;&o!3e)HF0iG-roC}45)IJJncAfl& zcDv1h8jXh8AZFIf1I1!7xL&V7YlpRhUwnHRFnJ&ZsMqT(OWkf4uwlLc${Y~Z(rh+k zP_yozROGPNx%t zYBrnTa=GpS@dO@^M`lw$Hk%D(v)TI^)z1&}?|{%zI-Q2qYQ%imjK(Sbae!tK9 z)pxp1ry~SXZqDdrt@!Um-zX02**$sYyhwuOZ002ovPDHLkV1f_+1M2_) literal 456 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 TB`juJ00000NkvXXu0mjf!sjcP diff --git a/Telegram/Resources/icons/call_answer@3x.png b/Telegram/Resources/icons/call_answer@3x.png index 0060a291d99ec91ef9de1aa44cba2391fcd4453a..b74b73fef73429710b3962b38908ded12d154223 100644 GIT binary patch literal 1771 zcmcgt={MVn0{tN*6ETTb)J{szkY@C@Qp;QOXcn5v|nF5o(LnG8KwxYiZEZ zk~}50QdL0`W2r`IwIO(>v<4m97_HiBy#L^RdLQn+AMQE#%f08^?6aOOYEWG$003%k zu4L~6jruPjDhHfTJ2!M7pa`M|5dfOIPBq;levL0KXV zAIGMjEPD_oVNf$IG)-I4hoaCc>4iB_Ij9Q%rzN2filwrK>R~Gw8^uctn+eN8VtO^s zS_DZkAYO?gCo@Oqe+c0ys6HVH)z#Ijgu=3_s;YvD3ghB}>FMbKu~Cwzs!$%+2+h8Rbv@aPHjXze?_Sg?V_~oO~x4 zQy{0LbT)J(bC#=t^j8&fZ$CepEaTRWy8<&lKH_|xR7x4e`C1z*YwIoEl^wIR{59j3 zUrL`m3;Oez&@|H)Hm6bfkziE!T7(*RqYHB@qn)kj?B`Pki5Kkc7 z{XQ+EJN52F$lLPj|B%bM-1USDW3F>cOLZ+zb?A{@)#2J3E6<<1b$@@d463KAyF0OI zwPY%2tK##0aLOWAQfIUh9MjF(M<1uD1U-pvS7;RX+rgrZ5Jl;QK~x5VF>QNtLS1IZ z--LU66L7eqX8GA?BZwkZlj85ZE7a7~A{CwduOv?$%WyJBpf!^HNW!55QdfQn=4{?}!7T}rk&8m)!m z6s81#{Ual5T&QQ;yShA`NTfQ8s)BLqoS3x~o~_tcw!XgZN+hxa@k{YiFB>bX_cB@= z6iGqG% zASzBu!Ss%f4rVa(B7s^kB$vy%{8MQvV~milO zIb{(KzQrI24i5L5M{n16MTw2W`7RA338Gk)=9ZSY&WvWdVgk zq1(H^|K^2`i;vIkF;59G`cs;i$lBX3BsF~Yd*`R6=lXQxYkrz?Om1G@5lp9{j*gC7 ze_x-_@@mUtbpyepN3pxIlD(nVu@L)>*||47TGn3Dnm{1f*xCwkcPZZ9*-0v1#dqr) z7$6&2;)Rr~Y#CQTKbp>k6-~0WF{VduW^Pki&qy{n zT=GlAW4jvzn0F{&iq}`_SC^zDyYRLmX)H$QPIjkl{1qB7^FR!fNQuI#4|M>F7R`DwI<(~$IV~woq52M-zD?MHW%y~v@ zYbzx8u-O?VRaY{6-vN~bT-x5(b2)X2EK)T3YXkvWamH0&5Kco<`Ty>xXgQ)GL?>^12B bZS2Bp<_D`dMITfT-V1PZ_9WMnsMr4i6}2QR literal 1024 zcmV+b1poVqP)Mfv`t#HsW8Y|)_>?hFQ`RC^xC+nXc5s1te}!MMG?3#lAyxW9(F(w z87IA3G;`#BD;MKoKF^(d&beb+8ihikP$(1%h4Ks3YW3RMn%C>~|BT1u86F-Mi^Z74 z*4NjAWOR0Rrl+T)5rbS2icL*Ti9{kk+_T_s!@*L_$jCq=76=3g!$~9(o-9Qov6q(@ z!f<(cd6+T=J04*;l}aTP3ekwU-EP8g8jU71GZT&2{rx>*IIt=%E=D7EdwWYBv9Ylc zjo9VoC3!@>UXP|gmzS3ZiFtTr4mvR*Gj9^BAYc~H4Y68#kSJvbSUTO z=H}+t*H>1nqobqB%1W#U1i87ntE;Q5xk79e!eX&}ett$;U0+|9mX`AHRuh|`?RNXg z$qA!mp{ZK2VQe9g!0GAfR1hmFDmptmi*$Q@d^DL%so*v+Fu-`ywzjt9ayfc2u~>X~ zc*xirM@B{j0s(qAqtW>G_7*Aj^z@V>3vyy&f|0cI^YgN@GW25k`S}+Y7Yw)U?d_bL z9Q1B_z25KlGu##z7kP5D_$&JQ`l6ex+1Xi4uO?U#i9};#V+^scudkVznS}BN3%ISV zt+llkKJX>s1qB7H@0nmtLf=eySOoLI$H&L}`@7riURqk}>FH@`XecZ!R45b>Bs)7> zB9Ugs;a80 z=&B7|U0s>Y<`}tRG-z=d931@byn!3*@qyRt9UUEo@(_LfPq~T#w5A+9ZyJqeV`GE$ zhIV##+S}X1S5{Y7!vqve9B5NHE8OGb<3Ih_b8~YgB_*%|9S%n@DWGz4wok$i*4x_~ zUAx0W_sz{sFj=@13!Q2~Ujp4@@UP)mEOJ>sKR>6MSa`-cI5-Fd0;whj2!%qc)tcNk z$ZN3>&?4Dvwzx;-_{74;L0w&4&=C53z9hs5|8&CHa3PgS>+9>Anwm@|Q%g$=`4{2m zfO3Lh@KGw2wY9a7!-a(flKQr?vcl_(v6l6$tSq@)UQtm|Q&R)onOdy|ZJ1nONDF1j uZnyXM_q$xKGzx`6p-?Ck3ME;-1sDLXr<3DN-@Tv!0000$adZ=w+Zps9aTZhu3vfhdslM${p7NOC~Z^$e*)k^_=1o}scVVHgHL#J4KN z7Dd6Xo2DsbS;lI|LHfB~R?j7AZq1{lW?k|a4rTkSNsJp>2hHsk^lZyC3XkYmAt z)^+vb4-VA#y%!J#?oHsYB|J8B&KN2PFLt X4%|7-VJS|E00000NkvXXu0mjfMMk2^ literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/call_camera_active@2x.png b/Telegram/Resources/icons/call_camera_active@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3692b731e0c0b15d2e3801a060e1acef7abc4995 GIT binary patch literal 733 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 Aj{pDw literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/call_camera_muted@3x.png b/Telegram/Resources/icons/call_camera_muted@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..7dd2aa9dba1cd3335ea84c3e621feb407b1fd2c7 GIT binary patch literal 2114 zcmb_e_ct4g7muw(sTm%=DvyelC@JdM)LubRt9f1#wPRK*ZJOA}Dm7}A1mzjg7}eH@ zpk^yIn^2>?wl=k?mwx|)?>XNe?!7VlQR0XZ9b`ni~%3!vu zI>|xORwV=AY@_7B>blt+Ka|7o2x$x1oytQt(;aS1nF2*$nn?I#Cth-Qc7M({dNgE( zq3t(XjNaTFZ$V?wE77C(_0Su|I_Q;~F(p?{^;Odasv`)cjFBi-;2aD_D|3BF&&zL)3D8-XD4&t zK33UO{^POE4r}!~X{f2OWVAz{Io;vnJqz%_!;;nqTYM<~kQe`~Zzd+CTqQPR#%dYDy#*(y z&>`)Ng5rkiY5|vekE~aN{i7wiN?UF&D_xNXpVMIGUuRxcwZ-oGdSwPKjK6SHw%L@T z6v50_Cu;NB9-OocJL^R)QZI}Vt;A-*bsnvnNH>9*X&aitw@bdR9d6AhR}+iW8)4s zLM4anCnz_6fI4yvMY6>HBUGU6qMOU;gJokA)jq6 z*}6V=VwBj@YCv4U6E)6X1~_sxRsAS?GoqXzdP@+Pc;qNZ?Zlib_zrF>#JINxJC6$e z4a#-&@!ZF=P@bx|o1?UjBY8POSB49c9UZmdOTpZ1%_Gk=pU@g@tLz0DyxtaSspLAU zZ=}OA>131;WWDPVTi-(b&(oQh(I!F8d#h6od6qr8*BBGF2!$kz@a2~0;Q@WK5=d>( z>SWy$%hkEJuiN6!?$sCWV0g;ISuIQzt9%(Y$oZGPBN8t(7^!iGThG}qOO?ye+^G%! z%@yJNYh+{ufnwtX3P8O((yBgrJ;qiS86dI-Ux-J$gS6mqxCN0<>bldLxC2}4RmpOh zgu69n)kTG22Y8l+?-R8|TBw=Za=0LegQs1aJd?hc1m)q~<-uG8s_o?D?BoD8W`M(j zsu5eVzns@81`)j}A_&ySN}JR-qUMIm(}>$_OrCGZxJOe>cZLWwQK*+>*GyOzcA9h( z*}#O_rU@mac3b7C=33rGp|TKFG93?2Zr<{iGhZH0%PWC(;mC4UPtA$z(7nfxn~VkJ#|?*Ys{l&O9r35bpHs#6{V)QRa6(A#?P50F^}w9*`5W_uYB4fp*?j zbYUv5qp^q_ySsuXOiWIuT(K*`EndxM7M}5-NYNkhw8!9YGHyX7Q!#%_J9>kWDLI_z z!jbIuE`O^A;e-}-g?b__^c$TY+D9%D7PjYDFXO*2@!n&w%gkO&TK_1Lfcns@;6MXN zpyAvygWJc)$M24^+K-Zdxw!aJoEHfr`D(^)7g_A)(|>KW@#`eW_wj3m+Y$H$YhcC? z;o5m%mSPN$X9@&oY0;Ix|MT?d;>bMd_Us$#{x=@uiniXYJ1ECW>#>AX=+aOgR7?!& zC0tim7bJLLzCDNt1xods_t3$5A5+3)1>rR2I6~xY3JJWl$^9rCF@g*+me36L_@Ybt zkA6J2^_gmvzQ`viKN6sZq_DH7IdxzE!{!B`E@sk`_a$){h`(cFW+ zEC-~8s%ctE*bZze?j#Y9zv6SIve`;412U9& z^}hZ*-dk-c_2QX??1!7iah+m33~q1Dch6Cig>=uy=XOisyQiqR0@fbNRU)`Uy)WKb zrvp-t!~%HL4afexDC&EuCArcy|3Zo=x)GMzXrs|fv9>4YKgPS^g32MHzS#0!N#$YL zKp`6vOh{N|M-Rn{MK$Jj`yIs_mL@IxS!LCsJPF)^ImPnR0DR d_v0?!(#l{5?7DH`fD2!A@ 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 diff --git a/Telegram/Resources/icons/call_record_active.png b/Telegram/Resources/icons/call_record_active.png index 4659bbb6c867209b1b34b08c808ba6e3e32dda8f..79447233a7ce6a760cec75df6e5d34c7b8e573ba 100644 GIT binary patch literal 489 zcmV#Cm0I37l$SuU4(v)SiedS}kMDTt`-^ zRIs6^@yh>{nBmApC<8CI%MwyaXca14p~YfB?v`OlUrzXXd926VYxsNe5X9LIDzoy7KfJ@F%s zyynH?`@PVC#TtG?GN{u(vd5a? za43XeA7i>}?O$2i;9o}}gx2dd?RGm_tya0omQn;cx7lyY6|xGc f6i~&#?hgF`?b+AyuCrT600000NkvXXu0mjfAwS$w literal 412 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 literal 945 zcmV;i15W&jP)a`-@!z;WD z_ukC0nQ11@vvWB2-22RPKJL9^R~G_-Kp@nD!C>%sJgHRb{{H^;^|fBF=W@AZGC4at zt7BGnyFHW1G(N%k`MJ$z(;q9h+x_(P)M$xXt;X}b&b0cH)qiff(GBvdMFi3~J3G?{ zF{l;|i4X)q_GK7l_vrO{RT%OEfXXgav1~Rge@4je5&9L!agv5We>0g(S|$%R;!7Bn$2d~rcfwIC6>?U>4${#YPG5$v0|}Eyj0qzg9}jRkg>6`@4PQ* z#BOeG#6PE|rf8ep-Ce1~_V)JZhlKOn+gk-Qa&>i;_+r8|gXisEDyGwErjyIdOR?F? z%8G)-CMPF}Wf1|>gw1AyY;1>Bxm;$(v)yhdEGH%=lr5vz*Vp3tqR}YRjOY0;xm79^ zm&?T*9*f1qmRDC-iuZ@LwKbv&kBp2kEkQS^3ZJn$IXPjf4HzFEe|viq8~go!#fkOz z_e1=MXFWbXZgGz*2tp!}$Y!&D{^9QKE*_81%*=dR&5Xv=(^IkkQmNF}*QZ8P4+H|l z>kkHlaybu&!-Vto^>vkYD?L3uP<)B$mzI`fuetzeFx}nV>g~j)r>BWDXzJGSw*`p6 zt*tG>Axr@islCfwTwJ6}!qL$Ya|78L!^6YS&1i43M1ef{0C;|W-rU?A7#L{BgT-Qr zL?TdBXg@nUJ3o0kfMqeOIjnVme}7?N0hUgWvRbWPulL~K0J;Tp_z$ycVtIL)&Nne0 z9v&_(E)EY5Ay6}!%;V!@3*-0qcc0Ivl~bL=;ebxn_%?F6oYU#l)`_*Zw->4+Bv@yZ zUS3`{Ha5VCMi1mrGq$(4A@n!A2G~P#+&3G#PjZp$i7{ z^Yg0qUl{=>e3}^ZPC;H6RNzKm8_NFY2fThmVn_^$Au%L|Kp+qZ1OlNj{t7Svj(H8B T+5qV^00000NkvXXu0mjfC=0uO diff --git a/Telegram/Resources/icons/call_record_muted.png b/Telegram/Resources/icons/call_record_muted.png index 0747c8afa4b5c00fcfff75f64be02c363e4bc195..ac6b48bf88e4d4c527eddc4fb211d5bb1a6e03b6 100644 GIT binary patch literal 744 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 Vkz32R+aCY`002ovPDHLkV1k!LlCJ;& diff --git a/Telegram/Resources/icons/call_record_muted@3x.png b/Telegram/Resources/icons/call_record_muted@3x.png index dbdc210e47feba6beae12e27e3b79706e8fadc0c..62f9f8a6a08368675de2d693095749653e33b2ba 100644 GIT binary patch literal 2435 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 literal 1089 zcmV-H1it%;P)R8Zj6#B-T|~5uiZ*Vn$lUZHXhrlzR^&T8 zL58{Gb?%HabLTPtmCBi!^P79`Ip>~hS(zqHnlx#WOFEryU|?WlVu@;S-`}rds*aA1)6>&z0UaM7x3{;ekE*Y)@9pg^i`DDvtHa??%*FEZ@<=2yJUmP^ zRz<1uY|4xqQ0?sOfCsQbc(TE|!puNaM@L7BQRT#w4WdPsP)?^)Rxp@>ED!jwK@21X z3xz_mf{l!f00}7@M0QfJcswrmY!twT+85R5=cfYkgOu&|_BKl{Wg z1Gew)Z|T^SEGCH9T3T9&*c2|5q+?UQ2qa~@ySq~d7={gg7tBUW@$PcDO3Oyk#)OEi zwY3$`M%SjRglyDpC`sAw@9)(CRw_118v&!Eqx{*dRx8RzZ<9kL8`TXQF>JIqr+^Jz zKNz-TGN}$Q(9h4005-LPVc6Q*+JH@Ar&-%gv)PQ=yuZH}%EE=%nwy)^9~&APH;EjW;(pd9!FV zDtW~BcsxwcGMNl(l`|8Rm^lf9mSRdbUH(!P&^)o zLLVOlInwr(sRhWDHkscl%^1)_$dYWFg zvVZ@485|s3Uthnvy88Y7<>W~u62V|_XlSUSqJnwt)YKH!YPP#8P#z z3Fy?TgH6~GgbLUMpRG(zPEyS#=Fn(jVuD^ak*8twvWY+D8y_D>tG1$jJ{5qWY*1nA z_4@w-3^X=2mSdxWs)S& +#include namespace tgcalls { class InstanceImpl; @@ -42,6 +43,7 @@ namespace { constexpr auto kMinLayer = 65; constexpr auto kHangupTimeoutMs = 5000; constexpr auto kSha256Size = 32; +constexpr auto kDropFramesWhileInactive = 5 * crl::time(1000); const auto kDefaultVersion = "2.4.4"_q; const auto RegisterTag = tgcalls::Register(); @@ -319,12 +321,31 @@ void Call::actuallyAnswer() { }).send(); } -void Call::setMute(bool mute) { - _mute = mute; +void Call::setMuted(bool mute) { + _muted = mute; if (_instance) { - _instance->setMuteMicrophone(_mute); + _instance->setMuteMicrophone(mute); + } +} + +void Call::setVideoEnabled(bool enabled) { + if (_state.current() != State::Established) { + return; + } + _videoEnabled = enabled; + if (enabled) { + if (!_videoCapture) { + _videoCapture = tgcalls::VideoCaptureInterface::Create(); + } + if (_instance) { + _instance->requestVideo(_videoCapture); + } else { + _videoState = VideoState::OutgoingRequested; + } + _videoCapture->setIsVideoEnabled(true); + } else if (_videoCapture) { + _videoCapture->setIsVideoEnabled(false); } - _muteChanged.notify(_mute); } crl::time Call::getDurationMs() const { @@ -430,6 +451,7 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { } _id = data.vid().v; _accessHash = data.vaccess_hash().v; + setVideoEnabled(data.is_video()); auto gaHashBytes = bytes::make_span(data.vg_a_hash().v); if (gaHashBytes.size() != kSha256Size) { LOG(("Call Error: Wrong g_a_hash size %1, expected %2." @@ -650,7 +672,7 @@ void Call::createAndStartController(const MTPDphoneCall &call) { .encryptionKey = tgcalls::EncryptionKey( std::move(encryptionKeyValue), (_type == Type::Outgoing)), - .videoCapture = nullptr, + .videoCapture = _videoEnabled.current() ? _videoCapture : nullptr, .stateUpdated = [=](tgcalls::State state, tgcalls::VideoState videoState) { crl::on_main(weak, [=] { handleControllerStateChange(state, videoState); @@ -662,6 +684,14 @@ void Call::createAndStartController(const MTPDphoneCall &call) { }); }, .remoteVideoIsActiveUpdated = [=](bool active) { + crl::on_main(weak, [=] { + if (!active) { + _frames.fire(QImage()); + _remoteVideoInactiveFrom = crl::now(); + } else { + _remoteVideoInactiveFrom = 0; + } + }); }, .signalingDataEmitted = [=](const std::vector &data) { const auto bytes = QByteArray( @@ -706,8 +736,6 @@ void Call::createAndStartController(const MTPDphoneCall &call) { } } - descriptor.videoCapture = tgcalls::CreateVideoCapture(); - const auto version = call.vprotocol().match([&]( const MTPDphoneCallProtocol &data) { return data.vlibrary_versions().v; @@ -727,13 +755,18 @@ void Call::createAndStartController(const MTPDphoneCall &call) { } const auto raw = _instance.get(); - if (_mute) { - raw->setMuteMicrophone(_mute); + if (_muted.current()) { + raw->setMuteMicrophone(_muted.current()); } const auto &settings = Core::App().settings(); raw->setIncomingVideoOutput(webrtc::CreateVideoSink([=](QImage frame) { crl::on_main(weak, [=] { - _frames.fire_copy(frame); + if (_remoteVideoInactiveFrom > 0 + && (_remoteVideoInactiveFrom + kDropFramesWhileInactive + > crl::now())) { + } else { + _frames.fire_copy(frame); + } }); })); raw->setAudioOutputDevice( @@ -748,6 +781,18 @@ void Call::createAndStartController(const MTPDphoneCall &call) { void Call::handleControllerStateChange( tgcalls::State state, tgcalls::VideoState videoState) { + _videoState = [&] { + switch (videoState) { + case tgcalls::VideoState::Possible: return VideoState::Disabled; + case tgcalls::VideoState::OutgoingRequested: + return VideoState::OutgoingRequested; + case tgcalls::VideoState::IncomingRequested: + return VideoState::IncomingRequested; + case tgcalls::VideoState::Active: return VideoState::Enabled; + } + Unexpected("VideoState value in Call::handleControllerStateChange."); + }(); + switch (state) { case tgcalls::State::WaitInit: { DEBUG_LOG(("Call Info: State changed to WaitingInit.")); @@ -780,10 +825,7 @@ void Call::handleControllerBarCountChange(int count) { } void Call::setSignalBarCount(int count) { - if (_signalBarCount != count) { - _signalBarCount = count; - _signalBarCountChanged.notify(count); - } + _signalBarCount = count; } template @@ -986,9 +1028,7 @@ void Call::handleControllerError(const QString &error) { void Call::destroyController() { if (_instance) { - AssertIsDebug(); const auto state = _instance->stop(); - LOG(("CALL_LOG: %1").arg(QString::fromStdString(state.debugLog))); DEBUG_LOG(("Call Info: Destroying call controller..")); _instance.reset(); diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index 343a20a32..c5b4c39e6 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -21,6 +21,7 @@ class Track; namespace tgcalls { class Instance; +class VideoCaptureInterface; enum class State; enum class VideoState; } // namespace tgcalls @@ -91,29 +92,50 @@ public: Ringing, Busy, }; - State state() const { + [[nodiscard]] State state() const { return _state.current(); } - rpl::producer stateValue() const { + [[nodiscard]] rpl::producer stateValue() const { return _state.value(); } + enum class VideoState { + Disabled, + OutgoingRequested, + IncomingRequested, + Enabled + }; + [[nodiscard]] VideoState videoState() const { + return _videoState.current(); + } + [[nodiscard]] rpl::producer videoStateValue() const { + return _videoState.value(); + } + static constexpr auto kSignalBarStarting = -1; static constexpr auto kSignalBarFinished = -2; static constexpr auto kSignalBarCount = 4; - base::Observable &signalBarCountChanged() { - return _signalBarCountChanged; + [[nodiscard]] rpl::producer signalBarCountValue() const { + return _signalBarCount.value(); } - void setMute(bool mute); - bool isMute() const { - return _mute; + void setMuted(bool mute); + [[nodiscard]] bool muted() const { + return _muted.current(); } - base::Observable &muteChanged() { - return _muteChanged; + [[nodiscard]] rpl::producer mutedValue() const { + return _muted.value(); } - rpl::producer frames() const { + void setVideoEnabled(bool enabled); + [[nodiscard]] bool videoEnabled() const { + return _videoEnabled.current(); + } + [[nodiscard]] rpl::producer videoEnabledValue() const { + return _videoEnabled.value(); + } + + [[nodiscard]] rpl::producer frames() const { return _frames.events(); } @@ -178,17 +200,18 @@ private: MTP::Sender _api; Type _type = Type::Outgoing; rpl::variable _state = State::Starting; + rpl::variable _videoState = VideoState::Disabled; FinishType _finishAfterRequestingCall = FinishType::None; bool _answerAfterDhConfigReceived = false; - int _signalBarCount = kSignalBarStarting; - base::Observable _signalBarCountChanged; + rpl::variable _signalBarCount = kSignalBarStarting; crl::time _startTime = 0; base::DelayedCallTimer _finishByTimeoutTimer; base::Timer _discardByTimeoutTimer; - bool _mute = false; - base::Observable _muteChanged; + rpl::variable _muted = false; + rpl::variable _videoEnabled = false; rpl::event_stream _frames; + crl::time _remoteVideoInactiveFrom = 0; DhConfig _dhConfig; bytes::vector _ga; @@ -203,6 +226,7 @@ private: uint64 _keyFingerprint = 0; std::unique_ptr _instance; + std::shared_ptr _videoCapture; std::unique_ptr _waitingTrack; diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 1bfdc9eba..bc34d8d81 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -89,9 +89,10 @@ SignalBars::SignalBars( resize( _st.width + (_st.width + _st.skip) * (Call::kSignalBarCount - 1), _st.width * Call::kSignalBarCount); - subscribe(call->signalBarCountChanged(), [=](int count) { + call->signalBarCountValue( + ) | rpl::start_with_next([=](int count) { changed(count); - }); + }, lifetime()); } bool SignalBars::isDisplayed() const { @@ -307,6 +308,7 @@ Panel::Panel(not_null call) , _answerHangupRedial(this, st::callAnswer, &st::callHangup) , _decline(this, object_ptr