From 8349cb0dd4c381536ba46970df68ae40385cbb77 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 12:29:56 +0300 Subject: [PATCH 001/216] Removed currency column from channel earn section when it's empty. --- .../earn/info_channel_earn_list.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp index a48262873..ebaf61e21 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp @@ -731,6 +731,7 @@ void InnerWidget::fill() { rpl::producer currencyValue, rpl::producer creditsValue, const tr::phrase<> &text, + bool showCurrency, bool showCredits) { const auto line = container->add( Ui::CreateSkipWidget(container, 0), @@ -793,7 +794,9 @@ void InnerWidget::fill() { st::channelEarnOverviewSubMinorLabelPos.y()); icon->moveToLeft( - available / 2 + st::boxRowPadding.left() / 2, + showCurrency + ? (available / 2 + st::boxRowPadding.left() / 2) + : 0, 0); creditsLabel->moveToLeft(rect::right(icon) + skip, 0); creditsSecondLabel->moveToLeft( @@ -807,6 +810,12 @@ void InnerWidget::fill() { creditsLabel->moveToLeft(x, 0); creditsSecondLabel->moveToLeft(x, 0); } + if (!showCurrency) { + const auto x = std::numeric_limits::max(); + majorLabel->moveToLeft(x, 0); + minorLabel->moveToLeft(x, 0); + secondMinorLabel->moveToLeft(x, 0); + } }, minorLabel->lifetime()); Ui::ToggleChildrenVisibility(line, true); @@ -829,6 +838,7 @@ void InnerWidget::fill() { rpl::duplicate(currencyStateValue) | rpl::map(availValueMap), rpl::duplicate(creditsStateValue) | rpl::map(availValueMap), tr::lng_channel_earn_available, + canViewCurrencyEarn, hasAnyCredits); Ui::AddSkip(container); Ui::AddSkip(container); @@ -836,6 +846,7 @@ void InnerWidget::fill() { rpl::duplicate(currencyStateValue) | rpl::map(currentValueMap), rpl::duplicate(creditsStateValue) | rpl::map(currentValueMap), tr::lng_channel_earn_reward, + canViewCurrencyEarn, hasAnyCredits); Ui::AddSkip(container); Ui::AddSkip(container); @@ -843,6 +854,7 @@ void InnerWidget::fill() { rpl::duplicate(currencyStateValue) | rpl::map(overallValueMap), rpl::duplicate(creditsStateValue) | rpl::map(overallValueMap), tr::lng_channel_earn_total, + canViewCurrencyEarn, hasAnyCredits); Ui::AddSkip(container); } From f650c679e02e8c6f788d9b8c89d09884731f066b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 12:41:00 +0300 Subject: [PATCH 002/216] Improved text padding in ShowOrPremiumBox. --- .../ui/boxes/show_or_premium_box.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Telegram/SourceFiles/ui/boxes/show_or_premium_box.cpp b/Telegram/SourceFiles/ui/boxes/show_or_premium_box.cpp index 485af50a8..e44a172f1 100644 --- a/Telegram/SourceFiles/ui/boxes/show_or_premium_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/show_or_premium_box.cpp @@ -143,45 +143,46 @@ void ShowOrPremiumBox( box->closeBox(); }); + const auto buttonPadding = QMargins( + st::showOrBox.buttonPadding.left(), + 0, + st::showOrBox.buttonPadding.right(), + 0); box->addRow(MakeShowOrPremiumIcon(box, skin.icon)); box->addRow( object_ptr( box, std::move(skin.showTitle), st::boostCenteredTitle), - st::showOrTitlePadding); + st::showOrTitlePadding + buttonPadding); box->addRow( object_ptr( box, std::move(skin.showAbout), st::boostText), - st::showOrAboutPadding); + st::showOrAboutPadding + buttonPadding); const auto show = box->addRow( object_ptr( box, std::move(skin.showButton), st::showOrShowButton), - QMargins( - st::showOrBox.buttonPadding.left(), - 0, - st::showOrBox.buttonPadding.right(), - 0)); + buttonPadding); show->setTextTransform(RoundButton::TextTransform::NoTransform); box->addRow( MakeShowOrLabel(box, std::move(skin.orPremium)), - st::showOrLabelPadding); + st::showOrLabelPadding + buttonPadding); box->addRow( object_ptr( box, std::move(skin.premiumTitle), st::boostCenteredTitle), - st::showOrTitlePadding); + st::showOrTitlePadding + buttonPadding); box->addRow( object_ptr( box, std::move(skin.premiumAbout), st::boostText), - st::showOrPremiumAboutPadding); + st::showOrPremiumAboutPadding + buttonPadding); const auto premium = CreateChild( box.get(), From 50f9f36c3de6579d90e9d505f463a77b0527439b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 13:02:39 +0300 Subject: [PATCH 003/216] Fixed padding for history entries in channel earn section. --- .../channel_statistics/earn/info_channel_earn_list.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp index ebaf61e21..51cf9506a 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp @@ -1012,8 +1012,7 @@ void InnerWidget::fill() { not_null listsContainer) { const auto hasCurrencyTab = !data.currencyEarn.firstHistorySlice.list.empty(); - const auto hasCreditsTab = !data.creditsStatusSlice.list.empty() - && data.premiumBotId; + const auto hasCreditsTab = !data.creditsStatusSlice.list.empty(); const auto hasOneTab = (hasCurrencyTab || hasCreditsTab) && (hasCurrencyTab != hasCreditsTab); @@ -1029,7 +1028,9 @@ void InnerWidget::fill() { listsContainer, st::defaultTabsSlider)), st::boxRowPadding); - slider->toggle(!hasOneTab, anim::type::instant); + slider->toggle( + ((hasCurrencyTab ? 1 : 0) + (hasCreditsTab ? 1 : 0) > 1), + anim::type::instant); if (hasCurrencyTab) { slider->entity()->addSection(currencyTabText); @@ -1053,11 +1054,13 @@ void InnerWidget::fill() { if (hasOneTab) { if (hasCurrencyTab) { AddHeader(listsContainer, tr::lng_channel_earn_history_title); + AddSkip(listsContainer); } else if (hasCreditsTab) { AddHeader( listsContainer, tr::lng_channel_earn_credits_history); slider->entity()->setActiveSectionFast(1); + AddSkip(listsContainer); } } else { slider->entity()->setActiveSectionFast(*sectionIndex); From fd2d12d6b1d1ce6080990529271b363bda88034d Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 20:32:21 +0300 Subject: [PATCH 004/216] Removed time shift when reschedule history item. --- Telegram/SourceFiles/history/view/history_view_context_menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index b86c7cd6e..3cddfc986 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -587,7 +587,7 @@ bool AddRescheduleAction( const auto itemDate = firstItem->date(); const auto date = (itemDate == Api::kScheduledUntilOnlineTimestamp) ? HistoryView::DefaultScheduleTime() - : itemDate + 600; + : itemDate + (firstItem->isScheduled() ? 0 : crl::time(600)); const auto box = request.navigation->parentController()->show( HistoryView::PrepareScheduleBox( From 71f83b59938e863a00dba8b848067186663051f4 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 21:40:35 +0300 Subject: [PATCH 005/216] Made creation of title with userpic more generic. --- .../boxes/moderate_messages_box.cpp | 42 ++++++------------- Telegram/SourceFiles/ui/boxes/confirm_box.cpp | 30 +++++++++++++ Telegram/SourceFiles/ui/boxes/confirm_box.h | 5 +++ 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp index 22d234ef0..0b8b4dc90 100644 --- a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp +++ b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp @@ -757,38 +757,22 @@ void DeleteChatBox(not_null box, not_null peer) { return base::EventFilterResult::Continue; }); - const auto line = container->add(object_ptr(container)); - const auto &st = st::mainMenuUserpic; - line->resize(line->width(), st.size.height()); - const auto userpic = Ui::CreateChild( - line, + container, peer, - st); + st::mainMenuUserpic); userpic->showSavedMessagesOnSelf(true); - const auto label = Ui::CreateChild( - line, - peer->isSelf() - ? tr::lng_saved_messages() | Ui::Text::ToBold() - : maybeUser - ? tr::lng_profile_delete_conversation() | Ui::Text::ToBold() - : rpl::single(Ui::Text::Bold(peer->name())) | rpl::type_erased(), - box->getDelegate()->style().title); - line->widthValue( - ) | rpl::start_with_next([=](int width) { - userpic->moveToLeft(st::boxRowPadding.left(), 0); - const auto skip = st::defaultBoxCheckbox.textPosition.x(); - label->resizeToWidth(width - - rect::right(userpic) - - skip - - st::boxRowPadding.right()); - label->moveToLeft( - rect::right(userpic) + skip, - ((userpic->height() - label->height()) / 2)); - }, label->lifetime()); - - userpic->setAttribute(Qt::WA_TransparentForMouseEvents); - label->setAttribute(Qt::WA_TransparentForMouseEvents); + Ui::IconWithTitle( + container, + userpic, + Ui::CreateChild( + container, + peer->isSelf() + ? tr::lng_saved_messages() | Ui::Text::ToBold() + : maybeUser + ? tr::lng_profile_delete_conversation() | Ui::Text::ToBold() + : rpl::single(peer->name()) | Ui::Text::ToBold(), + box->getDelegate()->style().title)); Ui::AddSkip(container); Ui::AddSkip(container); diff --git a/Telegram/SourceFiles/ui/boxes/confirm_box.cpp b/Telegram/SourceFiles/ui/boxes/confirm_box.cpp index 5af3f3b28..275be6c21 100644 --- a/Telegram/SourceFiles/ui/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/confirm_box.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/boxes/confirm_box.h" #include "lang/lang_keys.h" +#include "ui/rect.h" #include "ui/widgets/buttons.h" #include "styles/style_layers.h" @@ -100,4 +101,33 @@ object_ptr MakeConfirmBox(ConfirmBoxArgs &&args) { return Box(ConfirmBox, std::move(args)); } +void IconWithTitle( + not_null container, + not_null icon, + not_null title) { + const auto line = container->add( + object_ptr(container), + st::boxRowPadding); + icon->setParent(line); + title->setParent(line); + + icon->heightValue( + ) | rpl::start_with_next([=](int height) { + line->resize(line->width(), height); + }, icon->lifetime()); + + line->widthValue( + ) | rpl::start_with_next([=](int width) { + icon->moveToLeft(0, 0); + const auto skip = st::defaultBoxCheckbox.textPosition.x(); + title->resizeToWidth(width - rect::right(icon) - skip); + title->moveToLeft( + rect::right(icon) + skip, + ((icon->height() - title->height()) / 2)); + }, title->lifetime()); + + icon->setAttribute(Qt::WA_TransparentForMouseEvents); + title->setAttribute(Qt::WA_TransparentForMouseEvents); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/boxes/confirm_box.h b/Telegram/SourceFiles/ui/boxes/confirm_box.h index c33192e29..97ba8eb41 100644 --- a/Telegram/SourceFiles/ui/boxes/confirm_box.h +++ b/Telegram/SourceFiles/ui/boxes/confirm_box.h @@ -60,4 +60,9 @@ inline void InformBox(not_null box, ConfirmBoxArgs &&args) { return MakeInformBox({ .text = std::move(text) }); } +void IconWithTitle( + not_null container, + not_null icon, + not_null title); + } // namespace Ui From c03fcf9a236a06bfec87dd025efe849d864a3faf Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 21:20:01 +0300 Subject: [PATCH 006/216] Added icon and name of topic to deletion confirmation box. --- .../SourceFiles/window/window_peer_menu.cpp | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 1164b150c..3b025b138 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/layers/generic_box.h" #include "ui/delayed_activation.h" +#include "ui/vertical_list.h" #include "main/main_session.h" #include "main/main_session_settings.h" #include "menu/menu_mute.h" @@ -68,6 +69,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_memento.h" #include "info/channel_statistics/boosts/info_boosts_widget.h" #include "info/channel_statistics/earn/info_channel_earn_widget.h" +#include "info/profile/info_profile_cover.h" #include "info/profile/info_profile_values.h" #include "info/statistics/info_statistics_widget.h" #include "info/stories/info_stories_widget.h" @@ -1563,11 +1565,28 @@ void PeerMenuDeleteTopicWithConfirmation( PeerMenuDeleteTopic(navigation, strong); } }; - navigation->parentController()->show(Ui::MakeConfirmBox({ - .text = tr::lng_forum_topic_delete_sure(tr::now), - .confirmed = callback, - .confirmText = tr::lng_box_delete(), - .confirmStyle = &st::attentionBoxButton, + const auto controller = navigation->parentController(); + controller->show(Box([=](not_null box) { + Ui::AddSkip(box->verticalLayout()); + Ui::IconWithTitle( + box->verticalLayout(), + Ui::CreateChild( + box, + controller, + topic), + Ui::CreateChild( + box, + topic->title(), + box->getDelegate()->style().title)); + Ui::AddSkip(box->verticalLayout()); + Ui::AddSkip(box->verticalLayout()); + Ui::ConfirmBox(box, { + .text = tr::lng_forum_topic_delete_sure(tr::now), + .confirmed = callback, + .confirmText = tr::lng_box_delete(), + .confirmStyle = &st::attentionBoxButton, + .labelPadding = st::boxRowPadding, + }); })); } From eb27c121176dfe1cf4b81e2b19e50c4d9ca8ccd0 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 18 Aug 2024 21:53:12 +0300 Subject: [PATCH 007/216] Added icon and name of contact to deletion confirmation box. --- .../SourceFiles/window/window_peer_menu.cpp | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 3b025b138..e2ac57f67 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/compose/compose_show.h" #include "chat_helpers/message_field.h" #include "chat_helpers/share_message_phrase_factory.h" +#include "ui/controls/userpic_button.h" #include "ui/wrap/slide_wrap.h" #include "ui/widgets/fields/input_field.h" #include "api/api_chat_participants.h" @@ -1545,16 +1546,28 @@ void PeerMenuDeleteContact( user->session().api().applyUpdates(result); }).send(); }; - controller->show( - Ui::MakeConfirmBox({ + auto box = Box([=](not_null box) { + Ui::AddSkip(box->verticalLayout()); + Ui::IconWithTitle( + box->verticalLayout(), + Ui::CreateChild( + box, + user, + st::mainMenuUserpic), + Ui::CreateChild( + box, + tr::lng_info_delete_contact() | Ui::Text::ToBold(), + box->getDelegate()->style().title)); + Ui::ConfirmBox(box, { .text = text, .confirmed = deleteSure, .confirmText = tr::lng_box_delete(), - }), - Ui::LayerOption::CloseOther); + .confirmStyle = &st::attentionBoxButton, + }); + }); + controller->show(std::move(box), Ui::LayerOption::CloseOther); } - void PeerMenuDeleteTopicWithConfirmation( not_null navigation, not_null topic) { From a38dcb6ee54975ee09ac63991013db2cf15df43f Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 19 Aug 2024 12:02:12 +0300 Subject: [PATCH 008/216] Improved color of topic icon in TopicIconView. --- Telegram/SourceFiles/info/profile/info_profile_cover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index 9d69f6738..2793f20a6 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -129,7 +129,7 @@ void TopicIconView::paintInRect(QPainter &p, QRect rect) { if (_player && _player->ready()) { paint(_player->frame( st::infoTopicCover.photo.size, - QColor(0, 0, 0, 0), + st::windowFg->c, false, crl::now(), _paused()).image); From a26bae70c7dec545ce04068965dab08c4befa19e Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 19 Aug 2024 12:53:42 +0300 Subject: [PATCH 009/216] Added Enter shortcut to EditForumTopicBox for confirmation. --- Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp index ed8a77787..be668fcd3 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_forum_topic.h" #include "data/data_session.h" #include "data/stickers/data_custom_emoji.h" +#include "base/event_filter.h" #include "base/random.h" #include "base/qt_signal_producer.h" #include "chat_helpers/emoji_list_widget.h" @@ -482,6 +483,9 @@ void EditForumTopicBox( state->defaultIcon.current().colorId, }; }, title->lifetime()); + title->submits() | rpl::start_with_next([box] { + box->triggerButton(0); + }, title->lifetime()); if (!topic || !topic->isGeneral()) { Ui::AddDividerText(top, tr::lng_forum_choose_title_and_icon()); From 95bdb925d5424f1126560b5975aea3db434784eb Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 20 Aug 2024 16:10:27 +0200 Subject: [PATCH 010/216] Fix paddings in text messages disabler. --- .../chat_helpers/message_field.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index b3c53942d..8c4a86ea1 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -1063,10 +1063,26 @@ base::unique_qptr CreateDisabledFieldView( st::historySendDisabled); label->setAttribute(Qt::WA_TransparentForMouseEvents); raw->setPointerCursor(false); + + const auto &st = st::historyComposeField; + + const auto metrics = QFontMetricsF(st.style.font->f); + const auto realAscent = int(base::SafeRound(metrics.ascent())); + const auto ascentAdd = st.style.font->ascent - realAscent; + const auto customFontMarginTop = ascentAdd; + const auto leading = qMax(metrics.leading(), qreal(0.0)); + const auto adjustment = (metrics.ascent() + leading) + - ((st.style.font->height * 4) / 5); + const auto placeholderCustomFontSkip = int(base::SafeRound(-adjustment)); + + const auto margins = st.textMargins + + st.placeholderMargins + + QMargins(0, style::ConvertScale(4) + + placeholderCustomFontSkip + + customFontMarginTop, 0, 0); + raw->widthValue( ) | rpl::start_with_next([=](int width) { - const auto &st = st::historyComposeField; - const auto margins = (st.textMargins + st.placeholderMargins); const auto available = width - margins.left() - margins.right(); const auto skip = st::historySendDisabledIconSkip; label->resizeToWidth(available - skip); @@ -1075,8 +1091,6 @@ base::unique_qptr CreateDisabledFieldView( raw->paintRequest( ) | rpl::start_with_next([=] { auto p = QPainter(raw); - const auto &st = st::historyComposeField; - const auto margins = (st.textMargins + st.placeholderMargins); const auto &icon = st::historySendDisabledIcon; icon.paint( p, From a4017e930e54d65f0f6c19820de325502f1b4377 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 20 Aug 2024 16:11:11 +0200 Subject: [PATCH 011/216] Add device selectors to one-on-one calls. --- .../Resources/icons/calls/call_cancel.png | Bin 214 -> 1483 bytes .../Resources/icons/calls/call_cancel@2x.png | Bin 426 -> 1596 bytes .../Resources/icons/calls/call_cancel@3x.png | Bin 912 -> 1652 bytes .../icons/calls/mini_calls_arrow.png | Bin 0 -> 240 bytes .../icons/calls/mini_calls_arrow@2x.png | Bin 0 -> 324 bytes .../icons/calls/mini_calls_arrow@3x.png | Bin 0 -> 422 bytes Telegram/SourceFiles/calls/calls.style | 42 +++ Telegram/SourceFiles/calls/calls_call.cpp | 13 + Telegram/SourceFiles/calls/calls_call.h | 8 + Telegram/SourceFiles/calls/calls_panel.cpp | 55 ++++ Telegram/SourceFiles/calls/calls_panel.h | 11 + .../calls/ui/calls_device_menu.cpp | 250 ++++++++++++++++++ .../SourceFiles/calls/ui/calls_device_menu.h | 36 +++ Telegram/cmake/td_ui.cmake | 2 + Telegram/lib_ui | 2 +- 15 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 Telegram/Resources/icons/calls/mini_calls_arrow.png create mode 100644 Telegram/Resources/icons/calls/mini_calls_arrow@2x.png create mode 100644 Telegram/Resources/icons/calls/mini_calls_arrow@3x.png create mode 100644 Telegram/SourceFiles/calls/ui/calls_device_menu.cpp create mode 100644 Telegram/SourceFiles/calls/ui/calls_device_menu.h diff --git a/Telegram/Resources/icons/calls/call_cancel.png b/Telegram/Resources/icons/calls/call_cancel.png index 607033d0fc9da3bd689b030e4b5215622bf61094..db5452f423f81c452db1975843105dda6bf5cf2e 100644 GIT binary patch literal 1483 zcmbVMONbmr7;ZxjW|NR1f-GLFbWAYBe%18sZr5y^Y^GOdB)x8SM|N{CSW{gy)9iFt zr@J;iv*5uzka!Z&i{zA`2M>~?5Mez?>-E+5 zzyH(obI)%bdtywIq^-58vmoZDvhnB!@edo@E{kbXR6U$X(&opq@rd;9nQ=+lc*n0V z^JVuSA}mm`#~M`a29ZEZ()7M=gvko!pg~)HXv?=RtjoanYTXn_ZNIt})5W#9 zI$2vGmM8Cf7EE`MAP6YOpc{0;1a)n>&x^!5JJw{-hwv3!p2-A)Wp^G_SWJPX8Vb>M z2qrBRPvD87HSr99Iy5!Cs2NbvCy_aYU=a*IS%{0hCR%Ww8wwLUTW)h6Ax%ruR85O2 zi(8suS(c_l4MIgAl%yAO+*QJ4=ZL|f35orP`z!<*BW|!&Zp%W|fek^F(}u~=Pr_qb z7e|_*>X}V_pht3Cv>JE%!abtV4h?9?6M;2yY}96)C2jUE)cN&20)%f}HL(&vy7|^C|DoFn$+yhv`nmolZooNYg zJvg5;=mB?pEmaI?yA}mT(p90nKvP^$=etWMemA5lNvvNdbenBuhpEHdiB#E z-zkrM0t$}3|BD-c-adQk)SFkgj6Hs(xZ`g72l^7)Ux3x8H#c>UGg@B1s2FF#M0wz%JZWx9U* y?4|BEpOwMK=PqBkcJ1aHzZVwQ$9J4uz9aoG{zrMKd}LeJZfmo1&W8tHIsP{tqu!wa delta 197 zcmX@jeT{K~WIY=L1H(gx88d*?Tu&Frkcif|(;c~-6?t5i?```YU&XI4wEm&`?w|`l zKSpz;%5`w7|8P+L!DKL@qg+kW;{}^gl1GQ4Vq1$u;=(BHGd<629^aI8OPO)Apl06H zyC-$rb|mb4=seSQ;mu?0Dc@T6vGSd?5&kvBO2zonR@;BiPS^#-z6#0x|GM3Izi{ diff --git a/Telegram/Resources/icons/calls/call_cancel@2x.png b/Telegram/Resources/icons/calls/call_cancel@2x.png index 611f89d36ca23e5e6585f8c2332b26aee7dda4f2..468337a51051fef56b1c22a2142aaf6a0b6f4fa6 100644 GIT binary patch literal 1596 zcmbVMX^hlV9IpzZ$SOgJ#%R)XO%S2eV>(BlGc3!@x-)?;%P{N__XBU*H`DG+`?_ss zXJ#cN9*JTUqREQ7CZZoDEFaK?gm5Ir#27R&N)S9FvVKs4pwYx5@pX;{3`(TQJNn-5 z{r>lV$KXJJ*W!B@Qxw&e&7^Z=&G_S%8_9fT*8@w*a;u#gbt&q$JN{wTwKvfJ%myWG);&#?XeAWQHROuh=Q18<{Bw zZJrv)t5aoF)|j3(bfOLjfr&gw*UgIMf_jo^@&dB=k2!{JLcDU4>GcKDBg!D1!VaS4 zkie=uFVZnN1fwt-mZPg_kryS74|9UZ@-ZOAff%OSA49}BS`p;ZkF-9|%GujThD%#CAY{cb|i>r=``X-5*-M%$8NI3|4*vVsD=|pOLrI2&jRZ_)MKRCEfgq5`t>Q(%^DU@?HKW)Fpc2c+SyAwz zkth(NS3pV9XwZY#1ZyfNV#kEUV#9_!Z~p1jraJiB_Xs5}VOPdsi{&W*Pvf`stlyR6njrW7@~Yb$g&iThkFC{f}_B zU@k6tHRzz;67klx^NAzcbABbZ4B`H1WApB^s_no@EAY2L6CyuB8$%Z9T@Gnd#-)4h59tMjj{zx_#m$-+_lrrGKHW|r^G9J%A2wd?L$+O=}o#UD;Q`~2&P_y64R zNwX)C>3Gk_bLMlxQ(G5BzWbth^0&X@!jjafDw2ovbMDTCYc3R5)W=@PJ!BtPwrcGA zksseJL=$IM41f9S(3WRTpIF_U|7KE0k8c?(KKtv#D!L%YvZi_@py zUcYz$zK7?)#A8aF%r2fjJAZO~;`3c!CtljQPkT@5-}LkR8;!%KwyiB6%^61*l(*06 z+x79;o3-8Y%#k-g`rSM*{ORb+AIu&q9po?mv2n+vPN4byxc}QrFaE-Pw#Prp_6?+G I*KK{`Z_~RHv;Y7A literal 426 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U@Y`>aSW-L^Y-?^u0sYQZV%7o ze2!6kFTLw+_SAPqF^(ERpSNFK7XDnOK)EQ{zUM}Ry<&^hi_HBOwlI6JOyE!ubWmz= zVd!KKVpL(mE3k{XSL~^QH#vI=gA+-c{*#Nj;@9$FqDdhZLV{zwWJhH!Z^K za@zdA{|?{eo)YwG(_#g=n$8;{!LZ8V)zIq&DB zyoWbFzu!^*J7a;E-)qzVkJ=xJ$+Ua?E10AB^GIRK6Y=Ammv(a7$nAW0G*hwm=)~8b zF8tFtCw1w%%&q$q+Y&2IPun1Awp!Tl>Hj39yf9Z{{0RAMC{$yhHtJa z$&{TEHUSA~9#KYV=qYK2BSb_xONJ=rp-rY?R?(x>;_;IdsmM`kvtM8ZBL;Iy|CkAf z#|DzpSY8UtROd!AQUX|k25pfnX{v64Qk1Ib1$gfqGZa~Y*!d{c#w+Ttz2vIH{7)I`i!(Znod3_VMcjW~iBQjv)bWAD5bF9ZQ3bjucX2`1uE3X}FI ziVP%wFc^|qo=%5YNXyVC(xEUPq(hldI^*^Eq;y8E%g2#4>ZGaF zV;4mec4cw2Ze33d_MUM%u}XybC&$X&4P9G@<5A#j8$$^HG{zXz@$543keYj{=>$PE zbtK|l$`njElKKwNLiM#0f;fyO6NQ>vTj&F}&9J%m{d#5XKcwg+q47zmQj(FPAbG^S_ z=$xFp1SWlIpZoZ_)QhukKeRq_ecCng*dV*A`?R{e`G|Yv7lq`({RhUI-76!94vf$2 zXvu8o*t0OT|FwxDtKJv~e;i!Mzw;>h;I-k@(_QX-%UtS_?!K4a`mFEt^oH5q-wMqy z%;)kW6T)P(8r;aeyM1xyr}+oAy+a*( zAJ~4`{#tdPlk=n4;v?RR{O>8Rxc{h|-)`+qiqT^ySN!=ZAUkoKh??tNB?{ zqVl6Ze`+$A+26cSkweuP(iF|9<(+n>Qz4zYy`%W1(fu zG5urP#g|1yM@wtIeefVbCsS(iM$LKi<|UPunz~0;as{tQ%!=tceE2ZG=jDx3lOKKj zXeia|wr4x_9_xbPoEsQaU)Jg1m`t<3JojX0dcI?>k!kz1B zfZnag$2o&_bajt@{aPC2!POhe_bAz&D_BQQuTS;ut5>V+r~TTo@etc3l?7VUr%&Iw zVS~f8qhiY@G-#bSkqusb^~ENp{jLg1zXG4`c+d3f=F-b^{5uV z{OC2#*tE}tRmkk!(ffgy-o1NQ^RZlL)3MmNpKal9K2N{;w(R&M(+(}}84FA|)~J7% zTz&Ta(%xH243VYhijzXW6;}xRsRgDUpR#>ts?a?TE@87*yz94TrJE_%OE9Ue`O(xb z{a4p_t7*GT_2jp!UFsL`0|mFXT*@)~e|n{-Y1G=VZ>ul;vp;9>N0*7pX%vy}Cu(#( aQt#E4+I&yTc@i+EF?hQAxvXb4y$E4b&+ z>yk44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSVF5FO4N|zKE$K6mTIcEF7~;YE zc9J3AVFdve-Tw_@-)oe3?H{BE{3=}dRQBYnb53IFb3Ar>=;d*rmN~snvNF=g?EuG} zo&(Ka*7u*X-0x9w@x8{<0xSECSKdfmnreOSrGL==u0ytMUwT`_=JL%vcjw}w3x?j; zU+(bxzg2nZ6+vd!hBN<8G>Yzopr0IjxfS^xk5 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/calls/mini_calls_arrow@3x.png b/Telegram/Resources/icons/calls/mini_calls_arrow@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..87dd6a9cb411c0ce82d6b2868eb1434cba414a94 GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@HB~Jt)g!KQTYJhje{O9;u7a=eE+BLkmG?Q zCZ7gQ14gw2EbrzXIQ;kXB8^j0e#!J@N{3Yj@Sswmx3#N3dT;o$xhC^w@Lim9F2%7}DOjSdG*(})?~bPBRhztjk3&NbUemd uniqueId) { _videoOutgoing->setState(Webrtc::VideoState::Active); } +auto Call::playbackDeviceIdValue() const +-> rpl::producer { + return _playbackDeviceId.value(); +} + +rpl::producer Call::captureDeviceIdValue() const { + return _captureDeviceId.value(); +} + +rpl::producer Call::cameraDeviceIdValue() const { + return _cameraDeviceId.value(); +} + void Call::finish(FinishType type, const MTPPhoneCallDiscardReason &reason) { Expects(type != FinishType::None); diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index 0a99c8067..1d01d6d5f 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -31,6 +31,7 @@ enum class AudioState; namespace Webrtc { enum class VideoState; class VideoTrack; +struct DeviceResolvedId; } // namespace Webrtc namespace Calls { @@ -220,6 +221,13 @@ public: void toggleCameraSharing(bool enabled); void toggleScreenSharing(std::optional uniqueId); + [[nodiscard]] auto playbackDeviceIdValue() const + -> rpl::producer; + [[nodiscard]] auto captureDeviceIdValue() const + -> rpl::producer; + [[nodiscard]] auto cameraDeviceIdValue() const + -> rpl::producer; + [[nodiscard]] rpl::lifetime &lifetime() { return _lifetime; } diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 1a442cfc2..c3f94e0ec 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_cloud_file.h" #include "data/data_changes.h" #include "calls/group/calls_group_common.h" +#include "calls/ui/calls_device_menu.h" #include "calls/calls_emoji_fingerprint.h" #include "calls/calls_signal_bars.h" #include "calls/calls_userpic.h" @@ -24,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/call_button.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/popup_menu.h" #include "ui/widgets/shadow.h" #include "ui/widgets/rp_window.h" #include "ui/layers/layer_manager.h" @@ -130,6 +132,7 @@ Panel::Panel(not_null call) initWidget(); initControls(); initLayout(); + initMediaDeviceToggles(); showAndActivate(); } @@ -736,6 +739,58 @@ void Panel::initGeometry() { updateControlsGeometry(); } +void Panel::initMediaDeviceToggles() { + _cameraDeviceToggle = _camera->addCornerButton( + st::callCornerButton, + &st::callCornerButtonInactive); + _audioDeviceToggle = _mute->entity()->addCornerButton( + st::callCornerButton, + &st::callCornerButtonInactive); + + _cameraDeviceToggle->setClickedCallback([=] { + showDevicesMenu(_cameraDeviceToggle, { + { Webrtc::DeviceType::Camera, _call->cameraDeviceIdValue() }, + }); + }); + _audioDeviceToggle->setClickedCallback([=] { + showDevicesMenu(_audioDeviceToggle, { + { Webrtc::DeviceType::Playback, _call->playbackDeviceIdValue() }, + { Webrtc::DeviceType::Capture, _call->captureDeviceIdValue() }, + }); + }); +} + +void Panel::showDevicesMenu( + not_null button, + std::vector types) { + if (!_call || _devicesMenu) { + return; + } + const auto chosen = [=](Webrtc::DeviceType type, QString id) { + switch (type) { + case Webrtc::DeviceType::Playback: + Core::App().settings().setCallPlaybackDeviceId(id); + break; + case Webrtc::DeviceType::Capture: + Core::App().settings().setCallCaptureDeviceId(id); + break; + case Webrtc::DeviceType::Camera: + Core::App().settings().setCameraDeviceId(id); + break; + } + Core::App().saveSettingsDelayed(); + }; + _devicesMenu = MakeDeviceSelectionMenu( + widget(), + &Core::App().mediaDevices(), + std::move(types), + chosen); + _devicesMenu->setForcedVerticalOrigin( + Ui::PopupMenu::VerticalOrigin::Bottom); + _devicesMenu->popup(button->mapToGlobal(QPoint()) + - QPoint(st::callDeviceSelectionMenu.menu.widthMin / 2, 0)); +} + void Panel::refreshOutgoingPreviewInBody(State state) { const auto inBody = (state != State::Established) && (_call->videoOutgoing()->state() != Webrtc::VideoState::Inactive) diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index 11c6dceae..e53045a44 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -37,6 +37,7 @@ class FadeWrap; template class PaddingWrap; class RpWindow; +class PopupMenu; namespace GL { enum class Backend; } // namespace GL @@ -55,6 +56,7 @@ namespace Calls { class Userpic; class SignalBars; class VideoBubble; +struct DeviceSelection; class Panel final : private Group::Ui::DesktopCapture::ChooseSourceDelegate { public: @@ -104,6 +106,7 @@ private: void initControls(); void reinitWithCall(Call *call); void initLayout(); + void initMediaDeviceToggles(); void initGeometry(); [[nodiscard]] bool handleClose() const; @@ -126,6 +129,10 @@ private: void showRemoteLowBattery(); void refreshAnswerHangupRedialLabel(); + void showDevicesMenu( + not_null button, + std::vector types); + [[nodiscard]] QRect incomingFrameGeometry() const; [[nodiscard]] QRect outgoingFrameGeometry() const; @@ -156,8 +163,10 @@ private: Ui::Animations::Simple _hangupShownProgress; object_ptr> _screencast; object_ptr _camera; + Ui::CallButton *_cameraDeviceToggle = nullptr; base::unique_qptr _startVideo; object_ptr> _mute; + Ui::CallButton *_audioDeviceToggle = nullptr; object_ptr _name; object_ptr _status; object_ptr _fingerprint = { nullptr }; @@ -170,6 +179,8 @@ private: int _bodyTop = 0; int _buttonsTop = 0; + base::unique_qptr _devicesMenu; + base::Timer _updateDurationTimer; base::Timer _updateOuterRippleTimer; diff --git a/Telegram/SourceFiles/calls/ui/calls_device_menu.cpp b/Telegram/SourceFiles/calls/ui/calls_device_menu.cpp new file mode 100644 index 000000000..1db1941c0 --- /dev/null +++ b/Telegram/SourceFiles/calls/ui/calls_device_menu.cpp @@ -0,0 +1,250 @@ +/* +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/ui/calls_device_menu.h" + +#include "lang/lang_keys.h" +#include "ui/widgets/menu/menu_item_base.h" +#include "ui/widgets/checkbox.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/popup_menu.h" +#include "ui/widgets/scroll_area.h" +#include "ui/wrap/vertical_layout.h" +#include "webrtc/webrtc_device_common.h" +#include "webrtc/webrtc_environment.h" +#include "styles/style_calls.h" +#include "styles/style_layers.h" + +namespace Calls { +namespace { + +class Subsection final : public Ui::Menu::ItemBase { +public: + Subsection( + not_null parent, + const style::Menu &st, + const QString &text); + + not_null action() const override; + bool isEnabled() const override; + +private: + int contentHeight() const override; + + const style::Menu &_st; + const base::unique_qptr _text; + const not_null _dummyAction; + +}; + +class Selector final : public Ui::Menu::ItemBase { +public: + Selector( + not_null parent, + const style::Menu &st, + rpl::producer> devices, + rpl::producer chosen, + Fn selected); + + not_null action() const override; + bool isEnabled() const override; + +private: + int contentHeight() const override; + [[nodiscard]] int registerId(const QString &id); + + const base::unique_qptr _scroll; + const not_null _list; + const not_null _dummyAction; + + base::flat_map _ids; + +}; + +Subsection::Subsection( + not_null parent, + const style::Menu &st, + const QString &text) +: Ui::Menu::ItemBase(parent, st) +, _st(st) +, _text(base::make_unique_q( + this, + text, + st::callDeviceSelectionLabel)) +, _dummyAction(new QAction(parent)) { + setPointerCursor(false); + + initResizeHook(parent->sizeValue()); + + _text->resizeToWidth(st::callDeviceSelectionLabel.minWidth); + _text->moveToLeft(st.itemPadding.left(), st.itemPadding.top()); +} + +not_null Subsection::action() const { + return _dummyAction; +} + +bool Subsection::isEnabled() const { + return false; +} + +int Subsection::contentHeight() const { + return _st.itemPadding.top() + + _text->height() + + _st.itemPadding.bottom(); +} + +Selector::Selector( + not_null parent, + const style::Menu &st, + rpl::producer> devices, + rpl::producer chosen, + Fn selected) +: Ui::Menu::ItemBase(parent, st) +, _scroll(base::make_unique_q(this)) +, _list(_scroll->setOwnedWidget(object_ptr(this))) +, _dummyAction(new QAction(parent)) { + setPointerCursor(false); + + initResizeHook(parent->sizeValue()); + + const auto padding = st.itemPadding; + const auto group = std::make_shared(); + std::move( + chosen + ) | rpl::start_with_next([=](Webrtc::DeviceResolvedId id) { + const auto value = id.isDefault() ? 0 : registerId(id.value); + if (!group->hasValue() || group->current() != value) { + group->setValue(value); + } + }, lifetime()); + + group->setChangedCallback([=](int value) { + if (value == 0) { + selected({}); + } else { + for (const auto &[id, index] : _ids) { + if (index == value) { + selected(id); + break; + } + } + } + }); + + std::move( + devices + ) | rpl::start_with_next([=](const std::vector &v) { + while (_list->count()) { + delete _list->widgetAt(0); + } + _list->add( + object_ptr( + _list.get(), + group, + 0, + tr::lng_settings_call_device_default(tr::now), + st::groupCallCheckbox, + st::groupCallRadio), + padding); + for (const auto &device : v) { + if (device.inactive) { + continue; + } + _list->add( + object_ptr( + _list.get(), + group, + registerId(device.id), + device.name, + st::groupCallCheckbox, + st::groupCallRadio), + padding); + } + resize(width(), contentHeight()); + }, lifetime()); +} + +not_null Selector::action() const { + return _dummyAction; +} + +bool Selector::isEnabled() const { + return false; +} + +int Selector::contentHeight() const { + _list->resizeToWidth(width()); + if (_list->count() <= 3) { + _scroll->resize(width(), _list->height()); + } else { + _scroll->resize( + width(), + 3.5 * st::defaultRadio.diameter); + } + return _scroll->height(); +} + +int Selector::registerId(const QString &id) { + auto &result = _ids[id]; + if (!result) { + result = int(_ids.size()); + } + return result; +} + +void AddDeviceSelection( + not_null menu, + not_null environment, + DeviceSelection type, + Fn selected) { + const auto title = [&] { + switch (type.type) { + case Webrtc::DeviceType::Camera: + return tr::lng_settings_call_camera(tr::now); + case Webrtc::DeviceType::Playback: + return tr::lng_settings_call_section_output(tr::now); + case Webrtc::DeviceType::Capture: + return tr::lng_settings_call_section_input(tr::now); + } + Unexpected("Type in AddDeviceSelection."); + }(); + menu->addAction( + base::make_unique_q(menu, menu->st().menu, title)); + menu->addAction( + base::make_unique_q( + menu, + menu->st().menu, + environment->devicesValue(type.type), + std::move(type.chosen), + selected)); +} + +} // namespace + +base::unique_qptr MakeDeviceSelectionMenu( + not_null parent, + not_null environment, + std::vector types, + Fn choose) { + auto result = base::make_unique_q( + parent, + st::callDeviceSelectionMenu); + const auto raw = result.get(); + for (auto type : types) { + if (!raw->empty()) { + raw->addSeparator(); + } + const auto selected = [=, type = type.type](QString id) { + choose(type, id); + }; + AddDeviceSelection(raw, environment, std::move(type), selected); + } + return result; +} + +} // namespace Calls diff --git a/Telegram/SourceFiles/calls/ui/calls_device_menu.h b/Telegram/SourceFiles/calls/ui/calls_device_menu.h new file mode 100644 index 000000000..bff2fcc42 --- /dev/null +++ b/Telegram/SourceFiles/calls/ui/calls_device_menu.h @@ -0,0 +1,36 @@ +/* +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 "base/unique_qptr.h" + +namespace Webrtc { +class Environment; +struct DeviceResolvedId; +enum class DeviceType : uchar; +} // namespace Webrtc + +namespace Ui { +class RpWidget; +class PopupMenu; +} // namespace Ui + +namespace Calls { + +struct DeviceSelection { + Webrtc::DeviceType type; + rpl::producer chosen; +}; + +[[nodiscard]] base::unique_qptr MakeDeviceSelectionMenu( + not_null parent, + not_null environment, + std::vector types, + Fn choose); + +} // namespace Calls diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index ca583b017..8ec670702 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -64,6 +64,8 @@ PRIVATE calls/group/ui/calls_group_scheduled_labels.h calls/group/ui/desktop_capture_choose_source.cpp calls/group/ui/desktop_capture_choose_source.h + calls/ui/calls_device_menu.cpp + calls/ui/calls_device_menu.h chat_helpers/field_characters_count_manager.cpp chat_helpers/field_characters_count_manager.h diff --git a/Telegram/lib_ui b/Telegram/lib_ui index fc5386f1f..47ec1b045 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit fc5386f1fd4a17fafa88f1bca544e92c4c0ddf99 +Subproject commit 47ec1b0455ac1f2faab68a4c859baab7eef9e136 From c3fda41224d859631d5d0135544ccada2615d6fe Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 20 Aug 2024 17:21:11 +0200 Subject: [PATCH 012/216] Check for local URLs more strictly. --- Telegram/SourceFiles/boxes/send_files_box.cpp | 3 ++- Telegram/SourceFiles/core/file_utilities.h | 6 ++++- Telegram/SourceFiles/core/mime_type.cpp | 13 ++++++++++- Telegram/SourceFiles/core/mime_type.h | 1 + .../SourceFiles/history/history_widget.cpp | 2 +- .../platform/mac/file_utilities_mac.mm | 4 ++++ .../storage/storage_media_prepare.cpp | 23 +++++++++---------- 7 files changed, 36 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 0eade94ca..b613b4db9 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/premium_limits_box.h" #include "boxes/premium_preview_box.h" #include "boxes/send_credits_box.h" +#include "platform/platform_file_utilities.h" #include "ui/effects/scroll_content_shadow.h" #include "ui/widgets/fields/number_input.h" #include "ui/widgets/checkbox.h" @@ -70,7 +71,7 @@ constexpr auto kMaxMessageLength = 4096; using Ui::SendFilesWay; [[nodiscard]] inline bool CanAddUrls(const QList &urls) { - return !urls.isEmpty() && ranges::all_of(urls, &QUrl::isLocalFile); + return !urls.isEmpty() && ranges::all_of(urls, Core::UrlIsLocal); } [[nodiscard]] bool CanAddFiles(not_null data) { diff --git a/Telegram/SourceFiles/core/file_utilities.h b/Telegram/SourceFiles/core/file_utilities.h index 815b89772..e3efd5960 100644 --- a/Telegram/SourceFiles/core/file_utilities.h +++ b/Telegram/SourceFiles/core/file_utilities.h @@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +namespace Core { +bool UrlIsLocal(const QUrl &url); +} // namespace Core + namespace Main { class Session; } // namespace Main @@ -45,7 +49,7 @@ void ShowInFolder(const QString &filepath); namespace internal { inline QString UrlToLocalDefault(const QUrl &url) { - return url.toLocalFile(); + return Core::UrlIsLocal(url) ? url.toLocalFile() : QString(); } void UnsafeOpenUrlDefault(const QString &url); diff --git a/Telegram/SourceFiles/core/mime_type.cpp b/Telegram/SourceFiles/core/mime_type.cpp index 5e15fd4e3..2748f7628 100644 --- a/Telegram/SourceFiles/core/mime_type.cpp +++ b/Telegram/SourceFiles/core/mime_type.cpp @@ -226,13 +226,24 @@ bool CanSendFiles(not_null data) { if (data->hasImage()) { return true; } else if (const auto urls = ReadMimeUrls(data); !urls.empty()) { - if (ranges::all_of(urls, &QUrl::isLocalFile)) { + if (ranges::all_of(urls, UrlIsLocal)) { return true; } } return false; } +bool UrlIsLocal(const QUrl &url) { + if (!url.isLocalFile()) { + return false; + } + const auto result = url.toLocalFile(); + if (result.startsWith("//")) { + return false; + } + return !result.isEmpty(); +} + QString FileExtension(const QString &filepath) { const auto reversed = ranges::views::reverse(filepath); const auto last = ranges::find_first_of(reversed, ".\\/"); diff --git a/Telegram/SourceFiles/core/mime_type.h b/Telegram/SourceFiles/core/mime_type.h index ebf4db64b..57793a4b0 100644 --- a/Telegram/SourceFiles/core/mime_type.h +++ b/Telegram/SourceFiles/core/mime_type.h @@ -68,6 +68,7 @@ struct MimeImageData { [[nodiscard]] QString ReadMimeText(not_null data); [[nodiscard]] QList ReadMimeUrls(not_null data); [[nodiscard]] bool CanSendFiles(not_null data); +[[nodiscard]] bool UrlIsLocal(const QUrl &url); enum class NameType : uchar { Unknown, diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 2b3696f35..6a7fbf53b 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -5769,7 +5769,7 @@ bool HistoryWidget::canSendFiles(not_null data) const { } else if (data->hasImage()) { return true; } else if (const auto urls = Core::ReadMimeUrls(data); !urls.empty()) { - if (ranges::all_of(urls, &QUrl::isLocalFile)) { + if (ranges::all_of(urls, Core::UrlIsLocal)) { return true; } } diff --git a/Telegram/SourceFiles/platform/mac/file_utilities_mac.mm b/Telegram/SourceFiles/platform/mac/file_utilities_mac.mm index 1447454de..a41b55f1c 100644 --- a/Telegram/SourceFiles/platform/mac/file_utilities_mac.mm +++ b/Telegram/SourceFiles/platform/mac/file_utilities_mac.mm @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/mac/file_utilities_mac.h" #include "base/platform/mac/base_utilities_mac.h" +#include "core/mime_type.h" #include "lang/lang_keys.h" #include "styles/style_window.h" @@ -379,6 +380,9 @@ namespace Platform { namespace File { QString UrlToLocal(const QUrl &url) { + if (!Core::UrlIsLocal(url)) { + return QString(); + } auto result = url.toLocalFile(); if (result.startsWith(u"/.file/id="_q)) { NSString *nsurl = [[[NSURL URLWithString: [NSString stringWithUTF8String: (u"file://"_q + result).toUtf8().constData()]] filePathURL] path]; diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index 36fa14097..5578d1d09 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -83,10 +83,9 @@ bool ValidatePhotoEditorMediaDragData(not_null data) { } if (!urls.isEmpty()) { - const auto url = urls.front(); - if (url.isLocalFile()) { - using namespace Core; - const auto file = Platform::File::UrlToLocal(url); + using namespace Core; + const auto file = Platform::File::UrlToLocal(urls.front()); + if (!file.isEmpty()) { const auto info = QFileInfo(file); return FileIsImage(file, MimeTypeForFile(info).name()) && QImageReader(file).canRead(); @@ -107,10 +106,10 @@ bool ValidateEditMediaDragData( } if (albumType == Ui::AlbumType::PhotoVideo && !urls.isEmpty()) { - const auto url = urls.front(); - if (url.isLocalFile()) { - using namespace Core; - const auto info = QFileInfo(Platform::File::UrlToLocal(url)); + using namespace Core; + const auto file = Platform::File::UrlToLocal(urls.front()); + if (!file.isEmpty()) { + const auto info = QFileInfo(file); return IsMimeAcceptedForPhotoVideoAlbum(MimeTypeForFile(info).name()); } } @@ -134,10 +133,10 @@ MimeDataState ComputeMimeDataState(const QMimeData *data) { auto allAreSmallImages = true; for (const auto &url : urls) { - if (!url.isLocalFile()) { + const auto file = Platform::File::UrlToLocal(url); + if (file.isEmpty()) { return MimeDataState::None; } - const auto file = Platform::File::UrlToLocal(url); const auto info = QFileInfo(file); if (info.isDir()) { @@ -171,13 +170,13 @@ PreparedList PrepareMediaList( auto locals = QStringList(); locals.reserve(files.size()); for (const auto &url : files) { - if (!url.isLocalFile()) { + locals.push_back(Platform::File::UrlToLocal(url)); + if (locals.back().isEmpty()) { return { PreparedList::Error::NonLocalUrl, url.toDisplayString() }; } - locals.push_back(Platform::File::UrlToLocal(url)); } return PrepareMediaList(locals, previewWidth, premium); } From 46304c7a2d133f42de1de7c76b0d49eca1cf50e7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 21 Aug 2024 09:35:11 +0200 Subject: [PATCH 013/216] Fix build in Release. --- Telegram/SourceFiles/boxes/moderate_messages_box.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp index 0b8b4dc90..ee579e9eb 100644 --- a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp +++ b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp @@ -771,7 +771,9 @@ void DeleteChatBox(not_null box, not_null peer) { ? tr::lng_saved_messages() | Ui::Text::ToBold() : maybeUser ? tr::lng_profile_delete_conversation() | Ui::Text::ToBold() - : rpl::single(peer->name()) | Ui::Text::ToBold(), + : rpl::single( + peer->name() + ) | Ui::Text::ToBold() | rpl::type_erased(), box->getDelegate()->style().title)); Ui::AddSkip(container); From 6b83c52c7cf9ac0a6ed967ade987b7764b73cc3b Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 21 Aug 2024 10:47:27 +0200 Subject: [PATCH 014/216] Improve top senders rebuild. Fixes #28296. --- .../payments/ui/payments_reaction_box.cpp | 33 ++++++++++++++++--- .../SourceFiles/ui/dynamic_thumbnails.cpp | 4 ++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp index a5091c019..ffa8fc01b 100644 --- a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "payments/ui/payments_reaction_box.h" +#include "base/qt/qt_compare.h" #include "lang/lang_keys.h" #include "ui/boxes/boost_box.h" // MakeBoostFeaturesBadge. #include "ui/effects/premium_bubble.h" @@ -196,7 +197,7 @@ void PaidReactionSlider( state->name.setText(st::defaultTextStyle, data.name); const auto count = data.count; - const auto photo = data.photo; + const auto photo = data.photo->clone(); photo->subscribeToUpdates([=] { result->update(); }); @@ -248,7 +249,16 @@ void FillTopReactors( object_ptr(container, height), st::paidReactTopMargin)); const auto parent = wrap->entity(); + struct Key { + std::shared_ptr photo; + int count = 0; + QString name; + + inline auto operator<=>(const Key &) const = default; + inline bool operator==(const Key &) const = default; + }; struct State { + base::flat_map> cache; std::vector> widgets; rpl::event_stream<> updated; std::optional initialChosen; @@ -290,11 +300,26 @@ void FillTopReactors( wrap->hide(anim::type::normal); } else { for (const auto &widget : state->widgets) { - delete widget; + widget->hide(); } state->widgets.clear(); for (const auto &entry : list) { - state->widgets.push_back(MakeTopReactor(parent, entry)); + const auto key = Key{ + .photo = entry.photo, + .count = entry.count, + .name = entry.name, + }; + const auto i = state->cache.find(key); + const auto widget = (i != end(state->cache)) + ? i->second + : MakeTopReactor(parent, entry); + state->widgets.push_back(widget); + widget->show(); + } + for (const auto &[k, widget] : state->cache) { + if (widget->isHidden()) { + delete widget; + } } wrap->show(anim::type::normal); } @@ -313,7 +338,7 @@ void FillTopReactors( } const auto count = int(state->widgets.size()); auto left = (width - single * count) / 2; - for (const auto widget : state->widgets) { + for (const auto &widget : state->widgets) { widget->setGeometry(left, 0, single, height); left += single; } diff --git a/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp b/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp index 2a472c152..bd2ed0b14 100644 --- a/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp +++ b/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp @@ -261,7 +261,9 @@ void PeerUserpic::subscribeToUpdates(Fn callback) { _subscribed = nullptr; return; } - _subscribed = std::make_unique(std::move(callback)); + const auto old = std::exchange( + _subscribed, + std::make_unique(std::move(callback))); _peer->session().changes().peerUpdates( _peer, From 10ebd7e6ef687c9e6d1eee3344cc92bac404b5b6 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 20 Aug 2024 11:15:46 +0300 Subject: [PATCH 015/216] Moved out AdminLog::FilterValue to separate file. --- .../admin_log/history_admin_log_filter.h | 4 +- .../history_admin_log_filter_value.h | 54 +++++++++++++++++++ .../admin_log/history_admin_log_inner.h | 3 +- .../admin_log/history_admin_log_section.h | 40 +------------- Telegram/cmake/td_ui.cmake | 1 + 5 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 Telegram/SourceFiles/history/admin_log/history_admin_log_filter_value.h diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h index 7876c3204..e515bbc15 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h @@ -8,10 +8,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/layers/box_content.h" -#include "history/admin_log/history_admin_log_section.h" +#include "history/admin_log/history_admin_log_filter_value.h" namespace AdminLog { +struct FilterValue; + class FilterBox : public Ui::BoxContent { public: FilterBox( diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter_value.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter_value.h new file mode 100644 index 000000000..89d55c37f --- /dev/null +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter_value.h @@ -0,0 +1,54 @@ +/* +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 + +namespace AdminLog { + +struct FilterValue final { + enum class Flag : uint32 { + Join = (1U << 0), + Leave = (1U << 1), + Invite = (1U << 2), + Ban = (1U << 3), + Unban = (1U << 4), + Kick = (1U << 5), + Unkick = (1U << 6), + Promote = (1U << 7), + Demote = (1U << 8), + Info = (1U << 9), + Settings = (1U << 10), + Pinned = (1U << 11), + Edit = (1U << 12), + Delete = (1U << 13), + GroupCall = (1U << 14), + Invites = (1U << 15), + Topics = (1U << 16), + + MAX_FIELD = (1U << 16), + }; + using Flags = base::flags; + friend inline constexpr bool is_flag_type(Flag) { return true; }; + + // Empty "flags" means all events. + Flags flags = 0; + std::vector> admins; + bool allUsers = true; + +}; + +inline bool operator==(const FilterValue &a, const FilterValue &b) { + return (a.flags == b.flags) + && (a.admins == b.admins) + && (a.allUsers == b.allUsers); +} + +inline bool operator!=(const FilterValue &a, const FilterValue &b) { + return !(a == b); +} + +} // namespace AdminLog diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h index 5f55e5d40..ed13def82 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_element.h" #include "history/admin_log/history_admin_log_item.h" -#include "history/admin_log/history_admin_log_section.h" +#include "history/admin_log/history_admin_log_filter_value.h" #include "menu/menu_antispam_validator.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" @@ -34,6 +34,7 @@ enum class PointState : char; namespace Ui { class PopupMenu; class ChatStyle; +class ChatTheme; struct PeerUserpicView; } // namespace Ui diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h index 43c27d043..8a547ee81 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/section_widget.h" #include "window/section_memento.h" #include "history/admin_log/history_admin_log_item.h" +#include "history/admin_log/history_admin_log_filter_value.h" #include "mtproto/sender.h" namespace Ui { @@ -28,45 +29,6 @@ class FixedBar; class InnerWidget; class SectionMemento; -struct FilterValue { - enum class Flag : uint32 { - Join = (1U << 0), - Leave = (1U << 1), - Invite = (1U << 2), - Ban = (1U << 3), - Unban = (1U << 4), - Kick = (1U << 5), - Unkick = (1U << 6), - Promote = (1U << 7), - Demote = (1U << 8), - Info = (1U << 9), - Settings = (1U << 10), - Pinned = (1U << 11), - Edit = (1U << 12), - Delete = (1U << 13), - GroupCall = (1U << 14), - Invites = (1U << 15), - Topics = (1U << 16), - - MAX_FIELD = (1U << 16), - }; - using Flags = base::flags; - friend inline constexpr bool is_flag_type(Flag) { return true; }; - - // Empty "flags" means all events. - Flags flags = 0; - std::vector> admins; - bool allUsers = true; -}; - -inline bool operator==(const FilterValue &a, const FilterValue &b) { - return (a.flags == b.flags && a.admins == b.admins && a.allUsers == b.allUsers); -} - -inline bool operator!=(const FilterValue &a, const FilterValue &b) { - return !(a == b); -} - class Widget final : public Window::SectionWidget { public: Widget( diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 8ec670702..d1db73c56 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -124,6 +124,7 @@ PRIVATE editor/scene/scene_item_line.cpp editor/scene/scene_item_line.h + history/admin_log/history_admin_log_filter_value.h history/history_view_top_toast.cpp history/history_view_top_toast.h history/view/controls/history_view_characters_limit.cpp From 1e6236a98733e1604469d96d860a19f6251dec48 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 20 Aug 2024 22:12:33 +0300 Subject: [PATCH 016/216] Wrapped filter value labels with EditFlagsControl. --- Telegram/Resources/langs/lang.strings | 6 ++ .../boxes/peers/edit_peer_permissions_box.cpp | 21 +++++ .../boxes/peers/edit_peer_permissions_box.h | 9 +- .../admin_log/history_admin_log_filter.cpp | 92 +++++++++++++++++-- .../admin_log/history_admin_log_filter.h | 7 +- 5 files changed, 125 insertions(+), 10 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 05ae9113e..6787d39da 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4344,11 +4344,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_admin_log_filter" = "Filter"; "lng_admin_log_filter_title" = "Filter"; "lng_admin_log_filter_all_actions" = "All actions"; +"lng_admin_log_filter_actions_type_subtitle" = "Filter actions by type"; +"lng_admin_log_filter_actions_member_section" = "Members And Admins"; "lng_admin_log_filter_restrictions" = "New restrictions"; "lng_admin_log_filter_admins_new" = "New admins"; "lng_admin_log_filter_members_new" = "New members"; +"lng_admin_log_filter_actions_settings_section" = "Group Settings"; "lng_admin_log_filter_info_group" = "Group info"; "lng_admin_log_filter_info_channel" = "Channel info"; +"lng_admin_log_filter_actions_messages_section" = "Messages"; "lng_admin_log_filter_messages_deleted" = "Deleted messages"; "lng_admin_log_filter_messages_edited" = "Edited messages"; "lng_admin_log_filter_messages_pinned" = "Pinned messages"; @@ -4358,6 +4362,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_admin_log_filter_members_removed" = "Leaving members"; "lng_admin_log_filter_topics" = "Topics"; "lng_admin_log_filter_all_admins" = "All users and admins"; +"lng_admin_log_filter_actions_admins_subtitle" = "Filter actions by admins"; +"lng_admin_log_filter_actions_admins_section" = "Show Actions by All Admins"; "lng_admin_log_about" = "What is this?"; "lng_admin_log_about_text" = "This is a list of all service actions taken by the group's members and admins in the last 48 hours."; "lng_admin_log_about_text_channel" = "This is a list of all service actions taken by the channel's admins in the last 48 hours."; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index 385cb1ac6..3cb0265ba 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/edit_peer_permissions_box.h" #include "lang/lang_keys.h" +#include "history/admin_log/history_admin_log_filter.h" #include "core/ui_integration.h" #include "data/stickers/data_custom_emoji.h" #include "data/data_channel.h" @@ -55,6 +56,11 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000); return {}; } +[[nodiscard]] auto Dependencies(AdminLog::FilterValue::Flags) { + using Flag = AdminLog::FilterValue::Flag; + return std::vector>{}; +} + [[nodiscard]] auto NestedRestrictionLabelsList( Data::RestrictionsSetOptions options) -> std::vector> { @@ -1432,3 +1438,18 @@ EditFlagsControl CreateEditPowerSaving( return result; } + +EditFlagsControl CreateEditAdminLogFilter( + QWidget *parent, + AdminLog::FilterValue::Flags flags, + bool isChannel) { + auto widget = object_ptr(parent); + auto descriptor = AdminLog::FilterValueLabels(isChannel); + auto result = CreateEditFlags( + widget.data(), + flags, + std::move(descriptor)); + result.widget = std::move(widget); + + return result; +} diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h index 05e1962d4..b7e63e2e2 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h @@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "data/data_chat_participant_status.h" #include "base/object_ptr.h" +#include "data/data_chat_participant_status.h" +#include "history/admin_log/history_admin_log_filter_value.h" namespace style { struct SettingsButton; @@ -115,3 +116,9 @@ using AdminRightLabel = EditFlagsLabel; PowerSaving::Flags flags, rpl::producer forceDisabledMessage ) -> EditFlagsControl; + +[[nodiscard]] auto CreateEditAdminLogFilter( + QWidget *parent, + AdminLog::FilterValue::Flags flags, + bool isChannel +) -> EditFlagsControl; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp index 6265c81e4..bf0fc2fca 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp @@ -7,15 +7,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "history/admin_log/history_admin_log_filter.h" -#include "ui/widgets/checkbox.h" -#include "ui/effects/ripple_animation.h" -#include "ui/text/text_options.h" -#include "ui/painter.h" -#include "lang/lang_keys.h" -#include "data/data_peer_values.h" -#include "data/data_channel.h" -#include "data/data_user.h" #include "base/unixtime.h" +#include "boxes/peers/edit_peer_permissions_box.h" +#include "data/data_channel.h" +#include "data/data_peer_values.h" +#include "data/data_user.h" +#include "history/admin_log/history_admin_log_filter_value.h" +#include "lang/lang_keys.h" +#include "ui/effects/ripple_animation.h" +#include "ui/layers/generic_box.h" +#include "ui/painter.h" +#include "ui/text/text_options.h" +#include "ui/vertical_list.h" +#include "ui/widgets/checkbox.h" #include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_chat.h" @@ -440,4 +444,76 @@ void FilterBox::resizeToContent() { setDimensions(_inner->width(), _inner->height()); } +EditFlagsDescriptor FilterValueLabels(bool isChannel) { + using Label = EditFlagsLabel; + using Flag = FilterValue::Flag; + + const auto adminRights = Flag::Promote | Flag::Demote; + const auto restrictions = Flag::Ban + | Flag::Unban + | Flag::Kick + | Flag::Unkick; + const auto membersNew = Flag::Join | Flag::Invite; + const auto membersRemoved = Flag::Leave; + + auto members = std::vector