From e7558512373ca80ed24225b6b618ddd897db8d9c Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 31 Aug 2023 22:42:51 +0400 Subject: [PATCH 001/155] Update lib_base --- Telegram/lib_base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_base b/Telegram/lib_base index 764b55db1..57e2519de 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 764b55db1a4a8b9d8ba966d7f0fa46c9f384737e +Subproject commit 57e2519de75fb5732e53d28282ac97e881061421 From e34e640dbb07bc044cfb5fba114b048134c23bcb Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 1 Sep 2023 00:22:25 +0000 Subject: [PATCH 002/155] Update User-Agent for DNS to Chrome 116.0.5845.96. --- .../SourceFiles/mtproto/details/mtproto_domain_resolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp index f09fe11f9..b07d2c5e5 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp @@ -65,7 +65,7 @@ QByteArray DnsUserAgent() { static const auto kResult = QByteArray( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/115.0.5790.102 Safari/537.36"); + "Chrome/116.0.5845.96 Safari/537.36"); return kResult; } From 119f7e757d3b1a4896132ed52e9c81a05165b9d9 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 Sep 2023 10:52:30 +0400 Subject: [PATCH 003/155] Don't show yourself in notification exceptions. --- Telegram/SourceFiles/data/notify/data_notify_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/data/notify/data_notify_settings.cpp b/Telegram/SourceFiles/data/notify/data_notify_settings.cpp index c522b8aa5..beb47698b 100644 --- a/Telegram/SourceFiles/data/notify/data_notify_settings.cpp +++ b/Telegram/SourceFiles/data/notify/data_notify_settings.cpp @@ -44,7 +44,7 @@ constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * crl::time(1000); [[nodiscard]] bool SkipAddException(not_null peer) { if (const auto user = peer->asUser()) { - return user->isInaccessible(); + return user->isInaccessible() || user->isSelf(); } else if (const auto chat = peer->asChat()) { return chat->isDeactivated() || chat->isForbidden(); } else if (const auto channel = peer->asChannel()) { From 48072446821edcdd11b502906bb2123a903be321 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sun, 3 Sep 2023 23:43:15 +0400 Subject: [PATCH 004/155] Don't use crl::on_main unnecessarily with XDP::SettingWatcher g_dbus_connection_signal_subscribe calls the callback on the same thread --- .../platform/linux/integration_linux.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/integration_linux.cpp b/Telegram/SourceFiles/platform/linux/integration_linux.cpp index f842fd808..bdbd51999 100644 --- a/Telegram/SourceFiles/platform/linux/integration_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/integration_linux.cpp @@ -216,14 +216,13 @@ LinuxIntegration::LinuxIntegration() #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) QWindowSystemInterface::handleThemeChange(); #else // Qt >= 6.5.0 - try { - const auto ivalue = value.get_dynamic(); - - crl::on_main([=] { - Core::App().settings().setSystemDarkMode(ivalue == 1); - }); - } catch (...) { - } + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + try { + Core::App().settings().setSystemDarkMode( + value.get_dynamic() == 1); + } catch (...) { + } + }); #endif // Qt < 6.5.0 } }) { From ae2182c1e5c395d2ba48b5084f358e45b78ceaf3 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 30 Aug 2023 23:33:54 +0300 Subject: [PATCH 005/155] Removed document's requirement when it's unavailable in userpic builder. --- .../info_userpic_emoji_builder_preview.cpp | 16 ++++++++++------ .../userpic/info_userpic_emoji_builder_preview.h | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp index c7997381c..54e3767f7 100644 --- a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp +++ b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp @@ -47,9 +47,8 @@ PreviewPainter::PreviewPainter(int size) } } -not_null PreviewPainter::document() const { - Expects(_media != nullptr); - return _media->owner(); +DocumentData *PreviewPainter::document() const { + return _media ? _media->owner() : nullptr; } void PreviewPainter::setPlayOnce(bool value) { @@ -183,7 +182,7 @@ void EmojiUserpic::result(int size, Fn done) { const auto painter = lifetime().make_state(size); // Reset to the first frame. const auto document = _painter.document(); - painter->setDocument(document, [=] { + const auto callback = [=] { auto background = GenerateGradient(Size(size), _colors, false); { @@ -194,12 +193,17 @@ void EmojiUserpic::result(int size, Fn done) { } } } - if (*_playOnce) { + if (*_playOnce && document) { done({ std::move(background), document->id, _colors }); } else { done({ std::move(background) }); } - }); + }; + if (document) { + painter->setDocument(document, callback); + } else { + callback(); + } } void EmojiUserpic::setGradientColors(std::vector colors) { diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.h b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.h index 13561ac79..9961c54a7 100644 --- a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.h +++ b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.h @@ -29,7 +29,7 @@ class PreviewPainter final { public: PreviewPainter(int size); - [[nodiscard]] not_null document() const; + [[nodiscard]] DocumentData *document() const; void setPlayOnce(bool value); void setDocument( From 98bb520f476c3ca1df950969d6e5079036ec0de5 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 31 Aug 2023 14:21:24 +0300 Subject: [PATCH 006/155] Adjusted code for refactor of input fields in lib_ui. --- .../SourceFiles/boxes/add_contact_box.cpp | 49 +++++++++-------- Telegram/SourceFiles/boxes/connection_box.cpp | 4 +- .../SourceFiles/boxes/create_poll_box.cpp | 53 +++++++++++-------- .../SourceFiles/boxes/edit_caption_box.cpp | 20 ++++--- .../boxes/filters/edit_filter_box.cpp | 7 +-- .../boxes/filters/edit_filter_links.cpp | 2 +- Telegram/SourceFiles/boxes/passcode_box.cpp | 39 ++++++++------ Telegram/SourceFiles/boxes/passcode_box.h | 1 - .../boxes/peers/edit_contact_box.cpp | 6 +-- .../boxes/peers/edit_forum_topic_box.cpp | 8 ++- .../boxes/peers/edit_participant_box.cpp | 7 +-- .../boxes/peers/edit_peer_info_box.cpp | 18 +++---- .../boxes/peers/edit_peer_type_box.cpp | 2 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 18 ++++--- Telegram/SourceFiles/boxes/sessions_box.cpp | 4 +- Telegram/SourceFiles/boxes/share_box.cpp | 7 ++- Telegram/SourceFiles/boxes/stickers_box.cpp | 2 +- .../calls/group/calls_group_menu.cpp | 2 +- .../calls/group/calls_group_panel.cpp | 2 +- .../calls/group/calls_group_settings.cpp | 2 +- .../group/ui/calls_group_recording_box.cpp | 6 +-- .../chat_helpers/emoji_suggestions_widget.cpp | 2 +- .../chat_helpers/field_autocomplete.cpp | 2 +- .../chat_helpers/gifs_list_widget.cpp | 2 +- .../chat_helpers/message_field.cpp | 23 +++++--- .../SourceFiles/chat_helpers/message_field.h | 5 +- .../chat_helpers/stickers_list_footer.cpp | 2 +- Telegram/SourceFiles/core/core_settings.cpp | 2 +- Telegram/SourceFiles/data/data_drafts.cpp | 2 +- Telegram/SourceFiles/data/data_forum.cpp | 2 +- Telegram/SourceFiles/data/data_types.cpp | 2 +- .../data/stickers/data_custom_emoji.cpp | 2 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 13 ++--- .../admin_log/history_admin_log_section.cpp | 15 ++++-- .../SourceFiles/history/history_widget.cpp | 33 +++++++----- Telegram/SourceFiles/history/history_widget.h | 2 +- .../history_view_compose_controls.cpp | 41 +++++++------- .../controls/history_view_compose_controls.h | 3 +- .../view/history_view_schedule_box.cpp | 2 +- .../view/history_view_top_bar_widget.cpp | 12 +++-- .../SourceFiles/info/info_content_widget.cpp | 2 +- Telegram/SourceFiles/info/info_top_bar.cpp | 5 +- .../info/profile/info_profile_members.cpp | 2 +- Telegram/SourceFiles/intro/intro_code.cpp | 1 + Telegram/SourceFiles/intro/intro_code.h | 2 +- .../intro/intro_password_check.cpp | 10 ++-- Telegram/SourceFiles/intro/intro_signup.cpp | 2 +- .../main/main_session_settings.cpp | 2 +- .../passport/passport_edit_identity_box.cpp | 2 +- .../passport/passport_panel_edit_contact.cpp | 9 ++-- .../passport/passport_panel_edit_document.cpp | 2 +- .../passport/passport_panel_password.cpp | 2 +- .../passport/ui/passport_details_row.cpp | 16 ++++-- .../payments/ui/payments_field.cpp | 9 ++-- .../platform/linux/main_window_linux.cpp | 4 +- .../platform/mac/main_window_mac.mm | 4 +- .../mac/touchbar/items/mac_scrubber_item.mm | 4 +- .../settings_cloud_password_common.cpp | 4 +- .../settings_cloud_password_email.cpp | 9 ++-- .../settings_cloud_password_email_confirm.cpp | 7 +-- .../settings_cloud_password_hint.cpp | 9 ++-- .../settings_cloud_password_input.cpp | 2 +- .../SourceFiles/settings/settings_chat.cpp | 2 +- .../SourceFiles/settings/settings_folders.cpp | 2 +- .../settings/settings_information.cpp | 8 ++- .../settings/settings_local_passcode.cpp | 2 +- .../details/storage_settings_scheme.cpp | 2 +- .../support/support_autocomplete.cpp | 16 +++--- .../SourceFiles/support/support_helper.cpp | 9 ++-- .../SourceFiles/ui/boxes/choose_date_time.cpp | 11 ++-- .../ui/boxes/confirm_phone_box.cpp | 3 +- .../SourceFiles/ui/boxes/edit_invite_link.cpp | 3 +- .../SourceFiles/ui/boxes/rate_call_box.cpp | 15 ++++-- Telegram/SourceFiles/ui/boxes/report_box.cpp | 5 +- .../SourceFiles/ui/controls/tabbed_search.cpp | 16 +++--- .../ui/search_field_controller.cpp | 12 +++-- .../SourceFiles/ui/widgets/color_editor.cpp | 2 +- .../ui/widgets/fields/special_fields.cpp | 1 + .../ui/widgets/fields/special_fields.h | 2 +- .../SourceFiles/ui/widgets/multi_select.cpp | 31 ++++++----- .../ui/widgets/sent_code_field.cpp | 2 +- .../SourceFiles/ui/widgets/sent_code_field.h | 2 +- .../window/notifications_manager_default.cpp | 15 ++++-- .../window/themes/window_theme_editor_box.cpp | 2 +- .../window/window_lock_widgets.cpp | 2 +- .../SourceFiles/window/window_peer_menu.cpp | 7 ++- Telegram/lib_spellcheck | 2 +- Telegram/lib_ui | 2 +- Telegram/lib_webview | 2 +- 89 files changed, 413 insertions(+), 300 deletions(-) diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp index ccea61d70..aab01656d 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp @@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/toast/toast.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/fields/special_fields.h" #include "ui/widgets/popup_menu.h" #include "ui/text/format_values.h" @@ -297,8 +298,11 @@ void AddContactBox::prepare() { : tr::lng_enter_contact_data()); updateButtons(); - connect(_first, &Ui::InputField::submitted, [=] { submit(); }); - connect(_last, &Ui::InputField::submitted, [=] { submit(); }); + const auto submitted = [=] { submit(); }; + _first->submits( + ) | rpl::start_with_next(submitted, _first->lifetime()); + _last->submits( + ) | rpl::start_with_next(submitted, _last->lifetime()); connect(_phone, &Ui::PhoneInput::submitted, [=] { submit(); }); setDimensions( @@ -567,23 +571,24 @@ void GroupInfoBox::prepare() { _description->setSubmitSettings( Core::App().settings().sendSubmitWay()); - connect(_description, &Ui::InputField::resized, [=] { + _description->heightChanges( + ) | rpl::start_with_next([=] { descriptionResized(); - }); - connect(_description, &Ui::InputField::submitted, [=] { - submit(); - }); - connect(_description, &Ui::InputField::cancelled, [=] { + }, _description->lifetime()); + _description->submits( + ) | rpl::start_with_next([=] { submit(); }, _description->lifetime()); + _description->cancelled( + ) | rpl::start_with_next([=] { closeBox(); - }); + }, _description->lifetime()); Ui::Emoji::SuggestionsController::Init( getDelegate()->outerContainer(), _description, &_navigation->session()); } - - connect(_title, &Ui::InputField::submitted, [=] { submitName(); }); + _title->submits( + ) | rpl::start_with_next([=] { submitName(); }, _title->lifetime()); addButton( ((_type != Type::Group || _canAddBot) @@ -1522,20 +1527,22 @@ void EditNameBox::prepare() { _first->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName); _last->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName); - connect(_first, &Ui::InputField::submitted, [=] { submit(); }); - connect(_last, &Ui::InputField::submitted, [=] { submit(); }); + _first->submits( + ) | rpl::start_with_next([=] { submit(); }, _first->lifetime()); + _last->submits( + ) | rpl::start_with_next([=] { submit(); }, _last->lifetime()); _first->customTab(true); _last->customTab(true); - QObject::connect( - _first, - &Ui::InputField::tabbed, - [=] { _last->setFocus(); }); - QObject::connect( - _last, - &Ui::InputField::tabbed, - [=] { _first->setFocus(); }); + _first->tabbed( + ) | rpl::start_with_next([=] { + _last->setFocus(); + }, _first->lifetime()); + _last->tabbed( + ) | rpl::start_with_next([=] { + _first->setFocus(); + }, _last->lifetime()); } void EditNameBox::setInnerFocus() { diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index 626671cb4..144582a53 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -18,7 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/facade.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" +#include "ui/widgets/fields/number_input.h" +#include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/widgets/dropdown_menu.h" #include "ui/wrap/slide_wrap.h" diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index ca1eb70f3..3274e4eeb 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/vertical_layout.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/fade_wrap.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/shadow.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" @@ -184,7 +184,8 @@ not_null CreateWarningLabel( QString(), st::createPollWarning); result->setAttribute(Qt::WA_TransparentForMouseEvents); - QObject::connect(field, &Ui::InputField::changed, [=] { + field->changes( + ) | rpl::start_with_next([=] { Ui::PostponeCall(crl::guard(field, [=] { const auto length = field->getLastText().size(); const auto value = valueLimit - length; @@ -198,7 +199,7 @@ not_null CreateWarningLabel( } result->setVisible(shown); })); - }); + }, field->lifetime()); return result; } @@ -243,13 +244,14 @@ Options::Option::Option( _content->resize(_content->width(), height); }, _field->lifetime()); - QObject::connect(_field, &Ui::InputField::changed, [=] { + _field->changes( + ) | rpl::start_with_next([=] { Ui::PostponeCall(crl::guard(_field, [=] { if (_hasCorrect) { _correct->toggle(isGood(), anim::type::normal); } })); - }); + }, _field->lifetime()); createShadow(); createRemove(); @@ -303,10 +305,11 @@ void Options::Option::createRemove() { const auto toggle = lifetime.make_state>(false); _removeAlways = lifetime.make_state>(false); - QObject::connect(field, &Ui::InputField::changed, [=] { + field->changes( + ) | rpl::start_with_next([field, toggle] { // Don't capture 'this'! Because Option is a value type. *toggle = !field->getLastText().isEmpty(); - }); + }, field->lifetime()); rpl::combine( toggle->value(), _removeAlways->value(), @@ -649,28 +652,32 @@ void Options::addEmptyOption() { _position + _list.size() + _destroyed.size(), _chooseCorrectGroup)); const auto field = _list.back()->field(); - QObject::connect(field, &Ui::InputField::submitted, [=] { + field->submits( + ) | rpl::start_with_next([=] { const auto index = findField(field); if (_list[index]->isGood() && index + 1 < _list.size()) { _list[index + 1]->setFocus(); } - }); - QObject::connect(field, &Ui::InputField::changed, [=] { + }, field->lifetime()); + field->changes( + ) | rpl::start_with_next([=] { Ui::PostponeCall(crl::guard(field, [=] { validateState(); })); - }); - QObject::connect(field, &Ui::InputField::focused, [=] { + }, field->lifetime()); + field->focusedChanges( + ) | rpl::filter(rpl::mappers::_1) | rpl::start_with_next([=] { _scrollToWidget.fire_copy(field); - }); - QObject::connect(field, &Ui::InputField::tabbed, [=] { + }, field->lifetime()); + field->tabbed( + ) | rpl::start_with_next([=] { const auto index = findField(field); if (index + 1 < _list.size()) { _list[index + 1]->setFocus(); } else { _tabbed.fire({}); } - }); + }, field->lifetime()); base::install_event_filter(field, [=](not_null event) { if (event->type() != QEvent::KeyPress || !field->getLastText().isEmpty()) { @@ -927,9 +934,10 @@ object_ptr CreatePollBox::setupContent() { st::boxDividerLabel), st::createPollLimitPadding)); - connect(question, &Ui::InputField::tabbed, [=] { + question->tabbed( + ) | rpl::start_with_next([=] { options->focusFirst(); - }); + }, question->lifetime()); AddSkip(container); AddSubsectionTitle(container, tr::lng_polls_create_settings()); @@ -975,9 +983,10 @@ object_ptr CreatePollBox::setupContent() { } }, question->lifetime()); - connect(solution, &Ui::InputField::tabbed, [=] { + solution->tabbed( + ) | rpl::start_with_next([=] { question->setFocus(); - }); + }, solution->lifetime()); quiz->setDisabled(_disabled & PollData::Flag::Quiz); if (multiple) { @@ -1009,12 +1018,12 @@ object_ptr CreatePollBox::setupContent() { const auto text = question->getLastText().trimmed(); return !text.isEmpty() && (text.size() <= kQuestionLimit); }; - - connect(question, &Ui::InputField::submitted, [=] { + question->submits( + ) | rpl::start_with_next([=] { if (isValidQuestion()) { options->focusFirst(); } - }); + }, question->lifetime()); _setInnerFocus = [=] { question->setFocusFast(); diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 4a2b53c5f..defc4bd64 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -54,7 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/ui_utility.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" @@ -488,9 +488,16 @@ void EditCaptionBox::setupField() { Core::App().settings().sendSubmitWay()); _field->setMaxHeight(st::defaultComposeFiles.caption.heightMax); - connect(_field, &Ui::InputField::submitted, [=] { save(); }); - connect(_field, &Ui::InputField::cancelled, [=] { closeBox(); }); - connect(_field, &Ui::InputField::resized, [=] { captionResized(); }); + _field->submits( + ) | rpl::start_with_next([=] { save(); }, _field->lifetime()); + _field->cancelled( + ) | rpl::start_with_next([=] { + closeBox(); + }, _field->lifetime()); + _field->heightChanges( + ) | rpl::start_with_next([=] { + captionResized(); + }, _field->lifetime()); _field->setMimeDataHook([=]( not_null data, Ui::InputField::MimeAction action) { @@ -522,10 +529,11 @@ void EditCaptionBox::setInitialText() { setCloseByOutsideClick(true); } }); - connect(_field, &Ui::InputField::changed, [=] { + _field->changes( + ) | rpl::start_with_next([=] { _checkChangedTimer.callOnce(kChangesDebounceTimeout); setCloseByOutsideClick(false); - }); + }, _field->lifetime()); } void EditCaptionBox::setupControls() { diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp index 88bbdca03..0c3760831 100644 --- a/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp +++ b/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/text/text_options.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/wrap/slide_wrap.h" #include "ui/effects/panel_animation.h" #include "ui/filter_icons.h" @@ -619,11 +619,12 @@ void EditFilterBox( nameEditing->custom = true; }, box->lifetime()); - QObject::connect(name, &Ui::InputField::changed, [=] { + name->changes( + ) | rpl::start_with_next([=] { if (!nameEditing->settingDefault) { nameEditing->custom = true; } - }); + }, name->lifetime()); const auto updateDefaultTitle = [=](const Data::ChatFilter &filter) { if (nameEditing->custom) { return; diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp index d7e2c0920..557eefa9a 100644 --- a/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp +++ b/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp @@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/invite_link_label.h" #include "ui/text/text_utilities.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/popup_menu.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/slide_wrap.h" diff --git a/Telegram/SourceFiles/boxes/passcode_box.cpp b/Telegram/SourceFiles/boxes/passcode_box.cpp index 5ec269aac..dd165ac61 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.cpp +++ b/Telegram/SourceFiles/boxes/passcode_box.cpp @@ -21,10 +21,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/layers/generic_box.h" #include "ui/text/text_utilities.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" +#include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" -#include "ui/widgets/sent_code_field.h" -#include "ui/wrap/vertical_layout.h" #include "ui/wrap/fade_wrap.h" #include "ui/painter.h" #include "passport/passport_encryption.h" @@ -306,15 +305,26 @@ void PasscodeBox::prepare() { connect(_oldPasscode, &Ui::MaskedInputField::changed, [=] { oldChanged(); }); connect(_newPasscode, &Ui::MaskedInputField::changed, [=] { newChanged(); }); connect(_reenterPasscode, &Ui::MaskedInputField::changed, [=] { newChanged(); }); - connect(_passwordHint, &Ui::InputField::changed, [=] { newChanged(); }); - connect(_recoverEmail, &Ui::InputField::changed, [=] { emailChanged(); }); + _passwordHint->changes( + ) | rpl::start_with_next([=] { + newChanged(); + }, _passwordHint->lifetime()); + _recoverEmail->changes( + ) | rpl::start_with_next([=] { + if (!_emailError.isEmpty()) { + _emailError = QString(); + update(); + } + }, _recoverEmail->lifetime()); const auto fieldSubmit = [=] { submit(); }; connect(_oldPasscode, &Ui::MaskedInputField::submitted, fieldSubmit); connect(_newPasscode, &Ui::MaskedInputField::submitted, fieldSubmit); connect(_reenterPasscode, &Ui::MaskedInputField::submitted, fieldSubmit); - connect(_passwordHint, &Ui::InputField::submitted, fieldSubmit); - connect(_recoverEmail, &Ui::InputField::submitted, fieldSubmit); + _passwordHint->submits( + ) | rpl::start_with_next(fieldSubmit, _passwordHint->lifetime()); + _recoverEmail->submits( + ) | rpl::start_with_next(fieldSubmit, _recoverEmail->lifetime()); _recover->addClickHandler([=] { recoverByEmail(); }); @@ -1061,13 +1071,6 @@ void PasscodeBox::newChanged() { } } -void PasscodeBox::emailChanged() { - if (!_emailError.isEmpty()) { - _emailError = QString(); - update(); - } -} - void PasscodeBox::recoverByEmail() { if (!_cloudFields.hasRecovery) { Assert(_session != nullptr); @@ -1189,8 +1192,12 @@ void RecoverBox::prepare() { + _recoverCode->height() + st::passcodeTextLine)); - connect(_recoverCode, &Ui::InputField::changed, [=] { codeChanged(); }); - connect(_recoverCode, &Ui::InputField::submitted, [=] { submit(); }); + _recoverCode->changes( + ) | rpl::start_with_next([=] { + codeChanged(); + }, _recoverCode->lifetime()); + _recoverCode->submits( + ) | rpl::start_with_next([=] { submit(); }, _recoverCode->lifetime()); } void RecoverBox::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/boxes/passcode_box.h b/Telegram/SourceFiles/boxes/passcode_box.h index ee11765a2..75a235b16 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.h +++ b/Telegram/SourceFiles/boxes/passcode_box.h @@ -90,7 +90,6 @@ private: void closeReplacedBy(); void oldChanged(); void newChanged(); - void emailChanged(); void save(bool force = false); void badOldPasscode(); void recoverByEmail(); diff --git a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp index 0aa24c79e..19af19ac6 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/vertical_layout.h" #include "ui/widgets/labels.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/text/format_values.h" // Ui::FormatPhone #include "ui/text/text_utilities.h" #include "info/profile/info_profile_cover.h" @@ -239,8 +239,8 @@ void Controller::initNameFields( _save(); } }; - QObject::connect(first, &Ui::InputField::submitted, submit); - QObject::connect(last, &Ui::InputField::submitted, submit); + first->submits() | rpl::start_with_next(submit, first->lifetime()); + last->submits() | rpl::start_with_next(submit, last->lifetime()); first->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName); first->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName); } diff --git a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp index d5dbc6789..5caa2ce5c 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/peers/edit_forum_topic_box.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/shadow.h" #include "ui/effects/emoji_fly_animation.h" #include "ui/abstract_button.h" @@ -465,15 +465,13 @@ void EditForumTopicBox( ChooseNextColorId(current.colorId, state->otherColorIds), }; }); - base::qt_signal_producer( - title, - &Ui::InputField::changed + title->changes( ) | rpl::start_with_next([=] { state->defaultIcon = DefaultIcon{ title->getLastText().trimmed(), state->defaultIcon.current().colorId, }; - }, box->lifetime()); + }, title->lifetime()); if (!topic || !topic->isGeneral()) { Settings::AddDividerText( diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index f47beae75..6e205cb84 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/box_content_divider.h" #include "ui/layers/generic_box.h" #include "ui/toast/toast.h" @@ -461,13 +461,14 @@ not_null EditAdminBox::addRankInput( st::rightsAboutMargin); result->setMaxLength(kAdminRoleLimit); result->setInstantReplaces(Ui::InstantReplaces::TextOnly()); - connect(result, &Ui::InputField::changed, [=] { + result->changes( + ) | rpl::start_with_next([=] { const auto text = result->getLastText(); const auto removed = TextUtilities::RemoveEmoji(text); if (removed != text) { result->setText(removed); } - }); + }, result->lifetime()); container->add( object_ptr( diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 01251e1f8..3e95dcc1f 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -51,7 +51,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/widgets/box_content_divider.h" #include "ui/wrap/padding_wrap.h" @@ -519,10 +519,10 @@ object_ptr Controller::createTitleEdit() { result->entity(), &_peer->session()); - QObject::connect( - result->entity(), - &Ui::InputField::submitted, - [=] { submitTitle(); }); + result->entity()->submits( + ) | rpl::start_with_next([=] { + submitTitle(); + }, result->entity()->lifetime()); _controls.title = result->entity(); return result; @@ -555,10 +555,10 @@ object_ptr Controller::createDescriptionEdit() { result->entity(), &_peer->session()); - QObject::connect( - result->entity(), - &Ui::InputField::submitted, - [=] { submitDescription(); }); + result->entity()->submits( + ) | rpl::start_with_next([=] { + submitDescription(); + }, result->entity()->lifetime()); _controls.description = result->entity(); return result; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp index 2739eb125..bae0be7fe 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp @@ -32,7 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/userpic_button.h" #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/widgets/box_content_divider.h" #include "ui/wrap/padding_wrap.h" diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 46ac4b111..efea9ad8e 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -31,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/scroll_content_shadow.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/popup_menu.h" #include "ui/wrap/vertical_layout.h" @@ -1030,17 +1030,21 @@ void SendFilesBox::setupCaption() { Core::App().settings().sendSubmitWay()); _caption->setMaxLength(kMaxMessageLength); - connect(_caption, &Ui::InputField::resized, [=] { + _caption->heightChanges( + ) | rpl::start_with_next([=] { captionResized(); - }); - connect(_caption, &Ui::InputField::submitted, [=]( - Qt::KeyboardModifiers modifiers) { + }, _caption->lifetime()); + _caption->submits( + ) | rpl::start_with_next([=](Qt::KeyboardModifiers modifiers) { const auto ctrlShiftEnter = modifiers.testFlag(Qt::ShiftModifier) && (modifiers.testFlag(Qt::ControlModifier) || modifiers.testFlag(Qt::MetaModifier)); send({}, ctrlShiftEnter); - }); - connect(_caption, &Ui::InputField::cancelled, [=] { closeBox(); }); + }, _caption->lifetime()); + _caption->cancelled( + ) | rpl::start_with_next([=] { + closeBox(); + }, _caption->lifetime()); _caption->setMimeDataHook([=]( not_null data, Ui::InputField::MimeAction action) { diff --git a/Telegram/SourceFiles/boxes/sessions_box.cpp b/Telegram/SourceFiles/boxes/sessions_box.cpp index e30174be6..d458111f2 100644 --- a/Telegram/SourceFiles/boxes/sessions_box.cpp +++ b/Telegram/SourceFiles/boxes/sessions_box.cpp @@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "main/main_session.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/slide_wrap.h" @@ -144,7 +144,7 @@ void RenameBox(not_null box) { Core::App().settings().setCustomDeviceModel(result); Core::App().saveSettingsDelayed(); }; - QObject::connect(name, &Ui::InputField::submitted, submit); + name->submits() | rpl::start_with_next(submit, name->lifetime()); box->addButton(tr::lng_settings_save(), submit); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 154961016..d348b5aaf 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/checkbox.h" #include "ui/widgets/multi_select.h" #include "ui/widgets/scroll_area.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/popup_menu.h" #include "ui/wrap/slide_wrap.h" #include "ui/text/text_options.h" @@ -226,9 +226,8 @@ void ShareBox::prepareCommentField() { const auto field = _comment->entity(); - connect(field, &Ui::InputField::submitted, [=] { - submit({}); - }); + field->submits( + ) | rpl::start_with_next([=] { submit({}); }, field->lifetime()); if (const auto show = uiShow(); show->valid()) { InitMessageFieldHandlers( _descriptor.session, diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index b1eef8d91..4f8c682a0 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -31,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "ui/effects/slide_animation.h" #include "ui/widgets/discrete_sliders.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/image/image.h" #include "ui/cached_round_corners.h" #include "ui/painter.h" diff --git a/Telegram/SourceFiles/calls/group/calls_group_menu.cpp b/Telegram/SourceFiles/calls/group/calls_group_menu.cpp index aad072371..51a9068a7 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_menu.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_menu.cpp @@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/menu/menu_action.h" #include "ui/widgets/labels.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/effects/ripple_animation.h" #include "ui/layers/generic_box.h" #include "ui/painter.h" diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index 210eb0dce..6002963a9 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/call_button.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/dropdown_menu.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/tooltip.h" #include "ui/widgets/rp_window.h" #include "ui/chat/group_call_bar.h" diff --git a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp index 59ed26a62..121d6d037 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp @@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/continuous_sliders.h" #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/popup_menu.h" #include "ui/wrap/slide_wrap.h" #include "ui/text/text_utilities.h" diff --git a/Telegram/SourceFiles/calls/group/ui/calls_group_recording_box.cpp b/Telegram/SourceFiles/calls/group/ui/calls_group_recording_box.cpp index 5d084bb37..30a492a3f 100644 --- a/Telegram/SourceFiles/calls/group/ui/calls_group_recording_box.cpp +++ b/Telegram/SourceFiles/calls/group/ui/calls_group_recording_box.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image_prepare.h" #include "ui/layers/generic_box.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "styles/style_calls.h" #include "styles/style_layers.h" @@ -287,7 +287,7 @@ void EditGroupCallTitleBox( box->closeBox(); done(result); }; - QObject::connect(input, &Ui::InputField::submitted, submit); + input->submits() | rpl::start_with_next(submit, input->lifetime()); box->addButton(tr::lng_settings_save(), submit); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } @@ -346,7 +346,7 @@ void AddTitleGroupCallRecordingBox( box->closeBox(); done(result); }; - QObject::connect(input, &Ui::InputField::submitted, submit); + input->submits() | rpl::start_with_next(submit, input->lifetime()); box->addButton(tr::lng_group_call_recording_start_button(), submit); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index a97d1fe42..f6c54ec6d 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "ui/widgets/shadow.h" #include "ui/widgets/inner_dropdown.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/emoji_config.h" #include "ui/ui_utility.h" #include "ui/cached_round_corners.h" diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index 8f5f5fec5..2c7bf803c 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -31,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/clip/media_clip_reader.h" #include "ui/widgets/popup_menu.h" #include "ui/widgets/scroll_area.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/text/text_options.h" #include "ui/image/image.h" #include "ui/effects/path_shift_gradient.h" diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 0ae43c3dd..13cfda86d 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/click_handler_types.h" #include "ui/controls/tabbed_search.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/popup_menu.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image.h" diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index 304c7d3a0..a9c0fd789 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -190,16 +190,18 @@ void EditLinkBox( } }; - QObject::connect(text, &Ui::InputField::submitted, [=] { + text->submits( + ) | rpl::start_with_next([=] { url->setFocusFast(); - }); - QObject::connect(url, &Ui::InputField::submitted, [=] { + }, text->lifetime()); + url->submits( + ) | rpl::start_with_next([=] { if (text->getLastText().isEmpty()) { text->setFocusFast(); } else { submit(); } - }); + }, url->lifetime()); box->setTitle(url->getLastText().isEmpty() ? tr::lng_formatting_link_create_title() @@ -223,8 +225,14 @@ void EditLinkBox( url->customTab(true); text->customTab(true); - QObject::connect(url, &Ui::InputField::tabbed, [=] { text->setFocus(); }); - QObject::connect(text, &Ui::InputField::tabbed, [=] { url->setFocus(); }); + url->tabbed( + ) | rpl::start_with_next([=] { + text->setFocus(); + }, url->lifetime()); + text->tabbed( + ) | rpl::start_with_next([=] { + url->setFocus(); + }, text->lifetime()); } TextWithEntities StripSupportHashtag(TextWithEntities text) { @@ -590,7 +598,8 @@ AutocompleteQuery ParseMentionHashtagBotCommandQuery( MessageLinksParser::MessageLinksParser(not_null field) : _field(field) , _timer([=] { parse(); }) { - _connection = QObject::connect(_field, &Ui::InputField::changed, [=] { + _lifetime = _field->changes( + ) | rpl::start_with_next([=] { const auto length = _field->getTextWithTags().text.size(); const auto timeout = (std::abs(length - _lastLength) > 2) ? 0 diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h index acc2808a1..9c4ba031f 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.h +++ b/Telegram/SourceFiles/chat_helpers/message_field.h @@ -7,9 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "base/timer.h" -#include "base/qt_connection.h" #include "chat_helpers/compose/compose_features.h" #ifndef TDESKTOP_DISABLE_SPELLCHECK @@ -132,7 +131,7 @@ private: int _lastLength = 0; bool _disabled = false; base::Timer _timer; - base::qt_connection _connection; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp index 15e2e8c34..0c09b6dd3 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp @@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lottie/lottie_single_player.h" #include "ui/dpr/dpr_icon.h" #include "ui/dpr/dpr_image.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/buttons.h" #include "ui/painter.h" #include "ui/rect_part.h" diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 4a2cb3023..fa5bcfd34 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/send_files_box.h" #include "history/view/history_view_quick_action.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "storage/serialize_common.h" #include "window/section_widget.h" #include "base/platform/base_platform_info.h" diff --git a/Telegram/SourceFiles/data/data_drafts.cpp b/Telegram/SourceFiles/data/data_drafts.cpp index 474822a48..0a6d64122 100644 --- a/Telegram/SourceFiles/data/data_drafts.cpp +++ b/Telegram/SourceFiles/data/data_drafts.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_drafts.h" #include "api/api_text_entities.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "chat_helpers/message_field.h" #include "history/history.h" #include "history/history_widget.h" diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index 507f54478..361135d88 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "core/application.h" #include "ui/layers/generic_box.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "storage/storage_facade.h" #include "storage/storage_shared_media.h" #include "window/window_session_controller.h" diff --git a/Telegram/SourceFiles/data/data_types.cpp b/Telegram/SourceFiles/data/data_types.cpp index 0873bd7ec..ba8a44470 100644 --- a/Telegram/SourceFiles/data/data_types.cpp +++ b/Telegram/SourceFiles/data/data_types.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "data/data_types.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "storage/cache/storage_cache_types.h" #include "base/openssl_help.h" diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index b9f34f030..54b16fec6 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ffmpeg/ffmpeg_frame_generator.h" #include "chat_helpers/stickers_lottie.h" #include "storage/file_download.h" // kMaxFileInMemory -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/text/text_custom_emoji.h" #include "ui/text/text_utilities.h" #include "ui/ui_utility.h" diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 7997b183f..2dc8a3045 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/edit_peer_requests_box.h" #include "ui/widgets/buttons.h" #include "ui/widgets/elastic_scroll.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/wrap/fade_wrap.h" #include "ui/effects/radial_animation.h" #include "ui/chat/requests_bar.h" @@ -78,6 +78,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +#include namespace Dialogs { namespace { @@ -340,12 +341,12 @@ Widget::Widget( Ui::PostponeCall(this, [=] { listScrollUpdated(); }); }, lifetime()); - QObject::connect(_filter, &Ui::InputField::changed, [=] { + _filter->changes( + ) | rpl::start_with_next([=] { applyFilterUpdate(); - }); - QObject::connect(_filter, &Ui::InputField::submitted, [=] { - submit(); - }); + }, _filter->lifetime()); + _filter->submits( + ) | rpl::start_with_next([=] { submit(); }, _filter->lifetime()); QObject::connect( _filter->rawTextEdit().get(), &QTextEdit::cursorPositionChanged, diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp index a64f98f47..b50db2c6b 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/ui_utility.h" #include "mainwidget.h" #include "mainwindow.h" @@ -125,9 +125,16 @@ FixedBar::FixedBar( _cancel->setClickedCallback([=] { cancelSearch(); }); _field->hide(); _filter->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); - connect(_field, &Ui::InputField::cancelled, [=] { cancelSearch(); }); - connect(_field, &Ui::InputField::changed, [=] { searchUpdated(); }); - connect(_field, &Ui::InputField::submitted, [=] { applySearch(); }); + _field->cancelled( + ) | rpl::start_with_next([=] { + cancelSearch(); + }, _field->lifetime()); + _field->changes( + ) | rpl::start_with_next([=] { + searchUpdated(); + }, _field->lifetime()); + _field->submits( + ) | rpl::start_with_next([=] { applySearch(); }, _field->lifetime()); _searchTimer.setCallback([=] { applySearch(); }); _cancel->hide(anim::type::instant); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index bd7e554e9..d3795d4e9 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -304,25 +304,30 @@ HistoryWidget::HistoryWidget( _joinChannel->addClickHandler([=] { joinChannel(); }); _muteUnmute->addClickHandler([=] { toggleMuteUnmute(); }); _reportMessages->addClickHandler([=] { reportSelectedMessages(); }); - connect( - _field, - &Ui::InputField::submitted, - [=](Qt::KeyboardModifiers modifiers) { sendWithModifiers(modifiers); }); - connect(_field, &Ui::InputField::cancelled, [=] { + _field->submits( + ) | rpl::start_with_next([=](Qt::KeyboardModifiers modifiers) { + sendWithModifiers(modifiers); + }, _field->lifetime()); + _field->cancelled( + ) | rpl::start_with_next([=] { escape(); - }); - connect(_field, &Ui::InputField::tabbed, [=] { + }, _field->lifetime()); + _field->tabbed( + ) | rpl::start_with_next([=] { fieldTabbed(); - }); - connect(_field, &Ui::InputField::resized, [=] { + }, _field->lifetime()); + _field->heightChanges( + ) | rpl::start_with_next([=] { fieldResized(); - }); - connect(_field, &Ui::InputField::focused, [=] { + }, _field->lifetime()); + _field->focusedChanges( + ) | rpl::filter(rpl::mappers::_1) | rpl::start_with_next([=] { fieldFocused(); - }); - connect(_field, &Ui::InputField::changed, [=] { + }, _field->lifetime()); + _field->changes( + ) | rpl::start_with_next([=] { fieldChanged(); - }); + }, _field->lifetime()); connect( controller->widget()->windowHandle(), &QWindow::visibleChanged, diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index ae1f9bf54..5011c52cb 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/bot_command.h" #include "chat_helpers/field_autocomplete.h" #include "window/section_widget.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "mtproto/sender.h" #include "base/flags.h" diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index e6a4717d8..22bccf2b6 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -60,7 +60,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/audio/media_audio.h" #include "ui/text/text_options.h" #include "ui/ui_utility.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/dropdown_menu.h" #include "ui/text/format_values.h" #include "ui/controls/emoji_button.h" @@ -1250,7 +1250,7 @@ bool ComposeControls::focused() const { } rpl::producer ComposeControls::focusedValue() const { - return rpl::single(focused()) | rpl::then(_focusChanges.events()); + return rpl::single(focused()) | rpl::then(_field->focusedChanges()); } rpl::producer ComposeControls::tabbedPanelShownValue() const { @@ -1291,12 +1291,9 @@ auto ComposeControls::sendContentRequests(SendRequestType requestType) const { return (_send->type() == type) && (sendRequestType == requestType); }); auto map = rpl::map_to(Api::SendOptions()); - auto submits = base::qt_signal_producer( - _field.get(), - &Ui::InputField::submitted); return rpl::merge( _send->clicks() | filter | map, - std::move(submits) | filter | map, + _field->submits() | filter | map, _sendCustomRequests.events()); } @@ -1317,12 +1314,9 @@ rpl::producer ComposeControls::editRequests() const { auto filter = rpl::filter([=] { return _send->type() == Ui::SendButton::Type::Save; }); - auto submits = base::qt_signal_producer( - _field.get(), - &Ui::InputField::submitted); return rpl::merge( _send->clicks() | filter | toValue, - std::move(submits) | filter | toValue); + _field->submits() | filter | toValue); } rpl::producer> ComposeControls::attachRequests() const { @@ -1776,17 +1770,22 @@ void ComposeControls::initKeyHandler() { void ComposeControls::initField() { _field->setMaxHeight(st::historyComposeFieldMaxHeight); updateSubmitSettings(); - //Ui::Connect(_field, &Ui::InputField::submitted, [=] { send(); }); - Ui::Connect(_field, &Ui::InputField::cancelled, [=] { escape(); }); - Ui::Connect(_field, &Ui::InputField::tabbed, [=] { fieldTabbed(); }); - Ui::Connect(_field, &Ui::InputField::resized, [=] { updateHeight(); }); - Ui::Connect(_field, &Ui::InputField::focused, [=] { - _focusChanges.fire(true); - }); - Ui::Connect(_field, &Ui::InputField::blurred, [=] { - _focusChanges.fire(false); - }); - Ui::Connect(_field, &Ui::InputField::changed, [=] { fieldChanged(); }); + _field->cancelled( + ) | rpl::start_with_next([=] { + escape(); + }, _field->lifetime()); + _field->tabbed( + ) | rpl::start_with_next([=] { + fieldTabbed(); + }, _field->lifetime()); + _field->heightChanges( + ) | rpl::start_with_next([=] { + updateHeight(); + }, _field->lifetime()); + _field->changes( + ) | rpl::start_with_next([=] { + fieldChanged(); + }, _field->lifetime()); InitMessageField(_show, _field, [=](not_null emoji) { if (_history && Data::AllowEmojiWithoutPremium(_history->peer)) { return true; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h index 06d8ae9a8..3dc5e46fa 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h @@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/round_rect.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" class History; class DocumentData; @@ -424,7 +424,6 @@ private: std::unique_ptr _preview; Fn _raiseEmojiSuggestions; - rpl::event_stream _focusChanges; rpl::lifetime _historyLifetime; rpl::lifetime _uploaderSubscriptions; diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index 95c7c6270..286edd189 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/event_filter.h" #include "base/qt/qt_key_modifiers.h" #include "base/unixtime.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "ui/widgets/popup_menu.h" 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 b752fe2f3..d79ea16b4 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -27,7 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/userpic_button.h" #include "ui/wrap/fade_wrap.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/popup_menu.h" #include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/effects/radial_animation.h" @@ -1225,10 +1225,12 @@ bool TopBarWidget::toggleSearch(bool shown, anim::type animated) { _searchCancel.create(this, st::dialogsCancelSearch); _searchCancel->show(anim::type::instant); _searchCancel->setClickedCallback([=] { _searchCancelled.fire({}); }); - QObject::connect(_searchField, &Ui::InputField::submitted, [=] { + _searchField->submits( + ) | rpl::start_with_next([=] { _searchSubmitted.fire({}); - }); - QObject::connect(_searchField, &Ui::InputField::changed, [=] { + }, _searchField->lifetime()); + _searchField->changes( + ) | rpl::start_with_next([=] { const auto was = _searchQuery.current(); const auto now = _searchField->getLastText(); if (_jumpToDate && was.isEmpty() != now.isEmpty()) { @@ -1243,7 +1245,7 @@ bool TopBarWidget::toggleSearch(bool shown, anim::type animated) { } } _searchQuery = now; - }); + }, _searchField->lifetime()); } else { Assert(_searchField != nullptr); } diff --git a/Telegram/SourceFiles/info/info_content_widget.cpp b/Telegram/SourceFiles/info/info_content_widget.cpp index e96ba3cfc..c14624677 100644 --- a/Telegram/SourceFiles/info/info_content_widget.cpp +++ b/Telegram/SourceFiles/info/info_content_widget.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "ui/widgets/scroll_area.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/wrap/padding_wrap.h" #include "ui/search_field_controller.h" #include "lang/lang_keys.h" diff --git a/Telegram/SourceFiles/info/info_top_bar.cpp b/Telegram/SourceFiles/info/info_top_bar.cpp index f15a6b549..1172ea9e1 100644 --- a/Telegram/SourceFiles/info/info_top_bar.cpp +++ b/Telegram/SourceFiles/info/info_top_bar.cpp @@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/shadow.h" #include "ui/wrap/fade_wrap.h" #include "ui/wrap/padding_wrap.h" @@ -253,7 +253,8 @@ void TopBar::createSearchView( }; cancel->addClickHandler(cancelSearch); - field->connect(field, &Ui::InputField::cancelled, cancelSearch); + field->cancelled( + ) | rpl::start_with_next(cancelSearch, field->lifetime()); wrap->widthValue( ) | rpl::start_with_next([=](int newWidth) { diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.cpp b/Telegram/SourceFiles/info/profile/info_profile_members.cpp index b226935c3..85e689903 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members.cpp @@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_memento.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/scroll_area.h" #include "ui/wrap/padding_wrap.h" #include "ui/text/text_utilities.h" // Ui::Text::ToUpper diff --git a/Telegram/SourceFiles/intro/intro_code.cpp b/Telegram/SourceFiles/intro/intro_code.cpp index f1e165283..bdd63a7ba 100644 --- a/Telegram/SourceFiles/intro/intro_code.cpp +++ b/Telegram/SourceFiles/intro/intro_code.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/update_checker.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/fields/masked_input_field.h" #include "ui/text/format_values.h" // Ui::FormatPhone #include "ui/text/text_utilities.h" #include "ui/boxes/confirm_box.h" diff --git a/Telegram/SourceFiles/intro/intro_code.h b/Telegram/SourceFiles/intro/intro_code.h index 8e0fc5743..65f39117b 100644 --- a/Telegram/SourceFiles/intro/intro_code.h +++ b/Telegram/SourceFiles/intro/intro_code.h @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "intro/intro_step.h" #include "intro/intro_widget.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/masked_input_field.h" #include "base/timer.h" namespace Ui { diff --git a/Telegram/SourceFiles/intro/intro_password_check.cpp b/Telegram/SourceFiles/intro/intro_password_check.cpp index 935f55d01..d2bff066e 100644 --- a/Telegram/SourceFiles/intro/intro_password_check.cpp +++ b/Telegram/SourceFiles/intro/intro_password_check.cpp @@ -8,15 +8,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "intro/intro_password_check.h" #include "intro/intro_widget.h" -#include "core/file_utilities.h" #include "core/core_cloud_password.h" #include "ui/boxes/confirm_box.h" #include "boxes/passcode_box.h" #include "lang/lang_keys.h" #include "intro/intro_signup.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" -#include "ui/widgets/labels.h" +#include "ui/widgets/fields/input_field.h" +#include "ui/widgets/fields/password_input.h" #include "main/main_account.h" #include "base/random.h" #include "styles/style_intro.h" @@ -46,7 +45,10 @@ PasswordCheckWidget::PasswordCheckWidget( _toRecover->addClickHandler([=] { toRecover(); }); _toPassword->addClickHandler([=] { toPassword(); }); connect(_pwdField, &Ui::PasswordInput::changed, [=] { hideError(); }); - connect(_codeField, &Ui::InputField::changed, [=] { hideError(); }); + _codeField->changes( + ) | rpl::start_with_next([=] { + hideError(); + }, _codeField->lifetime()); setTitleText(tr::lng_signin_title()); updateDescriptionText(); diff --git a/Telegram/SourceFiles/intro/intro_signup.cpp b/Telegram/SourceFiles/intro/intro_signup.cpp index b11db8672..0f2f38284 100644 --- a/Telegram/SourceFiles/intro/intro_signup.cpp +++ b/Telegram/SourceFiles/intro/intro_signup.cpp @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "ui/controls/userpic_button.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "styles/style_intro.h" #include "styles/style_boxes.h" diff --git a/Telegram/SourceFiles/main/main_session_settings.cpp b/Telegram/SourceFiles/main/main_session_settings.cpp index 261ff01ed..769cd6998 100644 --- a/Telegram/SourceFiles/main/main_session_settings.cpp +++ b/Telegram/SourceFiles/main/main_session_settings.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session_settings.h" #include "chat_helpers/tabbed_selector.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/chat/attach/attach_send_files_way.h" #include "window/section_widget.h" #include "support/support_common.h" diff --git a/Telegram/SourceFiles/passport/passport_edit_identity_box.cpp b/Telegram/SourceFiles/passport/passport_edit_identity_box.cpp index b76d5bf45..68285b9b7 100644 --- a/Telegram/SourceFiles/passport/passport_edit_identity_box.cpp +++ b/Telegram/SourceFiles/passport/passport_edit_identity_box.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_edit_identity_box.h" #include "passport/passport_panel_controller.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/buttons.h" #include "ui/text_options.h" #include "lang/lang_keys.h" diff --git a/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp b/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp index 17fc1b9d0..9e1d10851 100644 --- a/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_edit_contact.cpp @@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/file_utilities.h" #include "passport/passport_panel_controller.h" #include "passport/ui/passport_details_row.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "ui/widgets/shadow.h" @@ -195,11 +195,12 @@ void VerifyBox::setupControls( if (codeLength > 0) { _code->setAutoSubmit(codeLength, _submit); } else { - connect(_code, &Ui::SentCodeField::submitted, _submit); + _code->submits() | rpl::start_with_next(_submit, _code->lifetime()); } - connect(_code, &Ui::SentCodeField::changed, [=] { + _code->changes( + ) | rpl::start_with_next([=] { problem->hide(anim::type::normal); - }); + }, _code->lifetime()); } void VerifyBox::setInnerFocus() { diff --git a/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp b/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp index f9779cab6..9f71e2e3a 100644 --- a/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_panel_edit_scans.h" #include "passport/ui/passport_details_row.h" #include "ui/effects/scroll_content_shadow.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" diff --git a/Telegram/SourceFiles/passport/passport_panel_password.cpp b/Telegram/SourceFiles/passport/passport_panel_password.cpp index 0f8e8e77a..7046f14f0 100644 --- a/Telegram/SourceFiles/passport/passport_panel_password.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_password.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/userpic_button.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/password_input.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/padding_wrap.h" #include "boxes/passcode_box.h" diff --git a/Telegram/SourceFiles/passport/ui/passport_details_row.cpp b/Telegram/SourceFiles/passport/ui/passport_details_row.cpp index c567989f0..2fc7c3698 100644 --- a/Telegram/SourceFiles/passport/ui/passport_details_row.cpp +++ b/Telegram/SourceFiles/passport/ui/passport_details_row.cpp @@ -9,7 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "base/platform/base_platform_info.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" +#include "ui/widgets/fields/masked_input_field.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" @@ -268,9 +269,16 @@ AbstractTextRow::AbstractTextRow( , _field(this, st::passportDetailsField, nullptr, value) , _value(value) { _field->setMaxLength(limit); - connect(_field, &Input::changed, [=] { - _value = valueCurrent(); - }); + if constexpr (std::is_same::value) { + _field->changes( + ) | rpl::start_with_next([=] { + _value = valueCurrent(); + }, _field->lifetime()); + } else { + connect(_field, &Input::changed, [=] { + _value = valueCurrent(); + }); + } } template diff --git a/Telegram/SourceFiles/payments/ui/payments_field.cpp b/Telegram/SourceFiles/payments/ui/payments_field.cpp index 914cc1ccf..73c87dff0 100644 --- a/Telegram/SourceFiles/payments/ui/payments_field.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_field.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "payments/ui/payments_field.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/boxes/country_select_box.h" #include "ui/text/format_values.h" #include "ui/ui_utility.h" @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_payments.h" #include +#include namespace Payments::Ui { namespace { @@ -610,7 +611,8 @@ void Field::setupValidator(Fn validator) { } else { const auto raw = _input->rawTextEdit(); QObject::connect(raw, &QTextEdit::cursorPositionChanged, save); - QObject::connect(_input, &InputField::changed, validate); + _input->changes( + ) | rpl::start_with_next(validate, _input->lifetime()); } } @@ -648,7 +650,8 @@ void Field::setupSubmit() { if (_masked) { QObject::connect(_masked, &MaskedInputField::submitted, submitted); } else { - QObject::connect(_input, &InputField::submitted, submitted); + _input->submits( + ) | rpl::start_with_next(submitted, _input->lifetime()); } } diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 7db2d34e7..7fec6ec89 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/event_filter.h" #include "ui/platform/ui_platform_window_title.h" #include "ui/widgets/popup_menu.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/ui_utility.h" #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION @@ -40,6 +40,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include +#include #include #include diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index 6110d4ce8..e674ec8c8 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -33,10 +33,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/about_box.h" #include "lang/lang_keys.h" #include "base/platform/mac/base_utilities_mac.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/ui_utility.h" #include +#include +#include #include #include diff --git a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_scrubber_item.mm b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_scrubber_item.mm index 0f851a03f..7ec68e337 100644 --- a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_scrubber_item.mm +++ b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_scrubber_item.mm @@ -30,7 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/mac/touchbar/mac_touchbar_common.h" #include "styles/style_basic.h" #include "styles/style_settings.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "window/section_widget.h" #include "window/window_controller.h" #include "window/window_session_controller.h" @@ -47,6 +47,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #import #import +#include + using TouchBar::kCircleDiameter; using TouchBar::CreateNSImageFromStyleIcon; diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp index 42eb5b782..4a0ba8d68 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp @@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "lottie/lottie_icon.h" #include "main/main_session.h" -#include "settings/cloud_password/settings_cloud_password_common.h" #include "settings/cloud_password/settings_cloud_password_email.h" #include "settings/cloud_password/settings_cloud_password_email_confirm.h" #include "settings/cloud_password/settings_cloud_password_hint.h" @@ -23,7 +22,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_common.h" #include "ui/boxes/confirm_box.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" +#include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email.cpp index 1e13fae55..0fedabd93 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/cloud_password/settings_cloud_password_manage.h" #include "ui/boxes/confirm_box.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" @@ -90,9 +90,10 @@ void Email::setupContent() { currentStepDataEmail); const auto newInput = wrap->entity(); const auto error = AddError(content, nullptr); - QObject::connect(newInput, &Ui::InputField::changed, [=] { + newInput->changes( + ) | rpl::start_with_next([=] { error->hide(); - }); + }, newInput->lifetime()); AddSkipInsteadOfField(content); const auto send = [=](Fn close) { @@ -189,7 +190,7 @@ void Email::setupContent() { }); const auto submit = [=] { button->clicked({}, Qt::LeftButton); }; - QObject::connect(newInput, &Ui::InputField::submitted, submit); + newInput->submits() | rpl::start_with_next(submit, newInput->lifetime()); setFocusCallback([=] { newInput->setFocus(); }); diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email_confirm.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email_confirm.cpp index 09fc68aa0..24d7fb2ac 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email_confirm.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_email_confirm.cpp @@ -136,9 +136,10 @@ void EmailConfirm::setupContent() { std::move(objectInput))); const auto error = AddError(content, nullptr); - QObject::connect(newInput, &Ui::InputField::changed, [=] { + newInput->changes( + ) | rpl::start_with_next([=] { error->hide(); - }); + }, newInput->lifetime()); AddSkipInsteadOfField(content); const auto resendInfo = Ui::CreateChild( @@ -326,7 +327,7 @@ void EmailConfirm::setupContent() { const auto submit = [=] { button->clicked({}, Qt::LeftButton); }; newInput->setAutoSubmit(currentStepDataCodeLength, submit); - QObject::connect(newInput, &Ui::InputField::submitted, submit); + newInput->submits() | rpl::start_with_next(submit, newInput->lifetime()); setFocusCallback([=] { newInput->setFocus(); }); diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_hint.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_hint.cpp index e7451ab83..f2a89376e 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_hint.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_hint.cpp @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/cloud_password/settings_cloud_password_email.h" #include "settings/cloud_password/settings_cloud_password_manage.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/vertical_layout.h" @@ -79,9 +79,10 @@ void Hint::setupContent() { currentStepDataHint); const auto newInput = wrap->entity(); const auto error = AddError(content, nullptr); - QObject::connect(newInput, &Ui::InputField::changed, [=] { + newInput->changes( + ) | rpl::start_with_next([=] { error->hide(); - }); + }, newInput->lifetime()); AddSkipInsteadOfField(content); const auto save = [=](const QString &hint) { @@ -142,7 +143,7 @@ void Hint::setupContent() { }); const auto submit = [=] { button->clicked({}, Qt::LeftButton); }; - QObject::connect(newInput, &Ui::InputField::submitted, submit); + newInput->submits() | rpl::start_with_next(submit, newInput->lifetime()); setFocusCallback([=] { newInput->setFocus(); }); diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp index 49af9c6a1..e532117b7 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp @@ -21,7 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/boxes/confirm_box.h" #include "ui/text/format_values.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp index 6b353438b..3ef6104b8 100644 --- a/Telegram/SourceFiles/settings/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/settings_chat.cpp @@ -21,7 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/local_storage_box.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/slide_wrap.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/color_editor.h" #include "ui/widgets/buttons.h" diff --git a/Telegram/SourceFiles/settings/settings_folders.cpp b/Telegram/SourceFiles/settings/settings_folders.cpp index 18a3630a7..c5be97152 100644 --- a/Telegram/SourceFiles/settings/settings_folders.cpp +++ b/Telegram/SourceFiles/settings/settings_folders.cpp @@ -30,7 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/widgets/box_content_divider.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/labels.h" #include "ui/wrap/slide_wrap.h" #include "window/window_controller.h" diff --git a/Telegram/SourceFiles/settings/settings_information.cpp b/Telegram/SourceFiles/settings/settings_information.cpp index da3f97859..9e9fedbb1 100644 --- a/Telegram/SourceFiles/settings/settings_information.cpp +++ b/Telegram/SourceFiles/settings/settings_information.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/slide_wrap.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/popup_menu.h" #include "ui/widgets/box_content_divider.h" #include "ui/widgets/menu/menu_add_action_callback_factory.h" @@ -538,10 +538,8 @@ void SetupBio( auto cursor = bio->textCursor(); cursor.setPosition(bio->getLastText().size()); bio->setTextCursor(cursor); - QObject::connect(bio, &Ui::InputField::submitted, [=] { - save(); - }); - QObject::connect(bio, &Ui::InputField::changed, updated); + bio->submits() | rpl::start_with_next([=] { save(); }, bio->lifetime()); + bio->changes() | rpl::start_with_next(updated, bio->lifetime()); bio->setInstantReplaces(Ui::InstantReplaces::Default()); bio->setInstantReplacesEnabled( Core::App().settings().replaceEmojiValue()); diff --git a/Telegram/SourceFiles/settings/settings_local_passcode.cpp b/Telegram/SourceFiles/settings/settings_local_passcode.cpp index e1c5d56d8..49e8ba019 100644 --- a/Telegram/SourceFiles/settings/settings_local_passcode.cpp +++ b/Telegram/SourceFiles/settings/settings_local_passcode.cpp @@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_domain.h" #include "ui/boxes/confirm_box.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" diff --git a/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp b/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp index 6940e8139..a1474b712 100644 --- a/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp +++ b/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "core/core_settings.h" #include "mtproto/mtproto_config.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/chat/attach/attach_send_files_way.h" #include "ui/power_saving.h" #include "window/themes/window_theme.h" diff --git a/Telegram/SourceFiles/support/support_autocomplete.cpp b/Telegram/SourceFiles/support/support_autocomplete.cpp index aba4ee89a..aaf9fec54 100644 --- a/Telegram/SourceFiles/support/support_autocomplete.cpp +++ b/Telegram/SourceFiles/support/support_autocomplete.cpp @@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/chat_theme.h" #include "ui/chat/chat_style.h" #include "ui/widgets/scroll_area.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/buttons.h" #include "ui/wrap/padding_wrap.h" #include "ui/painter.h" @@ -418,16 +418,20 @@ void Autocomplete::setupContent() { }; inner->activated() | rpl::start_with_next(submit, lifetime()); - connect(input, &Ui::InputField::blurred, [=] { + input->focusedChanges( + ) | rpl::filter(!rpl::mappers::_1) | rpl::start_with_next([=] { base::call_delayed(10, this, [=] { if (!input->hasFocus()) { deactivate(); } }); - }); - connect(input, &Ui::InputField::cancelled, [=] { deactivate(); }); - connect(input, &Ui::InputField::changed, refresh); - connect(input, &Ui::InputField::submitted, submit); + }, input->lifetime()); + input->cancelled( + ) | rpl::start_with_next([=] { + deactivate(); + }, input->lifetime()); + input->changes() | rpl::start_with_next(refresh, input->lifetime()); + input->submits() | rpl::start_with_next(submit, input->lifetime()); input->customUpDown(true); _activate = [=] { diff --git a/Telegram/SourceFiles/support/support_helper.cpp b/Telegram/SourceFiles/support/support_helper.cpp index cb8fe49c5..fd273c09f 100644 --- a/Telegram/SourceFiles/support/support_helper.cpp +++ b/Telegram/SourceFiles/support/support_helper.cpp @@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "boxes/abstract_box.h" #include "ui/toast/toast.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/chat/attach/attach_prepare.h" #include "ui/text/format_values.h" #include "ui/text/text_entity.h" @@ -109,8 +109,11 @@ void EditInfoBox::prepare() { addButton(tr::lng_settings_save(), save); addButton(tr::lng_cancel(), [=] { closeBox(); }); - connect(_field, &Ui::InputField::submitted, save); - connect(_field, &Ui::InputField::cancelled, [=] { closeBox(); }); + _field->submits() | rpl::start_with_next(save, _field->lifetime()); + _field->cancelled( + ) | rpl::start_with_next([=] { + closeBox(); + }, _field->lifetime()); Ui::Emoji::SuggestionsController::Init( getDelegate()->outerContainer(), _field, diff --git a/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp b/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp index a56957bc4..e4d8092a5 100644 --- a/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp +++ b/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp @@ -11,13 +11,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/event_filter.h" #include "ui/boxes/calendar_box.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/time_input.h" #include "ui/ui_utility.h" #include "lang/lang_keys.h" #include "styles/style_layers.h" #include "styles/style_boxes.h" +#include + namespace Ui { namespace { @@ -147,8 +149,9 @@ ChooseDateTimeBoxDescriptor ChooseDateTimeBox( const auto calendar = content->lifetime().make_state>(); const auto calendarStyle = args.style.calendarStyle; - QObject::connect(state->day, &InputField::focused, [=] { - if (*calendar) { + state->day->focusedChanges( + ) | rpl::start_with_next([=](bool focused) { + if (*calendar || !focused) { return; } *calendar = box->getDelegate()->show( @@ -167,7 +170,7 @@ ChooseDateTimeBoxDescriptor ChooseDateTimeBox( ) | rpl::start_with_next(crl::guard(state->time, [=] { state->time->setFocusFast(); }), (*calendar)->lifetime()); - }); + }, state->day->lifetime()); const auto collect = [=] { const auto timeValue = state->time->valueCurrent().split(':'); diff --git a/Telegram/SourceFiles/ui/boxes/confirm_phone_box.cpp b/Telegram/SourceFiles/ui/boxes/confirm_phone_box.cpp index 9fab7f4a5..e69cd3e5f 100644 --- a/Telegram/SourceFiles/ui/boxes/confirm_phone_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/confirm_phone_box.cpp @@ -73,7 +73,8 @@ void ConfirmPhoneBox::prepare() { + st::usernameSkip + (_fragment ? (_fragment->height() + fragmentSkip()) : 0)); - connect(_code, &Ui::InputField::submitted, [=] { sendCode(); }); + _code->submits( + ) | rpl::start_with_next([=] { sendCode(); }, _code->lifetime()); showChildren(); } diff --git a/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp b/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp index a27a18859..388a258bd 100644 --- a/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp +++ b/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp @@ -10,7 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "ui/boxes/choose_date_time.h" #include "ui/widgets/labels.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" +#include "ui/widgets/fields/number_input.h" #include "ui/widgets/checkbox.h" #include "ui/wrap/slide_wrap.h" #include "base/unixtime.h" diff --git a/Telegram/SourceFiles/ui/boxes/rate_call_box.cpp b/Telegram/SourceFiles/ui/boxes/rate_call_box.cpp index 8d88bde67..d56889f0b 100644 --- a/Telegram/SourceFiles/ui/boxes/rate_call_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/rate_call_box.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "styles/style_layers.h" #include "styles/style_calls.h" @@ -92,11 +92,16 @@ void RateCallBox::ratingChanged(int value) { _comment->height()); updateMaxHeight(); - connect(_comment, &InputField::resized, [=] { + _comment->heightChanges( + ) | rpl::start_with_next([=] { commentResized(); - }); - connect(_comment, &InputField::submitted, [=] { send(); }); - connect(_comment, &InputField::cancelled, [=] { closeBox(); }); + }, _comment->lifetime()); + _comment->submits( + ) | rpl::start_with_next([=] { send(); }, _comment->lifetime()); + _comment->cancelled( + ) | rpl::start_with_next([=] { + closeBox(); + }, _comment->lifetime()); } _comment->setFocusFast(); } else if (_comment) { diff --git a/Telegram/SourceFiles/ui/boxes/report_box.cpp b/Telegram/SourceFiles/ui/boxes/report_box.cpp index fa0ac22ff..34c678bb4 100644 --- a/Telegram/SourceFiles/ui/boxes/report_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/report_box.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/layers/generic_box.h" #include "ui/wrap/vertical_layout.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/toast/toast.h" #include "info/profile/info_profile_icon.h" #include "styles/style_chat_helpers.h" @@ -148,7 +148,8 @@ void ReportDetailsBox( const auto text = details->getLastText(); done(text); }; - QObject::connect(details, &InputField::submitted, submit); + details->submits( + ) | rpl::start_with_next(submit, details->lifetime()); box->addButton(tr::lng_report_button(), submit); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } diff --git a/Telegram/SourceFiles/ui/controls/tabbed_search.cpp b/Telegram/SourceFiles/ui/controls/tabbed_search.cpp index a4022d514..6e5165aa8 100644 --- a/Telegram/SourceFiles/ui/controls/tabbed_search.cpp +++ b/Telegram/SourceFiles/ui/controls/tabbed_search.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qt_signal_producer.h" #include "lang/lang_keys.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/wrap/fade_wrap.h" #include "ui/widgets/buttons.h" #include "ui/painter.h" @@ -306,7 +306,8 @@ anim::type SearchWithGroups::animated() const { } void SearchWithGroups::initField() { - connect(_field, &InputField::changed, [=] { + _field->changes( + ) | rpl::start_with_next([=] { const auto last = FieldQuery(_field); _query = last; const auto empty = last.empty(); @@ -319,7 +320,7 @@ void SearchWithGroups::initField() { _chosenGroup = QString(); scrollGroupsToStart(); } - }); + }, _field->lifetime()); _fieldPlaceholderWidth = tr::lng_dlg_filter( ) | rpl::map([=](const QString &value) { @@ -492,9 +493,10 @@ void SearchWithGroups::initButtons() { _field->setFocus(); scrollGroupsToStart(); }); - QObject::connect(_field, &InputField::focused, [=] { + _field->focusedChanges( + ) | rpl::filter(rpl::mappers::_1) | rpl::start_with_next([=] { scrollGroupsToStart(); - }); + }, _field->lifetime()); _field->raise(); _fade->raise(); _search->raise(); @@ -519,9 +521,7 @@ void SearchWithGroups::ensureRounding(int size, float64 ratio) { } rpl::producer<> SearchWithGroups::escapes() const { - return base::qt_signal_producer( - _field.get(), - &Ui::InputField::cancelled); + return _field->cancelled(); } rpl::producer> SearchWithGroups::queryValue() const { diff --git a/Telegram/SourceFiles/ui/search_field_controller.cpp b/Telegram/SourceFiles/ui/search_field_controller.cpp index 60dcc1769..a26c59bbe 100644 --- a/Telegram/SourceFiles/ui/search_field_controller.cpp +++ b/Telegram/SourceFiles/ui/search_field_controller.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_widgets.h" #include "ui/wrap/padding_wrap.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/shadow.h" #include "ui/widgets/buttons.h" #include "lang/lang_keys.h" @@ -30,9 +30,10 @@ auto SearchFieldController::createRowView( auto field = createField(wrap, st.field).release(); field->show(); - field->connect(field, &Ui::InputField::cancelled, [=] { + field->cancelled( + ) | rpl::start_with_next([=] { field->setText(QString()); - }); + }, field->lifetime()); auto cancel = CreateChild( wrap, @@ -104,9 +105,10 @@ base::unique_qptr SearchFieldController::createField( tr::lng_dlg_filter(), _query.current()); auto field = result.get(); - field->connect(field, &Ui::InputField::changed, [=] { + field->changes( + ) | rpl::start_with_next([=] { _query = field->getLastText(); - }); + }, field->lifetime()); _view.reset(field); return result; } diff --git a/Telegram/SourceFiles/ui/widgets/color_editor.cpp b/Telegram/SourceFiles/ui/widgets/color_editor.cpp index dc2267adb..3141faef3 100644 --- a/Telegram/SourceFiles/ui/widgets/color_editor.cpp +++ b/Telegram/SourceFiles/ui/widgets/color_editor.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/rect.h" #include "ui/ui_utility.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/masked_input_field.h" #include "ui/widgets/shadow.h" #include "styles/style_boxes.h" #include "styles/style_media_view.h" diff --git a/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp b/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp index 245d8cddb..81b1b1a0d 100644 --- a/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "countries/countries_instance.h" // Countries::ValidPhoneCode +#include "styles/style_widgets.h" #include diff --git a/Telegram/SourceFiles/ui/widgets/fields/special_fields.h b/Telegram/SourceFiles/ui/widgets/fields/special_fields.h index d1dded516..6c000f801 100644 --- a/Telegram/SourceFiles/ui/widgets/fields/special_fields.h +++ b/Telegram/SourceFiles/ui/widgets/fields/special_fields.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/masked_input_field.h" namespace Ui { diff --git a/Telegram/SourceFiles/ui/widgets/multi_select.cpp b/Telegram/SourceFiles/ui/widgets/multi_select.cpp index 86526e111..99b7eaf7d 100644 --- a/Telegram/SourceFiles/ui/widgets/multi_select.cpp +++ b/Telegram/SourceFiles/ui/widgets/multi_select.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/multi_select.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/scroll_area.h" #include "ui/effects/animations.h" #include "ui/effects/cross_animation.h" @@ -453,7 +453,6 @@ protected: void keyPressEvent(QKeyEvent *e) override; private: - void submitted(Qt::KeyboardModifiers modifiers); void cancelled(); void queryChanged(); void fieldFocused(); @@ -659,10 +658,24 @@ MultiSelect::Inner::Inner( , _field(this, _st.field, std::move(placeholder), query) , _cancel(this, _st.fieldCancel) { _field->customUpDown(true); - connect(_field, &Ui::InputField::focused, [=] { fieldFocused(); }); - connect(_field, &Ui::InputField::changed, [=] { queryChanged(); }); - connect(_field, &Ui::InputField::submitted, this, &Inner::submitted); - connect(_field, &Ui::InputField::cancelled, this, &Inner::cancelled); + _field->focusedChanges( + ) | rpl::filter(rpl::mappers::_1) | rpl::start_with_next([=] { + fieldFocused(); + }, _field->lifetime()); + _field->changes( + ) | rpl::start_with_next([=] { + queryChanged(); + }, _field->lifetime()); + _field->submits( + ) | rpl::start_with_next([=](Qt::KeyboardModifiers m) { + if (_submittedCallback) { + _submittedCallback(m); + } + }, _field->lifetime()); + _field->cancelled( + ) | rpl::start_with_next([=] { + cancelled(); + }, _field->lifetime()); _cancel->setClickedCallback([=] { clearQuery(); _field->setFocus(); @@ -874,12 +887,6 @@ void MultiSelect::Inner::keyPressEvent(QKeyEvent *e) { } } -void MultiSelect::Inner::submitted(Qt::KeyboardModifiers modifiers) { - if (_submittedCallback) { - _submittedCallback(modifiers); - } -} - void MultiSelect::Inner::cancelled() { if (_cancelledCallback) { _cancelledCallback(); diff --git a/Telegram/SourceFiles/ui/widgets/sent_code_field.cpp b/Telegram/SourceFiles/ui/widgets/sent_code_field.cpp index b98d32466..f5ba4b858 100644 --- a/Telegram/SourceFiles/ui/widgets/sent_code_field.cpp +++ b/Telegram/SourceFiles/ui/widgets/sent_code_field.cpp @@ -19,7 +19,7 @@ SentCodeField::SentCodeField( rpl::producer placeholder, const QString &val) : Ui::InputField(parent, st, std::move(placeholder), val) { - connect(this, &Ui::InputField::changed, [this] { fix(); }); + changes() | rpl::start_with_next([=] { fix(); }, lifetime()); } void SentCodeField::setAutoSubmit(int length, Fn submitCallback) { diff --git a/Telegram/SourceFiles/ui/widgets/sent_code_field.h b/Telegram/SourceFiles/ui/widgets/sent_code_field.h index 12bbdb34e..4c3b519e5 100644 --- a/Telegram/SourceFiles/ui/widgets/sent_code_field.h +++ b/Telegram/SourceFiles/ui/widgets/sent_code_field.h @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "base/timer.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" namespace Ui { diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index f68524d1c..b72cb48dd 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/message_field.h" #include "lang/lang_keys.h" #include "ui/widgets/buttons.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/platform/ui_platform_utility.h" #include "ui/text/text_options.h" #include "ui/text/text_utilities.h" @@ -1105,9 +1105,16 @@ void Notification::showReplyField() { // Catch mouse press event to activate the window. QCoreApplication::instance()->installEventFilter(this); - connect(_replyArea, &Ui::InputField::resized, [=] { replyResized(); }); - connect(_replyArea, &Ui::InputField::submitted, [=] { sendReply(); }); - connect(_replyArea, &Ui::InputField::cancelled, [=] { replyCancel(); }); + _replyArea->heightChanges( + ) | rpl::start_with_next([=] { + replyResized(); + }, _replyArea->lifetime()); + _replyArea->submits( + ) | rpl::start_with_next([=] { sendReply(); }, _replyArea->lifetime()); + _replyArea->cancelled( + ) | rpl::start_with_next([=] { + replyCancel(); + }, _replyArea->lifetime()); _replySend.create(this, st::notifySendReply); _replySend->moveToRight(st::notifyBorderWidth, st::notifyMinHeight); diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp index 46b5cf5fb..b45e02b69 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "ui/boxes/confirm_box.h" #include "ui/text/text_utilities.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index c0b02c9c3..813db805b 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text.h" #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" #include "ui/toast/toast.h" diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 92025ae40..26571b1d6 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/compose/compose_show.h" #include "chat_helpers/message_field.h" #include "ui/wrap/slide_wrap.h" -#include "ui/widgets/input_fields.h" +#include "ui/widgets/fields/input_field.h" #include "api/api_chat_participants.h" #include "lang/lang_keys.h" #include "ui/boxes/confirm_box.h" @@ -1924,9 +1924,8 @@ QPointer ShowForwardMessagesBox( const auto field = comment->entity(); - QObject::connect(field, &Ui::InputField::submitted, [=] { - submit({}); - }); + field->submits( + ) | rpl::start_with_next([=] { submit({}); }, field->lifetime()); InitMessageFieldHandlers( session, show, diff --git a/Telegram/lib_spellcheck b/Telegram/lib_spellcheck index c989a9f41..dfc42b20c 160000 --- a/Telegram/lib_spellcheck +++ b/Telegram/lib_spellcheck @@ -1 +1 @@ -Subproject commit c989a9f41e5bd8268587af2256efa89327cb3ae0 +Subproject commit dfc42b20ce602b105e5400e03eed626fd5bab7df diff --git a/Telegram/lib_ui b/Telegram/lib_ui index bcf88b906..5a2402ad5 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit bcf88b90658c7e0925c11c486732d874477baf0d +Subproject commit 5a2402ad5d7e41a48c84d56c45df6b5d49e8b176 diff --git a/Telegram/lib_webview b/Telegram/lib_webview index 5b9092bcb..552d96a51 160000 --- a/Telegram/lib_webview +++ b/Telegram/lib_webview @@ -1 +1 @@ -Subproject commit 5b9092bcb27a207fed3cb2155bb98db46d7cedfa +Subproject commit 552d96a51fa5c8e50f9d6f631055558d99356cb4 From 9edbb9762a6bde3cde4ebff30964dfa976b77414 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 1 Sep 2023 10:59:00 +0300 Subject: [PATCH 007/155] Fixed some cases when peer may not be removed from filter from menu. --- .../SourceFiles/boxes/choose_filter_box.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/boxes/choose_filter_box.cpp b/Telegram/SourceFiles/boxes/choose_filter_box.cpp index 12d58b538..bc61e9fe2 100644 --- a/Telegram/SourceFiles/boxes/choose_filter_box.cpp +++ b/Telegram/SourceFiles/boxes/choose_filter_box.cpp @@ -32,27 +32,27 @@ Data::ChatFilter ChangedFilter( auto never = base::duplicate(filter.never()); if (add) { never.remove(history); - const auto result = Data::ChatFilter( - filter.id(), - filter.title(), - filter.iconEmoji(), - filter.flags(), - filter.always(), - filter.pinned(), - std::move(never)); - if (result.contains(history)) { - return result; - } else { - never = base::duplicate(result.never()); - always.insert(history); - } } else { - const auto alwaysIt = always.find(history); - if (alwaysIt != end(always)) { - always.erase(alwaysIt); - } else { - never.insert(history); - } + always.remove(history); + } + const auto result = Data::ChatFilter( + filter.id(), + filter.title(), + filter.iconEmoji(), + filter.flags(), + std::move(always), + filter.pinned(), + std::move(never)); + const auto in = result.contains(history); + if (in == add) { + return result; + } + always = base::duplicate(result.always()); + never = base::duplicate(result.never()); + if (add) { + always.insert(history); + } else { + never.insert(history); } return Data::ChatFilter( filter.id(), From 7740780eebfa80c3aa58e20b6a6720e453e9b015 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 3 Sep 2023 17:20:13 +0300 Subject: [PATCH 008/155] Respected presence of plain link in preview text for mini icons. --- .../SourceFiles/dialogs/ui/dialogs_message_view.cpp | 11 +++++++++-- .../SourceFiles/dialogs/ui/dialogs_message_view.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp index 253bdc967..17eb3158d 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp @@ -186,9 +186,12 @@ void MessageView::prepare( _senderCache = { st::dialogsTextWidthMin }; } TextUtilities::Trim(preview.text); + auto textToCache = DialogsPreviewText(std::move(preview.text)); + _hasPlainLinkAtBegin = !textToCache.entities.empty() + && (textToCache.entities.front().type() == EntityType::PlainLink); _textCache.setMarkedText( st::dialogsTextStyle, - DialogsPreviewText(std::move(preview.text)), + std::move(textToCache), DialogTextOptions(), context); _textCachedFor = item; @@ -325,7 +328,11 @@ void MessageView::paint( *_leftIcon, context.active, context.selected); - icon.paint(p, rect.topLeft(), rect.width()); + if (_hasPlainLinkAtBegin && !context.active) { + icon.paint(p, rect.topLeft(), rect.width(), palette->linkFg->c); + } else { + icon.paint(p, rect.topLeft(), rect.width()); + } rect.setLeft(rect.x() + icon.width() + st::dialogsMiniIconSkip); } for (const auto &image : _imagesCache) { diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h index 14f677536..86ddc7b0e 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h @@ -94,6 +94,7 @@ private: mutable std::unique_ptr _spoiler; mutable std::unique_ptr _loadingContext; mutable const style::ThreeStateIcon *_leftIcon = nullptr; + mutable bool _hasPlainLinkAtBegin = false; }; From 738aff9c4fdc5b7c10fd518ac2a6339ed6781d06 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 3 Sep 2023 17:47:36 +0300 Subject: [PATCH 009/155] Fixed paint of mini icon in dialogs list even there is no space for it. --- .../dialogs/ui/dialogs_message_view.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp index 17eb3158d..928e80e88 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp @@ -328,15 +328,23 @@ void MessageView::paint( *_leftIcon, context.active, context.selected); - if (_hasPlainLinkAtBegin && !context.active) { - icon.paint(p, rect.topLeft(), rect.width(), palette->linkFg->c); - } else { - icon.paint(p, rect.topLeft(), rect.width()); + const auto w = (icon.width()); + if (rect.width() > w) { + if (_hasPlainLinkAtBegin && !context.active) { + icon.paint( + p, + rect.topLeft(), + rect.width(), + palette->linkFg->c); + } else { + icon.paint(p, rect.topLeft(), rect.width()); + } + rect.setLeft(rect.x() + w + st::dialogsMiniIconSkip); } - rect.setLeft(rect.x() + icon.width() + st::dialogsMiniIconSkip); } for (const auto &image : _imagesCache) { - if (rect.width() < st::dialogsMiniPreview) { + const auto w = st::dialogsMiniPreview + st::dialogsMiniPreviewSkip; + if (rect.width() < w) { break; } const auto mini = QRect( @@ -352,9 +360,7 @@ void MessageView::paint( FillSpoilerRect(p, mini, frame); } } - rect.setLeft(rect.x() - + st::dialogsMiniPreview - + st::dialogsMiniPreviewSkip); + rect.setLeft(rect.x() + w); } if (!_imagesCache.empty()) { rect.setLeft(rect.x() + st::dialogsMiniPreviewRight); From aad1296829114368442f619e8f6b17a590cb1f77 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 3 Sep 2023 17:51:29 +0300 Subject: [PATCH 010/155] Fixed overlapping right badges on ellipsis in dialogs list. --- Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp index 928e80e88..6f4700f2c 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp @@ -365,7 +365,10 @@ void MessageView::paint( if (!_imagesCache.empty()) { rect.setLeft(rect.x() + st::dialogsMiniPreviewRight); } - if (!rect.isEmpty()) { + // Style of _textCache. + static const auto ellipsisWidth = st::dialogsTextStyle.font->width( + kQEllipsis); + if (rect.width() > ellipsisWidth) { _textCache.draw(p, { .position = rect.topLeft(), .availableWidth = rect.width(), From 8255de1ba80ef9d25012e7446e014ed237169f11 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 29 Aug 2023 13:45:15 +0400 Subject: [PATCH 011/155] Update API scheme to layer 162. --- Telegram/SourceFiles/data/data_story.cpp | 4 ++-- Telegram/SourceFiles/mtproto/scheme/api.tl | 10 +++++++--- Telegram/SourceFiles/mtproto/scheme/layer.tl | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/data/data_story.cpp b/Telegram/SourceFiles/data/data_story.cpp index d5faa4350..fab608d99 100644 --- a/Telegram/SourceFiles/data/data_story.cpp +++ b/Telegram/SourceFiles/data/data_story.cpp @@ -512,8 +512,8 @@ void Story::applyFields( if (const auto areas = data.vmedia_areas()) { locations.reserve(areas->v.size()); for (const auto &area : areas->v) { - if (const auto parsed = ParseLocation(area)) { - locations.push_back(*parsed); + if (const auto location = ParseLocation(area)) { + locations.push_back(*location); } } } diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index bced7ee92..889ecc90f 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -150,7 +150,7 @@ messageActionPaymentSent#96163f56 flags:# recurring_init:flags.2?true recurring_ messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction; messageActionScreenshotTaken#4792929b = MessageAction; messageActionCustomAction#fae69f56 message:string = MessageAction; -messageActionBotAllowed#c516d679 flags:# attach_menu:flags.1?true domain:flags.0?string app:flags.2?BotApp = MessageAction; +messageActionBotAllowed#c516d679 flags:# attach_menu:flags.1?true from_request:flags.3?true domain:flags.0?string app:flags.2?BotApp = MessageAction; messageActionSecureValuesSentMe#1b287353 values:Vector credentials:SecureCredentialsEncrypted = MessageAction; messageActionSecureValuesSent#d95c6154 types:Vector = MessageAction; messageActionContactSignUp#f3f25f76 = MessageAction; @@ -570,7 +570,7 @@ chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true r chatInvitePublicJoinRequests#ed107ab7 = ExportedChatInvite; chatInviteAlready#5a686d7c chat:Chat = ChatInvite; -chatInvite#300c44c1 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector = ChatInvite; +chatInvite#300c44c1 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true verified:flags.7?true scam:flags.8?true fake:flags.9?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector = ChatInvite; chatInvitePeek#61695cb0 chat:Chat expires:int = ChatInvite; inputStickerSetEmpty#ffb62b95 = InputStickerSet; @@ -1528,7 +1528,7 @@ messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector date:int = Mess sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage; -storyViews#c64c0b97 flags:# views_count:int reactions_count:int recent_viewers:flags.0?Vector = StoryViews; +storyViews#c64c0b97 flags:# has_viewers:flags.1?true views_count:int reactions_count:int recent_viewers:flags.0?Vector = StoryViews; storyItemDeleted#51e6ee4f id:int = StoryItem; storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem; @@ -2017,6 +2017,9 @@ bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:fla bots.getBotInfo#dcd914fd flags:# bot:flags.0?InputUser lang_code:string = bots.BotInfo; bots.reorderUsernames#9709b1c2 bot:InputUser order:Vector = Bool; bots.toggleUsername#53ca973 bot:InputUser username:string active:Bool = Bool; +bots.canSendMessage#1359f4e6 bot:InputUser = Bool; +bots.allowSendMessage#f132e3ef bot:InputUser = Updates; +bots.invokeWebViewCustomMethod#87fc5e7 bot:InputUser custom_method:string params:DataJSON = DataJSON; payments.getPaymentForm#37148dbb flags:# invoice:InputInvoice theme_params:flags.0?DataJSON = payments.PaymentForm; payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt; @@ -2099,6 +2102,7 @@ chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool; chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector; chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector = Updates; +stories.canSendStory#b100d45d = Bool; stories.sendStory#d455fcec flags:# pinned:flags.2?true noforwards:flags.4?true media:InputMedia media_areas:flags.5?Vector caption:flags.0?string entities:flags.1?Vector privacy_rules:Vector random_id:long period:flags.3?int = Updates; stories.editStory#a9b91ae4 flags:# id:int media:flags.0?InputMedia media_areas:flags.3?Vector caption:flags.1?string entities:flags.1?Vector privacy_rules:flags.2?Vector = Updates; stories.deleteStories#b5d501d7 id:Vector = Vector; diff --git a/Telegram/SourceFiles/mtproto/scheme/layer.tl b/Telegram/SourceFiles/mtproto/scheme/layer.tl index 2f8c6ce82..072ac8db6 100644 --- a/Telegram/SourceFiles/mtproto/scheme/layer.tl +++ b/Telegram/SourceFiles/mtproto/scheme/layer.tl @@ -1 +1 @@ -// LAYER 161 +// LAYER 162 From d77c7a70ab154af690d33edd27dbacddd701682f Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 29 Aug 2023 21:36:12 +0400 Subject: [PATCH 012/155] Implement new bot web-app methods. --- Telegram/Resources/langs/lang.strings | 4 + Telegram/SourceFiles/apiwrap.cpp | 15 +- Telegram/SourceFiles/apiwrap.h | 8 +- Telegram/SourceFiles/core/ui_integration.cpp | 14 +- Telegram/SourceFiles/core/ui_integration.h | 5 +- .../export/data/export_data_types.cpp | 1 + .../export/data/export_data_types.h | 1 + .../export/output/export_output_html.cpp | 2 + .../export/output/export_output_json.cpp | 2 + Telegram/SourceFiles/history/history_item.cpp | 4 + .../inline_bots/bot_attach_web_view.cpp | 368 +++++++++++------- .../inline_bots/bot_attach_web_view.h | 24 +- .../ui/chat/attach/attach_bot_webview.cpp | 206 +++++++--- .../ui/chat/attach/attach_bot_webview.h | 60 +-- 14 files changed, 478 insertions(+), 236 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index a045ba1f0..4b314e4e9 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1611,6 +1611,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_action_suggested_video" = "{user} suggests you to use this profile video."; "lng_action_suggested_video_button" = "View Video"; "lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu."; +"lng_action_webapp_bot_allowed" = "You allowed this bot to message you in his web-app."; "lng_action_set_wallpaper_me" = "You set a new wallpaper for this chat"; "lng_action_set_wallpaper" = "{user} set a new wallpaper for this chat"; "lng_action_set_wallpaper_button" = "View Wallpaper"; @@ -1799,6 +1800,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_bot_share_location_unavailable" = "Sorry, location sharing is currently unavailable in Telegram Desktop."; "lng_bot_share_phone" = "Do you want to share your phone number with this bot?"; "lng_bot_share_phone_confirm" = "Share"; +"lng_bot_allow_write_title" = "Allow messaging"; +"lng_bot_allow_write" = "Do you want to allow this bot writing you?"; +"lng_bot_allow_write_confirm" = "Allow"; "lng_attach_failed" = "Failed"; "lng_attach_file" = "File"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index aebc9b809..2bea4bba8 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3316,24 +3316,24 @@ void ApiWrap::forwardMessages( _session->data().sendHistoryChangeNotifications(); } -void ApiWrap::shareContact( +FullMsgId ApiWrap::shareContact( const QString &phone, const QString &firstName, const QString &lastName, const SendAction &action) { const auto userId = UserId(0); - sendSharedContact(phone, firstName, lastName, userId, action); + return sendSharedContact(phone, firstName, lastName, userId, action); } -void ApiWrap::shareContact( +FullMsgId ApiWrap::shareContact( not_null user, const SendAction &action) { const auto userId = peerToUser(user->id); const auto phone = _session->data().findContactPhone(user); if (phone.isEmpty()) { - return; + return {}; } - sendSharedContact( + return sendSharedContact( phone, user->firstName, user->lastName, @@ -3341,7 +3341,7 @@ void ApiWrap::shareContact( action); } -void ApiWrap::sendSharedContact( +FullMsgId ApiWrap::sendSharedContact( const QString &phone, const QString &firstName, const QString &lastName, @@ -3391,6 +3391,7 @@ void ApiWrap::sendSharedContact( MTP_string(), // vcard MTP_long(userId.bare)), HistoryMessageMarkupData()); + const auto result = item->fullId(); const auto media = MTP_inputMediaContact( MTP_string(phone), @@ -3405,6 +3406,8 @@ void ApiWrap::sendSharedContact( (action.options.scheduled ? Data::HistoryUpdate::Flag::ScheduledSent : Data::HistoryUpdate::Flag::MessageSent)); + + return result; } void ApiWrap::sendVoiceMessage( diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 954500f76..b064d8df7 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -290,12 +290,14 @@ public: Data::ResolvedForwardDraft &&draft, const SendAction &action, FnMut &&successCallback = nullptr); - void shareContact( + FullMsgId shareContact( const QString &phone, const QString &firstName, const QString &lastName, const SendAction &action); - void shareContact(not_null user, const SendAction &action); + FullMsgId shareContact( + not_null user, + const SendAction &action); void applyAffectedMessages( not_null peer, const MTPmessages_AffectedMessages &result); @@ -484,7 +486,7 @@ private: SharedMediaType type, Api::SearchResult &&parsed); - void sendSharedContact( + FullMsgId sendSharedContact( const QString &phone, const QString &firstName, const QString &lastName, diff --git a/Telegram/SourceFiles/core/ui_integration.cpp b/Telegram/SourceFiles/core/ui_integration.cpp index ead942262..8f1be8324 100644 --- a/Telegram/SourceFiles/core/ui_integration.cpp +++ b/Telegram/SourceFiles/core/ui_integration.cpp @@ -370,7 +370,6 @@ QString UiIntegration::phrasePanelCloseAnyway() { return tr::lng_bot_close_warning_sure(tr::now); } -#if 0 // disabled for now QString UiIntegration::phraseBotSharePhone() { return tr::lng_bot_share_phone(tr::now); } @@ -382,7 +381,18 @@ QString UiIntegration::phraseBotSharePhoneTitle() { QString UiIntegration::phraseBotSharePhoneConfirm() { return tr::lng_bot_share_phone_confirm(tr::now); } -#endif + +QString UiIntegration::phraseBotAllowWrite() { + return tr::lng_bot_allow_write(tr::now); +} + +QString UiIntegration::phraseBotAllowWriteTitle() { + return tr::lng_bot_allow_write_title(tr::now); +} + +QString UiIntegration::phraseBotAllowWriteConfirm() { + return tr::lng_bot_allow_write_confirm(tr::now); +} bool OpenGLLastCheckFailed() { return QFile::exists(OpenGLCheckFilePath()); diff --git a/Telegram/SourceFiles/core/ui_integration.h b/Telegram/SourceFiles/core/ui_integration.h index 65661ecfd..cd3e4ff58 100644 --- a/Telegram/SourceFiles/core/ui_integration.h +++ b/Telegram/SourceFiles/core/ui_integration.h @@ -84,11 +84,12 @@ public: QString phrasePanelCloseWarning() override; QString phrasePanelCloseUnsaved() override; QString phrasePanelCloseAnyway() override; -#if 0 // disabled for now QString phraseBotSharePhone() override; QString phraseBotSharePhoneTitle() override; QString phraseBotSharePhoneConfirm() override; -#endif + QString phraseBotAllowWrite() override; + QString phraseBotAllowWriteTitle() override; + QString phraseBotAllowWriteConfirm() override; }; diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 6b9fc2997..723eeae9b 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -1173,6 +1173,7 @@ ServiceAction ParseServiceAction( content.domain = ParseString(*domain); } content.attachMenu = data.is_attach_menu(); + content.fromRequest = data.is_from_request(); result.content = content; }, [&](const MTPDmessageActionSecureValuesSentMe &data) { // Should not be in user inbox. diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index 27fb14ea1..4635ea269 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -439,6 +439,7 @@ struct ActionBotAllowed { Utf8String app; Utf8String domain; bool attachMenu = false; + bool fromRequest = false; }; struct ActionSecureValuesSent { diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp index efa4a7599..d4581c737 100644 --- a/Telegram/SourceFiles/export/output/export_output_html.cpp +++ b/Telegram/SourceFiles/export/output/export_output_html.cpp @@ -1127,6 +1127,8 @@ auto HtmlWriter::Wrap::pushMessage( return data.attachMenu ? "You allowed this bot to message you " "when you added it in the attachment menu."_q + : data.fromRequest + ? "You allowed this bot to message you in his web-app."_q : data.app.isEmpty() ? ("You allowed this bot to message you when you opened " + SerializeString(data.app)) diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index 9dfd21620..a232b2788 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -477,6 +477,8 @@ QByteArray SerializeMessage( }, [&](const ActionBotAllowed &data) { if (data.attachMenu) { pushAction("attach_menu_bot_allowed"); + } else if (data.fromRequest) { + pushAction("web_app_bot_allowed"); } else if (data.appId) { pushAction("allow_sending_messages"); push("reason_app_id", data.appId); diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index ff5aa329b..d81196689 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -3887,6 +3887,10 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) { result.text = { tr::lng_action_attach_menu_bot_allowed(tr::now) }; + } else if (action.is_from_request()) { + result.text = { + tr::lng_action_webapp_bot_allowed(tr::now) + }; } else if (const auto app = action.vapp()) { const auto bot = history()->peer->asUser(); const auto botId = bot ? bot->id : PeerId(); diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index be7a81472..410fa6b79 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_common.h" #include "core/click_handler_types.h" #include "data/data_bot_app.h" +#include "data/data_changes.h" #include "data/data_user.h" #include "data/data_file_origin.h" #include "data/data_document.h" @@ -462,6 +463,226 @@ void AttachWebView::request( resolve(); } +Webview::ThemeParams AttachWebView::botThemeParams() { + return Window::Theme::WebViewParams(); +} + +bool AttachWebView::botHandleLocalUri(QString uri) { + const auto local = Core::TryConvertUrlToLocal(uri); + if (uri == local || Core::InternalPassportLink(local)) { + return local.startsWith(u"tg://"_q); + } else if (!local.startsWith(u"tg://"_q, Qt::CaseInsensitive)) { + return false; + } + botClose(); + crl::on_main([=, shownUrl = _lastShownUrl] { + const auto variant = QVariant::fromValue(ClickHandlerContext{ + .attachBotWebviewUrl = shownUrl, + }); + UrlClickHandler::Open(local, variant); + }); + return true; +} + +void AttachWebView::botHandleInvoice(QString slug) { + Expects(_panel != nullptr); + + using Result = Payments::CheckoutResult; + const auto weak = base::make_weak(_panel.get()); + const auto reactivate = [=](Result result) { + if (const auto strong = weak.get()) { + strong->invoiceClosed(slug, [&] { + switch (result) { + case Result::Paid: return "paid"; + case Result::Failed: return "failed"; + case Result::Pending: return "pending"; + case Result::Cancelled: return "cancelled"; + } + Unexpected("Payments::CheckoutResult value."); + }()); + } + }; + _panel->hideForPayment(); + Payments::CheckoutProcess::Start(&_bot->session(), slug, reactivate); +} + +void AttachWebView::botHandleMenuButton(Ui::BotWebView::MenuButton button) { + Expects(_bot != nullptr); + Expects(_panel != nullptr); + + using Button = Ui::BotWebView::MenuButton; + const auto bot = _bot; + switch (button) { + case Button::OpenBot: + botClose(); + if (bot->session().windows().empty()) { + Core::App().domain().activate(&bot->session().account()); + } + if (!bot->session().windows().empty()) { + const auto window = bot->session().windows().front(); + window->showPeerHistory(bot); + window->window().activate(); + } + break; + case Button::RemoveFromMenu: + const auto attached = ranges::find( + _attachBots, + not_null{ _bot }, + &AttachWebViewBot::user); + const auto name = (attached != end(_attachBots)) + ? attached->name + : _bot->name(); + const auto done = crl::guard(this, [=] { + removeFromMenu(bot); + botClose(); + if (const auto active = Core::App().activeWindow()) { + active->activate(); + } + }); + _panel->showBox(Ui::MakeConfirmBox({ + tr::lng_bot_remove_from_menu_sure( + tr::now, + lt_bot, + Ui::Text::Bold(name), + Ui::Text::WithEntities), + done, + })); + break; + } +} + +void AttachWebView::botSendData(QByteArray data) { + if (!_context + || _context->fromSwitch + || _context->fromBotApp + || _context->action.history->peer != _bot + || _lastShownQueryId) { + return; + } + const auto randomId = base::RandomValue(); + _session->api().request(MTPmessages_SendWebViewData( + _bot->inputUser, + MTP_long(randomId), + MTP_string(_lastShownButtonText), + MTP_bytes(data) + )).done([=](const MTPUpdates &result) { + _session->api().applyUpdates(result); + }).send(); + crl::on_main(this, [=] { cancel(); }); +} + +void AttachWebView::botSwitchInlineQuery( + std::vector chatTypes, + QString query) { + const auto controller = _context + ? _context->controller.get() + : nullptr; + const auto types = PeerTypesFromNames(chatTypes); + if (!_bot + || !_bot->isBot() + || _bot->botInfo->inlinePlaceholder.isEmpty() + || !controller) { + return; + } else if (!types) { + if (_context->dialogsEntryState.key.owningHistory()) { + controller->switchInlineQuery( + _context->dialogsEntryState, + _bot, + query); + } + } else { + const auto bot = _bot; + const auto done = [=](not_null thread) { + controller->switchInlineQuery(thread, bot, query); + }; + ShowChooseBox( + controller, + types, + done, + tr::lng_inline_switch_choose()); + } + crl::on_main(this, [=] { cancel(); }); +} + +void AttachWebView::botCheckWriteAccess(Fn callback) { + _session->api().request(MTPbots_CanSendMessage( + _bot->inputUser + )).done([=](const MTPBool &result) { + callback(mtpIsTrue(result)); + }).fail([=] { + callback(false); + }).send(); +} + +void AttachWebView::botAllowWriteAccess(Fn callback) { + _session->api().request(MTPbots_AllowSendMessage( + _bot->inputUser + )).done([=](const MTPUpdates &result) { + _session->api().applyUpdates(result); + callback(true); + }).fail([=] { + callback(false); + }).send(); +} + +void AttachWebView::botSharePhone(Fn callback) { + const auto history = _bot->owner().history(_bot); + auto action = Api::SendAction(history); + action.clearDraft = false; + const auto id = history->session().api().shareContact( + _bot->session().user(), + action); + const auto owner = &_bot->owner(); + const auto lifetime = std::make_shared(); + const auto check = [=] { + const auto item = id ? owner->message(id) : nullptr; + if (!item || item->hasFailed()) { + lifetime->destroy(); + callback(false); + } + }; + + _bot->session().changes().historyUpdates( + history, + Data::HistoryUpdate::Flag::ClientSideMessages + ) | rpl::start_with_next(check, *lifetime); + + owner->itemRemoved( + ) | rpl::start_with_next([=](not_null item) { + if (item->fullId() == id) { + check(); + } + }, *lifetime); + + owner->itemIdChanged( + ) | rpl::start_with_next([=](const Data::Session::IdChange &change) { + if (FullMsgId(change.newId.peer, change.oldId) == id) { + lifetime->destroy(); + callback(true); + } + }, *lifetime); + + check(); +} + +void AttachWebView::botInvokeCustomMethod( + Ui::BotWebView::CustomMethodRequest request) { + const auto callback = request.callback; + _bot->session().api().request(MTPbots_InvokeWebViewCustomMethod( + _bot->inputUser, + MTP_string(request.method), + MTP_dataJSON(MTP_bytes(request.params)) + )).done([=](const MTPDataJSON &result) { + callback(result.data().vdata().v); + }).fail([=](const MTP::Error &error) { + callback(base::make_unexpected(error.type())); + }).send(); +} + +void AttachWebView::botClose() { + crl::on_main(this, [=] { cancel(); }); +} + AttachWebView::Context AttachWebView::LookupContext( not_null controller, const Api::SendAction &action) { @@ -568,7 +789,7 @@ void AttachWebView::cancel() { ActiveWebViews().remove(this); _session->api().request(base::take(_requestId)).cancel(); _session->api().request(base::take(_prolongId)).cancel(); - _panel = nullptr; + base::take(_panel); _lastShownContext = base::take(_context); _bot = nullptr; _app = nullptr; @@ -723,6 +944,8 @@ std::optional AttachWebView::lookupLastAction( } void AttachWebView::resolve() { + Expects(!_panel); + resolveUsername(_botUsername, [=](not_null bot) { if (!_context) { return; @@ -1004,98 +1227,6 @@ void AttachWebView::show( bool allowClipboardRead) { Expects(_bot != nullptr && _context != nullptr); - const auto close = crl::guard(this, [=] { - crl::on_main(this, [=] { cancel(); }); - }); - const auto sendData = crl::guard(this, [=](QByteArray data) { - if (!_context - || _context->fromSwitch - || _context->fromBotApp - || _context->action.history->peer != _bot - || queryId) { - return; - } - const auto randomId = base::RandomValue(); - _session->api().request(MTPmessages_SendWebViewData( - _bot->inputUser, - MTP_long(randomId), - MTP_string(buttonText), - MTP_bytes(data) - )).done([=](const MTPUpdates &result) { - _session->api().applyUpdates(result); - }).send(); - crl::on_main(this, [=] { cancel(); }); - }); - const auto switchInlineQuery = crl::guard(this, [=]( - std::vector typeNames, - QString query) { - const auto controller = _context - ? _context->controller.get() - : nullptr; - const auto types = PeerTypesFromNames(typeNames); - if (!_bot - || !_bot->isBot() - || _bot->botInfo->inlinePlaceholder.isEmpty() - || !controller) { - return; - } else if (!types) { - if (_context->dialogsEntryState.key.owningHistory()) { - controller->switchInlineQuery( - _context->dialogsEntryState, - _bot, - query); - } - } else { - const auto bot = _bot; - const auto done = [=](not_null thread) { - controller->switchInlineQuery(thread, bot, query); - }; - ShowChooseBox( - controller, - types, - done, - tr::lng_inline_switch_choose()); - } - crl::on_main(this, [=] { cancel(); }); - }); - const auto handleLocalUri = [close, url](QString uri) { - const auto local = Core::TryConvertUrlToLocal(uri); - if (uri == local || Core::InternalPassportLink(local)) { - return local.startsWith(u"tg://"_q); - } else if (!local.startsWith(u"tg://"_q, Qt::CaseInsensitive)) { - return false; - } - close(); - crl::on_main([=] { - const auto variant = QVariant::fromValue(ClickHandlerContext{ - .attachBotWebviewUrl = url, - }); - UrlClickHandler::Open(local, variant); - }); - return true; - }; - const auto panel = std::make_shared< - base::weak_ptr>(nullptr); - const auto handleInvoice = [=, session = _session](QString slug) { - using Result = Payments::CheckoutResult; - const auto reactivate = [=](Result result) { - if (const auto strong = panel->get()) { - strong->invoiceClosed(slug, [&] { - switch (result) { - case Result::Paid: return "paid"; - case Result::Failed: return "failed"; - case Result::Pending: return "pending"; - case Result::Cancelled: return "cancelled"; - } - Unexpected("Payments::CheckoutResult value."); - }()); - } - }; - if (const auto strong = panel->get()) { - strong->hideForPayment(); - } - Payments::CheckoutProcess::Start(session, slug, reactivate); - }; auto title = Info::Profile::NameValue(_bot); ActiveWebViews().emplace(this); @@ -1104,9 +1235,6 @@ void AttachWebView::show( _attachBots, not_null{ _bot }, &AttachWebViewBot::user); - const auto name = (attached != end(_attachBots)) - ? attached->name - : _bot->name(); const auto hasSettings = (attached != end(_attachBots)) && !attached->inactive && attached->hasSettings; @@ -1119,59 +1247,19 @@ void AttachWebView::show( | (hasRemoveFromMenu ? Button::RemoveFromMenu : Button::None); const auto bot = _bot; - const auto handleMenuButton = crl::guard(this, [=](Button button) { - switch (button) { - case Button::OpenBot: - close(); - if (bot->session().windows().empty()) { - Core::App().domain().activate(&bot->session().account()); - } - if (!bot->session().windows().empty()) { - const auto window = bot->session().windows().front(); - window->showPeerHistory(bot); - window->window().activate(); - } - break; - case Button::RemoveFromMenu: - if (const auto strong = panel->get()) { - const auto done = crl::guard(this, [=] { - removeFromMenu(bot); - close(); - if (const auto active = Core::App().activeWindow()) { - active->activate(); - } - }); - strong->showBox(Ui::MakeConfirmBox({ - tr::lng_bot_remove_from_menu_sure( - tr::now, - lt_bot, - Ui::Text::Bold(name), - Ui::Text::WithEntities), - done, - })); - } - break; - } - }); - _lastShownUrl = url; + _lastShownQueryId = queryId; + _lastShownButtonText = buttonText; + base::take(_panel); _panel = Ui::BotWebView::Show({ .url = url, .userDataPath = _session->domain().local().webviewDataPath(), .title = std::move(title), .bottom = rpl::single('@' + _bot->username()), - .handleLocalUri = handleLocalUri, - .handleInvoice = handleInvoice, - .sendData = sendData, - .switchInlineQuery = switchInlineQuery, - .close = close, - .phone = _session->user()->phone(), + .delegate = static_cast(this), .menuButtons = buttons, - .handleMenuButton = handleMenuButton, - .themeParams = [] { return Window::Theme::WebViewParams(); }, .allowClipboardRead = allowClipboardRead, }); - *panel = _panel.get(); started(queryId); } diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h index 0cbd71ab4..a6c254ef8 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h @@ -7,9 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "mtproto/sender.h" #include "base/weak_ptr.h" #include "base/flags.h" +#include "mtproto/sender.h" +#include "ui/chat/attach/attach_bot_webview.h" namespace Api { struct SendAction; @@ -64,7 +65,9 @@ struct AttachWebViewBot { bool requestWriteAccess = false; }; -class AttachWebView final : public base::has_weak_ptr { +class AttachWebView final + : public base::has_weak_ptr + , public Ui::BotWebView::Delegate { public: explicit AttachWebView(not_null session); ~AttachWebView(); @@ -130,6 +133,21 @@ public: private: struct Context; + Webview::ThemeParams botThemeParams() override; + bool botHandleLocalUri(QString uri) override; + void botHandleInvoice(QString slug) override; + void botHandleMenuButton(Ui::BotWebView::MenuButton button) override; + void botSendData(QByteArray data) override; + void botSwitchInlineQuery( + std::vector chatTypes, + QString query) override; + void botCheckWriteAccess(Fn callback) override; + void botAllowWriteAccess(Fn callback) override; + void botSharePhone(Fn callback) override; + void botInvokeCustomMethod( + Ui::BotWebView::CustomMethodRequest request) override; + void botClose() override; + [[nodiscard]] static Context LookupContext( not_null controller, const Api::SendAction &action); @@ -185,6 +203,8 @@ private: std::unique_ptr _context; std::unique_ptr _lastShownContext; QString _lastShownUrl; + uint64 _lastShownQueryId = 0; + QString _lastShownButtonText; UserData *_bot = nullptr; QString _botUsername; QString _botAppName; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index 1930c5484..f25340450 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -315,25 +315,12 @@ Panel::Progress::Progress(QWidget *parent, Fn rect) Panel::Panel( const QString &userDataPath, rpl::producer title, - Fn handleLocalUri, - Fn handleInvoice, - Fn sendData, - Fn, QString)> switchInlineQuery, - Fn close, - QString phone, + not_null delegate, MenuButtons menuButtons, - Fn handleMenuButton, - Fn themeParams, bool allowClipboardRead) : _userDataPath(userDataPath) -, _handleLocalUri(std::move(handleLocalUri)) -, _handleInvoice(std::move(handleInvoice)) -, _sendData(std::move(sendData)) -, _switchInlineQuery(std::move(switchInlineQuery)) -, _close(std::move(close)) -, _phone(phone) +, _delegate(delegate) , _menuButtons(menuButtons) -, _handleMenuButton(std::move(handleMenuButton)) , _widget(std::make_unique()) , _allowClipboardRead(allowClipboardRead) { _widget->setInnerSize(st::paymentsPanelSize); @@ -344,14 +331,16 @@ Panel::Panel( if (_closeNeedConfirmation) { scheduleCloseWithConfirmation(); } else { - _close(); + _delegate->botClose(); } }, _widget->lifetime()); _widget->closeEvents( ) | rpl::filter([=] { return !_hiddenForPayment; - }) | rpl::start_with_next(_close, _widget->lifetime()); + }) | rpl::start_with_next([=] { + _delegate->botClose(); + }, _widget->lifetime()); _widget->backRequests( ) | rpl::start_with_next([=] { @@ -367,7 +356,7 @@ Panel::Panel( _themeUpdateScheduled = true; crl::on_main(_widget.get(), [=] { _themeUpdateScheduled = false; - updateThemeParams(themeParams()); + updateThemeParams(_delegate->botThemeParams()); }); }, _widget->lifetime()); @@ -540,7 +529,7 @@ bool Panel::showWebview( } if (_menuButtons & MenuButton::OpenBot) { callback(tr::lng_bot_open(tr::now), [=] { - _handleMenuButton(MenuButton::OpenBot); + _delegate->botHandleMenuButton(MenuButton::OpenBot); }, &st::menuIconLeave); } callback(tr::lng_bot_reload_page(tr::now), [=] { @@ -548,7 +537,7 @@ bool Panel::showWebview( }, &st::menuIconRestore); if (_menuButtons & MenuButton::RemoveFromMenu) { const auto handler = [=] { - _handleMenuButton(MenuButton::RemoveFromMenu); + _delegate->botHandleMenuButton(MenuButton::RemoveFromMenu); }; callback({ .text = tr::lng_bot_remove_from_menu(tr::now), @@ -624,7 +613,7 @@ bool Panel::createWebview() { const auto command = list.at(0).toString(); const auto arguments = ParseMethodArgs(list.at(1).toString()); if (command == "web_app_close") { - _close(); + _delegate->botClose(); } else if (command == "web_app_data_send") { sendDataMessage(arguments); } else if (command == "web_app_switch_inline_query") { @@ -645,8 +634,12 @@ bool Panel::createWebview() { openInvoice(arguments); } else if (command == "web_app_open_popup") { openPopup(arguments); + } else if (command == "web_app_request_write_access") { + requestWriteAccess(); } else if (command == "web_app_request_phone") { requestPhone(); + } else if (command == "web_app_invoke_custom_method") { + invokeCustomMethod(arguments); } else if (command == "web_app_setup_closing_behavior") { setupClosingBehaviour(arguments); } else if (command == "web_app_read_text_from_clipboard") { @@ -655,7 +648,7 @@ bool Panel::createWebview() { }); raw->setNavigationStartHandler([=](const QString &uri, bool newWindow) { - if (_handleLocalUri(uri)) { + if (_delegate->botHandleLocalUri(uri)) { return false; } else if (newWindow) { return true; @@ -694,27 +687,27 @@ void Panel::setTitle(rpl::producer title) { void Panel::sendDataMessage(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } const auto data = args["data"].toString(); if (data.isEmpty()) { LOG(("BotWebView Error: Bad 'data' in sendDataMessage.")); - _close(); + _delegate->botClose(); return; } - _sendData(data.toUtf8()); + _delegate->botSendData(data.toUtf8()); } void Panel::switchInlineQueryMessage(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } const auto query = args["query"].toString(); if (query.isEmpty()) { LOG(("BotWebView Error: Bad 'query' in switchInlineQueryMessage.")); - _close(); + _delegate->botClose(); return; } const auto valid = base::flat_set{ @@ -735,26 +728,26 @@ void Panel::switchInlineQueryMessage(const QJsonObject &args) { break; } } - _switchInlineQuery(types, query); + _delegate->botSwitchInlineQuery(types, query); } void Panel::openTgLink(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } const auto path = args["path_full"].toString(); if (path.isEmpty()) { LOG(("BotWebView Error: Bad 'path_full' in openTgLink.")); - _close(); + _delegate->botClose(); return; } - _handleLocalUri("https://t.me" + path); + _delegate->botHandleLocalUri("https://t.me" + path); } void Panel::openExternalLink(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } const auto url = args["url"].toString(); @@ -762,7 +755,7 @@ void Panel::openExternalLink(const QJsonObject &args) { if (url.isEmpty() || (!lower.startsWith("http://") && !lower.startsWith("https://"))) { LOG(("BotWebView Error: Bad 'url' in openExternalLink.")); - _close(); + _delegate->botClose(); return; } else if (!allowOpenLink()) { return; @@ -772,21 +765,21 @@ void Panel::openExternalLink(const QJsonObject &args) { void Panel::openInvoice(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } const auto slug = args["slug"].toString(); if (slug.isEmpty()) { LOG(("BotWebView Error: Bad 'slug' in openInvoice.")); - _close(); + _delegate->botClose(); return; } - _handleInvoice(slug); + _delegate->botHandleInvoice(slug); } void Panel::openPopup(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } using Button = Webview::PopupArgs::Button; @@ -805,7 +798,7 @@ void Panel::openPopup(const QJsonObject &args) { const auto i = types.find(fields["type"].toString()); if (i == end(types)) { LOG(("BotWebView Error: Bad 'type' in openPopup buttons.")); - _close(); + _delegate->botClose(); return; } buttons.push_back({ @@ -816,11 +809,11 @@ void Panel::openPopup(const QJsonObject &args) { } if (message.isEmpty()) { LOG(("BotWebView Error: Bad 'message' in openPopup.")); - _close(); + _delegate->botClose(); return; } else if (buttons.empty()) { LOG(("BotWebView Error: Bad 'buttons' in openPopup.")); - _close(); + _delegate->botClose(); return; } const auto widget = _webview->window.widget(); @@ -838,8 +831,65 @@ void Panel::openPopup(const QJsonObject &args) { } } +void Panel::requestWriteAccess() { + if (_inBlockingRequest) { + replyRequestWriteAccess(false); + return; + } + _inBlockingRequest = true; + const auto finish = [=](bool allowed) { + _inBlockingRequest = false; + replyRequestWriteAccess(allowed); + }; + const auto weak = base::make_weak(this); + _delegate->botCheckWriteAccess([=](bool allowed) { + if (!weak) { + return; + } else if (allowed) { + finish(true); + return; + } + using Button = Webview::PopupArgs::Button; + const auto widget = _webview->window.widget(); + const auto integration = &Ui::Integration::Instance(); + const auto result = Webview::ShowBlockingPopup({ + .parent = widget ? widget->window() : nullptr, + .title = integration->phraseBotAllowWriteTitle(), + .text = integration->phraseBotAllowWrite(), + .buttons = { + { + .id = "allow", + .text = integration->phraseBotAllowWriteConfirm(), + }, + { .id = "cancel", .type = Button::Type::Cancel }, + }, + }); + if (!weak) { + return; + } else if (result.id == "allow") { + _delegate->botAllowWriteAccess(crl::guard(this, finish)); + } else { + finish(false); + } + }); +} + +void Panel::replyRequestWriteAccess(bool allowed) { + postEvent("write_access_requested", QJsonObject{ + { u"status"_q, allowed ? u"allowed"_q : u"cancelled"_q } + }); +} + void Panel::requestPhone() { -#if 0 // disabled for now + if (_inBlockingRequest) { + replyRequestPhone(false); + return; + } + _inBlockingRequest = true; + const auto finish = [=](bool shared) { + _inBlockingRequest = false; + replyRequestPhone(shared); + }; using Button = Webview::PopupArgs::Button; const auto widget = _webview->window.widget(); const auto weak = base::make_weak(this); @@ -853,15 +903,62 @@ void Panel::requestPhone() { .id = "share", .text = integration->phraseBotSharePhoneConfirm(), }, - {.id = "cancel", .type = Button::Type::Cancel }, + { .id = "cancel", .type = Button::Type::Cancel }, }, }); - if (weak) { - postEvent("phone_requested", (result.id == "share") - ? QJsonObject{ { u"phone_number"_q, _phone } } - : EventData()); + if (!weak) { + return; + } else if (result.id == "share") { + _delegate->botSharePhone(crl::guard(this, finish)); + } else { + finish(false); } -#endif +} + +void Panel::replyRequestPhone(bool shared) { + postEvent("phone_requested", QJsonObject{ + { u"status"_q, shared ? u"sent"_q : u"cancelled"_q } + }); +} + +void Panel::invokeCustomMethod(const QJsonObject &args) { + const auto requestId = args["req_id"]; + if (requestId.isUndefined()) { + return; + } + const auto finish = [=](QJsonObject response) { + replyCustomMethod(requestId, std::move(response)); + }; + auto callback = crl::guard(this, [=](CustomMethodResult result) { + if (result) { + auto error = QJsonParseError(); + const auto parsed = QJsonDocument::fromJson( + "{ \"result\": " + *result + '}', + &error); + if (error.error != QJsonParseError::NoError + || !parsed.isObject() + || parsed.object().size() != 1) { + finish({ { u"error"_q, u"Could not parse response."_q } }); + } else { + finish(parsed.object()); + } + } else { + finish({ { u"error"_q, result.error() } }); + } + }); + const auto params = QJsonDocument( + args["params"].toObject() + ).toJson(QJsonDocument::Compact); + _delegate->botInvokeCustomMethod({ + .method = args["method"].toString(), + .params = params, + .callback = std::move(callback), + }); +} + +void Panel::replyCustomMethod(QJsonValue requestId, QJsonObject response) { + response["req_id"] = requestId; + postEvent(u"custom_method_invoked"_q, response); } void Panel::requestClipboardText(const QJsonObject &args) { @@ -929,7 +1026,7 @@ void Panel::closeWithConfirmation() { if (!weak) { return; } else if (result.id != "cancel") { - _close(); + _delegate->botClose(); } else { _closeWithConfirmationScheduled = false; } @@ -941,7 +1038,7 @@ void Panel::setupClosingBehaviour(const QJsonObject &args) { void Panel::processMainButtonMessage(const QJsonObject &args) { if (args.isEmpty()) { - _close(); + _delegate->botClose(); return; } @@ -1158,20 +1255,13 @@ rpl::lifetime &Panel::lifetime() { } std::unique_ptr Show(Args &&args) { - const auto params = args.themeParams(); auto result = std::make_unique( args.userDataPath, std::move(args.title), - std::move(args.handleLocalUri), - std::move(args.handleInvoice), - std::move(args.sendData), - std::move(args.switchInlineQuery), - std::move(args.close), - args.phone, + args.delegate, args.menuButtons, - std::move(args.handleMenuButton), - std::move(args.themeParams), args.allowClipboardRead); + const auto params = args.delegate->botThemeParams(); if (!result->showWebview(args.url, params, std::move(args.bottom))) { const auto available = Webview::Availability(); if (available.error != Webview::Available::Error::None) { diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h index c2898afc2..54bf92aa9 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h @@ -7,10 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/expected.h" #include "base/object_ptr.h" #include "base/weak_ptr.h" #include "base/flags.h" +class QJsonObject; +class QJsonValue; + namespace Ui { class BoxContent; class RpWidget; @@ -40,20 +44,37 @@ enum class MenuButton { inline constexpr bool is_flag_type(MenuButton) { return true; } using MenuButtons = base::flags; +using CustomMethodResult = base::expected; +struct CustomMethodRequest { + QString method; + QByteArray params; + Fn callback; +}; + +class Delegate { +public: + virtual Webview::ThemeParams botThemeParams() = 0; + virtual bool botHandleLocalUri(QString uri) = 0; + virtual void botHandleInvoice(QString slug) = 0; + virtual void botHandleMenuButton(MenuButton button) = 0; + virtual void botSendData(QByteArray data) = 0; + virtual void botSwitchInlineQuery( + std::vector chatTypes, + QString query) = 0; + virtual void botCheckWriteAccess(Fn callback) = 0; + virtual void botAllowWriteAccess(Fn callback) = 0; + virtual void botSharePhone(Fn callback) = 0; + virtual void botInvokeCustomMethod(CustomMethodRequest request) = 0; + virtual void botClose() = 0; +}; + class Panel final : public base::has_weak_ptr { public: Panel( const QString &userDataPath, rpl::producer title, - Fn handleLocalUri, - Fn handleInvoice, - Fn sendData, - Fn, QString)> switchInlineQuery, - Fn close, - QString phone, + not_null delegate, MenuButtons menuButtons, - Fn handleMenuButton, - Fn themeParams, bool allowClipboardRead); ~Panel(); @@ -96,7 +117,12 @@ private: void openExternalLink(const QJsonObject &args); void openInvoice(const QJsonObject &args); void openPopup(const QJsonObject &args); + void requestWriteAccess(); + void replyRequestWriteAccess(bool allowed); void requestPhone(); + void replyRequestPhone(bool shared); + void invokeCustomMethod(const QJsonObject &args); + void replyCustomMethod(QJsonValue requestId, QJsonObject response); void requestClipboardText(const QJsonObject &args); void setupClosingBehaviour(const QJsonObject &args); void createMainButton(); @@ -115,15 +141,9 @@ private: void setupProgressGeometry(); QString _userDataPath; - Fn _handleLocalUri; - Fn _handleInvoice; - Fn _sendData; - Fn, QString)> _switchInlineQuery; - Fn _close; - QString _phone; + const not_null _delegate; bool _closeNeedConfirmation = false; MenuButtons _menuButtons = {}; - Fn _handleMenuButton; std::unique_ptr _widget; std::unique_ptr _webview; std::unique_ptr _webviewBottom; @@ -139,6 +159,7 @@ private: bool _hiddenForPayment = false; bool _closeWithConfirmationScheduled = false; bool _allowClipboardRead = false; + bool _inBlockingRequest = false; }; @@ -147,15 +168,8 @@ struct Args { QString userDataPath; rpl::producer title; rpl::producer bottom; - Fn handleLocalUri; - Fn handleInvoice; - Fn sendData; - Fn, QString)> switchInlineQuery; - Fn close; - QString phone; + not_null delegate; MenuButtons menuButtons; - Fn handleMenuButton; - Fn themeParams; bool allowClipboardRead = false; }; [[nodiscard]] std::unique_ptr Show(Args &&args); From 076aa9452e987d51d1013625937ab7c6c313f833 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 Sep 2023 17:34:05 +0400 Subject: [PATCH 013/155] Unblock the bot before sharing phone number. --- .../SourceFiles/api/api_blocked_peers.cpp | 103 +++++++++++++----- Telegram/SourceFiles/api/api_blocked_peers.h | 17 ++- .../inline_bots/bot_attach_web_view.cpp | 16 +++ .../SourceFiles/window/window_peer_menu.cpp | 4 +- .../window/window_session_controller.cpp | 2 +- 5 files changed, 108 insertions(+), 34 deletions(-) diff --git a/Telegram/SourceFiles/api/api_blocked_peers.cpp b/Telegram/SourceFiles/api/api_blocked_peers.cpp index 9dfc886b1..0a79eb733 100644 --- a/Telegram/SourceFiles/api/api_blocked_peers.cpp +++ b/Telegram/SourceFiles/api/api_blocked_peers.cpp @@ -77,45 +77,59 @@ void BlockedPeers::block(not_null peer) { _session->changes().peerUpdated( peer, Data::PeerUpdate::Flag::IsBlocked); - } else if (_blockRequests.find(peer) == end(_blockRequests)) { - const auto requestId = _api.request(MTPcontacts_Block( - MTP_flags(0), - peer->input - )).done([=] { - _blockRequests.erase(peer); - peer->setIsBlocked(true); - if (_slice) { - _slice->list.insert( - _slice->list.begin(), - { peer->id, base::unixtime::now() }); - ++_slice->total; - _changes.fire_copy(*_slice); - } - }).fail([=] { - _blockRequests.erase(peer); - }).send(); - - _blockRequests.emplace(peer, requestId); + return; + } else if (blockAlreadySent(peer, true)) { + return; } + const auto requestId = _api.request(MTPcontacts_Block( + MTP_flags(0), + peer->input + )).done([=] { + const auto data = _blockRequests.take(peer); + peer->setIsBlocked(true); + if (_slice) { + _slice->list.insert( + _slice->list.begin(), + { peer->id, base::unixtime::now() }); + ++_slice->total; + _changes.fire_copy(*_slice); + } + if (data) { + for (const auto &callback : data->callbacks) { + callback(false); + } + } + }).fail([=] { + if (const auto data = _blockRequests.take(peer)) { + for (const auto &callback : data->callbacks) { + callback(false); + } + } + }).send(); + + _blockRequests.emplace(peer, Request{ + .requestId = requestId, + .blocking = true, + }); } void BlockedPeers::unblock( not_null peer, - Fn onDone, + Fn done, bool force) { if (!force && !peer->isBlocked()) { _session->changes().peerUpdated( peer, Data::PeerUpdate::Flag::IsBlocked); return; - } else if (_blockRequests.find(peer) != end(_blockRequests)) { + } else if (blockAlreadySent(peer, false, done)) { return; } const auto requestId = _api.request(MTPcontacts_Unblock( MTP_flags(0), peer->input )).done([=] { - _blockRequests.erase(peer); + const auto data = _blockRequests.take(peer); peer->setIsBlocked(false); if (_slice) { auto &list = _slice->list; @@ -130,13 +144,46 @@ void BlockedPeers::unblock( } _changes.fire_copy(*_slice); } - if (onDone) { - onDone(); + if (data) { + for (const auto &callback : data->callbacks) { + callback(true); + } } }).fail([=] { - _blockRequests.erase(peer); + if (const auto data = _blockRequests.take(peer)) { + for (const auto &callback : data->callbacks) { + callback(false); + } + } }).send(); - _blockRequests.emplace(peer, requestId); + const auto i = _blockRequests.emplace(peer, Request{ + .requestId = requestId, + .blocking = false, + }).first; + if (done) { + i->second.callbacks.push_back(std::move(done)); + } +} + +bool BlockedPeers::blockAlreadySent( + not_null peer, + bool blocking, + Fn done) { + const auto i = _blockRequests.find(peer); + if (i == end(_blockRequests)) { + return false; + } else if (i->second.blocking == blocking) { + if (done) { + i->second.callbacks.push_back(std::move(done)); + } + return true; + } + const auto callbacks = base::take(i->second.callbacks); + _blockRequests.erase(i); + for (const auto &callback : callbacks) { + callback(false); + } + return false; } void BlockedPeers::reload() { @@ -160,7 +207,7 @@ auto BlockedPeers::slice() -> rpl::producer { : (_changes.events() | rpl::type_erased()); } -void BlockedPeers::request(int offset, Fn onDone) { +void BlockedPeers::request(int offset, Fn done) { if (_requestId) { return; } @@ -170,7 +217,7 @@ void BlockedPeers::request(int offset, Fn onDone) { MTP_int(offset ? kBlockedPerPage : kBlockedFirstSlice) )).done([=](const MTPcontacts_Blocked &result) { _requestId = 0; - onDone(TLToSlice(result, _session->data())); + done(TLToSlice(result, _session->data())); }).fail([=] { _requestId = 0; }).send(); diff --git a/Telegram/SourceFiles/api/api_blocked_peers.h b/Telegram/SourceFiles/api/api_blocked_peers.h index af184c457..ca2000f67 100644 --- a/Telegram/SourceFiles/api/api_blocked_peers.h +++ b/Telegram/SourceFiles/api/api_blocked_peers.h @@ -39,20 +39,31 @@ public: void reload(); rpl::producer slice(); - void request(int offset, Fn onDone); + void request(int offset, Fn done); void block(not_null peer); void unblock( not_null peer, - Fn onDone = nullptr, + Fn done = nullptr, bool force = false); private: + struct Request { + std::vector> callbacks; + mtpRequestId requestId = 0; + bool blocking = false; + }; + + [[nodiscard]] bool blockAlreadySent( + not_null peer, + bool blocking, + Fn done = nullptr); + const not_null _session; MTP::Sender _api; - base::flat_map, mtpRequestId> _blockRequests; + base::flat_map, Request> _blockRequests; mtpRequestId _requestId = 0; std::optional _slice; rpl::event_stream _changes; diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 410fa6b79..1a90cafd8 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "inline_bots/bot_attach_web_view.h" +#include "api/api_blocked_peers.h" #include "api/api_common.h" #include "core/click_handler_types.h" #include "data/data_bot_app.h" @@ -626,7 +627,22 @@ void AttachWebView::botAllowWriteAccess(Fn callback) { } void AttachWebView::botSharePhone(Fn callback) { + const auto bot = _bot; const auto history = _bot->owner().history(_bot); + if (_bot->isBlocked()) { + const auto done = [=](bool success) { + if (success && _bot == bot) { + Assert(!_bot->isBlocked()); + botSharePhone(callback); + } else { + callback(false); + } + }; + _bot->session().api().blockedPeers().unblock( + _bot, + crl::guard(this, done)); + return; + } auto action = Api::SendAction(history); action.clearDraft = false; const auto id = history->session().api().shareContact( diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 26571b1d6..6b9173ac1 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1578,8 +1578,8 @@ void PeerMenuBlockUserBox( } void PeerMenuUnblockUserWithBotRestart(not_null user) { - user->session().api().blockedPeers().unblock(user, [=] { - if (user->isBot() && !user->isSupport()) { + user->session().api().blockedPeers().unblock(user, [=](bool success) { + if (success && user->isBot() && !user->isSupport()) { user->session().api().sendBotStart(user); } }); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 4ec3e2dfb..268518eed 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -314,7 +314,7 @@ void SessionNavigation::showPeerByLink(const PeerByLinkInfo &info) { if (info.startAutoSubmit) { peer->session().api().blockedPeers().unblock( peer, - [=] { showPeerByLinkResolved(peer, info); }, + [=](bool) { showPeerByLinkResolved(peer, info); }, true); } else { showPeerByLinkResolved(peer, info); From 7009e967d08f8c81d02a1faf972ce249409dd8e4 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 4 Sep 2023 12:06:16 +0400 Subject: [PATCH 014/155] Fix build with MSVC. --- .../info/userpic/info_userpic_emoji_builder_preview.cpp | 2 +- Telegram/lib_ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp index 54e3767f7..59e78131c 100644 --- a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp +++ b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_preview.cpp @@ -48,7 +48,7 @@ PreviewPainter::PreviewPainter(int size) } DocumentData *PreviewPainter::document() const { - return _media ? _media->owner() : nullptr; + return _media ? _media->owner().get() : nullptr; } void PreviewPainter::setPlayOnce(bool value) { diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 5a2402ad5..2107f5a16 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 5a2402ad5d7e41a48c84d56c45df6b5d49e8b176 +Subproject commit 2107f5a1647e8fc7b509313630ab9012257715ba From 876a803e0ea3e12c4592a39695fc296dad2c1164 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 4 Sep 2023 17:54:11 +0400 Subject: [PATCH 015/155] Version 4.9.5. - Several new bot web-app features. - Bug fixes and other minor improvements. --- Telegram/Resources/uwp/AppX/AppxManifest.xml | 2 +- Telegram/Resources/winrc/Telegram.rc | 8 ++++---- Telegram/Resources/winrc/Updater.rc | 8 ++++---- Telegram/SourceFiles/core/version.h | 4 ++-- Telegram/build/version | 8 ++++---- changelog.txt | 5 +++++ cmake | 2 +- 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index 3b5ae67a8..703efb68b 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -10,7 +10,7 @@ + Version="4.9.5.0" /> Telegram Desktop Telegram Messenger LLP diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index 17d4cbf11..53575af38 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,9,4,0 - PRODUCTVERSION 4,9,4,0 + FILEVERSION 4,9,5,0 + PRODUCTVERSION 4,9,5,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -62,10 +62,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop" - VALUE "FileVersion", "4.9.4.0" + VALUE "FileVersion", "4.9.5.0" VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "4.9.4.0" + VALUE "ProductVersion", "4.9.5.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 6a05c580e..78fefbb88 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,9,4,0 - PRODUCTVERSION 4,9,4,0 + FILEVERSION 4,9,5,0 + PRODUCTVERSION 4,9,5,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -53,10 +53,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop Updater" - VALUE "FileVersion", "4.9.4.0" + VALUE "FileVersion", "4.9.5.0" VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "4.9.4.0" + VALUE "ProductVersion", "4.9.5.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index feb1dfd8b..303bc5057 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs; constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs; constexpr auto AppName = "Telegram Desktop"_cs; constexpr auto AppFile = "Telegram"_cs; -constexpr auto AppVersion = 4009004; -constexpr auto AppVersionStr = "4.9.4"; +constexpr auto AppVersion = 4009005; +constexpr auto AppVersionStr = "4.9.5"; constexpr auto AppBetaVersion = false; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/build/version b/Telegram/build/version index 1b6e6f9ec..e6badc49d 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 4009004 +AppVersion 4009005 AppVersionStrMajor 4.9 -AppVersionStrSmall 4.9.4 -AppVersionStr 4.9.4 +AppVersionStrSmall 4.9.5 +AppVersionStr 4.9.5 BetaChannel 0 AlphaVersion 0 -AppVersionOriginal 4.9.4 +AppVersionOriginal 4.9.5 diff --git a/changelog.txt b/changelog.txt index 0c1ef6979..531a517df 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,8 @@ +4.9.5 (04.09.23) + +- Several new bot web-app features. +- Bug fixes and other minor improvements. + 4.9.4 (30.08.23) - Default private chats / groups / channels notification settings. diff --git a/cmake b/cmake index 121c2afbb..2440fc9e8 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 121c2afbbbf0ea89522da79cff56380fb1796c34 +Subproject commit 2440fc9e87b40b7224e927bfc3b914146d0cd4cf From 0079a18e9717611e29af08f0bc821afa45721ba0 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 4 Sep 2023 02:12:14 +0400 Subject: [PATCH 016/155] Call D-Bus ReloadConfig asynchronously --- .../SourceFiles/platform/linux/specific_linux.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index a4885388d..b7834a48a 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -371,15 +371,16 @@ bool GenerateServiceFile(bool silent = false) { } try { - const auto connection = Gio::DBus::Connection::get_sync( - Gio::DBus::BusType::SESSION); - - connection->call_sync( + Gio::DBus::Connection::get_sync( + Gio::DBus::BusType::SESSION + )->call( base::Platform::DBus::kObjectPath, base::Platform::DBus::kInterface, "ReloadConfig", {}, - base::Platform::DBus::kService); + {}, + base::Platform::DBus::kService + ); } catch (...) { } From 9f0a756f712015d25aa09f13df9ad75b93aefb89 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 Sep 2023 13:10:03 +0400 Subject: [PATCH 017/155] Version 4.9.5: Fix build with GCC. --- Telegram/SourceFiles/dialogs/dialogs_main_list.cpp | 5 ++++- Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp index 9e643555a..9c9ad67ba 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp @@ -194,11 +194,14 @@ UnreadState MainList::unreadState() const { result.chatsMuted = result.chats; result.marksMuted = result.marks; } - volatile auto touch = _unreadState.marks + _unreadState.marksMuted +#ifdef Q_OS_WIN + [[maybe_unused]] volatile auto touch = 0 + + _unreadState.marks + _unreadState.marksMuted + _unreadState.messages + _unreadState.messagesMuted + _unreadState.chats + _unreadState.chatsMuted + _unreadState.reactions + _unreadState.reactionsMuted + _unreadState.mentions; +#endif // Q_OS_WIN return result; } diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 1a90cafd8..623f2bea7 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -1261,7 +1261,6 @@ void AttachWebView::show( const auto buttons = (hasSettings ? Button::Settings : Button::None) | (hasOpenBot ? Button::OpenBot : Button::None) | (hasRemoveFromMenu ? Button::RemoveFromMenu : Button::None); - const auto bot = _bot; _lastShownUrl = url; _lastShownQueryId = queryId; From 191f832e5289fd5df9aa08a87b4e87587b6ddf8c Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 Sep 2023 16:42:12 +0400 Subject: [PATCH 018/155] Use notarytool instead of altool for notarization. --- Telegram/build/build.sh | 93 +-------------------------------------- Telegram/build/updates.py | 69 ++--------------------------- 2 files changed, 5 insertions(+), 157 deletions(-) diff --git a/Telegram/build/build.sh b/Telegram/build/build.sh index 65bb3725c..8239bb71b 100755 --- a/Telegram/build/build.sh +++ b/Telegram/build/build.sh @@ -402,66 +402,8 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "macstore" ]; then cd "$ReleasePath" fi fi - if [ "$NotarizeRequestId" == "" ]; then - echo "Beginning notarization process." - set +e - xcrun altool --notarize-app --primary-bundle-id "com.tdesktop.Telegram" --username "$AC_USERNAME" --password "@keychain:AC_PASSWORD" --file "$SetupFile" > request_uuid.txt - set -e - while IFS='' read -r line || [[ -n "$line" ]]; do - Prefix=$(echo $line | cut -d' ' -f 1) - Value=$(echo $line | cut -d' ' -f 3) - if [ "$Prefix" == "RequestUUID" ]; then - RequestUUID=$Value - fi - done < "request_uuid.txt" - if [ "$RequestUUID" == "" ]; then - cat request_uuid.txt - Error "Could not extract Request UUID." - fi - echo "Request UUID: $RequestUUID" - rm request_uuid.txt - else - RequestUUID=$NotarizeRequestId - echo "Continue notarization process with Request UUID: $RequestUUID" - fi - - RequestStatus= - LogFile= - while [[ "$RequestStatus" == "" ]]; do - sleep 5 - xcrun altool --notarization-info "$RequestUUID" --username "$AC_USERNAME" --password "@keychain:AC_PASSWORD" > request_result.txt - while IFS='' read -r line || [[ -n "$line" ]]; do - Prefix=$(echo $line | cut -d' ' -f 1) - Value=$(echo $line | cut -d' ' -f 2) - if [ "$Prefix" == "LogFileURL:" ]; then - LogFile=$Value - fi - if [ "$Prefix" == "Status:" ]; then - if [ "$Value" == "in" ]; then - echo "In progress..." - else - RequestStatus=$Value - echo "Status: $RequestStatus" - fi - fi - done < "request_result.txt" - done - if [ "$RequestStatus" != "success" ]; then - echo "Notarization problems, response:" - cat request_result.txt - if [ "$LogFile" != "" ]; then - echo "Requesting log: $LogFile" - curl $LogFile - fi - Error "Notarization FAILED." - fi - rm request_result.txt - - if [ "$LogFile" != "" ]; then - echo "Requesting log: $LogFile" - curl $LogFile > request_log.txt - fi - + echo "Beginning notarization process." + xcrun notarytool submit "$SetupFile" --keychain-profile "preston" --wait xcrun stapler staple "$ReleasePath/$BundleName" if [ "$MacArch" != "" ]; then @@ -543,34 +485,3 @@ sleep 1; echo -en "\007"; sleep 1; echo -en "\007"; - -if [ "$BuildTarget" == "mac" ]; then - if [ -f "$ReleasePath/request_log.txt" ]; then - DisplayingLog= - while IFS='' read -r line || [[ -n "$line" ]]; do - if [ "$DisplayingLog" == "1" ]; then - echo $line - else - Prefix=$(echo $line | cut -d' ' -f 1) - Value=$(echo $line | cut -d' ' -f 2) - if [ "$Prefix" == '"issues":' ]; then - if [ "$Value" != "null" ]; then - echo "NB! Notarization log issues:" - echo $line - DisplayingLog=1 - else - DisplayingLog=0 - fi - fi - fi - done < "$ReleasePath/request_log.txt" - if [ "$DisplayingLog" != "0" ] && [ "$DisplayingLog" != "1" ]; then - echo "NB! Notarization issues not found:" - cat "$ReleasePath/request_log.txt" - else - rm "$ReleasePath/request_log.txt" - fi - else - echo "NB! Notarization log not found :(" - fi -fi diff --git a/Telegram/build/updates.py b/Telegram/build/updates.py index 2b5418605..d1cdc7203 100644 --- a/Telegram/build/updates.py +++ b/Telegram/build/updates.py @@ -109,53 +109,9 @@ if building: finish(1, 'Adding tdesktop to archive.') print('Beginning notarization process.') - lines = subprocess.check_output('xcrun altool --notarize-app --primary-bundle-id "com.tdesktop.Telegram" --username "' + username + '" --password "@keychain:AC_PASSWORD" --file "' + archive + '"', stderr=subprocess.STDOUT, shell=True).decode('utf-8') - print('Response received.') - uuid = '' - for line in lines.split('\n'): - parts = line.strip().split(' ') - if len(parts) > 2 and parts[0] == 'RequestUUID': - uuid = parts[2] - if uuid == '': - finish(1, 'Could not extract Request UUID. Response: ' + lines) - print('Request UUID: ' + uuid) - else: - print('Continue with request UUID: ' + uuid) - - requestStatus = '' - logUrl = '' - while requestStatus == '': - time.sleep(5) - print('Checking...') - lines = subprocess.check_output('xcrun altool --notarization-info "' + uuid + '" --username "' + username + '" --password "@keychain:AC_PASSWORD"', stderr=subprocess.STDOUT, shell=True).decode('utf-8') - statusFound = False - for line in lines.split('\n'): - parts = line.strip().split(' ') - if len(parts) > 1: - if parts[0] == 'LogFileURL:': - logUrl = parts[1] - elif parts[0] == 'Status:': - if parts[1] == 'in': - print('In progress.') - statusFound = True - else: - requestStatus = parts[1] - print('Status: ' + requestStatus) - statusFound = True - if not statusFound: - print('Nothing: ' + lines) - if requestStatus != 'success': - print('Notarization problems, response: ' + lines) - if logUrl != '': - print('Requesting log...') - result = subprocess.call('curl ' + logUrl, shell=True) - if result != 0: - finish(1, 'Error calling curl ' + logUrl) - finish(1, 'Notarization failed.') - logLines = '' - if logUrl != '': - print('Requesting log...') - logLines = subprocess.check_output('curl ' + logUrl, shell=True).decode('utf-8') + result = subprocess.call('xcrun notarytool submit "' + archive + '" --keychain-profile "preston" --wait', shell=True) + if result != 0: + finish(1, 'Notarizing the archive.') result = subprocess.call('xcrun stapler staple Telegram.app', shell=True) if result != 0: finish(1, 'Error calling stapler') @@ -175,25 +131,6 @@ if building: subprocess.call('mv ' + archive + ' ' + outputFolder + '/', shell=True) subprocess.call('rm -rf ' + today, shell=True) print('Finished.') - - if logLines != '': - displayingLog = 0 - for line in logLines.split('\n'): - if displayingLog == 1: - print(line) - else: - parts = line.strip().split(' ') - if len(parts) > 1 and parts[0] == '"issues":': - if parts[1] != 'null': - print('NB! Notarization log issues:') - print(line) - displayingLog = 1 - else: - displayingLog = -1 - if displayingLog == 0: - print('NB! Notarization issues not found: ' + logLines) - else: - print('NB! Notarization log not found.') finish(0) commandPath = scriptPath + '/../../out/' + conf + '/' + outputFolder + '/command.txt' From 8adbbe6885cc857fb48effb7fdbbfe1e8388ea2c Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 Sep 2023 19:28:52 +0400 Subject: [PATCH 019/155] Don't expect itemId from shareContact. --- Telegram/SourceFiles/apiwrap.cpp | 46 ++++++++++++------- Telegram/SourceFiles/apiwrap.h | 21 +++++---- .../inline_bots/bot_attach_web_view.cpp | 36 ++------------- 3 files changed, 46 insertions(+), 57 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 2bea4bba8..aa83e5f8d 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3316,37 +3316,50 @@ void ApiWrap::forwardMessages( _session->data().sendHistoryChangeNotifications(); } -FullMsgId ApiWrap::shareContact( +void ApiWrap::shareContact( const QString &phone, const QString &firstName, const QString &lastName, - const SendAction &action) { + const SendAction &action, + Fn done) { const auto userId = UserId(0); - return sendSharedContact(phone, firstName, lastName, userId, action); + sendSharedContact( + phone, + firstName, + lastName, + userId, + action, + std::move(done)); } -FullMsgId ApiWrap::shareContact( +void ApiWrap::shareContact( not_null user, - const SendAction &action) { + const SendAction &action, + Fn done) { const auto userId = peerToUser(user->id); const auto phone = _session->data().findContactPhone(user); if (phone.isEmpty()) { - return {}; + if (done) { + done(false); + } + return; } return sendSharedContact( phone, user->firstName, user->lastName, userId, - action); + action, + std::move(done)); } -FullMsgId ApiWrap::sendSharedContact( +void ApiWrap::sendSharedContact( const QString &phone, const QString &firstName, const QString &lastName, UserId userId, - const SendAction &action) { + const SendAction &action, + Fn done) { sendAction(action); const auto history = action.history; @@ -3391,14 +3404,13 @@ FullMsgId ApiWrap::sendSharedContact( MTP_string(), // vcard MTP_long(userId.bare)), HistoryMessageMarkupData()); - const auto result = item->fullId(); const auto media = MTP_inputMediaContact( MTP_string(phone), MTP_string(firstName), MTP_string(lastName), MTP_string()); // vcard - sendMedia(item, media, action.options); + sendMedia(item, media, action.options, std::move(done)); _session->data().sendHistoryChangeNotifications(); _session->changes().historyUpdated( @@ -3406,8 +3418,6 @@ FullMsgId ApiWrap::sendSharedContact( (action.options.scheduled ? Data::HistoryUpdate::Flag::ScheduledSent : Data::HistoryUpdate::Flag::MessageSent)); - - return result; } void ApiWrap::sendVoiceMessage( @@ -3931,18 +3941,20 @@ void ApiWrap::uploadAlbumMedia( void ApiWrap::sendMedia( not_null item, const MTPInputMedia &media, - Api::SendOptions options) { + Api::SendOptions options, + Fn done) { const auto randomId = base::RandomValue(); _session->data().registerMessageRandomId(randomId, item->fullId()); - sendMediaWithRandomId(item, media, options, randomId); + sendMediaWithRandomId(item, media, options, randomId, std::move(done)); } void ApiWrap::sendMediaWithRandomId( not_null item, const MTPInputMedia &media, Api::SendOptions options, - uint64 randomId) { + uint64 randomId, + Fn done) { const auto history = item->history(); const auto replyTo = item->replyTo(); @@ -3984,10 +3996,12 @@ void ApiWrap::sendMediaWithRandomId( MTP_int(options.scheduled), (options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()) ), [=](const MTPUpdates &result, const MTP::Response &response) { + if (done) done(true); if (updateRecentStickers) { requestRecentStickersForce(true); } }, [=](const MTP::Error &error, const MTP::Response &response) { + if (done) done(false); sendMessageFail(error, peer, randomId, itemId); }); } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index b064d8df7..f61eb0957 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -290,14 +290,16 @@ public: Data::ResolvedForwardDraft &&draft, const SendAction &action, FnMut &&successCallback = nullptr); - FullMsgId shareContact( + void shareContact( const QString &phone, const QString &firstName, const QString &lastName, - const SendAction &action); - FullMsgId shareContact( + const SendAction &action, + Fn done = nullptr); + void shareContact( not_null user, - const SendAction &action); + const SendAction &action, + Fn done = nullptr); void applyAffectedMessages( not_null peer, const MTPmessages_AffectedMessages &result); @@ -486,12 +488,13 @@ private: SharedMediaType type, Api::SearchResult &&parsed); - FullMsgId sendSharedContact( + void sendSharedContact( const QString &phone, const QString &firstName, const QString &lastName, UserId userId, - const SendAction &action); + const SendAction &action, + Fn done); void deleteHistory( not_null peer, @@ -518,12 +521,14 @@ private: void sendMedia( not_null item, const MTPInputMedia &media, - Api::SendOptions options); + Api::SendOptions options, + Fn done = nullptr); void sendMediaWithRandomId( not_null item, const MTPInputMedia &media, Api::SendOptions options, - uint64 randomId); + uint64 randomId, + Fn done = nullptr); FileLoadTo fileLoadTaskOptions(const SendAction &action) const; void getTopPromotionDelayed(TimeId now, TimeId next); diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 623f2bea7..0a45d407d 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -645,40 +645,10 @@ void AttachWebView::botSharePhone(Fn callback) { } auto action = Api::SendAction(history); action.clearDraft = false; - const auto id = history->session().api().shareContact( + history->session().api().shareContact( _bot->session().user(), - action); - const auto owner = &_bot->owner(); - const auto lifetime = std::make_shared(); - const auto check = [=] { - const auto item = id ? owner->message(id) : nullptr; - if (!item || item->hasFailed()) { - lifetime->destroy(); - callback(false); - } - }; - - _bot->session().changes().historyUpdates( - history, - Data::HistoryUpdate::Flag::ClientSideMessages - ) | rpl::start_with_next(check, *lifetime); - - owner->itemRemoved( - ) | rpl::start_with_next([=](not_null item) { - if (item->fullId() == id) { - check(); - } - }, *lifetime); - - owner->itemIdChanged( - ) | rpl::start_with_next([=](const Data::Session::IdChange &change) { - if (FullMsgId(change.newId.peer, change.oldId) == id) { - lifetime->destroy(); - callback(true); - } - }, *lifetime); - - check(); + action, + std::move(callback)); } void AttachWebView::botInvokeCustomMethod( From 107b72f44251ede68c2946089e50116602392aac Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 Sep 2023 21:31:45 +0400 Subject: [PATCH 020/155] Fix possible crash in AddBotToGroupBox. --- Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index 6e205cb84..d867c0607 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -384,8 +384,11 @@ void EditAdminBox::prepare() { if (!_saveCallback) { return; } else if (_addAsAdmin && !_addAsAdmin->checked()) { + const auto weak = Ui::MakeWeak(this); AddBotToGroup(user(), peer(), _addingBot->token); - getDelegate()->hideLayer(); + if (const auto strong = weak.data()) { + strong->closeBox(); + } return; } else if (_addingBot && !_addingBot->existing) { const auto phrase = peer()->isBroadcast() From 4bfe40d02e1deadb805130ab2cb4fd7e18c1a2a1 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 Sep 2023 21:31:57 +0400 Subject: [PATCH 021/155] Don't close ShareBox by outside click. --- Telegram/SourceFiles/boxes/share_box.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index d348b5aaf..ad992b525 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -248,6 +248,8 @@ void ShareBox::prepareCommentField() { void ShareBox::prepare() { prepareCommentField(); + setCloseByOutsideClick(false); + _select->resizeToWidth(st::boxWideWidth); Ui::SendPendingMoveResizeEvents(_select); From eef3cdd31b50bdbdc95f91379ea24c54665dd0d0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 5 Sep 2023 21:32:11 +0400 Subject: [PATCH 022/155] Update mini_forward/mini_reply_story icons. --- Telegram/Resources/icons/mini_forward.png | Bin 337 -> 319 bytes Telegram/Resources/icons/mini_forward@2x.png | Bin 527 -> 539 bytes Telegram/Resources/icons/mini_forward@3x.png | Bin 772 -> 777 bytes Telegram/Resources/icons/mini_reply_story.png | Bin 563 -> 588 bytes .../Resources/icons/mini_reply_story@2x.png | Bin 1025 -> 1114 bytes .../Resources/icons/mini_reply_story@3x.png | Bin 1438 -> 1629 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Telegram/Resources/icons/mini_forward.png b/Telegram/Resources/icons/mini_forward.png index 0b12af15d0dac8b19147b9d028e133f6f8e5c890..e51712b550d7196348f23f4bed6ce73f77f2849f 100644 GIT binary patch delta 198 zcmV;%06G8B0>1)~fq$trL(3gO;}j?#EBDdMQDt* zYu7?FFv0arnKH%P+#Jp&z;JPKK{FDWi^WMZXU+tw`0?Y%vOi_Z5)u-!va%o=aC-XQ zy?YxsZUlM*;u6Ba8XO$V$jAtHH^~tP*EtXj0Jp=A?A*j1UH||907*qoM6N<$f{SEa ArvLx| delta 216 zcmV;}04M*y0?`7Hfq%P6L_t(26=Pr+Iv_tkpP!$f1ou9E{P^BQckCv9!@#DvVO5xz+$B!;9F4*;0TU&ql@BywA&iM7~m$S1ox*jer zuKV}z!xbSjUcP*(t*wo&p|rFVuIT5_pK$ign>Uq|l+aZJ`B8iK?tTCMeN$7Dii!%5 z3k)Too})*P3JVKkQ4JK@y?ZxADMT8mVeQ(r92^|jRbz@;SXeMIF=2`iLJ4XUrn3JMQGBPp*?O-CP0+#|kJ-t(>P8k^);Zgt*C*J~~eo0BmLx&Fe z`T60ugRm?sE32)oZCYB|x^?Ryaez$z{rk6|pn$L`SXBrK34e8VcD{W164^wo?5R_y zlAN?$TwH*O6031o1xZU<5fKr;fB(j65FSAylNLj8aPXf$fAAQDN9x$IV^~8QA*iXT z`T6r_JVxM`B47a{BjdSq=kObWNA|*n3j}gsR8$lm{rIJbiez9c;Wq`B?35`}2q#l5 zEiJ72Z{51JY=7CZ?(XjW`}boiAR(jG)YKsBKXKwjMn(p(Jb)(v>eED*2Zf+C_7zfz`V)GPCFNi*W z{yea@0;W`CL1Z@E0-_QOvQ8q|YHDi0VCnDgC!Ao2G#znN*=Pt55dr|DC6g7C;kw!Y O0000y|Nnpd_z@l+P7^yI769$|_wQdxNeT7sfLj2x0|+Kfn#9D!L>+5*d3nvu%x>Jc z0Wlg*u3NW`larHtI~W-mqoSgY9616v5t9M*mawoeId(`$NPq0wwF}ckOp%*6Zz?G% zk!FXKl+^9pw=vDaCGzs+OA`|lV(kEi`1R}8ahZin9Ow@;3vecYIdkS{XlS6RCdfT^ z?i@iiAO)_juDINYM|{bWC2VYLL|JhB_;EZ2VU=ocZwIC~qD)s;SI26^=g*&k(TFMa z=g*(a%uJ$;hJPrkuC9ig^7rpwU^30f$N<_3kwx>|*RNlFeSJwV9jJ86mMstqwr<_3 zrKN?Y8M&x<_39NcZ=)$7%zgg+Ind#Gd3jis!Yu%15oKj%tZE1d?%lgLGBOgEB8UaR zfD#cA!KH>G@!Z_p88c>3RJu`Q|ET8C5THQ_002t&>k+jYN8@7v00007!C z1LY6Mz(kT_tPCUr6axc9CS-&W-FNk#+i^Hwd+&44=$4;Q0#2uMKA%sgQ;)|ZLwfv_`F#HS|8u+DVzC&0f`8Wv^=l|$q|s=o)h3gv z-EL>IS>j~BBZx__R;w$OO1)mERWfHq$GXu{#}Xf(3h z?H`oFuQCb(VwcM`9*?oCC$AvTWVKp{!=Xg$2^aNe*6nuZa=B)+3E$;>K2x^m`+Yv2 zQmiK=2=-|@oqvWikdIp+PHa71L7`CScsvSFicaQ?v~iL z2cI7f2Xqc}B;mmrkH^tD(2?Y=qt$Am&|EGTICj_Twdmdl0CeKl4#gUo&F1_4&L?QI z*+36TBoa28jZQ0kI!L|wM1RV|s uG=#}yg0kTV@+(V}3Mds&D)5&p@DE9_dTR4~`VFH10000U-zLpFW}apqwTGF5W}f-}zTc1EOwaSo z(-VL29pF2_cYyD}@9w}eE9jx~;N*p+xKgS7 z0Ksp$T$W0uSZvvw+yVhpyWLhQl`QOpENW0n>~?#n)6wa4DB@eqqktg8WHR-7J&VP1 zo5y(mKp@E0YPBC9A8xmskpr6mUKFR(84L!;<1z74lTOa(v)}K>7D;I&kx1U&-de5J z^?D`6-@8mC5`UCd7zRBa&uX>07fdsr&*w!V5e5RnLM#?%vss!*##@a>LoSyShMZ2| z&(&%*#z;oNU@*{VG@MYN7-*{1Dq|R;;Opy4tyXhl%49N#VTiI=EXE$__4O4o23_WG zI9LLyRI1HpgPz2wJe^KHpN}OClqHi%#td}9cDr@CTz~9oVD3L04(NIG%H?utHk;Yg zKxI50r_VsYJDE&gUS2rSKr!q`=_8?k)9G}vSkTLw&89-3;7VgK7${=^qF%4RzrP!e zMxpTEet~9|DwRsG_Hm_w`cNoD0-DWcux?Y%{iGcuQJ6}lux+v7D}wOd?RJ4c;Q9IP zSIYlDmw(G891de>3}G=G4u639{k~qWC&npHNI>vdyilWV&VM0000000>D%PDHLkV1nuILwNuI diff --git a/Telegram/Resources/icons/mini_reply_story.png b/Telegram/Resources/icons/mini_reply_story.png index bfcbc0c48a1fb238c1057d4f2a82d8802eaa1f48..d1b436beb4072cf503e6ba8d1ba4837c5fcc0b91 100644 GIT binary patch delta 469 zcmV;`0V@8p1k41Gfq%A1L_t(26@5~_%YjiCeZ77~k^vC#x zlgXr9F7reVvXpYUT(jA1Fc{eF_WgdpSS%pv_4>_blS-wijei5tX!L%+4~IjO$;8)i zXQ5D7uh(L+_`|#1Zn!g<%!m31p~ieZM-sj#kw_p6pAiTIjYb2#F;1uR@pu>v1}f)r zx!3FEa5yMKz;3rIl}b!Do1IRlghH8WwF)=Za=EP4YHGEb9t(%Vkw}E8*Xx~5hp@?H zlDO%<-EMU{9e+Ioz+NsFg+f87R;x7{jrcO6=JR>NXf&F453yM6a5xBsLc&TUl5V$) z8$zKF+Q96N$0HsFYOmMp_xlV|Ua!}9JWdNku2d>En~g9&pHC)}0b`VSy*F7b7SHFi z#bP0jzjj>CNm8j4KWDXCc|4wPw@Rf-r_;1g&Y)B(kxuXVd^Vd+WWdx&ZpbKfI-QJ0 z<99747z~cbC1uKGD~S!IS=d?3BuXq53;zLG zP0GSn%0^i$S-FITEbL^1zrbZfDN1r#p>v*TIy2L3PUn1!uiyJV&-=~u%|{S_T%^LU z*Xvo9jm2W`_xpG}DpX~e&1Nr`%jtBQOeT>?1oC)1uGMO4wSQV^B}sBP9PV~IhGFDd zC=_b9+eV{N-sHJdDy>#4gTWvODwRs%a5x-N$LI6iZa1&jE3_;Y%WO8Y*=&-7AkOEr z5R$)iE|+^e9`$-1Y`5E|(8qIRKU26% z{VU--e0?w&IGs+p84p^mR;4g<&15nm{q=esjYj2i*)`+wKy|rX^Z7g&42n+Wiv|LL mWHRY?ySv?Puh$cO|A%jZ;+4Bej{0-}0000%4HgVlq8p2OEVKu%7f%Zp%4-i z38kdG@Fe9yit;4aypTvC4=5#hb9>>*ExDKbEz|#hGi&VGv*(;SnwS4P%&fKcx4yOZ zK5MOgR9?S${QdpY($fCep0~HR>FMdOudiSDDM11P0%~h(=YQtrUS3}Qa!*4;gOaP# zx{r?!SkBMSIa<4Tb8}-f8X19Juix0%SYKby%*x!@~uDlbV~G z`}z4v=)S%_KYu?zr)3#MrBa#A=KcNssi`R$h|L@yA5Xa>Mp;>zJE#Y1YPFi3dv$fS z2Mh`>*dv`xZ*Q*~C`v`)lx@zbsi`;vByFd{i@LnLM1ZriGmSAr-`UMJ1=9$a6uCYUZlpx#-i@6aza7^xm8tF z3DD)`Wq+PgQpWMh#jvwwXJ?aVK|ui@0O{Y}-b#`R#`^kt-cgjX5prQj;>y^j8`<9lLeqg(4ymNHW(a{kL!-S`&C+w215X_0SwY7?h z3aM<}+Hm1vB#e)bf0!u_%3AIM!_v$|Ei=j(uG(E-vCjQNa8+^&hsp VR12( delta 910 zcmV;919AM?2!RNYfq!dBL_t(Y4eeG-D0E>M9^;ZrLK-z8_nKUi$XHCuWh`XMC0U4+ z(F{hiH=Eg-qNG{OlqkwV60=2USST_?S-93@G0nmy!um)!%;>bKduP zp7;H}bH4X|&nOiCFPS$GCBrKeg@uI%gQ32@J}WCrtyW)NUVqls*1o;H$p*>`kZ5;z z_ZRnidU{GrOC!O(y}kSU`@_S-F)=an=~zW-YU;|$3e9|eer~th`}_Nwo0~H-GN{t+ zb`#Cf(NR)T62)bV;^N|qiwhFDwzgJLQ6UwOpP#?8vqO}Xm6cL54xW>fbANx2m_Q)V z($d1=Bpkh7-+$53AwhEC1WxnEsfAwy?prwBJSH3bf@C^|Y? zNH;Vz;K?AUuC5lc6gfCJfCjZok+5-neGP7CXebPYtbew)wwIR|u(-Zoz-TlQ8SRy? z9C+yV)6-E=+!@i{-i}~A z1TSW6Yz(W??5uHkc!)mW=_Or@#e!gu$HOXgIvtx)Xrot3N=n!ep{*nkY4qpkXIA0$ zdU0qh!hf?dQD$alc%Zo3)6;_uo}QlaXtdtu=B9A(EYjNA%0|`H)J#rJ^3M{}7%`8J zkFl|_tQvNFeEjO_D$VF{I0gm=kOC8sfG(Gd4LLhI13o@J&VmZ;loVo9Qxk{ybWj`f z^YbJfEmPD9hO5u#!(^l(1qB5}*45QT!7pQdeSaMsN{~-{`bdZ3gMcnTWVyMyTU%SS zH!=92L0PA#r}OimzX?}bTFU1_es^~_o;Bo&-0`eds})5r!eNhSajbz6FFXm6fFD38 z0DNq*#_a6u55gk~F_}zQ0N298LSkZKBr!^*a%5y=ad9y-Gcyvs!e+CPHI9#u8yg$H zkAK0D;E;(P<@>!j%;GT7)g)|tdwXzjFgrUtOfwetPGlP!8!0I%3?pZ1G@9k*WfDw& z(S|5_v=uuk@eN;ES{fZ4#fy?lDaKb-RiXUxXN#`%@$sQjsl>G67~|8IRF3v diff --git a/Telegram/Resources/icons/mini_reply_story@3x.png b/Telegram/Resources/icons/mini_reply_story@3x.png index 471cfa57d7bfbbe0b810b3b4ee69442d57f5d47d..e836bcd3d4ee639b3341e2224667e3e63292a073 100644 GIT binary patch delta 1518 zcmV+H0@%t@ZD{|21q)F8uamVPWz2zt7gz*4f$FZ{z6?aDVmc)vTe#sG;!s=-JrVz?I$IUA}$p`1|+o zSFT*)0b5&Jx3;#<&(GJ?)Y#eC@n-cN8W|Zqc<^9zbCYXYJ%WofGc$dCea+3y<>lqK zZru_ZC@wB0-G6W2z9lCo3uTmYurTfI?F2`}#Kc5tX=zYUkg>6`PORG6T2f?)mX;Qs zS|S3To}M_fJglCc9?@kG(bup%JUrIc)_6Gjf?Nm=4(6ShckkX|Nikpsa%S-%eE$5IyxH5^ zi;s`zNc@)rd{h1X{p8Kz;i19X^k>{oPfsUruu};M34aFHFcd_v)zwvUsGy)gInKq4 z7nKY1ByqqU9UXa0)v%Nl6@8e3|?E z`{a=Flz#-ElamuDzI^$TgQ#GDwIPd$RVF4TTBVGP44Ol9)=tP$IXO9}r>Bgf0S+Ns z|NQxr>_$gNYpwP6_R<6bhIT@lLb@dt5C%8|?ANbf6G&TIo7$SKtu1zunLz&2d3q2X zUc7igKn!7+Ly3urgaaQ;O-)rk;T#aRuC7k)rhmi_befu)NS+9Mp*W$BA3sLgkx&(3 zqo7+~UuQsec6QVbRaRCKZcI#!h@OUJX=#c4O2SeEs-OJ)d^0mMjh@_ZWMt&h($ezs zvNk2KZTR^3NNHcXbO|X|$_XJK#X?|UpcI-Me`I8Y;G~K=#IEu2aS~HVpoRYOL$E5sVU|@g{uV23|BTR{czjyDR=&Xy23qIbJl@-J=wZNlCkLX1a zKSb5oOoTqXF{v=b^z<~=FFZUPMOAfmweXYd?(SxT5RHsMP`?6(8H-1A%XUm%0DdK&6_t#?OX|* zMQlCa8^$D-ofZ&B#L3C&TwT!(j@un}OFuk3Y-MGoTkTvW5ZSO_v`(mbaVc}I7IlMX zXJ?Z`AP}Owyu5U)DUd)ot*WZZ&CL}*F)|2HWBY_YFeN2LMqcL>w*L9^=YQ1n;5tR8 z3P%9p@!7Lyh}vwoK7IOxCY2+nY!DC-fGV2}h0vu;l`9n+8_Pc93?i^_Cybk6uB_w; z?}kjy_6D>zu}kVnOyFVliHfg7zh&Q}{|GtDZWo-0H znVFgBR7BlkGm)@FPb)5j8E3JMjt=EZtHV1aqlXV4vhQoyt`M!QAGmmk`@+o16)|Xp zf(CbLxD&?BFgZa4N+0~s!ysU-l986wlR~kJ`sOdqgT4X*LK+&j0`b07*qoM6N<$g7`@KJOBUy delta 1326 zcmV+}1=0H544w;+fqw`|L_t(o3GG-}D79S_eoYzrGEYBciV{L3E{Hx;VT)V44KLN|4-j`wte3BJ?FgV9DV&4&c!)vul=lN zt+U^~*IN7KxbM&R3TU?iI@*}q+uQ#m`#e284Gavtyu4^bsDFvAp`l@HY;0?5>%qan zzw)1^rY21oHMTJ~H?OFuxV^oV594z*Ha5nRJ32a!jEqc9PDVvVvHCBNO-xLRi;FKW zFF&0#(%akH$;rw5{Jg)vKkKZgr-!0OM@Kz9J=s~!Wp{V?_4Rd1O@z(O&Fbpvh=>R* zgTB7LD0^pTCx2^oe}C`g?yuiHV8oSbsGZnPz)?o32f2YJciidr*_FsHliWQ&LhQ#ai9R z;pXO6TU(o*ovoVO+S>Z+>WT#P>(?*U1{_yVP=M1H8X77EOfbKH|0XVQZd6z`G&B$> zd|)T4KyzGKSsB46BqXQ=6M&A6&fVP|vD(_&!cd{1o}S+6=_!GBcXunq{h7eoK}92A zd`k}q)_+}HUDOcAS)rrw@NkL?3=C9=<2YpJzP>&RhM-nJSbJ&<9)*q?8yg93e}7*g zh~tcnjZvE@BN19!T2M)>tgMt6vQs~Q{v?JS9UZJ*PDX_yAnYW$31(nwYC1PJM_|Hl zWcI14sidSN#zI_lc6RRV?QLsoQ}!R|UQ0~hkB=!vqJTC{Mxf@ei;D~Of#ND^jhJ?Jb|_4WfCTI9?JdftLW!D69Vkgw z4u1{~!UmEWiVA2QMSUZ$K0G`O4-Xp{7>EM6v$He8n3$D-smi1a8-Y;+gK$H()7V8?j&bdfSLGT134GA@D2+8QxS3k!?f+<)B2 z$VjnCMu$~dU0o$HAq|RVNCy5_L_|#&3Fi)*_pi8B>V$2+lr>OFNxpItiDYqck*?Fw z&=3-jmJX7WlaaEcqoXzC!OeVcZ;!@=a)GxFnsFhsBhwP9=jUe>AI*3;oE`SYh-_I| zSqXNv==}Wrj*gD#AA_K%a!aDc;eVW%m|*E}Ys1w?`dbHH_sz?Yl7irYkO<1l%V}bz z!5tnRwzs#V+N7nW;b1CiSm|pkT(DH+K%QgeLu{b_{(dw!G$5XUDI_`}3D&r#rlzj0 z4sS?>v)XEWeSPtd(N6H9Aw$%EZ5?Q4kD7{`d{tEyUSZ+pMBWA9wXmYQiYI1Xw6a34 kqOx7l%E7ns|9A!d1I1E6H3|;h@c;k-07*qoM6N<$f}?_Wc>n+a From 547a39d835b06fe52cc4e3d9c90b0799afc33fbe Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 Sep 2023 01:23:26 +0400 Subject: [PATCH 023/155] Update tg_owt in snap --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 476b6b7bb..b985ac256 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -538,7 +538,7 @@ parts: webrtc: source: https://github.com/desktop-app/tg_owt.git source-depth: 1 - source-commit: dcb5069ff76bd293e86928804208737e6cee2ccc + source-commit: 0532942ac6176a66ef184fb728a4cbb02958fc0b plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s From 289257dd0f2642901cacf52ae91ed21731611233 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 Sep 2023 10:53:30 +0400 Subject: [PATCH 024/155] Update submodules --- Telegram/lib_base | 2 +- Telegram/lib_ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/lib_base b/Telegram/lib_base index 57e2519de..c36d961ea 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 57e2519de75fb5732e53d28282ac97e881061421 +Subproject commit c36d961eaf3d3a09d100509196aa039958f264bc diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 2107f5a16..b2293c86e 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 2107f5a1647e8fc7b509313630ab9012257715ba +Subproject commit b2293c86e12537941d98e464748a060760377914 From 483909854a222eef2c875d64417b9ee8877ee9d0 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 31 Aug 2023 15:34:18 +0400 Subject: [PATCH 025/155] Use brackets include for QtWaylandScanner-generated headers --- .../platform/linux/linux_wayland_integration.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp index b6cc6c888..ab93809ad 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp @@ -12,14 +12,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qt_signal_producer.h" #include "base/flat_map.h" -#include "qwayland-wayland.h" -#include "qwayland-plasma-shell.h" - #include #include #include #include +#include +#include + using namespace QNativeInterface; using namespace QNativeInterface::Private; using namespace base::Platform::Wayland; From 7ffb3415971aa048fb85d78427b426d338b0e402 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 5 Sep 2023 11:01:47 +0300 Subject: [PATCH 026/155] Removed some unwanted include directives of styles in header files. --- .../info/downloads/info_downloads_provider.cpp | 1 + .../info/media/info_media_list_section.cpp | 1 + .../SourceFiles/info/media/info_media_provider.cpp | 1 + Telegram/SourceFiles/layout/layout_mosaic.h | 2 -- .../media/view/media_view_playback_controls.h | 2 -- Telegram/SourceFiles/overview/overview_layout.cpp | 7 ++----- Telegram/SourceFiles/overview/overview_layout.h | 3 ++- Telegram/SourceFiles/ui/boxes/country_select_box.h | 1 - Telegram/SourceFiles/ui/effects/round_checkbox.cpp | 13 ++++++------- Telegram/SourceFiles/ui/effects/round_checkbox.h | 6 +++++- .../SourceFiles/ui/widgets/continuous_sliders.cpp | 1 + .../SourceFiles/ui/widgets/continuous_sliders.h | 6 +++++- .../SourceFiles/ui/widgets/discrete_sliders.cpp | 1 - Telegram/SourceFiles/ui/widgets/level_meter.cpp | 1 + Telegram/SourceFiles/ui/widgets/level_meter.h | 5 ++++- 15 files changed, 29 insertions(+), 22 deletions(-) diff --git a/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp b/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp index 36059ac33..5dbea6fdf 100644 --- a/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp +++ b/Telegram/SourceFiles/info/downloads/info_downloads_provider.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "storage/storage_shared_media.h" #include "layout/layout_selection.h" +#include "styles/style_overview.h" namespace Info::Downloads { namespace { diff --git a/Telegram/SourceFiles/info/media/info_media_list_section.cpp b/Telegram/SourceFiles/info/media/info_media_list_section.cpp index 2bf957192..ba207ff28 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_section.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_section.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_shared_media.h" #include "layout/layout_selection.h" #include "ui/painter.h" +#include "styles/style_chat_helpers.h" #include "styles/style_info.h" namespace Info::Media { diff --git a/Telegram/SourceFiles/info/media/info_media_provider.cpp b/Telegram/SourceFiles/info/media/info_media_provider.cpp index 3e75975fa..2fc69733e 100644 --- a/Telegram/SourceFiles/info/media/info_media_provider.cpp +++ b/Telegram/SourceFiles/info/media/info_media_provider.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer_values.h" #include "data/data_document.h" #include "styles/style_info.h" +#include "styles/style_overview.h" namespace Info::Media { namespace { diff --git a/Telegram/SourceFiles/layout/layout_mosaic.h b/Telegram/SourceFiles/layout/layout_mosaic.h index b8730f84c..8695d9dc1 100644 --- a/Telegram/SourceFiles/layout/layout_mosaic.h +++ b/Telegram/SourceFiles/layout/layout_mosaic.h @@ -10,8 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "layout/abstract_layout_item.h" #include "layout/layout_position.h" -#include "styles/style_chat_helpers.h" - namespace Mosaic::Layout { struct FoundItem { diff --git a/Telegram/SourceFiles/media/view/media_view_playback_controls.h b/Telegram/SourceFiles/media/view/media_view_playback_controls.h index 5f79cba52..ac5e15baa 100644 --- a/Telegram/SourceFiles/media/view/media_view_playback_controls.h +++ b/Telegram/SourceFiles/media/view/media_view_playback_controls.h @@ -9,8 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "base/object_ptr.h" -#include "base/unique_qptr.h" -#include "styles/style_widgets.h" namespace Ui { class LabelSimple; diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index 9ac811f19..ea4ebd6ec 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -14,14 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_web_page.h" #include "data/data_media_types.h" #include "data/data_peer.h" -#include "data/data_file_origin.h" #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "data/data_file_click_handler.h" -#include "styles/style_overview.h" -#include "styles/style_chat.h" -#include "core/file_utilities.h" -#include "boxes/add_contact_box.h" #include "ui/boxes/confirm_box.h" #include "lang/lang_keys.h" #include "layout/layout_selection.h" @@ -50,6 +45,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/power_saving.h" #include "ui/ui_utility.h" +#include "styles/style_overview.h" +#include "styles/style_chat.h" namespace Overview { namespace Layout { diff --git a/Telegram/SourceFiles/overview/overview_layout.h b/Telegram/SourceFiles/overview/overview_layout.h index e566de4a5..d17ae7f6c 100644 --- a/Telegram/SourceFiles/overview/overview_layout.h +++ b/Telegram/SourceFiles/overview/overview_layout.h @@ -13,12 +13,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/click_handler_types.h" #include "ui/effects/animations.h" #include "ui/effects/radial_animation.h" -#include "styles/style_overview.h" class Image; namespace style { struct RoundCheckbox; +struct OverviewFileLayout; } // namespace style namespace Data { @@ -367,6 +367,7 @@ struct DocumentFields { TimeId dateOverride = 0; bool forceFileLayout = false; }; + class Document final : public RadialProgressItem { public: Document( diff --git a/Telegram/SourceFiles/ui/boxes/country_select_box.h b/Telegram/SourceFiles/ui/boxes/country_select_box.h index 507e478e9..553fd39e2 100644 --- a/Telegram/SourceFiles/ui/boxes/country_select_box.h +++ b/Telegram/SourceFiles/ui/boxes/country_select_box.h @@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/layers/box_content.h" -#include "styles/style_widgets.h" namespace Countries { struct Info; diff --git a/Telegram/SourceFiles/ui/effects/round_checkbox.cpp b/Telegram/SourceFiles/ui/effects/round_checkbox.cpp index 78996a89c..fbd67b220 100644 --- a/Telegram/SourceFiles/ui/effects/round_checkbox.cpp +++ b/Telegram/SourceFiles/ui/effects/round_checkbox.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/ui_utility.h" #include "ui/painter.h" #include "ui/effects/outline_segments.h" -#include "ui/image/image_prepare.h" +#include "styles/style_widgets.h" #include @@ -21,6 +21,10 @@ namespace { constexpr auto kAnimationTimerDelta = crl::time(7); constexpr auto kWideScale = 3; +[[nodiscard]] int CountFramesCount(const style::RoundCheckbox *st) { + return (st->duration / kAnimationTimerDelta) + 1; +} + class CheckCaches : public QObject { public: CheckCaches(QObject *parent) : QObject(parent) { @@ -46,7 +50,6 @@ private: QPixmap check; }; - int countFramesCount(const style::RoundCheckbox *st); Frames &framesForStyle( const style::RoundCheckbox *st, bool displayInactive); @@ -141,10 +144,6 @@ QRect WideDestRect( return QRect(iconLeft, iconTop, iconSize, iconSize); } -int CheckCaches::countFramesCount(const style::RoundCheckbox *st) { - return (st->duration / kAnimationTimerDelta) + 1; -} - CheckCaches::Frames &CheckCaches::framesForStyle( const style::RoundCheckbox *st, bool displayInactive) { @@ -163,7 +162,7 @@ void CheckCaches::prepareFramesData( const style::RoundCheckbox *st, bool displayInactive, Frames &frames) { - frames.list.resize(countFramesCount(st)); + frames.list.resize(CountFramesCount(st)); frames.displayInactive = displayInactive; if (!frames.displayInactive) { diff --git a/Telegram/SourceFiles/ui/effects/round_checkbox.h b/Telegram/SourceFiles/ui/effects/round_checkbox.h index ff24ac597..49377c0ec 100644 --- a/Telegram/SourceFiles/ui/effects/round_checkbox.h +++ b/Telegram/SourceFiles/ui/effects/round_checkbox.h @@ -8,7 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/effects/animations.h" -#include "styles/style_widgets.h" + +namespace style { +struct RoundCheckbox; +struct RoundImageCheckbox; +} // namespace style class Painter; enum class ImageRoundRadius; diff --git a/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp b/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp index ea4e252ff..d400c1240 100644 --- a/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp +++ b/Telegram/SourceFiles/ui/widgets/continuous_sliders.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "base/timer.h" #include "base/platform/base_platform_info.h" +#include "styles/style_widgets.h" namespace Ui { namespace { diff --git a/Telegram/SourceFiles/ui/widgets/continuous_sliders.h b/Telegram/SourceFiles/ui/widgets/continuous_sliders.h index 51c82883d..e5900bcbf 100644 --- a/Telegram/SourceFiles/ui/widgets/continuous_sliders.h +++ b/Telegram/SourceFiles/ui/widgets/continuous_sliders.h @@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "styles/style_widgets.h" #include "ui/effects/animations.h" #include "ui/rp_widget.h" @@ -15,6 +14,11 @@ namespace base { class Timer; } // namespace base +namespace style { +struct FilledSlider; +struct MediaSlider; +} // namespace style + namespace Ui { class ContinuousSlider : public RpWidget { diff --git a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp index 174d84d29..3dda10b06 100644 --- a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp +++ b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp @@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "ui/painter.h" -#include "styles/style_widgets.h" namespace Ui { diff --git a/Telegram/SourceFiles/ui/widgets/level_meter.cpp b/Telegram/SourceFiles/ui/widgets/level_meter.cpp index fe0511d4c..15acd28ab 100644 --- a/Telegram/SourceFiles/ui/widgets/level_meter.cpp +++ b/Telegram/SourceFiles/ui/widgets/level_meter.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/level_meter.h" #include "ui/painter.h" +#include "styles/style_widgets.h" namespace Ui { diff --git a/Telegram/SourceFiles/ui/widgets/level_meter.h b/Telegram/SourceFiles/ui/widgets/level_meter.h index 4fe15b7f4..70ffa8c1a 100644 --- a/Telegram/SourceFiles/ui/widgets/level_meter.h +++ b/Telegram/SourceFiles/ui/widgets/level_meter.h @@ -7,9 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "styles/style_widgets.h" #include "ui/rp_widget.h" +namespace style { +struct LevelMeter; +} // namespace style + namespace Ui { class LevelMeter : public RpWidget { From 787ed443f481820aefda514b6b4aaf7e55318360 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 5 Sep 2023 13:34:41 +0300 Subject: [PATCH 027/155] Increased clickable area to change forward options in sections. --- Telegram/SourceFiles/history/history_widget.cpp | 17 +++++++++++------ .../controls/history_view_compose_controls.cpp | 9 ++++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index d3795d4e9..6a0f06df8 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -4329,12 +4329,14 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) { } void HistoryWidget::updateOverStates(QPoint pos) { + const auto isReadyToForward = readyToForward(); + const auto skip = isReadyToForward ? 0 : st::historyReplySkip; const auto replyEditForwardInfoRect = QRect( - st::historyReplySkip, + skip, _field->y() - st::historySendPadding - st::historyReplyHeight, - width() - st::historyReplySkip - _fieldBarCancel->width(), + width() - skip - _fieldBarCancel->width(), st::historyReplyHeight); - auto inReplyEditForward = (_editMsgId || replyToId() || readyToForward()) + auto inReplyEditForward = (_editMsgId || replyToId() || isReadyToForward) && replyEditForwardInfoRect.contains(pos); auto inPhotoEdit = inReplyEditForward && _photoEditMedia @@ -6170,16 +6172,19 @@ bool HistoryWidget::cornerButtonsHas(HistoryView::CornerButtonType type) { } void HistoryWidget::mousePressEvent(QMouseEvent *e) { + const auto isReadyToForward = readyToForward(); const auto hasSecondLayer = (_editMsgId || _replyToId - || readyToForward() + || isReadyToForward || _kbReplyTo); _replyForwardPressed = hasSecondLayer && QRect( 0, _field->y() - st::historySendPadding - st::historyReplyHeight, st::historyReplySkip, st::historyReplyHeight).contains(e->pos()); - if (_replyForwardPressed && !_fieldBarCancel->isHidden()) { + if (_replyForwardPressed + && !_fieldBarCancel->isHidden() + && !isReadyToForward) { updateField(); } else if (_inPhotoEdit && _photoEditMedia) { EditCaptionBox::StartPhotoEdit( @@ -6189,7 +6194,7 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) { _field->getTextWithTags(), crl::guard(_list, [=] { cancelEdit(); })); } else if (_inReplyEditForward) { - if (readyToForward()) { + if (isReadyToForward) { _forwardPanel->editOptions(controller()->uiShow()); } else { controller()->showPeerHistory( diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 22bccf2b6..cb1affa57 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -612,7 +612,7 @@ void FieldHeader::init() { const auto isLeftIcon = (pos.x() < st::historyReplySkip); const auto isLeftButton = (e->button() == Qt::LeftButton); if (type == QEvent::MouseButtonPress) { - if (isLeftButton && isLeftIcon) { + if (isLeftButton && isLeftIcon && !inPreviewRect) { *leftIconPressed = true; update(); } else if (isLeftButton && inPhotoEdit) { @@ -966,11 +966,13 @@ MsgId FieldHeader::getDraftMessageId() const { } void FieldHeader::updateControlsGeometry(QSize size) { + const auto isReadyToForward = readyToForward(); + const auto skip = isReadyToForward ? 0 : st::historyReplySkip; _cancel->moveToRight(0, 0); _clickableRect = QRect( - st::historyReplySkip, + skip, 0, - width() - st::historyReplySkip - _cancel->width(), + width() - skip - _cancel->width(), height()); _shownMessagePreviewRect = QRect( st::historyReplySkip, @@ -1000,6 +1002,7 @@ void FieldHeader::updateForwarding( if (readyToForward()) { replyToMessage({}); } + updateControlsGeometry(size()); } rpl::producer FieldHeader::editMsgIdValue() const { From 90adc2d97cfe44d9689f96487d039ffd1413f2a1 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 5 Sep 2023 12:21:26 +0300 Subject: [PATCH 028/155] Fixed misaligned line in expanded reaction menu with disabled animation. Fixed #26748. --- .../history_view_reactions_selector.cpp | 61 +++++++++++-------- .../history_view_reactions_selector.h | 7 ++- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp index c07fc9269..13570306b 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp @@ -424,7 +424,8 @@ void Selector::paintCollapsed(QPainter &p) { } void Selector::paintExpanding(Painter &p, float64 progress) { - const auto rects = paintExpandingBg(p, progress); + const auto rects = updateExpandingRects(progress); + paintExpandingBg(p, rects); progress /= kFullDuration; if (_footer) { _footer->paintExpanding( @@ -443,8 +444,7 @@ void Selector::paintExpanding(Painter &p, float64 progress) { paintFadingExpandIcon(p, progress); } -auto Selector::paintExpandingBg(QPainter &p, float64 progress) --> ExpandingRects { +Selector::ExpandingRects Selector::updateExpandingRects(float64 progress) { progress = (progress >= kExpandDuration) ? 1. : (progress / kExpandDuration); @@ -463,22 +463,6 @@ auto Selector::paintExpandingBg(QPainter &p, float64 progress) (height() - _outer.y() - _outer.height()), expanding); const auto outer = _outer.marginsAdded({ 0, expandUp, 0, expandDown }); - if (_useTransparency) { - const auto pattern = _cachedRound.validateFrame(frame, 1., radius); - const auto fill = _cachedRound.FillWithImage(p, outer, pattern); - if (!fill.isEmpty()) { - p.fillRect(fill, _st.bg); - } - } else { - const auto inner = outer.marginsRemoved(marginsForShadow()); - p.fillRect(inner, _st.bg); - p.fillRect( - inner.x(), - inner.y() + inner.height(), - inner.width(), - st::lineWidth, - st::defaultPopupMenu.shadow.fallback); - } const auto categories = anim::interpolate( 0, extendTopForCategories(), @@ -495,9 +479,26 @@ auto Selector::paintExpandingBg(QPainter &p, float64 progress) .radius = radius, .expanding = expanding, .finalBottom = height() - margins.bottom(), + .frame = frame, + .outer = outer, }; } +void Selector::paintExpandingBg(QPainter &p, const ExpandingRects &rects) { + if (_useTransparency) { + const auto pattern = _cachedRound.validateFrame( + rects.frame, + 1., + rects.radius); + const auto fill = _cachedRound.FillWithImage(p, rects.outer, pattern); + if (!fill.isEmpty()) { + p.fillRect(fill, _st.bg); + } + } else { + paintNonTransparentExpandRect(p, rects.outer - marginsForShadow()); + } +} + void Selector::paintFadingExpandIcon(QPainter &p, float64 progress) { if (progress >= 1.) { return; @@ -514,6 +515,18 @@ void Selector::paintFadingExpandIcon(QPainter &p, float64 progress) { p.setOpacity(1.); } +void Selector::paintNonTransparentExpandRect( + QPainter &p, + const QRect &inner) const { + p.fillRect(inner, _st.bg); + p.fillRect( + inner.x(), + inner.y() + inner.height(), + inner.width(), + st::lineWidth, + st::defaultPopupMenu.shadow.fallback); +} + void Selector::paintExpanded(QPainter &p) { if (!_expandFinished) { finishExpand(); @@ -521,14 +534,7 @@ void Selector::paintExpanded(QPainter &p) { if (_useTransparency) { p.drawImage(0, 0, _paintBuffer); } else { - const auto inner = rect().marginsRemoved(marginsForShadow()); - p.fillRect(inner, _st.bg); - p.fillRect( - inner.x(), - inner.y() + inner.height(), - inner.width(), - st::lineWidth, - st::defaultPopupMenu.shadow.fallback); + paintNonTransparentExpandRect(p, rect() - marginsForShadow()); } } @@ -536,6 +542,7 @@ void Selector::finishExpand() { Expects(!_expandFinished); _expandFinished = true; + updateExpandingRects(kExpandDuration); if (_useTransparency) { auto q = QPainter(&_paintBuffer); q.setCompositionMode(QPainter::CompositionMode_Source); diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.h b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.h index bf9ddb72b..f6b773dcd 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.h +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.h @@ -95,6 +95,8 @@ private: float64 radius = 0.; float64 expanding = 0.; int finalBottom = 0; + int frame = 0; + QRect outer; }; Selector( @@ -117,12 +119,15 @@ private: void paintAppearing(QPainter &p); void paintCollapsed(QPainter &p); void paintExpanding(Painter &p, float64 progress); - ExpandingRects paintExpandingBg(QPainter &p, float64 progress); + void paintExpandingBg(QPainter &p, const ExpandingRects &rects); void paintFadingExpandIcon(QPainter &p, float64 progress); void paintExpanded(QPainter &p); + void paintNonTransparentExpandRect(QPainter &p, const QRect &) const; void paintBubble(QPainter &p, int innerWidth); void paintBackgroundToBuffer(); + ExpandingRects updateExpandingRects(float64 progress); + [[nodiscard]] int recentCount() const; [[nodiscard]] int countSkipLeft() const; [[nodiscard]] int lookupSelectedIndex(QPoint position) const; From ed345e0823a1744ffdee9e49718f6b51987995c9 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 6 Sep 2023 13:26:36 +0300 Subject: [PATCH 029/155] Allowed to select loaded documents for bulk download menu item. --- .../SourceFiles/menu/menu_item_download_files.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/menu/menu_item_download_files.cpp b/Telegram/SourceFiles/menu/menu_item_download_files.cpp index 3c4573e80..1735e8041 100644 --- a/Telegram/SourceFiles/menu/menu_item_download_files.cpp +++ b/Telegram/SourceFiles/menu/menu_item_download_files.cpp @@ -34,8 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Menu { namespace { -using DocumentViewPtr = std::shared_ptr; -using Documents = std::vector>; +using Documents = std::vector, FullMsgId>>; using Photos = std::vector>; [[nodiscard]] bool Added( @@ -52,12 +51,8 @@ using Photos = std::vector>; } } } else if (const auto document = media->document()) { - if (const auto view = document->activeMediaView()) { - if (!view->loaded()) { - documents.emplace_back(view, item->fullId()); - return true; - } - } + documents.emplace_back(document, item->fullId()); + return true; } } } @@ -131,9 +126,7 @@ void AddAction( } }; const auto saveDocuments = [=](const QString &folderPath) { - for (const auto &pair : documents) { - const auto &document = pair.first->owner(); - const auto &origin = pair.second; + for (const auto &[document, origin] : documents) { if (!folderPath.isEmpty()) { document->save(origin, folderPath + document->filename()); } else { From 1b5b9f46d2152ad837c8013ccfedb74c56fd3313 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 6 Sep 2023 13:31:14 +0300 Subject: [PATCH 030/155] Allowed to save not loaded photos from bulk download menu item. --- .../menu/menu_item_download_files.cpp | 105 ++++++++++++------ 1 file changed, 69 insertions(+), 36 deletions(-) diff --git a/Telegram/SourceFiles/menu/menu_item_download_files.cpp b/Telegram/SourceFiles/menu/menu_item_download_files.cpp index 1735e8041..23f6c2525 100644 --- a/Telegram/SourceFiles/menu/menu_item_download_files.cpp +++ b/Telegram/SourceFiles/menu/menu_item_download_files.cpp @@ -35,7 +35,7 @@ namespace Menu { namespace { using Documents = std::vector, FullMsgId>>; -using Photos = std::vector>; +using Photos = std::vector, FullMsgId>>; [[nodiscard]] bool Added( HistoryItem *item, @@ -44,12 +44,8 @@ using Photos = std::vector>; if (item && !item->forbidsForward()) { if (const auto media = item->media()) { if (const auto photo = media->photo()) { - if (const auto view = photo->activeMediaView()) { - if (view->loaded()) { - photos.push_back(view); - return true; - } - } + photos.emplace_back(photo, item->fullId()); + return true; } else if (const auto document = media->document()) { documents.emplace_back(document, item->fullId()); return true; @@ -71,7 +67,7 @@ void AddAction( const auto icon = documents.empty() ? &st::menuIconSaveImage : &st::menuIconDownload; - const auto showToast = documents.empty(); + const auto shouldShowToast = documents.empty(); const auto weak = base::make_weak(controller); const auto saveImages = [=](const QString &folderPath) { @@ -91,38 +87,75 @@ void AddAction( if (path.isEmpty()) { return; } - QDir().mkpath(path); - const auto fullPath = [&](int i) { - return filedialogDefaultName( - u"photo_"_q + QString::number(i), - u".jpg"_q, - path); - }; - auto lastPath = QString(); - for (auto i = 0; i < photos.size(); i++) { - lastPath = fullPath(i + 1); - photos[i]->saveToFile(lastPath); + + const auto showToast = !shouldShowToast + ? Fn(nullptr) + : [=](const QString &lastPath) { + const auto filter = [lastPath](const auto ...) { + File::ShowInFolder(lastPath); + return false; + }; + controller->showToast({ + .text = (photos.size() > 1 + ? tr::lng_mediaview_saved_images_to + : tr::lng_mediaview_saved_to)( + tr::now, + lt_downloads, + Ui::Text::Link( + tr::lng_mediaview_downloads(tr::now), + "internal:show_saved_message"), + Ui::Text::WithEntities), + .st = &st::defaultToast, + .filter = filter, + }); + }; + + auto views = std::vector>(); + for (const auto &[photo, fullId] : photos) { + if (const auto view = photo->createMediaView()) { + view->wanted(Data::PhotoSize::Large, fullId); + views.push_back(view); + } } - if (showToast) { - const auto filter = [lastPath](const auto ...) { - File::ShowInFolder(lastPath); - return false; + const auto finalCheck = [=] { + for (const auto &[photo, _] : photos) { + if (photo->loading()) { + return false; + } + } + return true; + }; + + const auto saveToFiles = [=] { + const auto fullPath = [&](int i) { + return filedialogDefaultName( + u"photo_"_q + QString::number(i), + u".jpg"_q, + path); }; - controller->showToast({ - .text = (photos.size() > 1 - ? tr::lng_mediaview_saved_images_to - : tr::lng_mediaview_saved_to)( - tr::now, - lt_downloads, - Ui::Text::Link( - tr::lng_mediaview_downloads(tr::now), - "internal:show_saved_message"), - Ui::Text::WithEntities), - .st = &st::defaultToast, - .filter = filter, - }); + auto lastPath = QString(); + for (auto i = 0; i < views.size(); i++) { + lastPath = fullPath(i + 1); + views[i]->saveToFile(lastPath); + } + if (showToast) { + showToast(lastPath); + } + }; + + if (finalCheck()) { + saveToFiles(); + } else { + auto lifetime = std::make_shared(); + session->downloaderTaskFinished( + ) | rpl::start_with_next([=]() mutable { + if (finalCheck()) { + saveToFiles(); + base::take(lifetime)->destroy(); + } + }, *lifetime); } }; const auto saveDocuments = [=](const QString &folderPath) { From d2bd1091695dbd16af192f8c9f4e693a346d3af3 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 6 Sep 2023 14:24:32 +0300 Subject: [PATCH 031/155] Removed uppercase from some phrases in theme editor. --- .../SourceFiles/media/view/media_view_overlay_widget.cpp | 4 ++++ Telegram/SourceFiles/window/themes/window_theme_editor.cpp | 5 ++++- .../SourceFiles/window/themes/window_theme_editor_box.cpp | 2 +- Telegram/SourceFiles/window/themes/window_theme_preview.cpp | 6 ++---- Telegram/SourceFiles/window/themes/window_theme_warning.cpp | 3 +++ 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 59ed41e35..3a142408f 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -3921,10 +3921,12 @@ void OverlayWidget::initThemePreview() { _themePreviewId = 0; _themePreview = std::move(result); if (_themePreview) { + using TextTransform = Ui::RoundButton::TextTransform; _themeApply.create( _body, tr::lng_theme_preview_apply(), st::themePreviewApplyButton); + _themeApply->setTextTransform(TextTransform::NoTransform); _themeApply->show(); _themeApply->setClickedCallback([=] { const auto &object = Background()->themeObject(); @@ -3941,6 +3943,7 @@ void OverlayWidget::initThemePreview() { _body, tr::lng_cancel(), st::themePreviewCancelButton); + _themeCancel->setTextTransform(TextTransform::NoTransform); _themeCancel->show(); _themeCancel->setClickedCallback([this] { close(); }); if (const auto slug = _themeCloudData.slug; !slug.isEmpty()) { @@ -3948,6 +3951,7 @@ void OverlayWidget::initThemePreview() { _body, tr::lng_theme_share(), st::themePreviewCancelButton); + _themeShare->setTextTransform(TextTransform::NoTransform); _themeShare->show(); _themeShare->setClickedCallback([=] { QGuiApplication::clipboard()->setText( diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp index 613006078..e7baf9c61 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp @@ -672,7 +672,10 @@ Editor::Editor( , _select(this, st::defaultMultiSelect, tr::lng_country_ph()) , _leftShadow(this) , _topShadow(this) -, _save(this, tr::lng_theme_editor_save_button(tr::now).toUpper(), st::dialogsUpdateButton) { +, _save( + this, + tr::lng_theme_editor_save_button(tr::now), + st::dialogsUpdateButton) { const auto path = EditingPalettePath(); _inner = _scroll->setOwnedWidget(object_ptr(this, path)); diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp index b45e02b69..e92ee6ed5 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp @@ -692,7 +692,7 @@ void CreateForExistingBox( box->addRow( object_ptr( box, - tr::lng_theme_editor_import_existing() | Ui::Text::ToUpper(), + tr::lng_theme_editor_import_existing(), st::createThemeImportButton), style::margins( 0, diff --git a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp index 11878fd98..946649e12 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp @@ -12,14 +12,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/platform_window_title.h" #include "ui/text/text_options.h" #include "ui/text/text_utilities.h" -#include "ui/image/image_prepare.h" #include "ui/empty_userpic.h" #include "ui/emoji_config.h" #include "ui/painter.h" #include "ui/chat/chat_theme.h" #include "ui/chat/chat_style.h" #include "ui/chat/message_bubble.h" -#include "ui/image/image_prepare.h" #include "styles/style_widgets.h" #include "styles/style_window.h" #include "styles/style_media_view.h" @@ -32,7 +30,7 @@ namespace Window { namespace Theme { namespace { -QString fillLetters(const QString &name) { +[[nodiscard]] QString FillLetters(const QString &name) { QList letters; QList levels; auto level = 0; @@ -237,7 +235,7 @@ void Generator::addRow( Row row; row.name.setText(st::msgNameStyle, name, Ui::NameTextOptions()); - row.letters = fillLetters(name); + row.letters = FillLetters(name); row.peerIndex = peerIndex; row.date = date; diff --git a/Telegram/SourceFiles/window/themes/window_theme_warning.cpp b/Telegram/SourceFiles/window/themes/window_theme_warning.cpp index 3b0624f0a..8323de02d 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_warning.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_warning.cpp @@ -31,7 +31,10 @@ WarningWidget::WarningWidget(QWidget *parent) , _secondsLeft(kWaitBeforeRevertMs / 1000) , _keepChanges(this, tr::lng_theme_keep_changes(), st::defaultBoxButton) , _revert(this, tr::lng_theme_revert(), st::defaultBoxButton) { + using TextTransform = Ui::RoundButton::TextTransform; + _keepChanges->setTextTransform(TextTransform::NoTransform); _keepChanges->setClickedCallback([] { KeepApplied(); }); + _revert->setTextTransform(TextTransform::NoTransform); _revert->setClickedCallback([] { Revert(); }); updateText(); } From fd79973509458adfef5c26582fe66c1c48cc2110 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 6 Sep 2023 14:10:23 +0300 Subject: [PATCH 032/155] Fixed crash when importing custom theme with duplicated entries. --- .../window/themes/window_theme_editor_block.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp index 24a4b8e7d..ac217b30b 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp @@ -225,6 +225,10 @@ void EditorBlock::feed(const QString &name, QColor value, const QString ©OfE bool EditorBlock::feedCopy(const QString &name, const QString ©Of) { if (auto row = findRow(copyOf)) { + if (copyOf == name) { + LOG(("Theme Warning: Skipping value '%1: %2' (the value refers to itself.)").arg(name, copyOf)); + return true; + } if (findRow(name)) { // Remove the existing row and mark all its copies as unique keys. LOG(("Theme Warning: Color value '%1' appears more than once in the color scheme.").arg(name)); @@ -232,6 +236,10 @@ bool EditorBlock::feedCopy(const QString &name, const QString ©Of) { // row was invalidated by removeRow() call. row = findRow(copyOf); + // Should not happen, but still check. + if (!row) { + return true; + } } addRow(name, copyOf, row->value()); } else { From d4ad5d9f133982cb36baf8f60ab404e65199ad1c Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 7 Sep 2023 01:36:14 +0300 Subject: [PATCH 033/155] Removed uppercase from some phrases in export. --- Telegram/SourceFiles/export/view/export_view_progress.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/export/view/export_view_progress.cpp b/Telegram/SourceFiles/export/view/export_view_progress.cpp index f75780395..5b946428b 100644 --- a/Telegram/SourceFiles/export/view/export_view_progress.cpp +++ b/Telegram/SourceFiles/export/view/export_view_progress.cpp @@ -296,6 +296,7 @@ rpl::producer<> ProgressWidget::doneClicks() const { } void ProgressWidget::setupBottomButton(not_null button) { + button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); button->show(); sizeValue( @@ -361,7 +362,7 @@ void ProgressWidget::showDone() { tr::lng_export_done(), st::exportDoneButton); const auto desired = std::min( - st::exportDoneButton.font->width(tr::lng_export_done(tr::now).toUpper()) + st::exportDoneButton.font->width(tr::lng_export_done(tr::now)) + st::exportDoneButton.height - st::exportDoneButton.font->height, st::exportPanelSize.width() - 2 * st::exportCancelBottom); From ca30c35c2bc12f7c2a6acc02da3d38e5365f1453 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 7 Sep 2023 01:36:57 +0300 Subject: [PATCH 034/155] Added initial export writer for both html and json formats. --- .../export/output/export_output_abstract.h | 1 + .../output/export_output_html_and_json.cpp | 148 ++++++++++++++++++ .../output/export_output_html_and_json.h | 65 ++++++++ Telegram/cmake/td_export.cmake | 2 + 4 files changed, 216 insertions(+) create mode 100644 Telegram/SourceFiles/export/output/export_output_html_and_json.cpp create mode 100644 Telegram/SourceFiles/export/output/export_output_html_and_json.h diff --git a/Telegram/SourceFiles/export/output/export_output_abstract.h b/Telegram/SourceFiles/export/output/export_output_abstract.h index 7a2bb65ea..9ceef46eb 100644 --- a/Telegram/SourceFiles/export/output/export_output_abstract.h +++ b/Telegram/SourceFiles/export/output/export_output_abstract.h @@ -37,6 +37,7 @@ class Stats; enum class Format { Html, Json, + HtmlAndJson, }; class AbstractWriter { diff --git a/Telegram/SourceFiles/export/output/export_output_html_and_json.cpp b/Telegram/SourceFiles/export/output/export_output_html_and_json.cpp new file mode 100644 index 000000000..9220147ea --- /dev/null +++ b/Telegram/SourceFiles/export/output/export_output_html_and_json.cpp @@ -0,0 +1,148 @@ +/* +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 "export/output/export_output_html_and_json.h" + +#include "export/output/export_output_html.h" +#include "export/output/export_output_json.h" +#include "export/output/export_output_result.h" + +namespace Export::Output { + +HtmlAndJsonWriter::HtmlAndJsonWriter() { + _writers.push_back(CreateWriter(Format::Html)); + _writers.push_back(CreateWriter(Format::Json)); +} + +Format HtmlAndJsonWriter::format() { + return Format::HtmlAndJson; +} + +Result HtmlAndJsonWriter::start( + const Settings &settings, + const Environment &environment, + Stats *stats) { + return invoke([&](WriterPtr w) { + return w->start(settings, environment, stats); + }); +} + +Result HtmlAndJsonWriter::writePersonal(const Data::PersonalInfo &data) { + return invoke([&](WriterPtr w) { + return w->writePersonal(data); + }); +} + +Result HtmlAndJsonWriter::writeUserpicsStart(const Data::UserpicsInfo &data) { + return invoke([&](WriterPtr w) { + return w->writeUserpicsStart(data); + }); +} + +Result HtmlAndJsonWriter::writeUserpicsSlice(const Data::UserpicsSlice &d) { + return invoke([&](WriterPtr w) { + return w->writeUserpicsSlice(d); + }); +} + +Result HtmlAndJsonWriter::writeUserpicsEnd() { + return invoke([&](WriterPtr w) { + return w->writeUserpicsEnd(); + }); +} + +Result HtmlAndJsonWriter::writeStoriesStart(const Data::StoriesInfo &data) { + return invoke([&](WriterPtr w) { + return w->writeStoriesStart(data); + }); +} + +Result HtmlAndJsonWriter::writeStoriesSlice(const Data::StoriesSlice &data) { + return invoke([&](WriterPtr w) { + return w->writeStoriesSlice(data); + }); +} + +Result HtmlAndJsonWriter::writeStoriesEnd() { + return invoke([&](WriterPtr w) { + return w->writeStoriesEnd(); + }); +} + +Result HtmlAndJsonWriter::writeContactsList(const Data::ContactsList &data) { + return invoke([&](WriterPtr w) { + return w->writeContactsList(data); + }); +} + +Result HtmlAndJsonWriter::writeSessionsList(const Data::SessionsList &data) { + return invoke([&](WriterPtr w) { + return w->writeSessionsList(data); + }); +} + +Result HtmlAndJsonWriter::writeOtherData(const Data::File &data) { + return invoke([&](WriterPtr w) { + return w->writeOtherData(data); + }); +} + +Result HtmlAndJsonWriter::writeDialogsStart(const Data::DialogsInfo &data) { + return invoke([&](WriterPtr w) { + return w->writeDialogsStart(data); + }); +} + +Result HtmlAndJsonWriter::writeDialogStart(const Data::DialogInfo &data) { + return invoke([&](WriterPtr w) { + return w->writeDialogStart(data); + }); +} + +Result HtmlAndJsonWriter::writeDialogSlice(const Data::MessagesSlice &data) { + return invoke([&](WriterPtr w) { + return w->writeDialogSlice(data); + }); +} + +Result HtmlAndJsonWriter::writeDialogEnd() { + return invoke([&](WriterPtr w) { + return w->writeDialogEnd(); + }); +} + +Result HtmlAndJsonWriter::writeDialogsEnd() { + return invoke([&](WriterPtr w) { + return w->writeDialogsEnd(); + }); +} + +Result HtmlAndJsonWriter::finish() { + return invoke([&](WriterPtr w) { + return w->finish(); + }); +} + +QString HtmlAndJsonWriter::mainFilePath() { + return _writers.front()->mainFilePath(); +} + +HtmlAndJsonWriter::~HtmlAndJsonWriter() = default; + +Result HtmlAndJsonWriter::invoke(Fn method) const { + auto result = Result(Result::Type::Success, QString()); + for (const auto &writer : _writers) { + const auto current = method(writer); + if (!current) { + result = current; + } + } + return result; +} + +} // namespace Export::Output + diff --git a/Telegram/SourceFiles/export/output/export_output_html_and_json.h b/Telegram/SourceFiles/export/output/export_output_html_and_json.h new file mode 100644 index 000000000..2a40833a8 --- /dev/null +++ b/Telegram/SourceFiles/export/output/export_output_html_and_json.h @@ -0,0 +1,65 @@ +/* +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 "export/output/export_output_abstract.h" + +namespace Export::Output { + +class HtmlWriter; +class JsonWriter; +struct Result; + +class HtmlAndJsonWriter final : public AbstractWriter { +public: + HtmlAndJsonWriter(); + + Format format() override; + + Result start( + const Settings &settings, + const Environment &environment, + Stats *stats) override; + + Result writePersonal(const Data::PersonalInfo &data) override; + + Result writeUserpicsStart(const Data::UserpicsInfo &data) override; + Result writeUserpicsSlice(const Data::UserpicsSlice &data) override; + Result writeUserpicsEnd() override; + + Result writeStoriesStart(const Data::StoriesInfo &data) override; + Result writeStoriesSlice(const Data::StoriesSlice &data) override; + Result writeStoriesEnd() override; + + Result writeContactsList(const Data::ContactsList &data) override; + + Result writeSessionsList(const Data::SessionsList &data) override; + + Result writeOtherData(const Data::File &data) override; + + Result writeDialogsStart(const Data::DialogsInfo &data) override; + Result writeDialogStart(const Data::DialogInfo &data) override; + Result writeDialogSlice(const Data::MessagesSlice &data) override; + Result writeDialogEnd() override; + Result writeDialogsEnd() override; + + Result finish() override; + + QString mainFilePath() override; + + ~HtmlAndJsonWriter(); + +private: + using WriterPtr = const std::unique_ptr &; + Result invoke(Fn method) const; + + std::vector> _writers; + +}; + +} // namespace Export::Output diff --git a/Telegram/cmake/td_export.cmake b/Telegram/cmake/td_export.cmake index 097926b9f..c187e6543 100644 --- a/Telegram/cmake/td_export.cmake +++ b/Telegram/cmake/td_export.cmake @@ -26,6 +26,8 @@ PRIVATE export/output/export_output_file.h export/output/export_output_html.cpp export/output/export_output_html.h + export/output/export_output_html_and_json.cpp + export/output/export_output_html_and_json.h export/output/export_output_json.cpp export/output/export_output_json.h export/output/export_output_result.h From 29bfe4338629be950e0dd32f5a77d00771fca4ea Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 7 Sep 2023 01:53:42 +0300 Subject: [PATCH 035/155] Added ability to export chat for html and json formats simultaneously. --- Telegram/Resources/langs/lang.strings | 1 + .../SourceFiles/export/output/export_output_abstract.cpp | 2 ++ .../SourceFiles/export/view/export_view_settings.cpp | 9 ++++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4b314e4e9..d677c6b40 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3559,6 +3559,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_export_option_choose_format" = "Choose export format"; "lng_export_option_html" = "Human-readable HTML"; "lng_export_option_json" = "Machine-readable JSON"; +"lng_export_option_html_and_json" = "Both"; "lng_export_limits" = "From: {from}, to: {till}"; "lng_export_beginning" = "the oldest message"; "lng_export_end" = "present"; diff --git a/Telegram/SourceFiles/export/output/export_output_abstract.cpp b/Telegram/SourceFiles/export/output/export_output_abstract.cpp index f9df0d1f7..dbdb1bf99 100644 --- a/Telegram/SourceFiles/export/output/export_output_abstract.cpp +++ b/Telegram/SourceFiles/export/output/export_output_abstract.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "export/output/export_output_abstract.h" +#include "export/output/export_output_html_and_json.h" #include "export/output/export_output_html.h" #include "export/output/export_output_json.h" #include "export/output/export_output_stats.h" @@ -50,6 +51,7 @@ std::unique_ptr CreateWriter(Format format) { switch (format) { case Format::Html: return std::make_unique(); case Format::Json: return std::make_unique(); + case Format::HtmlAndJson: return std::make_unique(); } Unexpected("Format in Export::Output::CreateWriter."); } diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index 94e00b43a..bbc91c2dc 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -75,6 +75,9 @@ void ChooseFormatBox( box->setTitle(tr::lng_export_option_choose_format()); addFormatOption(tr::lng_export_option_html(tr::now), Format::Html); addFormatOption(tr::lng_export_option_json(tr::now), Format::Json); + addFormatOption( + tr::lng_export_option_html_and_json(tr::now), + Format::HtmlAndJson); box->addButton(tr::lng_settings_save(), [=] { done(group->value()); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } @@ -347,7 +350,11 @@ void SettingsWidget::addFormatAndLocationLabel( return data.format; }) | rpl::distinct_until_changed( ) | rpl::map([](Format format) { - const auto text = (format == Format::Html) ? "HTML" : "JSON"; + const auto text = (format == Format::Html) + ? "HTML" + : (format == Format::Json) + ? "JSON" + : tr::lng_export_option_html_and_json(tr::now); return Ui::Text::Link(text, u"internal:edit_format"_q); }); const auto label = container->add( From adbe5e9605af1a6b79c14498939d5dc5e59bb297 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 7 Sep 2023 12:29:55 +0300 Subject: [PATCH 036/155] Slightly improved style of mini icons in dialogs list. --- Telegram/SourceFiles/dialogs/dialogs.style | 1 + Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index 854faef97..729ef0662 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -468,6 +468,7 @@ dialogsMiniForwardIcon: ThreeStateIcon { active: icon {{ "mini_forward", dialogsTextFgActive, point(0px, 1px) }}; } dialogsMiniIconSkip: 2px; +dialogsMiniIconTextSkip: 1px; dialogsMiniReplyStoryIcon: ThreeStateIcon { icon: icon {{ "mini_reply_story", dialogsTextFg, point(0px, 1px) }}; over: icon {{ "mini_reply_story", dialogsTextFgOver, point(0px, 1px) }}; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp index 6f4700f2c..ca23562cb 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp @@ -316,7 +316,7 @@ void MessageView::paint( .elisionLines = lines, }); rect.setLeft(rect.x() + _senderCache.maxWidth()); - if (!_imagesCache.empty()) { + if (!_imagesCache.empty() && !_leftIcon) { const auto skip = st::dialogsMiniPreviewSkip + st::dialogsMiniPreviewRight; rect.setLeft(rect.x() + skip); @@ -339,7 +339,11 @@ void MessageView::paint( } else { icon.paint(p, rect.topLeft(), rect.width()); } - rect.setLeft(rect.x() + w + st::dialogsMiniIconSkip); + rect.setLeft(rect.x() + + w + + (_imagesCache.empty() + ? st::dialogsMiniIconTextSkip + : st::dialogsMiniIconSkip)); } } for (const auto &image : _imagesCache) { From 55fb3405e54118f7bce2799119b1a17c52054277 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 11 Sep 2023 08:06:12 +0400 Subject: [PATCH 037/155] Move feature warnings to the relevant code --- .../SourceFiles/platform/linux/specific_linux.cpp | 12 ------------ Telegram/lib_lottie | 2 +- Telegram/lib_ui | 2 +- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index b7834a48a..7fa797724 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -617,18 +617,6 @@ void start() { Glib::init(); Gio::init(); -#ifdef DESKTOP_APP_USE_PACKAGED_RLOTTIE - g_warning( - "Application has been built with foreign rlottie, " - "animated emojis won't be colored to the selected pack."); -#endif // DESKTOP_APP_USE_PACKAGED_RLOTTIE - -#ifdef DESKTOP_APP_USE_PACKAGED_FONTS - g_warning( - "Application was built without embedded fonts, " - "this may lead to font issues."); -#endif // DESKTOP_APP_USE_PACKAGED_FONTS - Webview::WebKitGTK::SetSocketPath(u"%1/%2-%3-webview-%4"_q.arg( QDir::tempPath(), h, diff --git a/Telegram/lib_lottie b/Telegram/lib_lottie index 3e9c2f102..e240a2de8 160000 --- a/Telegram/lib_lottie +++ b/Telegram/lib_lottie @@ -1 +1 @@ -Subproject commit 3e9c2f1026e4b5aa3202fca4cc67ece36c7cebb2 +Subproject commit e240a2de8e67c806894caf04ee32797e75c6ea38 diff --git a/Telegram/lib_ui b/Telegram/lib_ui index b2293c86e..e24eaa6b3 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit b2293c86e12537941d98e464748a060760377914 +Subproject commit e24eaa6b32799119caa78caacd57216f81d3e1a7 From bf255c0e0043db6338b98d79c351a6e62d1aa18b Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 4 Sep 2023 00:30:48 +0400 Subject: [PATCH 038/155] Don't use crl::on_main unnecessarily in Linux native notifications code All those dbus methods call callbacks on the same thread --- .../linux/notifications_manager_linux.cpp | 255 +++++++++--------- 1 file changed, 127 insertions(+), 128 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 7448d690e..20c26143b 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -91,15 +91,12 @@ std::unique_ptr CreateServiceWatcher() { const Glib::ustring &service, const Glib::ustring &oldOwner, const Glib::ustring &newOwner) { - if (activatable && newOwner.empty()) { - crl::on_main([] { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + if (activatable && newOwner.empty()) { Core::App().notifications().clearAll(); - }); - return; - } - - crl::on_main([] { - Core::App().notifications().createManager(); + } else { + Core::App().notifications().createManager(); + } }); }); } catch (...) { @@ -117,33 +114,35 @@ void StartServiceAsync(Fn callback) { connection, kService, [=](Fn result) { - Noexcept([&] { - try { - result(); // get the error if any - } catch (const Glib::Error &e) { - static const auto NotSupportedErrors = { - "org.freedesktop.DBus.Error.ServiceUnknown", - }; + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + try { + result(); // get the error if any + } catch (const Glib::Error &e) { + static const auto NotSupportedErrors = { + "org.freedesktop.DBus.Error.ServiceUnknown", + }; - const auto errorName = - Gio::DBus::ErrorUtils::get_remote_error(e).raw(); + const auto errorName = + Gio::DBus::ErrorUtils::get_remote_error(e).raw(); - if (!ranges::contains( - NotSupportedErrors, - errorName)) { - throw e; + if (!ranges::contains( + NotSupportedErrors, + errorName)) { + throw e; + } } - } - }); + }); - crl::on_main(callback); + callback(); + }); }); return; } catch (...) { } - crl::on_main(callback); + callback(); } bool GetServiceRegistered() { @@ -191,26 +190,26 @@ void GetServerInformation( "GetServerInformation", {}, [=](const Glib::RefPtr &result) { - Noexcept([&] { - const auto reply = connection->call_finish(result); + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + const auto reply = connection->call_finish(result); - const auto name = reply.get_child( - 0 - ).get_dynamic(); + const auto name = reply.get_child( + 0 + ).get_dynamic(); - const auto vendor = reply.get_child( - 1 - ).get_dynamic(); + const auto vendor = reply.get_child( + 1 + ).get_dynamic(); - const auto version = reply.get_child( - 2 - ).get_dynamic(); + const auto version = reply.get_child( + 2 + ).get_dynamic(); - const auto specVersion = reply.get_child( - 3 - ).get_dynamic(); + const auto specVersion = reply.get_child( + 3 + ).get_dynamic(); - crl::on_main([=] { callback(ServerInformation{ QString::fromStdString(name), QString::fromStdString(vendor), @@ -219,14 +218,14 @@ void GetServerInformation( QVersionNumber::fromString( QString::fromStdString(specVersion)), }); + }, [&] { + callback(std::nullopt); }); - }, [&] { - crl::on_main([=] { callback(std::nullopt); }); }); }, kService); }, [&] { - crl::on_main([=] { callback(std::nullopt); }); + callback(std::nullopt); }); } @@ -241,25 +240,27 @@ void GetCapabilities(Fn callback) { "GetCapabilities", {}, [=](const Glib::RefPtr &result) { - Noexcept([&] { - QStringList value; - ranges::transform( - connection->call_finish( - result - ).get_child( - 0 - ).get_dynamic>(), - ranges::back_inserter(value), - QString::fromStdString); + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + QStringList value; + ranges::transform( + connection->call_finish( + result + ).get_child( + 0 + ).get_dynamic>(), + ranges::back_inserter(value), + QString::fromStdString); - crl::on_main([=] { callback(value); }); - }, [&] { - crl::on_main([=] { callback({}); }); + callback(value); + }, [&] { + callback({}); + }); }); }, kService); }, [&] { - crl::on_main([=] { callback({}); }); + callback({}); }); } @@ -277,22 +278,24 @@ void GetInhibited(Fn callback) { Glib::ustring("Inhibited"), }), [=](const Glib::RefPtr &result) { - Noexcept([&] { - const auto value = connection->call_finish( - result - ).get_child( - 0 - ).get_dynamic>( - ).get(); + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + const auto value = connection->call_finish( + result + ).get_child( + 0 + ).get_dynamic>( + ).get(); - crl::on_main([=] { callback(value); }); - }, [&] { - crl::on_main([=] { callback(false); }); + callback(value); + }, [&] { + callback(false); + }); }); }, kService); }, [&] { - crl::on_main([=] { callback(false); }); + callback(false); }); } @@ -465,49 +468,51 @@ bool NotificationData::init( const auto weak = base::make_weak(this); const auto capabilities = CurrentCapabilities; - const auto signalEmitted = [=]( + const auto signalEmitted = crl::guard(weak, [=]( const Glib::RefPtr &connection, const Glib::ustring &sender_name, const Glib::ustring &object_path, const Glib::ustring &interface_name, const Glib::ustring &signal_name, const Glib::VariantContainerBase ¶meters) { - Noexcept([&] { - if (signal_name == "ActionInvoked") { - const auto id = parameters.get_child(0).get_dynamic(); + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + if (signal_name == "ActionInvoked") { + const auto id = parameters.get_child(0).get_dynamic(); - const auto actionName = parameters.get_child( - 1 - ).get_dynamic(); + const auto actionName = parameters.get_child( + 1 + ).get_dynamic(); - crl::on_main(weak, [=] { actionInvoked(id, actionName); }); - } else if (signal_name == "ActivationToken") { - const auto id = parameters.get_child(0).get_dynamic(); + actionInvoked(id, actionName); + } else if (signal_name == "ActivationToken") { + const auto id = parameters.get_child(0).get_dynamic(); - const auto token = parameters.get_child( - 1 - ).get_dynamic(); + const auto token = parameters.get_child( + 1 + ).get_dynamic(); - crl::on_main(weak, [=] { activationToken(id, token); }); - } else if (signal_name == "NotificationReplied") { - const auto id = parameters.get_child(0).get_dynamic(); + activationToken(id, token); + } else if (signal_name == "NotificationReplied") { + const auto id = parameters.get_child(0).get_dynamic(); - const auto text = parameters.get_child( - 1 - ).get_dynamic(); + const auto text = parameters.get_child( + 1 + ).get_dynamic(); - crl::on_main(weak, [=] { notificationReplied(id, text); }); - } else if (signal_name == "NotificationClosed") { - const auto id = parameters.get_child(0).get_dynamic(); + notificationReplied(id, text); + } else if (signal_name == "NotificationClosed") { + const auto id = parameters.get_child(0).get_dynamic(); - const auto reason = parameters.get_child( - 1 - ).get_dynamic(); + const auto reason = parameters.get_child( + 1 + ).get_dynamic(); - crl::on_main(weak, [=] { notificationClosed(id, reason); }); - } + notificationClosed(id, reason); + } + }); }); - }; + }); _imageKey = GetImageKey(CurrentServerInformationValue().specVersion); @@ -652,23 +657,19 @@ void NotificationData::show() { _hints, -1, }), - [=](const Glib::RefPtr &result) { - Noexcept([&] { - const auto notificationId = connection->call_finish( - result - ).get_child( - 0 - ).get_dynamic(); - - crl::on_main(weak, [=] { - _notificationId = notificationId; - }); - }, [&] { - crl::on_main(weak, [=] { + crl::guard(weak, [=](const Glib::RefPtr &result) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + _notificationId = connection->call_finish( + result + ).get_child( + 0 + ).get_dynamic(); + }, [&] { _manager->clearNotification(_id); }); }); - }, + }), kService); })); } @@ -966,34 +967,32 @@ Manager::Private::Private(not_null manager) })); _inhibitedSignalId = _dbusConnection->signal_subscribe( - [=]( + crl::guard(weak, [=]( const Glib::RefPtr &connection, const Glib::ustring &sender_name, const Glib::ustring &object_path, const Glib::ustring &interface_name, const Glib::ustring &signal_name, const Glib::VariantContainerBase ¶meters) { - Noexcept([&] { - const auto interface = parameters.get_child( - 0 - ).get_dynamic(); + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + Noexcept([&] { + const auto interface = parameters.get_child( + 0 + ).get_dynamic(); - if (interface != kInterface) { - return; - } + if (interface != kInterface) { + return; + } - const auto inhibited = parameters.get_child( - 1 - ).get_dynamic>( - ).at( - "Inhibited" - ).get_dynamic(); - - crl::on_main(weak, [=] { - _inhibited = inhibited; + _inhibited = parameters.get_child( + 1 + ).get_dynamic>( + ).at( + "Inhibited" + ).get_dynamic(); }); }); - }, + }), kService, kPropertiesInterface, "PropertiesChanged", From e52e1672e8b09b87fac138f973e5c386f1490a3a Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sun, 3 Sep 2023 18:12:33 +0400 Subject: [PATCH 039/155] Make PortalAutostart asynchronous --- .../platform/linux/specific_linux.cpp | 203 ++++++++++-------- 1 file changed, 113 insertions(+), 90 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 7fa797724..a5902e2df 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "storage/localstorage.h" #include "core/launcher.h" +#include "core/sandbox.h" #include "core/core_settings.h" #include "core/update_checker.h" #include "webview/platform/linux/webview_linux_webkitgtk.h" @@ -52,115 +53,138 @@ using Platform::internal::WaylandIntegration; namespace Platform { namespace { -bool PortalAutostart(bool start, bool silent) { +void PortalAutostart(bool enabled, Fn done) { if (cExeName().isEmpty()) { - return false; + if (done) { + done(false); + } + return; } - auto error = false; - - try { - const auto connection = Gio::DBus::Connection::get_sync( - Gio::DBus::BusType::SESSION); - - const auto handleToken = Glib::ustring("tdesktop") - + std::to_string(base::RandomValue()); - - std::vector commandline; - commandline.push_back(cExeName().toStdString()); - if (Core::Launcher::Instance().customWorkingDir()) { - commandline.push_back("-workdir"); - commandline.push_back(cWorkingDir().toStdString()); + const auto connection = [&] { + try { + return Gio::DBus::Connection::get_sync( + Gio::DBus::BusType::SESSION); + } catch (const std::exception &e) { + if (done) { + LOG(("Portal Autostart Error: %1").arg( + QString::fromStdString(e.what()))); + } + return Glib::RefPtr(); } - commandline.push_back("-autostart"); + }(); - std::map options; - options["handle_token"] = Glib::create_variant(handleToken); - options["reason"] = Glib::create_variant( - Glib::ustring( - tr::lng_settings_auto_start(tr::now).toStdString())); - options["autostart"] = Glib::create_variant(start); - options["commandline"] = Glib::create_variant(commandline); - options["dbus-activatable"] = Glib::create_variant(false); + if (!connection) { + if (done) { + done(false); + } + return; + } - auto uniqueName = connection->get_unique_name(); - uniqueName.erase(0, 1); - uniqueName.replace(uniqueName.find('.'), 1, 1, '_'); + const auto handleToken = Glib::ustring("tdesktop") + + std::to_string(base::RandomValue()); - const auto requestPath = Glib::ustring( - "/org/freedesktop/portal/desktop/request/") - + uniqueName - + '/' - + handleToken; + std::vector commandline; + commandline.push_back(cExeName().toStdString()); + if (Core::Launcher::Instance().customWorkingDir()) { + commandline.push_back("-workdir"); + commandline.push_back(cWorkingDir().toStdString()); + } + commandline.push_back("-autostart"); - const auto loop = Glib::MainLoop::create(); + std::map options; + options["handle_token"] = Glib::create_variant(handleToken); + options["reason"] = Glib::create_variant( + Glib::ustring( + tr::lng_settings_auto_start(tr::now).toStdString())); + options["autostart"] = Glib::create_variant(enabled); + options["commandline"] = Glib::create_variant(commandline); + options["dbus-activatable"] = Glib::create_variant(false); + + auto uniqueName = connection->get_unique_name(); + uniqueName.erase(0, 1); + uniqueName.replace(uniqueName.find('.'), 1, 1, '_'); + + const auto requestPath = Glib::ustring( + "/org/freedesktop/portal/desktop/request/") + + uniqueName + + '/' + + handleToken; + + const auto window = std::make_shared(); + window->setAttribute(Qt::WA_DontShowOnScreen); + window->setWindowModality(Qt::ApplicationModal); + window->show(); + + const auto signalId = std::make_shared(); + *signalId = connection->signal_subscribe( + [=]( + const Glib::RefPtr &connection, + const Glib::ustring &sender_name, + const Glib::ustring &object_path, + const Glib::ustring &interface_name, + const Glib::ustring &signal_name, + const Glib::VariantContainerBase ¶meters) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + (void)window; // don't destroy until finish - const auto signalId = connection->signal_subscribe( - [&]( - const Glib::RefPtr &connection, - const Glib::ustring &sender_name, - const Glib::ustring &object_path, - const Glib::ustring &interface_name, - const Glib::ustring &signal_name, - const Glib::VariantContainerBase ¶meters) { try { const auto response = parameters.get_child( 0 ).get_dynamic(); if (response) { - if (!silent) { + if (done) { LOG(("Portal Autostart Error: Request denied")); + done(false); } - error = true; + } else if (done) { + done(enabled); } } catch (const std::exception &e) { - if (!silent) { + if (done) { LOG(("Portal Autostart Error: %1").arg( QString::fromStdString(e.what()))); + done(false); } - error = true; } - loop->quit(); - }, - base::Platform::XDP::kService, - base::Platform::XDP::kRequestInterface, - "Response", - requestPath); + if (*signalId) { + connection->signal_unsubscribe(*signalId); + } + }); + }, + base::Platform::XDP::kService, + base::Platform::XDP::kRequestInterface, + "Response", + requestPath); - const auto signalGuard = gsl::finally([&] { - if (signalId != 0) { - connection->signal_unsubscribe(signalId); - } - }); + connection->call( + base::Platform::XDP::kObjectPath, + "org.freedesktop.portal.Background", + "RequestBackground", + Glib::create_variant(std::tuple{ + base::Platform::XDP::ParentWindowID(), + options, + }), + [=](const Glib::RefPtr &result) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + try { + connection->call_finish(result); + } catch (const std::exception &e) { + if (done) { + LOG(("Portal Autostart Error: %1").arg( + QString::fromStdString(e.what()))); + done(false); + } - connection->call_sync( - base::Platform::XDP::kObjectPath, - "org.freedesktop.portal.Background", - "RequestBackground", - Glib::create_variant(std::tuple{ - base::Platform::XDP::ParentWindowID(), - options, - }), - base::Platform::XDP::kService); - - if (signalId != 0) { - QWidget window; - window.setAttribute(Qt::WA_DontShowOnScreen); - window.setWindowModality(Qt::ApplicationModal); - window.show(); - loop->run(); - } - } catch (const std::exception &e) { - if (!silent) { - LOG(("Portal Autostart Error: %1").arg( - QString::fromStdString(e.what()))); - } - error = true; - } - - return !error; + if (*signalId) { + connection->signal_unsubscribe(*signalId); + } + } + }); + }, + base::Platform::XDP::kService); } bool GenerateDesktopFile( @@ -457,13 +481,12 @@ bool AutostartSupported() { } void AutostartToggle(bool enabled, Fn done) { + if (KSandbox::isFlatpak()) { + PortalAutostart(enabled, done); + return; + } + const auto success = [&] { - const auto silent = !done; - - if (KSandbox::isFlatpak()) { - return PortalAutostart(enabled, silent); - } - const auto autostart = QStandardPaths::writableLocation( QStandardPaths::GenericConfigLocation) + u"/autostart/"_q; @@ -479,7 +502,7 @@ void AutostartToggle(bool enabled, Fn done) { autostart, { u"-autostart"_q }, true, - silent); + !done); }(); if (done) { From 566f2dd67033b09a16ab52a9e8a348bbb174b406 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 Sep 2023 00:19:09 +0400 Subject: [PATCH 040/155] Switch XDP open with dialog to QWaylandWindow::requestXdgActivationToken --- .../platform/linux/linux_xdp_open_with_dialog.cpp | 14 ++++---------- Telegram/lib_base | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp b/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp index a425ff59f..9d2cf048e 100644 --- a/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_xdp_open_with_dialog.cpp @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_xdp_utilities.h" -#include "base/platform/linux/base_linux_wayland_integration.h" +#include "base/platform/linux/base_linux_xdg_activation_token.h" #include "base/random.h" #include @@ -23,6 +23,7 @@ namespace { constexpr auto kXDPOpenURIInterface = "org.freedesktop.portal.OpenURI"; constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"; +const auto XdgActivationToken = base::Platform::XdgActivationToken; } // namespace @@ -61,14 +62,6 @@ bool ShowXDPOpenWithDialog(const QString &filepath) { const auto handleToken = Glib::ustring("tdesktop") + std::to_string(base::RandomValue()); - const auto activationToken = []() -> Glib::ustring { - using base::Platform::WaylandIntegration; - if (const auto integration = WaylandIntegration::Instance()) { - return integration->activationToken().toStdString(); - } - return {}; - }(); - auto uniqueName = connection->get_unique_name(); uniqueName.erase(0, 1); uniqueName.replace(uniqueName.find('.'), 1, 1, '_'); @@ -118,7 +111,8 @@ bool ShowXDPOpenWithDialog(const QString &filepath) { }, { "activation_token", - Glib::create_variant(activationToken) + Glib::create_variant( + Glib::ustring(XdgActivationToken().toStdString())) }, { "ask", diff --git a/Telegram/lib_base b/Telegram/lib_base index c36d961ea..a7c44bbf5 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit c36d961eaf3d3a09d100509196aa039958f264bc +Subproject commit a7c44bbf531b5e547c92b6fcdd48ca6cdd18b9d2 From 0bf0fb29d24af89bd33a8345c00d4a3d9584ba21 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 12 Sep 2023 03:59:11 +0400 Subject: [PATCH 041/155] Add nodiscard for a bunch of platform specific methods --- Telegram/SourceFiles/platform/platform_specific.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 604676615..460431e0d 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -32,8 +32,8 @@ enum class SystemSettingsType { }; void SetApplicationIcon(const QIcon &icon); -QString SingleInstanceLocalServerName(const QString &hash); -PermissionStatus GetPermissionStatus(PermissionType type); +[[nodiscard]] QString SingleInstanceLocalServerName(const QString &hash); +[[nodiscard]] PermissionStatus GetPermissionStatus(PermissionType type); void RequestPermission(PermissionType type, Fn resultCallback); void OpenSystemSettingsForPermission(PermissionType type); bool OpenSystemSettings(SystemSettingsType type); @@ -42,8 +42,8 @@ void IgnoreApplicationActivationRightNow(); void AutostartRequestStateFromSystem(Fn callback); void AutostartToggle(bool enabled, Fn done = nullptr); [[nodiscard]] bool AutostartSkip(); -bool TrayIconSupported(); -bool SkipTaskbarSupported(); +[[nodiscard]] bool TrayIconSupported(); +[[nodiscard]] bool SkipTaskbarSupported(); void WriteCrashDumpDetails(); void NewVersionLaunched(int oldVersion); [[nodiscard]] QImage DefaultApplicationIcon(); From e8a1fc0300f34f62618db5c63ded521fd19f7ae2 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 12 Sep 2023 03:56:08 +0400 Subject: [PATCH 042/155] Add a method to check whether to run in background instead of checking for macOS --- .../platform/linux/specific_linux.h | 4 ++ .../SourceFiles/platform/mac/specific_mac.h | 4 ++ .../SourceFiles/platform/platform_specific.h | 1 + .../SourceFiles/platform/win/specific_win.h | 4 ++ .../settings/settings_advanced.cpp | 41 ++++++++++--------- Telegram/SourceFiles/window/main_window.cpp | 4 +- 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index e5e40cd2e..92445a933 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -24,6 +24,10 @@ inline void WriteCrashDumpDetails() { inline void AutostartRequestStateFromSystem(Fn callback) { } +inline bool RunInBackground() { + return false; +} + inline bool PreventsQuit(Core::QuitReason reason) { return false; } diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index 12cc59024..187ceb7b1 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -31,6 +31,10 @@ inline bool SkipTaskbarSupported() { return false; } +inline bool RunInBackground() { + return true; +} + void ActivateThisProcess(); inline uint64 ActivationWindowId(not_null window) { diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 460431e0d..7db700e00 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -44,6 +44,7 @@ void AutostartToggle(bool enabled, Fn done = nullptr); [[nodiscard]] bool AutostartSkip(); [[nodiscard]] bool TrayIconSupported(); [[nodiscard]] bool SkipTaskbarSupported(); +[[nodiscard]] bool RunInBackground(); void WriteCrashDumpDetails(); void NewVersionLaunched(int oldVersion); [[nodiscard]] QImage DefaultApplicationIcon(); diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h index 0b0945dd5..acb2eda92 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.h +++ b/Telegram/SourceFiles/platform/win/specific_win.h @@ -27,6 +27,10 @@ inline bool SkipTaskbarSupported() { return true; } +inline bool RunInBackground() { + return false; +} + inline bool PreventsQuit(Core::QuitReason reason) { return false; } diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index 8ac221a4f..d95c71f78 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -550,28 +550,29 @@ void SetupSystemIntegrationContent( Core::App().saveSettings(); }, roundIcon->lifetime()); #endif // OS_MAC_STORE - -#else // Q_OS_MAC - const auto closeToTaskbar = addSlidingCheckbox( - tr::lng_settings_close_to_taskbar(), - Core::App().settings().closeToTaskbar()); - - const auto closeToTaskbarShown = std::make_shared>(false); - Core::App().settings().workModeValue( - ) | rpl::start_with_next([=](WorkMode workMode) { - *closeToTaskbarShown = !Core::App().tray().has(); - }, closeToTaskbar->lifetime()); - - closeToTaskbar->toggleOn(closeToTaskbarShown->value()); - closeToTaskbar->entity()->checkedChanges( - ) | rpl::filter([=](bool checked) { - return (checked != Core::App().settings().closeToTaskbar()); - }) | rpl::start_with_next([=](bool checked) { - Core::App().settings().setCloseToTaskbar(checked); - Local::writeSettings(); - }, closeToTaskbar->lifetime()); #endif // Q_OS_MAC + if (!Platform::RunInBackground()) { + const auto closeToTaskbar = addSlidingCheckbox( + tr::lng_settings_close_to_taskbar(), + Core::App().settings().closeToTaskbar()); + + const auto closeToTaskbarShown = std::make_shared>(false); + Core::App().settings().workModeValue( + ) | rpl::start_with_next([=](WorkMode workMode) { + *closeToTaskbarShown = !Core::App().tray().has(); + }, closeToTaskbar->lifetime()); + + closeToTaskbar->toggleOn(closeToTaskbarShown->value()); + closeToTaskbar->entity()->checkedChanges( + ) | rpl::filter([=](bool checked) { + return (checked != Core::App().settings().closeToTaskbar()); + }) | rpl::start_with_next([=](bool checked) { + Core::App().settings().setCloseToTaskbar(checked); + Local::writeSettings(); + }, closeToTaskbar->lifetime()); + } + if (Platform::AutostartSupported() && controller) { const auto minimizedToggled = [=] { return cStartMinimized() diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index c1d17fa74..db485a177 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -416,8 +416,8 @@ bool MainWindow::hideNoQuit() { return true; } } - if (Platform::IsMac() || Core::App().settings().closeToTaskbar()) { - if (Platform::IsMac()) { + if (Platform::RunInBackground() || Core::App().settings().closeToTaskbar()) { + if (Platform::RunInBackground()) { closeWithoutDestroy(); } else { setWindowState(window()->windowState() | Qt::WindowMinimized); From e946bf533833c940349e04a1514d40c4251925af Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 12 Sep 2023 09:14:18 +0400 Subject: [PATCH 043/155] Run in background on Linux when minimization is not supported --- Telegram/SourceFiles/platform/linux/specific_linux.cpp | 8 ++++++++ Telegram/SourceFiles/platform/linux/specific_linux.h | 4 ---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index a5902e2df..ec0eb4600 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_dbus_utilities.h" #include "base/platform/linux/base_linux_xdp_utilities.h" +#include "ui/platform/ui_platform_window_title.h" #include "platform/linux/linux_desktop_environment.h" #include "platform/linux/linux_wayland_integration.h" #include "lang/lang_keys.h" @@ -534,6 +535,13 @@ bool SkipTaskbarSupported() { return false; } +bool RunInBackground() { + const auto layout = Ui::Platform::TitleControlsLayout(); + using TitleControl = Ui::Platform::TitleControl; + return !ranges::contains(layout.left, TitleControl::Minimize) + && !ranges::contains(layout.right, TitleControl::Minimize); +} + QString ExecutablePathForShortcuts() { if (Core::UpdaterDisabled()) { const auto &arguments = Core::Launcher::Instance().arguments(); diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index 92445a933..e5e40cd2e 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -24,10 +24,6 @@ inline void WriteCrashDumpDetails() { inline void AutostartRequestStateFromSystem(Fn callback) { } -inline bool RunInBackground() { - return false; -} - inline bool PreventsQuit(Core::QuitReason reason) { return false; } From 0b4ef3214e8e9d114393ac470c6769cf4ac4b19b Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 12 Sep 2023 09:17:34 +0400 Subject: [PATCH 044/155] Leverage QImage's CoW in Linux native notifications --- .../linux/notifications_manager_linux.cpp | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 20c26143b..f173cac01 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -355,7 +355,7 @@ public: void show(); void close(); - void setImage(const QImage &image); + void setImage(QImage image); private: const not_null _manager; @@ -695,7 +695,7 @@ void NotificationData::close() { _manager->clearNotification(_id); } -void NotificationData::setImage(const QImage &image) { +void NotificationData::setImage(QImage image) { if (_notification) { const auto imageData = [&] { QByteArray ba; @@ -718,20 +718,22 @@ void NotificationData::setImage(const QImage &image) { return; } - const auto convertedImage = image.hasAlphaChannel() - ? image.convertToFormat(QImage::Format_RGBA8888) - : image.convertToFormat(QImage::Format_RGB888); + if (image.hasAlphaChannel()) { + image.convertTo(QImage::Format_RGBA8888); + } else { + image.convertTo(QImage::Format_RGB888); + } _hints[_imageKey] = Glib::create_variant(std::tuple{ - convertedImage.width(), - convertedImage.height(), - int(convertedImage.bytesPerLine()), - convertedImage.hasAlphaChannel(), + image.width(), + image.height(), + int(image.bytesPerLine()), + image.hasAlphaChannel(), 8, - convertedImage.hasAlphaChannel() ? 4 : 3, + image.hasAlphaChannel() ? 4 : 3, std::vector( - convertedImage.constBits(), - convertedImage.constBits() + convertedImage.sizeInBytes()), + image.constBits(), + image.constBits() + image.sizeInBytes()), }); } From 456f4d7b8ae208d9e341497845865794e8ca8229 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 9 Sep 2023 16:16:49 +0300 Subject: [PATCH 045/155] Fixed api id and hash in Github Action on Windows for nightly builds. --- .github/workflows/win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 3c86918f2..fc810e37b 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -123,7 +123,7 @@ jobs: echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV API="-D TDESKTOP_API_TEST=ON" - if [ ${{ github.ref == 'refs/heads/nightly' }} ]; then + if [ $GITHUB_REF == 'refs/heads/nightly' ]; then echo "Use the open credentials." API="-D TDESKTOP_API_ID=611335 -D TDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c" fi From 3332f012cf9c553195945bd95318268005a0d22b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 11 Sep 2023 13:38:53 +0300 Subject: [PATCH 046/155] Added tooltip and ability to copy external link to sponsored messages. --- .../data/data_sponsored_messages.cpp | 2 +- .../data/data_sponsored_messages.h | 2 +- .../history/history_inner_widget.cpp | 4 +- Telegram/SourceFiles/history/history_item.cpp | 3 +- .../history/history_item_components.h | 1 + .../history/view/history_view_view_button.cpp | 49 ++++++++++++------- Telegram/lib_ui | 2 +- 7 files changed, 40 insertions(+), 23 deletions(-) diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.cpp b/Telegram/SourceFiles/data/data_sponsored_messages.cpp index fa21af469..ea42a0fe2 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/data_sponsored_messages.cpp @@ -297,7 +297,7 @@ void SponsoredMessages::append( : ImageWithLocation{}; return SponsoredFrom{ .title = qs(data.vsite_name()), - .isExternalLink = true, + .externalLink = externalLink, .userpic = std::move(userpic), .isForceUserpicDisplay = message.data().is_show_peer_photo(), }; diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.h b/Telegram/SourceFiles/data/data_sponsored_messages.h index e9cd46b45..2c8b1e72b 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.h +++ b/Telegram/SourceFiles/data/data_sponsored_messages.h @@ -31,7 +31,7 @@ struct SponsoredFrom { bool isBot = false; bool isExactPost = false; bool isRecommended = false; - bool isExternalLink = false; + QString externalLink; ImageWithLocation userpic; bool isForceUserpicDisplay = false; }; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 0071fd772..80534e1a9 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2544,7 +2544,9 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { }, &st::menuIconLink); } if (item && item->isSponsored()) { - _menu->addSeparator(&st::expandedMenuSeparator); + if (!_menu->empty()) { + _menu->addSeparator(&st::expandedMenuSeparator); + } auto item = base::make_unique_q( _menu, st::menuWithIcons, diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index d81196689..03129e338 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -3234,8 +3234,9 @@ void HistoryItem::setSponsoredFrom(const Data::SponsoredFrom &from) { from.userpic); } + sponsored->externalLink = from.externalLink; using Type = HistoryMessageSponsored::Type; - sponsored->type = from.isExternalLink + sponsored->type = (!from.externalLink.isEmpty()) ? Type::ExternalLink : from.isExactPost ? Type::Post diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index 75581f969..e5c7ec37b 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -146,6 +146,7 @@ struct HistoryMessageSponsored : public RuntimeComponent webpage) { }); } +[[nodiscard]] ClickHandlerPtr SponsoredLink( + not_null sponsored) { + if (!sponsored->externalLink.isEmpty()) { + return std::make_shared( + sponsored->externalLink, + false); + } else { + return std::make_shared([](ClickContext context) { + const auto my = context.other.value(); + const auto controller = my.sessionWindow.get(); + if (!controller) { + return; + } + const auto &data = controller->session().data(); + const auto details = data.sponsoredMessages().lookupDetails( + my.itemId); + if (!details.externalLink.isEmpty()) { + File::OpenUrl(details.externalLink); + } else if (details.hash) { + Api::CheckChatInvite(controller, *details.hash); + } else if (details.peer) { + controller->showPeerHistory( + details.peer, + Window::SectionShow::Way::Forward, + details.msgId); + } + }); + } +} + } // namespace struct ViewButton::Inner { @@ -156,24 +186,7 @@ ViewButton::Inner::Inner( not_null sponsored, Fn updateCallback) : margins(st::historyViewButtonMargins) -, link(std::make_shared([=](ClickContext context) { - const auto my = context.other.value(); - if (const auto controller = my.sessionWindow.get()) { - const auto &data = controller->session().data(); - const auto itemId = my.itemId; - const auto details = data.sponsoredMessages().lookupDetails(itemId); - if (!details.externalLink.isEmpty()) { - File::OpenUrl(details.externalLink); - } else if (details.hash) { - Api::CheckChatInvite(controller, *details.hash); - } else if (details.peer) { - controller->showPeerHistory( - details.peer, - Window::SectionShow::Way::Forward, - details.msgId); - } - } -})) +, link(SponsoredLink(sponsored)) , updateCallback(std::move(updateCallback)) , externalLink(sponsored->type == SponsoredType::ExternalLink) , text(st::historyViewButtonTextStyle, SponsoredPhrase(sponsored->type)) { diff --git a/Telegram/lib_ui b/Telegram/lib_ui index e24eaa6b3..aaa88be9d 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit e24eaa6b32799119caa78caacd57216f81d3e1a7 +Subproject commit aaa88be9d7eaba529b31d742444e80846a2aa003 From dbd4aecc56fe2d5cc9936a2599968fc476bc4c89 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 6 Sep 2023 13:40:49 +0400 Subject: [PATCH 047/155] Don't show message bottom info in bot about. --- Telegram/SourceFiles/history/view/media/history_view_gif.cpp | 3 +++ Telegram/SourceFiles/history/view/media/history_view_photo.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 074f89dab..ba5a5bbef 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -1923,6 +1923,9 @@ bool Gif::dataLoaded() const { } bool Gif::needInfoDisplay() const { + if (_parent->data()->isFakeBotAbout()) { + return false; + } return _parent->data()->isSending() || _data->uploading() || _parent->isUnderCursor() diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index a5cf0f41c..0c8849699 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -850,6 +850,9 @@ bool Photo::dataLoaded() const { } bool Photo::needInfoDisplay() const { + if (_parent->data()->isFakeBotAbout()) { + return false; + } return _parent->data()->isSending() || _parent->data()->hasFailed() || _parent->isUnderCursor() From a6b844408a6cdd3a5a64066fca672c4a617a8afe Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 Sep 2023 20:45:44 +0400 Subject: [PATCH 048/155] Add verified/fake/scam badge to ConfirmInviteBox. --- Telegram/SourceFiles/api/api_chat_invite.cpp | 46 +++++++++- Telegram/SourceFiles/api/api_chat_invite.h | 12 +++ .../info/profile/info_profile_badge.cpp | 85 +++++++++++++------ .../info/profile/info_profile_badge.h | 31 +++++-- 4 files changed, 139 insertions(+), 35 deletions(-) diff --git a/Telegram/SourceFiles/api/api_chat_invite.cpp b/Telegram/SourceFiles/api/api_chat_invite.cpp index 8b395d9a9..dd06d2abc 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.cpp +++ b/Telegram/SourceFiles/api/api_chat_invite.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "window/window_session_controller.h" +#include "info/profile/info_profile_badge.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "ui/empty_userpic.h" @@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/toast/toast.h" #include "boxes/premium_limits_box.h" #include "styles/style_boxes.h" +#include "styles/style_info.h" #include "styles/style_layers.h" namespace Api { @@ -195,6 +197,13 @@ ConfirmInviteBox::ConfirmInviteBox( : _session(session) , _submit(std::move(submit)) , _title(this, st::confirmInviteTitle) +, _badge(std::make_unique( + this, + st::infoPeerBadge, + _session, + rpl::single(Info::Profile::Badge::Content{ BadgeForInvite(invite) }), + nullptr, + [=] { return false; })) , _status(this, st::confirmInviteStatus) , _about(this, st::confirmInviteAbout) , _aboutRequests(this, st::confirmInviteStatus) @@ -275,9 +284,24 @@ ConfirmInviteBox::ChatInvite ConfirmInviteBox::Parse( .isMegagroup = data.is_megagroup(), .isBroadcast = data.is_broadcast(), .isRequestNeeded = data.is_request_needed(), + .isFake = data.is_fake(), + .isScam = data.is_scam(), + .isVerified = data.is_verified(), }; } +[[nodiscard]] Info::Profile::BadgeType ConfirmInviteBox::BadgeForInvite( + const ChatInvite &invite) { + using Type = Info::Profile::BadgeType; + return invite.isVerified + ? Type::Verified + : invite.isScam + ? Type::Scam + : invite.isFake + ? Type::Fake + : Type::None; +} + void ConfirmInviteBox::prepare() { addButton( (_requestApprove @@ -326,8 +350,26 @@ void ConfirmInviteBox::prepare() { void ConfirmInviteBox::resizeEvent(QResizeEvent *e) { BoxContent::resizeEvent(e); - _title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop); - _status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop); + + const auto padding = st::boxRowPadding; + auto nameWidth = width() - padding.left() - padding.right(); + auto badgeWidth = 0; + if (const auto widget = _badge->widget()) { + badgeWidth = st::infoVerifiedCheckPosition.x() + widget->width(); + nameWidth -= badgeWidth; + } + _title->resizeToWidth(std::min(nameWidth, _title->textMaxWidth())); + _title->moveToLeft( + (width() - _title->width() - badgeWidth) / 2, + st::confirmInviteTitleTop); + const auto badgeLeft = _title->x() + _title->width(); + const auto badgeTop = _title->y(); + const auto badgeBottom = _title->y() + _title->height(); + _badge->move(badgeLeft, badgeTop, badgeBottom); + + _status->move( + (width() - _status->width()) / 2, + st::confirmInviteStatusTop); auto bottom = _status->y() + _status->height() + st::boxPadding.bottom() diff --git a/Telegram/SourceFiles/api/api_chat_invite.h b/Telegram/SourceFiles/api/api_chat_invite.h index 1ae6f2529..c8d99548c 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.h +++ b/Telegram/SourceFiles/api/api_chat_invite.h @@ -12,6 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class UserData; class ChannelData; +namespace Info::Profile { +class Badge; +enum class BadgeType; +} // namespace Info::Profile + namespace Main { class Session; } // namespace Main @@ -66,10 +71,15 @@ private: bool isMegagroup = false; bool isBroadcast = false; bool isRequestNeeded = false; + bool isFake = false; + bool isScam = false; + bool isVerified = false; }; [[nodiscard]] static ChatInvite Parse( not_null session, const MTPDchatInvite &data); + [[nodiscard]] Info::Profile::BadgeType BadgeForInvite( + const ChatInvite &invite); ConfirmInviteBox( not_null session, @@ -81,12 +91,14 @@ private: Fn _submit; object_ptr _title; + std::unique_ptr _badge; object_ptr _status; object_ptr _about; object_ptr _aboutRequests; std::shared_ptr _photo; std::unique_ptr _photoEmpty; std::vector _participants; + bool _isChannel = false; bool _requestApprove = false; diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp index 61a99b336..73437e1dd 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp @@ -22,6 +22,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Info::Profile { namespace { +[[nodiscard]] rpl::producer ContentForPeer( + not_null peer) { + return rpl::combine( + BadgeValue(peer), + EmojiStatusIdValue(peer) + ) | rpl::map([=](BadgeType badge, DocumentId emojiStatusId) { + return Badge::Content{ badge, emojiStatusId }; + }); +} + } // namespace Badge::Badge( @@ -32,18 +42,37 @@ Badge::Badge( Fn animationPaused, int customStatusLoopsLimit, base::flags allowed) +: Badge( + parent, + st, + &peer->session(), + ContentForPeer(peer), + emojiStatusPanel, + std::move(animationPaused), + customStatusLoopsLimit, + allowed) { +} + +Badge::Badge( + not_null parent, + const style::InfoPeerBadge &st, + not_null session, + rpl::producer content, + EmojiStatusPanel *emojiStatusPanel, + Fn animationPaused, + int customStatusLoopsLimit, + base::flags allowed) : _parent(parent) , _st(st) -, _peer(peer) +, _session(session) , _emojiStatusPanel(emojiStatusPanel) , _customStatusLoopsLimit(customStatusLoopsLimit) , _allowed(allowed) , _animationPaused(std::move(animationPaused)) { - rpl::combine( - BadgeValue(peer), - EmojiStatusIdValue(peer) - ) | rpl::start_with_next([=](BadgeType badge, DocumentId emojiStatusId) { - setBadge(badge, emojiStatusId); + std::move( + content + ) | rpl::start_with_next([=](Content content) { + setContent(content); }, _lifetime); } @@ -51,37 +80,36 @@ Ui::RpWidget *Badge::widget() const { return _view.data(); } -void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { - if (!(_allowed & badge) - || (!_peer->session().premiumBadgesShown() - && badge == BadgeType::Premium)) { - badge = BadgeType::None; +void Badge::setContent(Content content) { + if (!(_allowed & content.badge) + || (!_session->premiumBadgesShown() + && content.badge == BadgeType::Premium)) { + content.badge = BadgeType::None; } - if (!(_allowed & badge)) { - badge = BadgeType::None; + if (!(_allowed & content.badge)) { + content.badge = BadgeType::None; } - if (badge != BadgeType::Premium) { - emojiStatusId = 0; + if (content.badge != BadgeType::Premium) { + content.emojiStatusId = 0; } - if (_badge == badge && _emojiStatusId == emojiStatusId) { + if (_content == content) { return; } - _badge = badge; - _emojiStatusId = emojiStatusId; + _content = content; _emojiStatus = nullptr; _view.destroy(); - if (_badge == BadgeType::None) { + if (_content.badge == BadgeType::None) { _updated.fire({}); return; } _view.create(_parent); _view->show(); - switch (_badge) { + switch (_content.badge) { case BadgeType::Verified: case BadgeType::Premium: { - if (_emojiStatusId) { - _emojiStatus = _peer->owner().customEmojiManager().create( - _emojiStatusId, + if (const auto id = _content.emojiStatusId) { + _emojiStatus = _session->data().customEmojiManager().create( + id, [raw = _view.data()] { raw->update(); }, sizeTag()); if (_customStatusLoopsLimit > 0) { @@ -107,7 +135,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { } }, _view->lifetime()); } else { - const auto icon = (_badge == BadgeType::Verified) + const auto icon = (_content.badge == BadgeType::Verified) ? &_st.verified : &_st.premium; _view->resize(icon->size()); @@ -120,7 +148,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { } break; case BadgeType::Scam: case BadgeType::Fake: { - const auto fake = (_badge == BadgeType::Fake); + const auto fake = (_content.badge == BadgeType::Fake); const auto size = Ui::ScamBadgeSize(fake); const auto skip = st::infoVerifiedCheckPosition.x(); _view->resize( @@ -139,7 +167,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { } break; } - if (_badge != BadgeType::Premium || !_premiumClickCallback) { + if (_content.badge != BadgeType::Premium || !_premiumClickCallback) { _view->setAttribute(Qt::WA_TransparentForMouseEvents); } else { _view->setClickedCallback(_premiumClickCallback); @@ -150,7 +178,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { void Badge::setPremiumClickCallback(Fn callback) { _premiumClickCallback = std::move(callback); - if (_view && _badge == BadgeType::Premium) { + if (_view && _content.badge == BadgeType::Premium) { if (!_premiumClickCallback) { _view->setAttribute(Qt::WA_TransparentForMouseEvents); } else { @@ -169,7 +197,8 @@ void Badge::move(int left, int top, int bottom) { return; } const auto star = !_emojiStatus - && (_badge == BadgeType::Premium || _badge == BadgeType::Verified); + && (_content.badge == BadgeType::Premium + || _content.badge == BadgeType::Verified); const auto fake = !_emojiStatus && !star; const auto skip = fake ? 0 : _st.position.x(); const auto badgeLeft = left + skip; diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.h b/Telegram/SourceFiles/info/profile/info_profile_badge.h index 9e9d01d75..daada96d1 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.h +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.h @@ -18,6 +18,10 @@ namespace Data { enum class CustomEmojiSizeTag : uchar; } // namespace Data +namespace Main { +class Session; +} // namespace Main + namespace Ui { class RpWidget; class AbstractButton; @@ -45,7 +49,25 @@ public: EmojiStatusPanel *emojiStatusPanel, Fn animationPaused, int customStatusLoopsLimit = 0, - base::flags allowed = base::flags::from_raw(-1)); + base::flags allowed + = base::flags::from_raw(-1)); + + struct Content { + BadgeType badge = BadgeType::None; + DocumentId emojiStatusId = 0; + + friend inline constexpr bool operator==(Content, Content) = default; + }; + Badge( + not_null parent, + const style::InfoPeerBadge &st, + not_null session, + rpl::producer content, + EmojiStatusPanel *emojiStatusPanel, + Fn animationPaused, + int customStatusLoopsLimit = 0, + base::flags allowed + = base::flags::from_raw(-1)); [[nodiscard]] Ui::RpWidget *widget() const; @@ -56,17 +78,16 @@ public: [[nodiscard]] Data::CustomEmojiSizeTag sizeTag() const; private: - void setBadge(BadgeType badge, DocumentId emojiStatusId); + void setContent(Content content); const not_null _parent; const style::InfoPeerBadge &_st; - const not_null _peer; + const not_null _session; EmojiStatusPanel *_emojiStatusPanel = nullptr; const int _customStatusLoopsLimit = 0; - DocumentId _emojiStatusId = 0; std::unique_ptr _emojiStatus; base::flags _allowed; - BadgeType _badge = BadgeType(); + Content _content; Fn _premiumClickCallback; Fn _animationPaused; object_ptr _view = { nullptr }; From e5227a7e0586a7398fdc66ad871aa2f79b10f09d Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 12 Sep 2023 11:38:36 +0400 Subject: [PATCH 049/155] Improve OpenGL windows on macOS. Fix #26268 by adding a workaround for incorrect FBO size. Fix #26166 by forcing sRGB color scheme on all app windows. --- Telegram/lib_ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index aaa88be9d..c53835710 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit aaa88be9d7eaba529b31d742444e80846a2aa003 +Subproject commit c538357107cd07005e01711f07ba5cb608db8718 From dfa5386a27555d0c4d76d5d64eb0a9278e7fd5f9 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 12 Sep 2023 14:45:49 +0400 Subject: [PATCH 050/155] Ensure closing is supported for running in background --- Telegram/SourceFiles/platform/linux/specific_linux.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index ec0eb4600..84a7f6e6a 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -538,7 +538,9 @@ bool SkipTaskbarSupported() { bool RunInBackground() { const auto layout = Ui::Platform::TitleControlsLayout(); using TitleControl = Ui::Platform::TitleControl; - return !ranges::contains(layout.left, TitleControl::Minimize) + return (ranges::contains(layout.left, TitleControl::Close) + || ranges::contains(layout.right, TitleControl::Close)) + && !ranges::contains(layout.left, TitleControl::Minimize) && !ranges::contains(layout.right, TitleControl::Minimize); } From 73f31104035084a95ff20e54fe772248df7de67c Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 7 Sep 2023 08:48:50 +0400 Subject: [PATCH 051/155] Update API scheme to layer 163. --- Telegram/SourceFiles/mtproto/scheme/api.tl | 13 +++++++------ Telegram/SourceFiles/mtproto/scheme/layer.tl | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 889ecc90f..42471d70b 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -279,6 +279,7 @@ updateChatUserTyping#83487af0 chat_id:long from_id:Peer action:SendMessageAction updateChatParticipants#7761198 participants:ChatParticipants = Update; updateUserStatus#e5bdf8de user_id:long status:UserStatus = Update; updateUserName#a7848924 user_id:long first_name:string last_name:string usernames:Vector = Update; +updateNewAuthorization#8951abef flags:# unconfirmed:flags.0?true hash:long date:flags.0?int device:flags.0?string location:flags.0?string = Update; updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update; updateEncryptedChatTyping#1710f156 chat_id:int = Update; updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update; @@ -293,7 +294,7 @@ updateUserPhone#5492a13 user_id:long phone:string = Update; updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update; updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update; updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update; -updateReadMessagesContents#68c13933 messages:Vector pts:int pts_count:int = Update; +updateReadMessagesContents#f8227181 flags:# messages:Vector pts:int pts_count:int date:flags.0?int = Update; updateChannelTooLong#108d941f flags:# channel_id:long pts:flags.0?int = Update; updateChannel#635b4c09 channel_id:long = Update; updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update; @@ -552,7 +553,7 @@ webPagePending#c586da1c id:long date:int = WebPage; webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector = WebPage; webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage; -authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization; +authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true unconfirmed:flags.5?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization; account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector = account.Authorizations; @@ -1369,7 +1370,7 @@ attachMenuBotIconColor#4576f3f0 name:string color:int = AttachMenuBotIconColor; attachMenuBotIcon#b2a7386b flags:# name:string icon:Document colors:flags.0?Vector = AttachMenuBotIcon; -attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true bot_id:long short_name:string peer_types:Vector icons:Vector = AttachMenuBot; +attachMenuBot#d90d8dfe flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true show_in_attach_menu:flags.3?true show_in_side_menu:flags.4?true side_menu_disclaimer_needed:flags.5?true bot_id:long short_name:string peer_types:flags.3?Vector icons:Vector = AttachMenuBot; attachMenuBotsNotModified#f1d88a5c = AttachMenuBots; attachMenuBots#3c4301c0 hash:long bots:Vector users:Vector = AttachMenuBots; @@ -1499,7 +1500,7 @@ inputBotAppShortName#908c0407 bot_id:InputUser short_name:string = InputBotApp; botAppNotModified#5da674b7 = BotApp; botApp#95fcd1d6 flags:# id:long access_hash:long short_name:string title:string description:string photo:Photo document:flags.0?Document hash:long = BotApp; -messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true app:BotApp = messages.BotApp; +messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true has_settings:flags.2?true app:BotApp = messages.BotApp; appWebViewResultUrl#3c1b4f0d url:string = AppWebViewResult; @@ -1667,7 +1668,7 @@ account.resetPassword#9308ce1b = account.ResetPasswordResult; account.declinePasswordReset#4c9409f6 = Bool; account.getChatThemes#d638de89 hash:long = account.Themes; account.setAuthorizationTTL#bf899aa0 authorization_ttl_days:int = Bool; -account.changeAuthorizationSettings#40f48462 flags:# hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool; +account.changeAuthorizationSettings#40f48462 flags:# confirmed:flags.3?true hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool; account.getSavedRingtones#e1902288 hash:long = account.SavedRingtones; account.saveRingtone#3dea5b03 id:InputDocument unsave:Bool = account.SavedRingtone; account.uploadRingtone#831a83a2 file:InputFile file_name:string mime_type:string = Document; @@ -1879,7 +1880,7 @@ messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot; messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool; messages.requestWebView#269dc2c1 flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = WebViewResult; messages.prolongWebView#b0d81a83 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = Bool; -messages.requestSimpleWebView#299bec8e flags:# from_switch_webview:flags.1?true bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult; +messages.requestSimpleWebView#1a46500a flags:# from_switch_webview:flags.1?true from_side_menu:flags.2?true bot:InputUser url:flags.3?string start_param:flags.4?string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult; messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent; messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates; messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio; diff --git a/Telegram/SourceFiles/mtproto/scheme/layer.tl b/Telegram/SourceFiles/mtproto/scheme/layer.tl index 072ac8db6..7c0a0f612 100644 --- a/Telegram/SourceFiles/mtproto/scheme/layer.tl +++ b/Telegram/SourceFiles/mtproto/scheme/layer.tl @@ -1 +1 @@ -// LAYER 162 +// LAYER 163 From fbd8abc1c671eabe90e2da14bae4b8be386d2767 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 6 Sep 2023 13:41:23 +0400 Subject: [PATCH 052/155] Start main menu bots. --- Telegram/Resources/langs/lang.strings | 11 + .../SourceFiles/core/local_url_handlers.cpp | 9 +- .../inline_bots/bot_attach_web_view.cpp | 322 +++++++++++++----- .../inline_bots/bot_attach_web_view.h | 44 ++- .../payments/ui/payments_panel.cpp | 38 +-- .../SourceFiles/storage/storage_account.cpp | 23 +- .../SourceFiles/storage/storage_account.h | 6 +- .../ui/chat/attach/attach_bot_webview.cpp | 11 +- .../ui/chat/attach/attach_bot_webview.h | 9 +- .../SourceFiles/window/window_main_menu.cpp | 42 +++ .../window/window_session_controller.cpp | 7 + .../window/window_session_controller.h | 1 + 12 files changed, 369 insertions(+), 154 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index d677c6b40..470156400 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2260,6 +2260,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_bot_remove_from_menu" = "Remove From Menu"; "lng_bot_remove_from_menu_sure" = "Remove {bot} from the attachment menu?"; "lng_bot_remove_from_menu_done" = "Bot removed from the menu."; +"lng_bot_remove_from_side_menu" = "Remove From Menu"; +"lng_bot_remove_from_side_menu_sure" = "Remove {bot} from the main menu?"; +"lng_bot_remove_from_side_menu_done" = "Bot removed from the main menu."; "lng_bot_settings" = "Settings"; "lng_bot_open" = "Open Bot"; "lng_bot_reload_page" = "Reload Page"; @@ -2271,6 +2274,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_bot_close_warning_title" = "Warning"; "lng_bot_close_warning" = "Changes that you made may not be saved."; "lng_bot_close_warning_sure" = "Close anyway"; +"lng_bot_add_to_side_menu" = "{bot} asks your permission to be added as an option to your main menu so you can access it any time."; +"lng_bot_add_to_side_menu_done" = "Bot added to the main menu."; "lng_typing" = "typing"; "lng_user_typing" = "{user} is typing"; @@ -3834,6 +3839,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_telegram_features_url" = "https://t.me/TelegramTips"; +"lng_mini_apps_disclaimer_title" = "Warning"; +"lng_mini_apps_disclaimer_text" = "You are about to use a mini app operated by an independent party **not affiliated with Telegram**. You must agree to the Terms of Use of mini apps to continue."; +"lng_mini_apps_disclaimer_button" = "I agree to the {link}"; +"lng_mini_apps_disclaimer_link" = "Terms of Use"; +"lng_mini_apps_tos_url" = "https://telegram.org/tos/mini-apps"; + "lng_ringtones_box_title" = "Notification Sound"; "lng_ringtones_box_cloud_subtitle" = "Choose your tone"; "lng_ringtones_box_upload_choose" = "Choose ringtone"; diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 9daf74d62..8d39fafb6 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -392,7 +392,6 @@ bool ResolveUsernameOrPhone( const auto storyParam = params.value(u"story"_q); const auto storyId = storyParam.toInt(); const auto appname = webChannelPreviewLink ? QString() : appnameParam; - const auto appstart = params.value(u"startapp"_q); const auto commentParam = params.value(u"comment"_q); const auto commentId = commentParam.toInt(); const auto topicParam = params.value(u"topic"_q); @@ -404,11 +403,11 @@ bool ResolveUsernameOrPhone( startToken = gameParam; resolveType = ResolveType::ShareGame; } - if (startToken.isEmpty() && params.contains(u"startapp"_q)) { - startToken = params.value(u"startapp"_q); - } if (!appname.isEmpty()) { resolveType = ResolveType::BotApp; + if (startToken.isEmpty() && params.contains(u"startapp"_q)) { + startToken = params.value(u"startapp"_q); + } } const auto myContext = context.value(); using Navigation = Window::SessionNavigation; @@ -437,6 +436,8 @@ bool ResolveUsernameOrPhone( .attachBotToggleCommand = (params.contains(u"startattach"_q) ? params.value(u"startattach"_q) : std::optional()), + .attachBotMenuOpen = (appname.isEmpty() + && params.contains(u"startapp"_q)), .attachBotChooseTypes = InlineBots::ParseChooseTypes( params.value(u"choose"_q)), .voicechatHash = (params.contains(u"livestream"_q) diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 0a45d407d..3d1c241e4 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -48,6 +48,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "mainwidget.h" #include "styles/style_boxes.h" +#include "styles/style_layers.h" #include "styles/style_menu_icons.h" #include @@ -56,11 +57,7 @@ namespace InlineBots { namespace { constexpr auto kProlongTimeout = 60 * crl::time(1000); - -struct ParsedBot { - UserData *bot = nullptr; - bool inactive = false; -}; +constexpr auto kRefreshBotsTimeout = 60 * 60 * crl::time(1000); [[nodiscard]] DocumentData *ResolveIcon( not_null session, @@ -113,8 +110,13 @@ struct ParsedBot { .user = user, .icon = ResolveIcon(session, data), .name = qs(data.vshort_name()), - .types = ResolvePeerTypes(data.vpeer_types().v), + .types = (data.vpeer_types() + ? ResolvePeerTypes(data.vpeer_types()->v) + : PeerTypes()), .inactive = data.is_inactive(), + .inMainMenu = data.is_show_in_side_menu(), + .inAttachMenu = data.is_show_in_attach_menu(), + .disclaimerRequired = data.is_side_menu_disclaimer_needed(), .hasSettings = data.is_has_settings(), .requestWriteAccess = data.is_request_write_access(), } : std::optional(); @@ -216,19 +218,18 @@ private: int contentHeight() const override; void prepare(); - void validateIcon(); void paint(Painter &p); const not_null _dummyAction; const style::Menu &_st; const AttachWebViewBot _bot; + MenuBotIcon _icon; + base::unique_qptr _menu; rpl::event_stream _forceShown; Ui::Text::String _text; - QImage _mask; - QImage _icon; int _textWidth = 0; const int _height; @@ -243,6 +244,7 @@ BotAction::BotAction( , _dummyAction(new QAction(parent)) , _st(st) , _bot(bot) +, _icon(this, _bot.media) , _height(_st.itemPadding.top() + _st.itemStyle.font->height + _st.itemPadding.bottom()) { @@ -250,55 +252,19 @@ BotAction::BotAction( initResizeHook(parent->sizeValue()); setClickedCallback(std::move(callback)); + _icon.move(_st.itemIconPosition); + paintRequest( ) | rpl::start_with_next([=] { Painter p(this); paint(p); }, lifetime()); - style::PaletteChanged( - ) | rpl::start_with_next([=] { - _icon = QImage(); - update(); - }, lifetime()); - enableMouseSelecting(); prepare(); } -void BotAction::validateIcon() { - if (_mask.isNull()) { - if (!_bot.media || !_bot.media->loaded()) { - return; - } - auto icon = QSvgRenderer(_bot.media->bytes()); - if (!icon.isValid()) { - _mask = QImage( - QSize(1, 1) * style::DevicePixelRatio(), - QImage::Format_ARGB32_Premultiplied); - _mask.fill(Qt::transparent); - } else { - const auto size = style::ConvertScale(icon.defaultSize()); - _mask = QImage( - size * style::DevicePixelRatio(), - QImage::Format_ARGB32_Premultiplied); - _mask.setDevicePixelRatio(style::DevicePixelRatio()); - _mask.fill(Qt::transparent); - { - auto p = QPainter(&_mask); - icon.render(&p, QRect(QPoint(), size)); - } - _mask = Images::Colored(std::move(_mask), QColor(255, 255, 255)); - } - } - if (_icon.isNull()) { - _icon = style::colorizeImage(_mask, st::menuIconColor); - } -} - void BotAction::paint(Painter &p) { - validateIcon(); - const auto selected = isSelected(); if (selected && _st.itemBgOver->c.alpha() < 255) { p.fillRect(0, 0, width(), _height, _st.itemBg); @@ -308,10 +274,6 @@ void BotAction::paint(Painter &p) { paintRipple(p, 0, 0); } - if (!_icon.isNull()) { - p.drawImage(_st.itemIconPosition, _icon); - } - p.setPen(selected ? _st.itemFgOver : _st.itemFg); _text.drawLeftElided( p, @@ -390,6 +352,53 @@ void BotAction::handleKeyPress(not_null e) { } // namespace +MenuBotIcon::MenuBotIcon( + QWidget *parent, + std::shared_ptr media) +: RpWidget(parent) +, _media(std::move(media)) { + style::PaletteChanged( + ) | rpl::start_with_next([=] { + _image = QImage(); + update(); + }, lifetime()); + + setAttribute(Qt::WA_TransparentForMouseEvents); + resize(st::menuIconAdmin.size()); + show(); +} + +void MenuBotIcon::paintEvent(QPaintEvent *e) { + validate(); + if (!_image.isNull()) { + QPainter(this).drawImage(0, 0, _image); + } +} + +void MenuBotIcon::validate() { + const auto ratio = style::DevicePixelRatio(); + const auto wanted = size() * ratio; + if (_mask.size() != wanted) { + if (!_media || !_media->loaded()) { + return; + } + auto icon = QSvgRenderer(_media->bytes()); + _mask = QImage(wanted, QImage::Format_ARGB32_Premultiplied); + _mask.setDevicePixelRatio(style::DevicePixelRatio()); + _mask.fill(Qt::transparent); + if (icon.isValid()) { + auto p = QPainter(&_mask); + icon.render(&p, rect()); + p.end(); + + _mask = Images::Colored(std::move(_mask), Qt::white); + } + } + if (_image.isNull()) { + _image = style::colorizeImage(_mask, st::menuIconColor); + } +} + bool PeerMatchesTypes( not_null peer, not_null bot, @@ -427,11 +436,14 @@ struct AttachWebView::Context { Dialogs::EntryState dialogsEntryState; Api::SendAction action; bool fromSwitch = false; + bool fromMainMenu = false; bool fromBotApp = false; }; AttachWebView::AttachWebView(not_null session) -: _session(session) { +: _session(session) +, _refreshTimer([=] { requestBots(); }) { + _refreshTimer.callEach(kRefreshBotsTimeout); } AttachWebView::~AttachWebView() { @@ -526,6 +538,7 @@ void AttachWebView::botHandleMenuButton(Ui::BotWebView::MenuButton button) { } break; case Button::RemoveFromMenu: + case Button::RemoveFromMainMenu: const auto attached = ranges::find( _attachBots, not_null{ _bot }, @@ -540,12 +553,15 @@ void AttachWebView::botHandleMenuButton(Ui::BotWebView::MenuButton button) { active->activate(); } }); + const auto main = (button == Button::RemoveFromMainMenu); _panel->showBox(Ui::MakeConfirmBox({ - tr::lng_bot_remove_from_menu_sure( - tr::now, - lt_bot, - Ui::Text::Bold(name), - Ui::Text::WithEntities), + (main + ? tr::lng_bot_remove_from_side_menu_sure + : tr::lng_bot_remove_from_menu_sure)( + tr::now, + lt_bot, + Ui::Text::Bold(name), + Ui::Text::WithEntities), done, })); break; @@ -556,6 +572,7 @@ void AttachWebView::botSendData(QByteArray data) { if (!_context || _context->fromSwitch || _context->fromBotApp + || _context->fromMainMenu || _context->action.history->peer != _bot || _lastShownQueryId) { return; @@ -687,6 +704,7 @@ bool AttachWebView::IsSame( && (a->controller == b.controller) && (a->dialogsEntryState == b.dialogsEntryState) && (a->fromSwitch == b.fromSwitch) + && (a->fromMainMenu == b.fromMainMenu) && (a->action.history == b.action.history) && (a->action.replyTo == b.action.replyTo) && (a->action.options.sendAs == b.action.options.sendAs) @@ -702,7 +720,7 @@ void AttachWebView::request( bot, button, LookupContext(controller, action), - button.fromMenu ? nullptr : controller.get()); + button.fromAttachMenu ? nullptr : controller.get()); } void AttachWebView::requestWithOptionalConfirm( @@ -762,7 +780,7 @@ void AttachWebView::request(const WebViewButton &button) { data.vquery_id().v, qs(data.vurl()), button.text, - button.fromMenu || button.url.isEmpty()); + button.fromAttachMenu || button.url.isEmpty()); }).fail([=](const MTP::Error &error) { _requestId = 0; if (error.type() == u"BOT_INVALID"_q) { @@ -800,13 +818,11 @@ void AttachWebView::requestBots() { _attachBots.reserve(data.vbots().v.size()); for (const auto &bot : data.vbots().v) { if (auto parsed = ParseAttachBot(_session, bot)) { - if (!parsed->inactive) { - if (const auto icon = parsed->icon) { - parsed->media = icon->createMediaView(); - icon->save(Data::FileOrigin(), {}); - } - _attachBots.push_back(std::move(*parsed)); + if (const auto icon = parsed->icon) { + parsed->media = icon->createMediaView(); + icon->save(Data::FileOrigin(), {}); } + _attachBots.push_back(std::move(*parsed)); } } _attachBotsUpdates.fire({}); @@ -818,13 +834,13 @@ void AttachWebView::requestBots() { void AttachWebView::requestAddToMenu( not_null bot, - const QString &startCommand) { + std::optional startCommand) { requestAddToMenu(bot, startCommand, nullptr, std::nullopt, PeerTypes()); } void AttachWebView::requestAddToMenu( not_null bot, - const QString &startCommand, + std::optional startCommand, Window::SessionController *controller, std::optional action, PeerTypes chooseTypes) { @@ -863,16 +879,22 @@ void AttachWebView::requestAddToMenu( const auto open = [=](PeerTypes types) { const auto strong = chooseController.get(); if (!strong) { - if (wasController) { + if (wasController || !startCommand) { // Just ignore the click if controller was destroyed. return true; } + } else if (!startCommand) { + _bot = bot; + acceptDisclaimer(strong, [=] { + requestSimple(strong, bot, { .fromMainMenu = true }); + }); + return true; } else if (const auto useTypes = chooseTypes & types) { const auto done = [=](not_null thread) { strong->showThread(thread); requestWithOptionalConfirm( bot, - { .startCommand = startCommand }, + { .startCommand = *startCommand }, LookupContext(strong, Api::SendAction(thread))); }; ShowChooseBox(strong, useTypes, done); @@ -883,7 +905,7 @@ void AttachWebView::requestAddToMenu( } requestWithOptionalConfirm( bot, - { .startCommand = startCommand }, + { .startCommand = *startCommand }, *context); return true; }; @@ -891,6 +913,14 @@ void AttachWebView::requestAddToMenu( _session->data().processUsers(data.vusers()); if (const auto parsed = ParseAttachBot(_session, data.vbot())) { if (bot == parsed->user) { + const auto i = ranges::find( + _attachBots, + not_null(bot), + &AttachWebViewBot::user); + if (i != end(_attachBots)) { + // Save flags in our list, like 'inactive'. + *i = *parsed; + } const auto types = parsed->types; if (parsed->inactive) { confirmAddToMenu(*parsed, [=] { @@ -910,7 +940,7 @@ void AttachWebView::requestAddToMenu( _addToMenuId = 0; _addToMenuBot = nullptr; _addToMenuContext = nullptr; - _addToMenuStartCommand = QString(); + _addToMenuStartCommand = std::nullopt; showToast(tr::lng_bot_menu_not_supported(tr::now)); }).send(); } @@ -983,18 +1013,27 @@ void AttachWebView::requestSimple( controller, Api::SendAction(bot->owner().history(bot)))); _context->fromSwitch = button.fromSwitch; - confirmOpen(controller, [=] { - requestSimple(button); - }); + _context->fromMainMenu = button.fromMainMenu; + if (button.fromMainMenu) { + acceptDisclaimer(controller, [=] { + requestSimple(button); + }); + } else { + confirmOpen(controller, [=] { + requestSimple(button); + }); + } } void AttachWebView::requestSimple(const WebViewButton &button) { using Flag = MTPmessages_RequestSimpleWebView::Flag; _requestId = _session->api().request(MTPmessages_RequestSimpleWebView( MTP_flags(Flag::f_theme_params + | (button.fromMainMenu ? Flag::f_from_side_menu : Flag::f_url) | (button.fromSwitch ? Flag::f_from_switch_webview : Flag())), _bot->inputUser, MTP_bytes(button.url), + MTP_string(""), // start_param MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)), MTP_string("tdesktop") )).done([=](const MTPSimpleWebViewResult &result) { @@ -1200,6 +1239,112 @@ void AttachWebView::confirmOpen( })); } +void AttachWebView::acceptDisclaimer( + not_null controller, + Fn done) { + const auto local = _bot ? &_bot->session().local() : nullptr; + if (!local) { + return; + } + const auto i = ranges::find( + _attachBots, + not_null(_bot), + &AttachWebViewBot::user); + if (i == end(_attachBots)) { + _attachBotsUpdates.fire({}); + return; + } else if (i->inactive) { + requestAddToMenu(_bot, {}, controller, {}, {}); + return; + } else if (!i->disclaimerRequired) { + done(); + return; + } + + const auto weak = base::make_weak(this); + controller->show(Box([=](not_null box) { + const auto updateCheck = std::make_shared>(); + const auto validateCheck = std::make_shared>(); + + const auto callback = [=](Fn close) { + if (validateCheck && (*validateCheck)() && weak) { + const auto i = ranges::find( + _attachBots, + not_null(_bot), + &AttachWebViewBot::user); + if (i == end(_attachBots)) { + _attachBotsUpdates.fire({}); + } else if (i->inactive) { + requestAddToMenu(_bot, std::nullopt); + } else { + i->disclaimerRequired = false; + requestBots(); + done(); + } + close(); + } + }; + + Ui::ConfirmBox(box, { + .text = tr::lng_mini_apps_disclaimer_text( + tr::now, + Ui::Text::RichLangValue), + .confirmed = callback, + .confirmText = tr::lng_box_ok(), + .title = tr::lng_mini_apps_disclaimer_title(), + }); + + auto checkView = std::make_unique( + st::defaultCheck, + false, + [=] { if (*updateCheck) { (*updateCheck)(); } }); + const auto check = checkView.get(); + const auto row = box->addRow( + object_ptr( + box.get(), + tr::lng_mini_apps_disclaimer_button( + lt_link, + rpl::single(Ui::Text::Link( + tr::lng_mini_apps_disclaimer_link(tr::now), + tr::lng_mini_apps_tos_url(tr::now))), + Ui::Text::WithEntities), + st::defaultBoxCheckbox, + std::move(checkView)), + { + st::boxRowPadding.left(), + st::boxRowPadding.left(), + st::boxRowPadding.right(), + st::defaultBoxCheckbox.margin.bottom(), + }); + row->setAllowTextLines(5); + row->setClickHandlerFilter([=]( + const ClickHandlerPtr &link, + Qt::MouseButton button) { + ActivateClickHandler(row, link, ClickContext{ + .button = button, + .other = QVariant::fromValue(ClickHandlerContext{ + .show = box->uiShow(), + }) + }); + return false; + }); + + (*updateCheck) = [=] { row->update(); }; + + const auto showError = Ui::CheckView::PrepareNonToggledError( + check, + box->lifetime()); + + (*validateCheck) = [=] { + if (check->checked()) { + return true; + } + showError(); + return false; + }; + })); +} + void AttachWebView::ClearAll() { while (!ActiveWebViews().empty()) { ActiveWebViews().front()->cancel(); @@ -1227,10 +1372,14 @@ void AttachWebView::show( const auto hasOpenBot = !_context || (_bot != _context->action.history->peer); const auto hasRemoveFromMenu = (attached != end(_attachBots)) - && !attached->inactive; + && (!attached->inactive || attached->inMainMenu); const auto buttons = (hasSettings ? Button::Settings : Button::None) | (hasOpenBot ? Button::OpenBot : Button::None) - | (hasRemoveFromMenu ? Button::RemoveFromMenu : Button::None); + | (!hasRemoveFromMenu + ? Button::None + : attached->inMainMenu + ? Button::RemoveFromMainMenu + : Button::RemoveFromMenu); _lastShownUrl = url; _lastShownQueryId = queryId; @@ -1318,16 +1467,20 @@ void AttachWebView::confirmAddToMenu( if (callback) { callback(); } - showToast(tr::lng_bot_add_to_menu_done(tr::now)); + showToast((bot.inMainMenu + ? tr::lng_bot_add_to_side_menu_done + : tr::lng_bot_add_to_menu_done)(tr::now)); }); close(); }; Ui::ConfirmBox(box, { - tr::lng_bot_add_to_menu( - tr::now, - lt_bot, - Ui::Text::Bold(bot.name), - Ui::Text::WithEntities), + (bot.inMainMenu + ? tr::lng_bot_add_to_side_menu + : tr::lng_bot_add_to_menu)( + tr::now, + lt_bot, + Ui::Text::Bold(bot.name), + Ui::Text::WithEntities), done, }); if (bot.requestWriteAccess) { @@ -1406,7 +1559,8 @@ std::unique_ptr MakeAttachBotsMenu( }, &st::menuIconFile); } for (const auto &bot : bots->attachBots()) { - if (!PeerMatchesTypes(peer, bot.user, bot.types)) { + if (!bot.inAttachMenu + || !PeerMatchesTypes(peer, bot.user, bot.types)) { continue; } const auto callback = [=] { @@ -1414,7 +1568,7 @@ std::unique_ptr MakeAttachBotsMenu( controller, actionFactory(), bot.user, - { .fromMenu = true }); + { .fromAttachMenu = true }); }; auto action = base::make_unique_q( raw, diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h index a6c254ef8..926312ea5 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h @@ -7,10 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "base/weak_ptr.h" #include "base/flags.h" +#include "base/timer.h" +#include "base/weak_ptr.h" #include "mtproto/sender.h" #include "ui/chat/attach/attach_bot_webview.h" +#include "ui/rp_widget.h" namespace Api { struct SendAction; @@ -60,9 +62,12 @@ struct AttachWebViewBot { std::shared_ptr media; QString name; PeerTypes types = 0; - bool inactive = false; - bool hasSettings = false; - bool requestWriteAccess = false; + bool inactive : 1 = false; + bool inMainMenu : 1 = false; + bool inAttachMenu : 1 = false; + bool disclaimerRequired : 1 = false; + bool hasSettings : 1 = false; + bool requestWriteAccess : 1 = false; }; class AttachWebView final @@ -76,7 +81,8 @@ public: QString text; QString startCommand; QByteArray url; - bool fromMenu = false; + bool fromAttachMenu = false; + bool fromMainMenu = false; bool fromSwitch = false; }; void request( @@ -116,10 +122,10 @@ public: void requestAddToMenu( not_null bot, - const QString &startCommand); + std::optional startCommand); void requestAddToMenu( not_null bot, - const QString &startCommand, + std::optional startCommand, Window::SessionController *controller, std::optional action, PeerTypes chooseTypes); @@ -171,6 +177,9 @@ private: void confirmOpen( not_null controller, Fn done); + void acceptDisclaimer( + not_null controller, + Fn done); enum class ToggledState { Removed, @@ -200,6 +209,8 @@ private: const not_null _session; + base::Timer _refreshTimer; + std::unique_ptr _context; std::unique_ptr _lastShownContext; QString _lastShownUrl; @@ -221,7 +232,7 @@ private: std::unique_ptr _addToMenuContext; UserData *_addToMenuBot = nullptr; mtpRequestId _addToMenuId = 0; - QString _addToMenuStartCommand; + std::optional _addToMenuStartCommand; base::weak_ptr _addToMenuChooseController; PeerTypes _addToMenuChooseTypes; @@ -239,4 +250,21 @@ private: Fn actionFactory, Fn attach); +class MenuBotIcon final : public Ui::RpWidget { +public: + MenuBotIcon( + QWidget *parent, + std::shared_ptr media); + +private: + void paintEvent(QPaintEvent *e) override; + + void validate(); + + std::shared_ptr _media; + QImage _image; + QImage _mask; + +}; + } // namespace InlineBots diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.cpp b/Telegram/SourceFiles/payments/ui/payments_panel.cpp index 0ee46d64a..d077fbe8d 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_panel.cpp @@ -735,41 +735,9 @@ void Panel::requestTermsAcceptance( (*update) = [=] { row->update(); }; - struct State { - bool error = false; - Ui::Animations::Simple errorAnimation; - }; - const auto state = box->lifetime().make_state(); - const auto showError = [=] { - const auto callback = [=] { - const auto error = state->errorAnimation.value( - state->error ? 1. : 0.); - if (error == 0.) { - check->setUntoggledOverride(std::nullopt); - } else { - const auto color = anim::color( - st::defaultCheck.untoggledFg, - st::boxTextFgError, - error); - check->setUntoggledOverride(color); - } - }; - state->error = true; - state->errorAnimation.stop(); - state->errorAnimation.start( - callback, - 0., - 1., - st::defaultCheck.duration); - }; - - row->checkedChanges( - ) | rpl::filter([=](bool checked) { - return checked; - }) | rpl::start_with_next([=] { - state->error = false; - check->setUntoggledOverride(std::nullopt); - }, row->lifetime()); + const auto showError = Ui::CheckView::PrepareNonToggledError( + check, + box->lifetime()); box->addButton(tr::lng_payments_terms_accept(), [=] { if (check->checked()) { diff --git a/Telegram/SourceFiles/storage/storage_account.cpp b/Telegram/SourceFiles/storage/storage_account.cpp index f0bda9aa6..60fb45382 100644 --- a/Telegram/SourceFiles/storage/storage_account.cpp +++ b/Telegram/SourceFiles/storage/storage_account.cpp @@ -2808,7 +2808,13 @@ void Account::writeTrustedBots() { } void Account::readTrustedBots() { - if (!_trustedBotsKey) return; + if (_trustedBotsRead) { + return; + } + _trustedBotsRead = true; + if (!_trustedBotsKey) { + return; + } FileReadDescriptor trusted; if (!ReadEncryptedFile(trusted, _trustedBotsKey, _basePath, _localKey)) { @@ -2845,10 +2851,7 @@ void Account::markBotTrustedOpenGame(PeerId botId) { } bool Account::isBotTrustedOpenGame(PeerId botId) { - if (!_trustedBotsRead) { - readTrustedBots(); - _trustedBotsRead = true; - } + readTrustedBots(); const auto i = _trustedBots.find(botId); return (i != end(_trustedBots)) && ((i->second & BotTrustFlag::NoOpenGame) == 0); @@ -2870,10 +2873,7 @@ void Account::markBotTrustedPayment(PeerId botId) { } bool Account::isBotTrustedPayment(PeerId botId) { - if (!_trustedBotsRead) { - readTrustedBots(); - _trustedBotsRead = true; - } + readTrustedBots(); const auto i = _trustedBots.find(botId); return (i != end(_trustedBots)) && ((i->second & BotTrustFlag::Payment) != 0); @@ -2895,10 +2895,7 @@ void Account::markBotTrustedOpenWebView(PeerId botId) { } bool Account::isBotTrustedOpenWebView(PeerId botId) { - if (!_trustedBotsRead) { - readTrustedBots(); - _trustedBotsRead = true; - } + readTrustedBots(); const auto i = _trustedBots.find(botId); return (i != end(_trustedBots)) && ((i->second & BotTrustFlag::OpenWebView) != 0); diff --git a/Telegram/SourceFiles/storage/storage_account.h b/Telegram/SourceFiles/storage/storage_account.h index c96ba84f8..3c1525ed7 100644 --- a/Telegram/SourceFiles/storage/storage_account.h +++ b/Telegram/SourceFiles/storage/storage_account.h @@ -184,9 +184,9 @@ private: Failed, }; enum class BotTrustFlag : uchar { - NoOpenGame = (1 << 0), - Payment = (1 << 1), - OpenWebView = (1 << 2), + NoOpenGame = (1 << 0), + Payment = (1 << 1), + OpenWebView = (1 << 2), }; friend inline constexpr bool is_flag_type(BotTrustFlag) { return true; }; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index f25340450..6a29bba46 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -535,12 +535,17 @@ bool Panel::showWebview( callback(tr::lng_bot_reload_page(tr::now), [=] { _webview->window.reload(); }, &st::menuIconRestore); - if (_menuButtons & MenuButton::RemoveFromMenu) { + const auto main = (_menuButtons & MenuButton::RemoveFromMainMenu); + if (main || (_menuButtons & MenuButton::RemoveFromMenu)) { const auto handler = [=] { - _delegate->botHandleMenuButton(MenuButton::RemoveFromMenu); + _delegate->botHandleMenuButton(main + ? MenuButton::RemoveFromMainMenu + : MenuButton::RemoveFromMenu); }; callback({ - .text = tr::lng_bot_remove_from_menu(tr::now), + .text = (main + ? tr::lng_bot_remove_from_side_menu + : tr::lng_bot_remove_from_menu)(tr::now), .handler = handler, .icon = &st::menuIconDeleteAttention, .isAttention = true, diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h index 54bf92aa9..b4709ac20 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h @@ -36,10 +36,11 @@ struct MainButtonArgs { }; enum class MenuButton { - None = 0x00, - Settings = 0x01, - OpenBot = 0x02, - RemoveFromMenu = 0x04, + None = 0x00, + Settings = 0x01, + OpenBot = 0x02, + RemoveFromMenu = 0x04, + RemoveFromMainMenu = 0x08, }; inline constexpr bool is_flag_type(MenuButton) { return true; } using MenuButtons = base::flags; diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 52c3e67e3..e64a9b768 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/empty_userpic.h" #include "ui/unread_badge_paint.h" #include "base/call_delayed.h" +#include "inline_bots/bot_attach_web_view.h" #include "mainwindow.h" #include "storage/localstorage.h" #include "storage/storage_account.h" @@ -198,6 +199,45 @@ void ShowCallsBox(not_null window) { }) | rpl::flatten_latest(); } +void SetupMenuBots( + not_null container, + not_null controller) { + const auto wrap = container->add( + object_ptr(container)); + const auto bots = &controller->session().attachWebView(); + + rpl::single( + rpl::empty + ) | rpl::then( + bots->attachBotsUpdates() + ) | rpl::start_with_next([=] { + wrap->clear(); + for (const auto &bot : bots->attachBots()) { + if (!bot.inMainMenu) { + continue; + } + const auto button = Settings::AddButton( + container, + rpl::single(bot.name), + st::mainMenuButton); + const auto icon = Ui::CreateChild( + button.get(), + bot.media); + button->heightValue( + ) | rpl::start_with_next([=](int height) { + icon->move( + st::mainMenuButton.iconLeft, + (height - icon->height()) / 2); + }, button->lifetime()); + button->setClickedCallback([=] { + bots->requestSimple(controller, bot.user, { + .fromMainMenu = true, + }); + }); + } + }, wrap->lifetime()); +} + } // namespace class MainMenu::ToggleAccountsButton final : public Ui::AbstractButton { @@ -784,6 +824,8 @@ void MainMenu::setupMenu() { Info::Stories::Make(controller->session().user())); }); + SetupMenuBots(_menu, controller); + addAction( tr::lng_menu_contacts(), { &st::menuIconProfile } diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 268518eed..3e5a1f85e 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -596,6 +596,13 @@ void SessionNavigation::showPeerByLinkResolved( contextUser->owner().history(contextUser)) : std::optional()), info.attachBotChooseTypes); + } else if (bot && info.attachBotMenuOpen) { + bot->session().attachWebView().requestAddToMenu( + bot, + std::nullopt, + parentController(), + std::optional(), + {}); } else { crl::on_main(this, [=] { showPeerHistory(peer, params, msgId); diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 7f541cf5e..8001aef05 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -212,6 +212,7 @@ public: bool botAppForceConfirmation = false; QString attachBotUsername; std::optional attachBotToggleCommand; + bool attachBotMenuOpen = false; InlineBots::PeerTypes attachBotChooseTypes; std::optional voicechatHash; FullMsgId clickFromMessageId; From 229f7a2c157b32dda76448ebf30ac1fb00255174 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 8 Sep 2023 11:26:07 +0400 Subject: [PATCH 053/155] Handle background / title colors in web-apps. --- .../payments/payments_checkout_process.cpp | 15 +++------- .../payments/payments_checkout_process.h | 2 +- .../payments/ui/payments_panel.cpp | 20 +++++++++++-- .../SourceFiles/payments/ui/payments_panel.h | 3 +- .../payments/ui/payments_panel_delegate.h | 5 ++++ .../ui/chat/attach/attach_bot_webview.cpp | 28 +++++++++++++++++-- .../ui/chat/attach/attach_bot_webview.h | 4 ++- .../window/themes/window_theme.cpp | 1 + Telegram/lib_webview | 2 +- 9 files changed, 61 insertions(+), 19 deletions(-) diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index 6b289c67c..d92eeea34 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -246,17 +246,6 @@ CheckoutProcess::CheckoutProcess( showForm(); _panel->toggleProgress(true); - style::PaletteChanged( - ) | rpl::filter([=] { - return !_themeUpdateScheduled; - }) | rpl::start_with_next([=] { - _themeUpdateScheduled = true; - crl::on_main(this, [=] { - _themeUpdateScheduled = false; - _panel->updateThemeParams(Window::Theme::WebViewParams()); - }); - }, _panel->lifetime()); - if (mode == Mode::Payment) { _session->api().cloudPassword().state( ) | rpl::start_with_next([=](const Core::CloudPasswordState &state) { @@ -846,4 +835,8 @@ QString CheckoutProcess::panelWebviewDataPath() { return _session->domain().local().webviewDataPath(); } +Webview::ThemeParams CheckoutProcess::panelWebviewThemeParams() { + return Window::Theme::WebViewParams(); +} + } // namespace Payments diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.h b/Telegram/SourceFiles/payments/payments_checkout_process.h index 1e37c3d28..5aa050259 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.h +++ b/Telegram/SourceFiles/payments/payments_checkout_process.h @@ -150,6 +150,7 @@ private: QVariant panelClickHandlerContext() override; QString panelWebviewDataPath() override; + Webview::ThemeParams panelWebviewThemeParams() override; std::optional panelOverrideExpireDateThreshold() override; @@ -163,7 +164,6 @@ private: bool _sendFormPending = false; bool _sendFormFailed = false; - bool _themeUpdateScheduled = false; rpl::lifetime _gettingPasswordState; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.cpp b/Telegram/SourceFiles/payments/ui/payments_panel.cpp index d077fbe8d..541683c64 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_panel.cpp @@ -82,6 +82,17 @@ Panel::Panel(not_null delegate) ) | rpl::start_with_next([=] { _delegate->panelCloseSure(); }, _widget->lifetime()); + + style::PaletteChanged( + ) | rpl::filter([=] { + return !_themeUpdateScheduled; + }) | rpl::start_with_next([=] { + _themeUpdateScheduled = true; + crl::on_main(_widget.get(), [=] { + _themeUpdateScheduled = false; + updateThemeParams(_delegate->panelWebviewThemeParams()); + }); + }, lifetime()); } Panel::~Panel() { @@ -483,11 +494,13 @@ bool Panel::showWebview( const QString &url, bool allowBack, rpl::producer bottomText) { - if (!_webview && !createWebview()) { + const auto params = _delegate->panelWebviewThemeParams(); + if (!_webview && !createWebview(params)) { return false; } showWebviewProgress(); _widget->hideLayer(anim::type::instant); + updateThemeParams(params); _webview->window.navigate(url); _widget->setBackAllowed(allowBack); if (bottomText) { @@ -511,7 +524,7 @@ bool Panel::showWebview( return true; } -bool Panel::createWebview() { +bool Panel::createWebview(const Webview::ThemeParams ¶ms) { auto outer = base::make_unique_q(_widget.get()); const auto container = outer.get(); _widget->showInner(std::move(outer)); @@ -532,8 +545,10 @@ bool Panel::createWebview() { _webview = std::make_unique( container, Webview::WindowConfig{ + .opaqueBg = params.opaqueBg, .userDataPath = _delegate->panelWebviewDataPath(), }); + const auto raw = &_webview->window; QObject::connect(container, &QObject::destroyed, [=] { if (_webview && &_webview->window == raw) { @@ -900,6 +915,7 @@ void Panel::updateThemeParams(const Webview::ThemeParams ¶ms) { return; } _webview->window.updateTheme( + params.opaqueBg, params.scrollBg, params.scrollBgOver, params.scrollBarBg, diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.h b/Telegram/SourceFiles/payments/ui/payments_panel.h index 47ec4284f..1c97355da 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel.h @@ -100,7 +100,7 @@ private: struct Progress; struct WebviewWithLifetime; - bool createWebview(); + bool createWebview(const Webview::ThemeParams ¶ms); void showWebviewProgress(); void hideWebviewProgress(); void showWebviewError( @@ -123,6 +123,7 @@ private: QPointer _weakEditInformation; QPointer _weakEditCard; rpl::event_stream _savedMethodChosen; + bool _themeUpdateScheduled = false; bool _webviewProgress = false; bool _testMode = false; diff --git a/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h b/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h index ca0ed0caf..b3113d558 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h @@ -16,6 +16,10 @@ namespace Ui { class BoxContent; } // namespace Ui +namespace Webview { +struct ThemeParams; +} // namespace Webview + namespace Payments::Ui { using namespace ::Ui; @@ -56,6 +60,7 @@ public: virtual QVariant panelClickHandlerContext() = 0; virtual QString panelWebviewDataPath() = 0; + virtual Webview::ThemeParams panelWebviewThemeParams() = 0; virtual std::optional panelOverrideExpireDateThreshold() = 0; }; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index 6a29bba46..45762cf00 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -494,7 +494,7 @@ bool Panel::showWebview( const QString &url, const Webview::ThemeParams ¶ms, rpl::producer bottomText) { - if (!_webview && !createWebview()) { + if (!_webview && !createWebview(params)) { return false; } const auto allowBack = false; @@ -555,12 +555,16 @@ bool Panel::showWebview( return true; } -bool Panel::createWebview() { +bool Panel::createWebview(const Webview::ThemeParams ¶ms) { auto outer = base::make_unique_q(_widget.get()); const auto container = outer.get(); _widget->showInner(std::move(outer)); _webviewParent = container; + container->paintRequest() | rpl::start_with_next([=] { + QPainter(container).fillRect(container->rect(), QColor(0, 128, 0, 255)); + }, container->lifetime()); + _webviewBottom = std::make_unique(_widget.get()); const auto bottom = _webviewBottom.get(); bottom->show(); @@ -580,6 +584,7 @@ bool Panel::createWebview() { _webview = std::make_unique( container, Webview::WindowConfig{ + .opaqueBg = params.opaqueBg, .userDataPath = _userDataPath, }); const auto raw = &_webview->window; @@ -649,6 +654,8 @@ bool Panel::createWebview() { setupClosingBehaviour(arguments); } else if (command == "web_app_read_text_from_clipboard") { requestClipboardText(arguments); + } else if (command == "web_app_set_header_color") { + processHeaderColor(arguments); } }); @@ -1089,6 +1096,22 @@ void Panel::processBackButtonMessage(const QJsonObject &args) { _widget->setBackAllowed(args["is_visible"].toBool()); } +void Panel::processHeaderColor(const QJsonObject &args) { + if (const auto color = ParseColor(args["color"].toString())) { + _widget->overrideTitleColor(color); + _headerColorLifetime.destroy(); + } else if (args["color_key"].toString() == u"secondary_bg_color"_q) { + _widget->overrideTitleColor(st::boxDividerBg->c); + _headerColorLifetime = style::PaletteChanged( + ) | rpl::start_with_next([=] { + _widget->overrideTitleColor(st::boxDividerBg->c); + }); + } else { + _widget->overrideTitleColor(std::nullopt); + _headerColorLifetime.destroy(); + } +} + void Panel::createMainButton() { _mainButton = std::make_unique