From c70482dbc43474bafecc0ad146a6baeae0d45ec4 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 8 Oct 2024 17:53:50 +0400 Subject: [PATCH 01/40] Qt 6.8.0-rc1 -> 6.8.0 --- Telegram/build/docker/centos_env/Dockerfile | 2 +- Telegram/build/prepare/prepare.py | 2 +- snap/snapcraft.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Telegram/build/docker/centos_env/Dockerfile b/Telegram/build/docker/centos_env/Dockerfile index c64e6085092e5f..89ca76a96f6d6d 100644 --- a/Telegram/build/docker/centos_env/Dockerfile +++ b/Telegram/build/docker/centos_env/Dockerfile @@ -2,7 +2,7 @@ {%- set GIT_FREEDESKTOP = GIT ~ "/gitlab-freedesktop-mirrors" -%} {%- set GIT_UPDATE_M4 = "git submodule set-url m4 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 && git config -f .gitmodules submodule.m4.shallow true && git submodule init && git submodule update" -%} {%- set QT = "6.8.0" -%} -{%- set QT_TAG = "v" ~ QT ~ "-rc1" -%} +{%- set QT_TAG = "v" ~ QT -%} {%- set CFLAGS_DEBUG = "$CFLAGS -O0 -fno-lto -U_FORTIFY_SOURCE" -%} {%- set LibrariesPath = "/usr/src/Libraries" -%} diff --git a/Telegram/build/prepare/prepare.py b/Telegram/build/prepare/prepare.py index f8ae5a6a2adf2e..497fe5ff4b2ed6 100644 --- a/Telegram/build/prepare/prepare.py +++ b/Telegram/build/prepare/prepare.py @@ -1629,7 +1629,7 @@ def runStages(): make install """) else: # qt > '6' - branch = 'v$QT' + ('-lts-lgpl' if qt < '6.3' else '-rc1') + branch = 'v$QT' + ('-lts-lgpl' if qt < '6.3' else '') stage('qt_' + qt, """ git clone -b """ + branch + """ https://github.com/qt/qt5.git qt_$QT cd qt_$QT diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 1e42e437cd954b..a158f9c0f9abe3 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -381,7 +381,7 @@ parts: override-pull: | QT=6.8.0 - git clone -b v${QT}-rc1 --depth=1 https://github.com/qt/qt5.git . + git clone -b v${QT} --depth=1 https://github.com/qt/qt5.git . git submodule update --init --recursive --depth=1 qtbase qtdeclarative qtwayland qtimageformats qtsvg qtshadertools cd qtbase From b0ecb2c535b46689a0b3eb2194977eb81dc89d62 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 8 Oct 2024 17:54:07 +0400 Subject: [PATCH 02/40] Update patches and lib_ui --- Telegram/build/prepare/prepare.py | 2 +- Telegram/lib_ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/build/prepare/prepare.py b/Telegram/build/prepare/prepare.py index 497fe5ff4b2ed6..ac5ee3b9e9351f 100644 --- a/Telegram/build/prepare/prepare.py +++ b/Telegram/build/prepare/prepare.py @@ -457,7 +457,7 @@ def runStages(): stage('patches', """ git clone https://github.com/desktop-app/patches.git cd patches - git checkout 5943c8aca4 + git checkout 54378fbc46 """) stage('msys64', """ diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 1d780ef6b03b45..6ce5ec6e43a286 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 1d780ef6b03b459041460f261d7b0f14fc17f32a +Subproject commit 6ce5ec6e43a28678ca89fd89b2fa90164e5bcef1 From 88703ba1eb1dd6be151fb4f126c1aafa3e27c9ee Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 10 Oct 2024 09:20:15 +0400 Subject: [PATCH 03/40] Toggle fullscreen by double click in media viewe title area --- Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 98549982fa485c..9362819b3a95a4 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -808,7 +808,7 @@ void OverlayWidget::setupWindow() { return result; } if (widgetPoint.y() <= st::mediaviewTitleButton.height) { - result |= Flag::Menu; + result |= Flag::Menu | Flag::FullScreen; } const auto inControls = ((_over != Over::None) && (_over != Over::Video)); if (inControls @@ -6046,6 +6046,7 @@ void OverlayWidget::handleMouseRelease( _dragging = 0; setCursor(style::cur_default); } else if (!_windowed + && position.y() > st::mediaviewTitleButton.height && (position - _lastAction).manhattanLength() >= st::mediaviewDeltaFromLastAction) { if (_themePreviewShown) { From 828ecabc78bab4bd9209071850dab03ea1b4a249 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 11:25:54 +0400 Subject: [PATCH 04/40] Don't show user badge in star stats rows. --- Telegram/SourceFiles/boxes/peer_list_box.cpp | 5 +++-- Telegram/SourceFiles/boxes/peer_list_box.h | 7 ++++++- .../info/statistics/info_statistics_list_controllers.cpp | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 715301d6c51361..b0f3c0a50cdefb 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -764,13 +764,14 @@ int PeerListRow::paintNameIconGetWidth( int availableWidth, int outerWidth, bool selected) { - if (special() + if (_skipPeerBadge + || special() || !_savedMessagesStatus.isEmpty() || _isRepliesMessagesChat || _isVerifyCodesChat) { return 0; } - return _bagde.drawGetWidth( + return _badge.drawGetWidth( p, QRect( nameLeft, diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index c23e2013f30c72..4c4374b84be91d 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -254,6 +254,10 @@ class PeerListRow { return _nameFirstLetters; } + void setSkipPeerBadge(bool skip) { + _skipPeerBadge = skip; + } + virtual void lazyInitialize(const style::PeerListItem &st); virtual void paintStatusText( Painter &p, @@ -291,7 +295,7 @@ class PeerListRow { std::unique_ptr _checkbox; Ui::Text::String _name; Ui::Text::String _status; - Ui::PeerBadge _bagde; + Ui::PeerBadge _badge; StatusType _statusType = StatusType::Online; crl::time _statusValidTill = 0; base::flat_set _nameFirstLetters; @@ -303,6 +307,7 @@ class PeerListRow { bool _isSearchResult : 1 = false; bool _isRepliesMessagesChat : 1 = false; bool _isVerifyCodesChat : 1 = false; + bool _skipPeerBadge : 1 = false; }; diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp index 817faf0bbffd7a..0dc51cb076eccb 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp @@ -851,6 +851,7 @@ void CreditsRow::init() { ? name : _entry.title; const auto joiner = QString(QChar(' ')) + QChar(8212) + QChar(' '); + setSkipPeerBadge(true); PeerListRow::setCustomStatus( langDateTime(_entry.date) + (_entry.refunded From 1038baf4677bfe65d7f877f33a552a496b12e89a Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 11:34:46 +0400 Subject: [PATCH 05/40] Allow timestamp links under spoilers. --- .../history/view/media/history_view_media.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.cpp b/Telegram/SourceFiles/history/view/media/history_view_media.cpp index 2fc97740286e7b..d41c93febe452e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media.cpp @@ -156,17 +156,23 @@ TextWithEntities AddTimestampLinks( } auto &entities = text.entities; - const auto i = ranges::lower_bound( + auto i = ranges::lower_bound( entities, from, std::less<>(), &EntityInText::offset); + while (i != entities.end() + && i->offset() < till + && i->type() == EntityType::Spoiler) { + ++i; + } if (i != entities.end() && i->offset() < till) { continue; } const auto intersects = [&](const EntityInText &entity) { - return entity.offset() + entity.length() > from; + return (entity.offset() + entity.length() > from) + && (entity.type() != EntityType::Spoiler); }; auto j = std::make_reverse_iterator(i); const auto e = std::make_reverse_iterator(entities.begin()); From 3cb33f08257e912dc131d9431e47dbb899dbefbc Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 12:10:41 +0400 Subject: [PATCH 06/40] Custom "Copy ID" for peer ID context menu. --- Telegram/SourceFiles/core/application.cpp | 9 ++++++++- .../info/profile/info_profile_actions.cpp | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 5810e8eb3e8651..b91813e167ce1f 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -1162,7 +1162,14 @@ bool Application::openCustomUrl( || passcodeLocked()) { return false; } - const auto command = base::StringViewMid(urlTrimmed, protocol.size(), 8192); + static const auto kTagExp = QRegularExpression( + u"\\~[a-zA-Z0-9_\\-]+\\~:"_q); + auto skip = protocol.size(); + const auto match = kTagExp.match(urlTrimmed, skip); + if (match.hasMatch()) { + skip += match.capturedLength(); + } + const auto command = base::StringViewMid(urlTrimmed, skip, 8192); const auto my = context.value(); const auto controller = my.sessionWindow.get() ? my.sessionWindow.get() diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 8a33807268e64b..f23cf8c1069510 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -185,7 +185,7 @@ base::options::toggle ShowPeerIdBelowAbout({ const auto raw = peer->id.value & PeerId::kChatTypeMask; value.append(Link( Italic(Lang::FormatCountDecimal(raw)), - "internal:copy:" + QString::number(raw))); + "internal:~peer_id~:copy:" + QString::number(raw))); return std::move(value); }); } @@ -979,6 +979,20 @@ object_ptr DetailsFiller::setupInfo() { state->labelText = std::move(text); label->setContextMenuHook([=]( Ui::FlatLabel::ContextMenuRequest request) { + if (request.link) { + const auto &url = request.link->url(); + if (url.startsWith(u"internal:~peer_id~:"_q)) { + const auto weak = base::make_weak(controller); + request.menu->addAction(u"Copy ID"_q, [=] { + Core::App().openInternalUrl( + url, + QVariant::fromValue(ClickHandlerContext{ + .sessionWindow = weak, + })); + }); + return; + } + } label->fillContextMenu(request); if (Ui::SkipTranslate(state->labelText.current())) { return; From af728e82fcf51850678699f959bd278c25dcf9f3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 13:21:19 +0400 Subject: [PATCH 07/40] Unify channel links and usernames clicks. --- Telegram/Resources/langs/lang.strings | 2 + Telegram/SourceFiles/core/application.cpp | 4 +- .../SourceFiles/core/local_url_handlers.cpp | 40 +++++++- .../info/profile/info_profile_actions.cpp | 93 +++++++++++++------ .../info/profile/info_profile_values.cpp | 24 +++-- .../info/profile/info_profile_values.h | 3 +- .../ui/boxes/collectible_info_box.cpp | 20 ++-- 7 files changed, 138 insertions(+), 48 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index a57fc8b1b13b19..20f7825cbb0f6c 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -453,6 +453,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_username_app_not_found" = "Bot application not found."; "lng_username_link" = "This link opens a chat with you:"; "lng_username_copied" = "Link copied to clipboard."; +"lng_username_text_copied" = "Username copied to clipboard."; "lng_usernames_edit" = "click to edit"; "lng_usernames_active" = "active"; @@ -487,6 +488,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_collectible_phone_info" = "This phone number was bought on **Fragment** on {date} for {price}"; "lng_collectible_phone_copy" = "Copy Phone Number"; "lng_collectible_learn_more" = "Learn More"; +"lng_collectible_phone_copied" = "Phone number copied to clipboard."; "lng_settings_section_info" = "Info"; diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index b91813e167ce1f..c1274732275272 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -1163,9 +1163,9 @@ bool Application::openCustomUrl( return false; } static const auto kTagExp = QRegularExpression( - u"\\~[a-zA-Z0-9_\\-]+\\~:"_q); + u"^\\~[a-zA-Z0-9_\\-]+\\~:"_q); auto skip = protocol.size(); - const auto match = kTagExp.match(urlTrimmed, skip); + const auto match = kTagExp.match(base::StringViewMid(urlTrimmed, skip)); if (match.hasMatch()) { skip += match.capturedLength(); } diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 910d291e992f70..c07832e9a7ae41 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -785,9 +785,9 @@ bool CopyPeerId( Window::SessionController *controller, const Match &match, const QVariant &context) { - TextUtilities::SetClipboardText(TextForMimeData{ match->captured(1) }); + TextUtilities::SetClipboardText({ match->captured(1) }); if (controller) { - controller->showToast(tr::lng_text_copied(tr::now)); + controller->showToast(u"ID copied to clipboard."_q); } return true; } @@ -926,6 +926,34 @@ bool ShowCollectibleUsername( return true; } +bool CopyUsernameLink( + Window::SessionController *controller, + const Match &match, + const QVariant &context) { + if (!controller) { + return false; + } + const auto username = match->captured(1); + TextUtilities::SetClipboardText({ + controller->session().createInternalLinkFull(username) + }); + controller->showToast(tr::lng_username_copied(tr::now)); + return true; +} + +bool CopyUsername( + Window::SessionController *controller, + const Match &match, + const QVariant &context) { + if (!controller) { + return false; + } + const auto username = match->captured(1); + TextUtilities::SetClipboardText({ '@' + username }); + controller->showToast(tr::lng_username_text_copied(tr::now)); + return true; +} + bool ShowStarsExamples( Window::SessionController *controller, const Match &match, @@ -1391,6 +1419,14 @@ const std::vector &InternalUrlHandlers() { u"^collectible_username/([a-zA-Z0-9\\-\\_\\.]+)@([0-9]+)$"_q, ShowCollectibleUsername, }, + { + u"^username_link/([a-zA-Z0-9\\-\\_\\.]+)@([0-9]+)$"_q, + CopyUsernameLink, + }, + { + u"^username_regular/([a-zA-Z0-9\\-\\_\\.]+)@([0-9]+)$"_q, + CopyUsername, + }, { u"^stars_examples$"_q, ShowStarsExamples, diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index f23cf8c1069510..55feed31799544 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -147,8 +147,10 @@ base::options::toggle ShowPeerIdBelowAbout({ + addToLink; } if (!link.isEmpty()) { + TextUtilities::SetClipboardText({ link }); if (const auto strong = weak.get()) { - FastShareLink(strong, link); + strong->showToast( + tr::lng_channel_public_link_copied(tr::now)); } } }; @@ -1074,8 +1076,65 @@ object_ptr DetailsFiller::setupInfo() { - button->width()); }, button->lifetime()); }; + const auto controller = _controller->parentController(); + const auto weak = base::make_weak(controller); + const auto peerIdRaw = QString::number(_peer->id.value); + const auto lnkHook = [=](Ui::FlatLabel::ContextMenuRequest request) { + const auto strong = weak.get(); + if (!strong || !request.link) { + return; + } + const auto url = request.link->url(); + if (url.startsWith(u"https://")) { + request.menu->addAction( + tr::lng_context_copy_link(tr::now), + [=] { + TextUtilities::SetClipboardText({ url }); + if (const auto strong = weak.get()) { + strong->showToast( + tr::lng_channel_public_link_copied(tr::now)); + } + }); + request.menu->addAction( + tr::lng_group_invite_share(tr::now), + [=] { + if (const auto strong = weak.get()) { + FastShareLink(strong, url); + } + }); + return; + } + static const auto kPrefix = QRegularExpression(u"^internal:" + "(collectible_username|username_link|username_regular)/" + "([a-zA-Z0-9\\-\\_\\.]+)@"_q); + const auto match = kPrefix.match(url); + if (!match.hasMatch()) { + return; + } + const auto username = match.captured(2); + const auto fullname = username + '@' + peerIdRaw; + const auto mentionLink = "internal:username_regular/" + fullname; + const auto linkLink = "internal:username_link/" + fullname; + const auto context = QVariant::fromValue(ClickHandlerContext{ + .sessionWindow = weak, + }); + const auto session = &strong->session(); + const auto link = session->createInternalLinkFull(username); + request.menu->addAction( + tr::lng_context_copy_mention(tr::now), + [=] { Core::App().openInternalUrl(mentionLink, context); }); + request.menu->addAction( + tr::lng_context_copy_link(tr::now), + [=] { Core::App().openInternalUrl(linkLink, context); }); + request.menu->addAction( + tr::lng_group_invite_share(tr::now), + [=] { + if (const auto strong = weak.get()) { + FastShareLink(strong, link); + } + }); + }; if (const auto user = _peer->asUser()) { - const auto controller = _controller->parentController(); if (user->session().supportMode()) { addInfoLineGeneric( user->session().supportHelper().infoLabelValue(user), @@ -1113,34 +1172,10 @@ object_ptr DetailsFiller::setupInfo() { _peer, controller, QString()); - const auto hook = [=](Ui::FlatLabel::ContextMenuRequest request) { - if (!request.link) { - return; - } - const auto text = request.link->copyToClipboardContextItemText(); - if (text.isEmpty()) { - return; - } - const auto link = request.link->copyToClipboardText(); - request.menu->addAction( - text, - [=] { QGuiApplication::clipboard()->setText(link); }); - const auto last = link.lastIndexOf('/'); - if (last < 0) { - return; - } - const auto mention = '@' + link.mid(last + 1); - if (mention.size() < 2) { - return; - } - request.menu->addAction( - tr::lng_context_copy_mention(tr::now), - [=] { QGuiApplication::clipboard()->setText(mention); }); - }; usernameLine.text->overrideLinkClickHandler(callback); usernameLine.subtext->overrideLinkClickHandler(callback); - usernameLine.text->setContextMenuHook(hook); - usernameLine.subtext->setContextMenuHook(hook); + usernameLine.text->setContextMenuHook(lnkHook); + usernameLine.subtext->setContextMenuHook(lnkHook); const auto copyUsername = Ui::CreateChild( usernameLine.text->parentWidget(), @@ -1215,6 +1250,8 @@ object_ptr DetailsFiller::setupInfo() { addToLink); linkLine.text->overrideLinkClickHandler(linkCallback); linkLine.subtext->overrideLinkClickHandler(linkCallback); + linkLine.text->setContextMenuHook(lnkHook); + linkLine.subtext->setContextMenuHook(lnkHook); { const auto qr = Ui::CreateChild( linkLine.text->parentWidget(), diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 624b488f0ade20..fba586e0d57767 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -166,13 +166,21 @@ rpl::producer UsernameValue( }) | Ui::Text::ToWithEntities(); } -QString UsernameUrl(not_null peer, const QString &username) { - return peer->isUsernameEditable(username) - ? peer->session().createInternalLinkFull(username) - : (u"internal:collectible_username/"_q - + username - + "@" - + QString::number(peer->id.value)); +QString UsernameUrl( + not_null peer, + const QString &username, + bool link) { + const auto type = !peer->isUsernameEditable(username) + ? u"collectible_username"_q + : link + ? u"username_link"_q + : u"username_regular"_q; + return u"internal:"_q + + type + + u"/"_q + + username + + "@" + + QString::number(peer->id.value); } rpl::producer> UsernamesValue( @@ -243,7 +251,7 @@ rpl::producer LinkValue(not_null peer, bool primary) { : peer->session().createInternalLinkFull(username)), .url = (username.isEmpty() ? QString() - : UsernameUrl(peer, username)), + : UsernameUrl(peer, username, true)), }; }); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.h b/Telegram/SourceFiles/info/profile/info_profile_values.h index 981b70aba15fd2..6001bd98005a25 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.h +++ b/Telegram/SourceFiles/info/profile/info_profile_values.h @@ -63,7 +63,8 @@ rpl::producer> MigratedOrMeValue( not_null peer); [[nodiscard]] QString UsernameUrl( not_null peer, - const QString &username); + const QString &username, + bool link = false); [[nodiscard]] TextWithEntities AboutWithEntities( not_null peer, const QString &value); diff --git a/Telegram/SourceFiles/ui/boxes/collectible_info_box.cpp b/Telegram/SourceFiles/ui/boxes/collectible_info_box.cpp index 4498becad171d0..d76d6802d56272 100644 --- a/Telegram/SourceFiles/ui/boxes/collectible_info_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/collectible_info_box.cpp @@ -187,12 +187,16 @@ void CollectibleInfoBox( lt_username, Ui::Text::Link(formatted), Ui::Text::WithEntities); - const auto copyCallback = [box, type, formatted, text = info.copyText] { - QGuiApplication::clipboard()->setText( - text.isEmpty() ? formatted : text); + const auto copyCallback = [box, type, formatted, text = info.copyText]( + bool copyLink) { + QGuiApplication::clipboard()->setText((text.isEmpty() || !copyLink) + ? formatted + : text); box->uiShow()->showToast((type == CollectibleType::Phone) - ? tr::lng_text_copied(tr::now) - : tr::lng_username_copied(tr::now)); + ? tr::lng_collectible_phone_copied(tr::now) + : copyLink + ? tr::lng_username_copied(tr::now) + : tr::lng_username_text_copied(tr::now)); }; box->addRow( object_ptr( @@ -201,7 +205,7 @@ void CollectibleInfoBox( st::collectibleHeader), st::collectibleHeaderPadding )->setClickHandlerFilter([copyCallback](const auto &...) { - copyCallback(); + copyCallback(false); return false; }); @@ -242,7 +246,9 @@ void CollectibleInfoBox( st::collectibleCopy); const auto copy = owned.data(); copy->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); - copy->setClickedCallback(copyCallback); + copy->setClickedCallback([copyCallback] { + copyCallback(true); + }); box->addButton(std::move(owned)); box->setNoContentMargin(true); From 388325a49652e4493d4a82d2ddd256300c1bee82 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 13:32:28 +0400 Subject: [PATCH 08/40] Set dpi awareness in the manifest. --- Telegram/Resources/winrc/Telegram.manifest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Telegram/Resources/winrc/Telegram.manifest b/Telegram/Resources/winrc/Telegram.manifest index 75569a75f11ddf..014c43ed54a377 100644 --- a/Telegram/Resources/winrc/Telegram.manifest +++ b/Telegram/Resources/winrc/Telegram.manifest @@ -16,6 +16,8 @@ + true/pm + PerMonitor UTF-8 From ac7b2e0da0abcede5f56aba066a5ae6a616c1e83 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 13:52:18 +0400 Subject: [PATCH 09/40] Keyboard navigation in closed topics. Fixes #27319. Fixes #28288. --- .../view/history_view_chat_preview.cpp | 5 ++++ .../history/view/history_view_list_widget.cpp | 23 +++++++++++++++---- .../history/view/history_view_list_widget.h | 5 ++++ .../view/history_view_replies_section.cpp | 4 +++- .../view/history_view_scheduled_section.cpp | 4 +++- .../business/settings_shortcut_messages.cpp | 4 +++- Telegram/lib_ui | 2 +- 7 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp index 3ab2ada3249f8e..1184746958399c 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp @@ -480,6 +480,11 @@ void Item::setupHistory() { using Type = Ui::ElasticScroll::OverscrollType; _scroll->setOverscrollTypes(Type::Real, Type::Real); + _inner->scrollKeyEvents( + ) | rpl::start_with_next([=](not_null e) { + _scroll->keyPressEvent(e); + }, lifetime()); + _scroll->events() | rpl::start_with_next([=](not_null e) { if (e->type() == QEvent::MouseButtonDblClick) { const auto button = static_cast(e.get())->button(); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 6f6484dc9a84b0..cef7612e9131cf 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -2604,7 +2604,11 @@ auto ListWidget::countScrollState() const -> ScrollTopState { } void ListWidget::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { + const auto key = e->key(); + const auto hasModifiers = (Qt::NoModifier != + (e->modifiers() + & ~(Qt::KeypadModifier | Qt::GroupSwitchModifier))); + if (key == Qt::Key_Escape || key == Qt::Key_Back) { if (hasSelectedText() || hasSelectedItems()) { cancelSelection(); } else { @@ -2616,22 +2620,33 @@ void ListWidget::keyPressEvent(QKeyEvent *e) { && !hasCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(getSelectedText()); #ifdef Q_OS_MAC - } else if (e->key() == Qt::Key_E + } else if (key == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier) && !showCopyRestriction() && !hasCopyRestrictionForSelected()) { TextUtilities::SetClipboardText(getSelectedText(), QClipboard::FindBuffer); #endif // Q_OS_MAC - } else if (e == QKeySequence::Delete || e->key() == Qt::Key_Backspace) { + } else if (e == QKeySequence::Delete || key == Qt::Key_Backspace) { _delegate->listDeleteRequest(); + } else if (!hasModifiers + && ((key == Qt::Key_Up) + || (key == Qt::Key_Down) + || (key == Qt::Key_PageUp) + || (key == Qt::Key_PageDown))) { + _scrollKeyEvents.fire(std::move(e)); } else if (!(e->modifiers() & ~Qt::ShiftModifier) - && e->key() != Qt::Key_Shift) { + && key != Qt::Key_Shift) { _delegate->listTryProcessKeyInput(e); } else { e->ignore(); } } +auto ListWidget::scrollKeyEvents() const +-> rpl::producer> { + return _scrollKeyEvents.events(); +} + void ListWidget::mouseDoubleClickEvent(QMouseEvent *e) { mouseActionStart(e->globalPos(), e->button()); trySwitchToWordSelection(); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 09121d3570a108..6be42640639196 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -382,6 +382,10 @@ class ListWidget final const TextState &reactionState) const; void toggleFavoriteReaction(not_null view) const; + + [[nodiscard]] auto scrollKeyEvents() const + -> rpl::producer>; + // ElementDelegate interface. Context elementContext() override; bool elementUnderCursor(not_null view) override; @@ -851,6 +855,7 @@ class ListWidget final rpl::event_stream _requestedToReplyToMessage; rpl::event_stream _requestedToReadMessage; rpl::event_stream _requestedToShowMessage; + rpl::event_stream> _scrollKeyEvents; rpl::lifetime _viewerLifetime; diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 845b70fcefe8d5..1ecf43c290af68 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -797,7 +797,9 @@ void RepliesWidget::setupComposeControls() { } }, lifetime()); - _composeControls->scrollKeyEvents( + rpl::merge( + _composeControls->scrollKeyEvents(), + _inner->scrollKeyEvents() ) | rpl::start_with_next([=](not_null e) { _scroll->keyPressEvent(e); }, lifetime()); diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 054c8f66b8d65c..cb5352f0b8e657 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -378,7 +378,9 @@ void ScheduledWidget::setupComposeControls() { } }, lifetime()); - _composeControls->scrollKeyEvents( + rpl::merge( + _composeControls->scrollKeyEvents(), + _inner->scrollKeyEvents() ) | rpl::start_with_next([=](not_null e) { _scroll->keyPressEvent(e); }, lifetime()); diff --git a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp index 68e4b8cc18333f..1610aafee8d57a 100644 --- a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp +++ b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp @@ -715,7 +715,9 @@ void ShortcutMessages::setupComposeControls() { } }, lifetime()); - _composeControls->scrollKeyEvents( + rpl::merge( + _composeControls->scrollKeyEvents(), + _inner->scrollKeyEvents() ) | rpl::start_with_next([=](not_null e) { _scroll->keyPressEvent(e); }, lifetime()); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 6ce5ec6e43a286..4ae0ffe56efb20 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 6ce5ec6e43a28678ca89fd89b2fa90164e5bcef1 +Subproject commit 4ae0ffe56efb20f795062713780c79e79cd39879 From 2d20e7a9e21334119e1e59dba6962844fa03008b Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 14:14:54 +0400 Subject: [PATCH 10/40] Add keyboard navigation to chat preview. --- .../SourceFiles/history/view/history_view_chat_preview.cpp | 5 +++++ .../SourceFiles/history/view/history_view_chat_preview.h | 1 + Telegram/SourceFiles/window/window_chat_preview.cpp | 3 ++- Telegram/lib_ui | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp index 1184746958399c..4747ce6096f88e 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp @@ -509,6 +509,10 @@ void Item::setupHistory() { _inner->refreshViewer(); _inner->setAttribute(Qt::WA_TransparentForMouseEvents); + + crl::on_main(this, [=] { + _inner->setFocus(); + }); } void Item::paintEvent(QPaintEvent *e) { @@ -537,6 +541,7 @@ bool Item::listScrollTo(int top, bool syntetic) { } void Item::listCancelRequest() { + _actions.fire({ .cancel = true }); } void Item::listDeleteRequest() { diff --git a/Telegram/SourceFiles/history/view/history_view_chat_preview.h b/Telegram/SourceFiles/history/view/history_view_chat_preview.h index 0598725c21226f..fa9e582a03c3e1 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_preview.h +++ b/Telegram/SourceFiles/history/view/history_view_chat_preview.h @@ -21,6 +21,7 @@ namespace HistoryView { struct ChatPreviewAction { FullMsgId openItemId; + bool cancel = false; bool openInfo = false; bool markRead = false; bool markUnread = false; diff --git a/Telegram/SourceFiles/window/window_chat_preview.cpp b/Telegram/SourceFiles/window/window_chat_preview.cpp index e95d58d4c57509..2a9607accbb4cd 100644 --- a/Telegram/SourceFiles/window/window_chat_preview.cpp +++ b/Telegram/SourceFiles/window/window_chat_preview.cpp @@ -64,7 +64,8 @@ bool ChatPreviewManager::show( if (const auto thread = weakThread.get()) { const auto itemId = action.openItemId; const auto owner = &thread->owner(); - if (action.markRead) { + if (action.cancel) { + } else if (action.markRead) { MarkAsReadThread(thread); } else if (action.markUnread) { if (const auto history = thread->asHistory()) { diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 4ae0ffe56efb20..bc5f66913dbc4e 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 4ae0ffe56efb20f795062713780c79e79cd39879 +Subproject commit bc5f66913dbc4e68d2d4314240d68df681284d3b From 6a69447d90e7f6c61aa92aab1e6eabe2fa340870 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 7 Oct 2024 18:47:31 +0300 Subject: [PATCH 11/40] Fixed non focused window when process credits payment from web view bot. --- Telegram/SourceFiles/payments/payments_non_panel_process.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Telegram/SourceFiles/payments/payments_non_panel_process.cpp b/Telegram/SourceFiles/payments/payments_non_panel_process.cpp index baa019072edb02..9f3652b1a04b79 100644 --- a/Telegram/SourceFiles/payments/payments_non_panel_process.cpp +++ b/Telegram/SourceFiles/payments/payments_non_panel_process.cpp @@ -138,6 +138,7 @@ Fn ProcessNonPanelPaymentFormFactory( controller->content().get(), form, maybeReturnToBot); + controller->window().activate(); }, [&](const CreditsReceiptPtr &receipt) { ProcessCreditsReceipt(controller, receipt, maybeReturnToBot); }, [](RealFormPresentedNotification) {}); From 86fa98dfbb2e4e75a629405e77047fedddae8450 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 7 Oct 2024 19:14:31 +0300 Subject: [PATCH 12/40] Fixed position of mini stars in header if gift box. --- Telegram/SourceFiles/boxes/star_gift_box.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index f1eed48e2efe6c..70737c2c0c5136 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -1255,7 +1255,7 @@ void GiftBox( stUser.photoSize * 2); content->sizeValue( ) | rpl::start_with_next([=](const QSize &size) { - widget->moveToLeft(stUser.photoSize / 2, 0); + widget->moveToLeft((size.width() - widget->width()) / 2, 0); const auto starsRect = Rect(widget->size()); stars->setPosition(starsRect.topLeft()); stars->setSize(starsRect.size()); From a32a9aa3fcbb0adb724101ff5d233f1ef2a04b41 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 8 Oct 2024 16:48:19 +0300 Subject: [PATCH 13/40] Added experimental option to disable floating reactions strip. --- .../reactions/history_view_reactions_button.cpp | 13 +++++++++++++ .../view/reactions/history_view_reactions_button.h | 2 ++ .../SourceFiles/settings/settings_experimental.cpp | 2 ++ Telegram/SourceFiles/window/main_window.cpp | 3 ++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp index 9f2759f36ba952..eee39b863ec7bd 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp @@ -22,6 +22,7 @@ For license and copyright information please follow this link: #include "core/click_handler_types.h" #include "main/main_session.h" #include "base/event_filter.h" +#include "base/options.h" #include "styles/style_chat.h" #include "styles/style_chat_helpers.h" #include "styles/style_menu_icons.h" @@ -59,8 +60,15 @@ constexpr auto kRefreshListDelay = crl::time(100); return CountMaxSizeWithMargins(st::reactionCornerShadow); } +base::options::toggle OptionDisableFloatReactions({ + .id = kOptionDisableFloatReactions, + .name = "Disable floating reactions strip", +}); + } // namespace +const char kOptionDisableFloatReactions[] = "disable-float-reactions"; + Button::Button( Fn update, ButtonParameters parameters, @@ -445,6 +453,11 @@ void Manager::showButtonDelayed() { void Manager::applyList(const Data::PossibleItemReactionsRef &reactions) { using Button = Strip::AddedButton; + if (OptionDisableFloatReactions.value()) { + _strip.applyList({}, Button::None); + _tagsStrip = {}; + return; + } _strip.applyList( reactions.recent, (/*reactions.customAllowed diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h index 4a1842d995f63b..fc15ec1bf681fc 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h @@ -38,6 +38,8 @@ class Session; namespace HistoryView::Reactions { +extern const char kOptionDisableFloatReactions[]; + enum class ExpandDirection { Up, Down, diff --git a/Telegram/SourceFiles/settings/settings_experimental.cpp b/Telegram/SourceFiles/settings/settings_experimental.cpp index 983497e8a14de0..78711a7fad7adc 100644 --- a/Telegram/SourceFiles/settings/settings_experimental.cpp +++ b/Telegram/SourceFiles/settings/settings_experimental.cpp @@ -21,6 +21,7 @@ For license and copyright information please follow this link: #include "chat_helpers/tabbed_panel.h" #include "dialogs/dialogs_widget.h" #include "info/profile/info_profile_actions.h" +#include "history/view/reactions/history_view_reactions_button.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "media/player/media_player_instance.h" @@ -157,6 +158,7 @@ void SetupExperimental( addToggle(Data::kOptionExternalVideoPlayer); addToggle(Window::kOptionNewWindowsSizeAsFirst); addToggle(Window::kOptionDisableTouchbar); + addToggle(HistoryView::Reactions::kOptionDisableFloatReactions); } } // namespace diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 208ed561cdb8ef..1b773fd0229b6f 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -76,7 +76,8 @@ base::options::toggle OptionNewWindowsSizeAsFirst({ base::options::toggle OptionDisableTouchbar({ .id = kOptionDisableTouchbar, - .name = "Disable Touch Bar (macOS only).", + .name = "Disable Touch Bar.", + .description = "macOS only", .scope = [] { #ifdef Q_OS_MAC return true; From 9557f0c844c841b2c9dfc1e98644444668de5d96 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 8 Oct 2024 17:34:55 +0300 Subject: [PATCH 14/40] Improved quality of profile photo in share QR box. --- Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp index 579a1b88163b09..76e799686231e5 100644 --- a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp @@ -18,6 +18,8 @@ For license and copyright information please follow this link: #include "main/main_session.h" #include "qr/qr_generate.h" #include "ui/controls/userpic_button.h" +#include "ui/dynamic_image.h" +#include "ui/dynamic_thumbnails.h" #include "ui/effects/animations.h" #include "ui/image/image_prepare.h" #include "ui/layers/generic_box.h" @@ -425,10 +427,18 @@ void FillPeerQrBox( : (rpl::single(QString()) | rpl::type_erased()); }; - const auto userpic = Ui::CreateChild( - box, - peer ? peer : controller->session().user().get(), - st::defaultUserpicButton); + const auto userpic = Ui::CreateChild(box); + const auto userpicSize = st::defaultUserpicButton.photoSize; + userpic->resize(Size(userpicSize)); + const auto userpicMedia = Ui::MakeUserpicThumbnail(peer + ? peer + : controller->session().user().get()); + userpicMedia->subscribeToUpdates([=] { userpic->update(); }); + userpic->paintRequest() | rpl::start_with_next([=] { + auto p = QPainter(userpic); + p.drawImage(0, 0, userpicMedia->image(userpicSize)); + }, userpic->lifetime()); + userpic->setVisible(peer != nullptr); PrepareQrWidget( box->verticalLayout(), @@ -781,10 +791,7 @@ void FillPeerQrBox( usernameValue()).current().toUpper(); const auto link = rpl::variable(linkValue()); const auto textWidth = font->width(username); - const auto top = Ui::GrabWidget( - userpic, - {}, - Qt::transparent); + const auto top = userpicMedia->image(photoSize); const auto weak = Ui::MakeWeak(box); crl::async([=] { @@ -837,13 +844,7 @@ void FillPeerQrBox( photoSize); if (userpicToggled) { - p.drawPixmap( - (resultSize.width() - photoSize) / 2, - 0, - top.scaled( - Size(photoSize * style::DevicePixelRatio()), - Qt::IgnoreAspectRatio, - Qt::SmoothTransformation)); + p.drawImage((resultSize.width() - photoSize) / 2, 0, top); } } crl::on_main(weak, [=] { From 8d9d7c4ceae4687a75530a3da8f251e87662382b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 8 Oct 2024 18:59:36 +0300 Subject: [PATCH 15/40] Added ability to remove background from QR in share QR box. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp | 76 +++++++++++++++---- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 20f7825cbb0f6c..16af5903f52286 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -5631,6 +5631,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_qr_box_quality1" = "Normal"; "lng_qr_box_quality2" = "High"; "lng_qr_box_quality3" = "Very High"; +"lng_qr_box_transparent_background" = "Transparent Background"; // Wnd specific diff --git a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp index 76e799686231e5..8a44464c7c9ec3 100644 --- a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp @@ -59,7 +59,11 @@ using Colors = std::vector; st::profileQrBackgroundMargins.bottom()); } -[[nodiscard]] QImage TelegramQr(const Qr::Data &data, int pixel, int max) { +[[nodiscard]] QImage TelegramQr( + const Qr::Data &data, + int pixel, + int max, + bool hasWhiteBackground) { Expects(data.size > 0); constexpr auto kCenterRatio = 0.175; @@ -70,8 +74,8 @@ using Colors = std::vector; auto qr = Qr::Generate( data, pixel * style::DevicePixelRatio(), - Qt::transparent, - Qt::white); + hasWhiteBackground ? Qt::transparent : Qt::black, + hasWhiteBackground ? Qt::white : Qt::transparent); { auto p = QPainter(&qr); auto hq = PainterHighQualityEnabler(p); @@ -81,10 +85,16 @@ using Colors = std::vector; - Margins((size.width() - (size.width() * kCenterRatio)) / 2); p.setPen(Qt::NoPen); p.setBrush(Qt::white); - p.setCompositionMode(QPainter::CompositionMode_Clear); - p.drawEllipse(centerRect); - p.setCompositionMode(QPainter::CompositionMode_SourceOver); - svg.render(&p, centerRect); + if (hasWhiteBackground) { + p.setCompositionMode(QPainter::CompositionMode_Clear); + p.drawEllipse(centerRect); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + svg.render(&p, centerRect); + } else { + p.drawEllipse(centerRect); + p.setCompositionMode(QPainter::CompositionMode_Clear); + svg.render(&p, centerRect); + } } return qr; } @@ -112,10 +122,11 @@ void Paint( int qrPixel, int radius, int textMaxHeight, - int photoSize) { + int photoSize, + bool hasWhiteBackground) { auto hq = PainterHighQualityEnabler(p); p.setPen(Qt::NoPen); - p.setBrush(Qt::white); + p.setBrush(hasWhiteBackground ? Qt::white : Qt::transparent); const auto roundedRect = qrRect + RoundedMargins(backgroundMargins, photoSize, textMaxHeight); p.drawRoundedRect(roundedRect, radius, radius); @@ -132,7 +143,9 @@ void Paint( backgroundColors, gradientRotation, 1. - (gradientRotationAdd / 45.)); - p.drawImage(qrRect, back); + if (hasWhiteBackground) { + p.drawImage(qrRect, back); + } const auto coloredSize = QSize(back.width(), textMaxHeight); auto colored = QImage( coloredSize * style::DevicePixelRatio(), @@ -151,7 +164,17 @@ void Paint( p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.drawImage(0, -back.height() + textMaxHeight, back); } - p.drawImage(qrRect, qrImage); + if (!hasWhiteBackground) { + auto copy = qrImage; + { + auto p = QPainter(©); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.drawImage(Rect(copy.size()), back); + } + p.drawImage(qrRect, copy); + } else { + p.drawImage(qrRect, qrImage); + } if (textMaxHeight) { p.drawImage( qrRect.x() - textAdditionalWidth / 2, @@ -168,6 +191,7 @@ not_null PrepareQrWidget( not_null topWidget, const style::font &font, rpl::producer userpicToggled, + rpl::producer backgroundToggled, rpl::producer username, rpl::producer links, rpl::producer bgs, @@ -187,6 +211,7 @@ not_null PrepareQrWidget( int textWidth = 0; int textMaxHeight = 0; int photoSize = 0; + bool backgroundToggled = false; }; const auto result = Ui::CreateChild(divider); topWidget->setParent(result); @@ -201,6 +226,7 @@ not_null PrepareQrWidget( st::creditsBoxAboutDivider); rpl::combine( std::move(userpicToggled), + std::move(backgroundToggled), std::move(username), std::move(bgs), std::move(links), @@ -208,11 +234,13 @@ not_null PrepareQrWidget( rpl::single(rpl::empty) | rpl::then(style::PaletteChanged()) ) | rpl::start_with_next([=]( bool userpicToggled, + bool backgroundToggled, const QString &username, const Colors &backgroundColors, const QString &link, const QString &about, const auto &) { + state->backgroundToggled = backgroundToggled; state->backgroundMargins = userpicToggled ? st::profileQrBackgroundMargins : NoPhotoBackgroundMargins(); @@ -230,7 +258,8 @@ not_null PrepareQrWidget( state->qrImage = TelegramQr( Qr::Encode(link.toUtf8(), Qr::Redundancy::Default), st::introQrPixel, - downTo).scaled( + downTo, + backgroundToggled).scaled( Size(qrMaxSize * style::DevicePixelRatio()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); @@ -293,7 +322,8 @@ not_null PrepareQrWidget( st::introQrPixel, st::profileQrBackgroundRadius, state->textMaxHeight, - state->photoSize); + state->photoSize, + state->backgroundToggled); if (!state->photoSize) { return; } @@ -395,6 +425,7 @@ void FillPeerQrBox( Ui::RpWidget* saveButton = nullptr; rpl::variable saveButtonBusy = false; rpl::variable userpicToggled = true; + rpl::variable backgroundToggled = true; rpl::variable bgs; Ui::Animations::Simple animation; rpl::variable chosen = 0; @@ -445,6 +476,7 @@ void FillPeerQrBox( userpic, state->font, state->userpicToggled.value(), + state->backgroundToggled.value(), usernameValue(), linkValue(), state->bgs.value(), @@ -729,6 +761,17 @@ void FillPeerQrBox( state->userpicToggled = !state->userpicToggled.current(); }); } + { + const auto backgroundToggle = box->verticalLayout()->add( + object_ptr( + box->verticalLayout(), + tr::lng_qr_box_transparent_background(), + st::settingsButtonNoIcon)); + backgroundToggle->toggleOn(state->backgroundToggled.value(), true); + backgroundToggle->setClickedCallback([=] { + state->backgroundToggled = !state->backgroundToggled.current(); + }); + } Ui::AddSkip(box->verticalLayout()); Ui::AddSkip(box->verticalLayout()); @@ -750,6 +793,7 @@ void FillPeerQrBox( } const auto userpicToggled = state->userpicToggled.current(); + const auto backgroundToggled = state->backgroundToggled.current(); const auto scale = style::kScaleDefault * (kMaxQualities + int(state->scaleValue.current() * 2)); const auto divider = std::max(1, style::Scale()) @@ -800,7 +844,8 @@ void FillPeerQrBox( link.current().toUtf8(), Qr::Redundancy::Default), introQrPixel, - qrMaxSize); + qrMaxSize, + backgroundToggled); const auto textMaxWidth = backgroundMargins.left() + (qrImage.width() / style::DevicePixelRatio()); const auto lines = int(textWidth / textMaxWidth) + 1; @@ -841,7 +886,8 @@ void FillPeerQrBox( introQrPixel, profileQrBackgroundRadius, textMaxHeight, - photoSize); + photoSize, + backgroundToggled); if (userpicToggled) { p.drawImage((resultSize.width() - photoSize) / 2, 0, top); From 44aa2aec5de7f8fee66bc5017fb7aac05903a87b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 8 Oct 2024 21:20:00 +0300 Subject: [PATCH 16/40] Added ability to change font size in share QR box. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp | 85 +++++++++++++++---- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 16af5903f52286..b69b92614e64fb 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -5632,6 +5632,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_qr_box_quality2" = "High"; "lng_qr_box_quality3" = "Very High"; "lng_qr_box_transparent_background" = "Transparent Background"; +"lng_qr_box_font_size" = "Font size"; // Wnd specific diff --git a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp index 8a44464c7c9ec3..1c5c516e7971a8 100644 --- a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp @@ -59,6 +59,13 @@ using Colors = std::vector; st::profileQrBackgroundMargins.bottom()); } +[[nodiscard]] style::font CreateFont(int size, int scale) { + return style::font( + style::ConvertScale(size, scale), + st::profileQrFont->flags(), + st::profileQrFont->family()); +} + [[nodiscard]] QImage TelegramQr( const Qr::Data &data, int pixel, @@ -189,7 +196,7 @@ void Paint( not_null PrepareQrWidget( not_null container, not_null topWidget, - const style::font &font, + rpl::producer fontSizeValue, rpl::producer userpicToggled, rpl::producer backgroundToggled, rpl::producer username, @@ -204,6 +211,7 @@ not_null PrepareQrWidget( } Ui::Animations::Basic updating; + style::font font; QImage qrImage; Colors backgroundColors; QString text; @@ -225,6 +233,7 @@ not_null PrepareQrWidget( divider, st::creditsBoxAboutDivider); rpl::combine( + std::move(fontSizeValue), std::move(userpicToggled), std::move(backgroundToggled), std::move(username), @@ -233,6 +242,7 @@ not_null PrepareQrWidget( std::move(about), rpl::single(rpl::empty) | rpl::then(style::PaletteChanged()) ) | rpl::start_with_next([=]( + int fontSize, bool userpicToggled, bool backgroundToggled, const QString &username, @@ -240,6 +250,7 @@ not_null PrepareQrWidget( const QString &link, const QString &about, const auto &) { + state->font = CreateFont(fontSize, style::Scale()); state->backgroundToggled = backgroundToggled; state->backgroundMargins = userpicToggled ? st::profileQrBackgroundMargins @@ -249,7 +260,7 @@ not_null PrepareQrWidget( : 0; state->backgroundColors = backgroundColors; state->text = username.toUpper(); - state->textWidth = font->width(state->text); + state->textWidth = state->font->width(state->text); { const auto remainder = qrMaxSize % st::introQrPixel; const auto downTo = remainder @@ -273,7 +284,9 @@ not_null PrepareQrWidget( const auto textMaxWidth = state->backgroundMargins.left() + (state->qrImage.width() / style::DevicePixelRatio()); const auto lines = int(state->textWidth / textMaxWidth) + 1; - state->textMaxHeight = state->textWidth ? (font->height * lines) : 0; + state->textMaxHeight = state->textWidth + ? (state->font->height * lines) + : 0; const auto whiteMargins = RoundedMargins( state->backgroundMargins, state->photoSize, @@ -312,7 +325,7 @@ not_null PrepareQrWidget( st::profileQrBackgroundPadding.top() + state->photoSize / 2); Paint( p, - font, + state->font, state->text, state->backgroundColors, state->backgroundMargins, @@ -392,7 +405,7 @@ not_null PrepareQrWidget( if (index == i) { const auto x = ((g.width() - bigDot->width()) * i) / float64(count - 1); - bigDot->move(g.x() + std::ceil(x), bigTop); + bigDot->move(g.x() + std::round(x), bigTop); } else { const auto k = (i < index) ? i : i - 1; const auto w = smallDots[k]->width(); @@ -430,18 +443,10 @@ void FillPeerQrBox( Ui::Animations::Simple animation; rpl::variable chosen = 0; rpl::variable scaleValue = 0; - - style::font font; + rpl::variable fontSizeValue = 28; }; const auto state = box->lifetime().make_state(); state->userpicToggled = !(customLink || !peer); - const auto createFont = [=](int scale) { - return style::font( - style::ConvertScale(30, scale), - st::profileQrFont->flags(), - st::profileQrFont->family()); - }; - state->font = createFont(style::Scale()); const auto usernameValue = [=] { return (customLink || !peer) @@ -474,7 +479,7 @@ void FillPeerQrBox( PrepareQrWidget( box->verticalLayout(), userpic, - state->font, + state->fontSizeValue.value(), state->userpicToggled.value(), state->backgroundToggled.value(), usernameValue(), @@ -744,6 +749,54 @@ void FillPeerQrBox( }, [](int) {}); } + { + Ui::AddSkip(box->verticalLayout()); + Ui::AddSkip(box->verticalLayout()); + Ui::AddSubsectionTitle( + box->verticalLayout(), + tr::lng_qr_box_font_size()); + Ui::AddSkip(box->verticalLayout()); + const auto seekSize = st::settingsScale.seekSize.height(); + const auto &labelSt = st::defaultFlatLabel; + + const auto slider = box->verticalLayout()->add( + object_ptr( + box->verticalLayout(), + st::settingsScale), + st::boxRowPadding); + slider->resize(slider->width(), seekSize); + const auto kSizeAmount = 8; + const auto kMinSize = 20; + const auto kMaxSize = 36; + const auto kStep = (kMaxSize - kMinSize) / (kSizeAmount - 1); + const auto updateGeometry = AddDotsToSlider( + slider, + st::settingsScale, + kSizeAmount); + const auto fontSizeToIndex = [=](int fontSize) { + return (fontSize - kMinSize) / kStep; + }; + const auto indexToFontSize = [=](int index) { + return kMinSize + index * kStep; + }; + slider->geometryValue( + ) | rpl::start_with_next([=](const QRect &rect) { + updateGeometry(fontSizeToIndex(state->fontSizeValue.current())); + }, box->lifetime()); + + box->setShowFinishedCallback([=] { + updateGeometry(fontSizeToIndex(state->fontSizeValue.current())); + }); + slider->setPseudoDiscrete( + kSizeAmount, + [=](int index) { return indexToFontSize(index); }, + state->fontSizeValue.current(), + [=](int fontSize) { + state->fontSizeValue = fontSize; + updateGeometry(fontSizeToIndex(fontSize)); + }, + [](int) {}); + } Ui::AddSkip(box->verticalLayout()); Ui::AddSkip(box->verticalLayout()); if (peer) { @@ -830,7 +883,7 @@ void FillPeerQrBox( scale) : 0; - const auto font = createFont(scale); + const auto font = CreateFont(state->fontSizeValue.current(), scale); const auto username = rpl::variable( usernameValue()).current().toUpper(); const auto link = rpl::variable(linkValue()); From 73b63aa414a5bc8953db480bcc98af559e5ab0a2 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 8 Oct 2024 21:41:40 +0300 Subject: [PATCH 17/40] Fixed update of width for username label in profile section. --- .../info/profile/info_profile_actions.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 55feed31799544..cc93514805cd65 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -1064,16 +1064,19 @@ object_ptr DetailsFiller::setupInfo() { not_null button, not_null label) { const auto parent = label->parentWidget(); - result->sizeValue() | rpl::start_with_next([=] { + rpl::combine( + label->geometryValue(), + button->sizeValue() + ) | rpl::start_with_next([=](const QRect &, const QSize &buttonSize) { const auto s = parent->size(); button->moveToRight( 0, - (s.height() - button->height()) / 2); + (s.height() - buttonSize.height()) / 2); label->resizeToWidth( s.width() - label->geometry().left() - st::lineWidth * 2 - - button->width()); + - buttonSize.width()); }, button->lifetime()); }; const auto controller = _controller->parentController(); @@ -1177,11 +1180,11 @@ object_ptr DetailsFiller::setupInfo() { usernameLine.text->setContextMenuHook(lnkHook); usernameLine.subtext->setContextMenuHook(lnkHook); - const auto copyUsername = Ui::CreateChild( + const auto qrButton = Ui::CreateChild( usernameLine.text->parentWidget(), st::infoProfileLabeledButtonQr); - fitLabelToButton(copyUsername, usernameLine.text); - copyUsername->setClickedCallback([=] { + fitLabelToButton(qrButton, usernameLine.text); + qrButton->setClickedCallback([=] { controller->show( Box(Ui::FillPeerQrBox, user, std::nullopt, nullptr)); return false; From e57742e7de64534e444e4f644f7513c47218ad4d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 14:32:11 +0400 Subject: [PATCH 18/40] Don't show non-working wallpaper button. --- .../history/view/media/history_view_theme_document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp index ef72e8f0858031..66db7403677a39 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp @@ -517,7 +517,7 @@ TextWithEntities ThemeDocumentBox::subtitle() { } rpl::producer ThemeDocumentBox::button() { - if (_parent->data()->out()) { + if (_parent->data()->out() || _parent->history()->peer->isChannel()) { return {}; } return rpl::conditional( From fdf826b686aac2d971f8f9ad20eb9aa4155df4aa Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 14:51:12 +0400 Subject: [PATCH 19/40] Improve gifts layout a bit. --- .../SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp | 6 +++++- .../SourceFiles/info/profile/info_profile_inner_widget.cpp | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp index 83649bf5a4b11d..dd12b664681edd 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp @@ -82,7 +82,7 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor) { }, [&](const GiftTypeStars &data) { _price.setMarkedText( st::semiboldTextStyle, - _delegate->star().append(QString::number(data.stars)), + _delegate->star().append(' ' + QString::number(data.stars)), kMarkupTextOptions, _delegate->textContext()); _userpic = !data.userpic @@ -284,6 +284,10 @@ void GiftButton::paintEvent(QPaintEvent *e) { const auto twidth = font->width(text); const auto pos = position + QPoint(singlew - twidth, font->height); p.save(); + const auto rubberOut = _extend.top(); + const auto inner = rect().marginsRemoved(_extend); + p.setClipRect(inner.marginsAdded( + { rubberOut, rubberOut, rubberOut, rubberOut })); p.translate(pos); p.rotate(45.); p.translate(-pos); diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index be2a2bb29074d9..5a9a819420c7e2 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -253,6 +253,9 @@ object_ptr InnerWidget::setupSharedMedia( if (!_topic) { addStoriesButton(_peer, st::infoIconMediaStories); + if (const auto user = _peer->asUser()) { + addPeerGiftsButton(user, st::infoIconMediaGifts); + } addSavedSublistButton(_peer, st::infoIconMediaSaved); } addMediaButton(MediaType::Photo, st::infoIconMediaPhoto); @@ -264,7 +267,6 @@ object_ptr InnerWidget::setupSharedMedia( addMediaButton(MediaType::GIF, st::infoIconMediaGif); if (const auto user = _peer->asUser()) { addCommonGroupsButton(user, st::infoIconMediaGroup); - addPeerGiftsButton(user, st::infoIconMediaGifts); } else if (const auto channel = _peer->asChannel()) { addSimilarChannelsButton(channel, st::infoIconMediaChannel); } From 6812e17d072428db806bf4a1c87d0316aa83d9b6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 16:26:32 +0400 Subject: [PATCH 20/40] Improve star gift size in the box. --- .../settings/settings_credits_graphics.cpp | 15 +++++++++------ Telegram/SourceFiles/ui/effects/credits.style | 4 ++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index 01ffb1aff3014a..1e92b697ba5f51 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -782,10 +782,13 @@ void ReceiptCreditsBox( std::unique_ptr lottie; rpl::lifetime downloadLifetime; }; - Ui::AddSkip(content, st::creditsHistoryEntryGiftStickerSpace - - (isStarGift ? st::creditsHistoryEntryGiftStickerSkip : 0)); + Ui::AddSkip(content, isStarGift + ? st::creditsHistoryEntryStarGiftSpace + : st::creditsHistoryEntryGiftStickerSpace); const auto icon = Ui::CreateChild(content); - icon->resize(Size(st::creditsHistoryEntryGiftStickerSize)); + icon->resize(Size(isStarGift + ? st::creditsHistoryEntryStarGiftSize + : st::creditsHistoryEntryGiftStickerSize)); const auto state = icon->lifetime().make_state(); auto &packs = session->giftBoxStickersPacks(); const auto document = starGiftSticker @@ -834,9 +837,9 @@ void ReceiptCreditsBox( }, icon->lifetime()); content->sizeValue( ) | rpl::start_with_next([=](const QSize &size) { - icon->move( - (size.width() - icon->width()) / 2, - isStarGift ? 0 : st::creditsHistoryEntryGiftStickerSkip); + icon->move((size.width() - icon->width()) / 2, isStarGift + ? st::creditsHistoryEntryStarGiftSkip + : st::creditsHistoryEntryGiftStickerSkip); }, icon->lifetime()); } else { const auto widget = content->add( diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style index 52453cfbed7d5a..b0861a8dca680c 100644 --- a/Telegram/SourceFiles/ui/effects/credits.style +++ b/Telegram/SourceFiles/ui/effects/credits.style @@ -54,6 +54,10 @@ creditsHistoryEntryGiftStickerSkip: -20px; creditsHistoryEntryGiftStickerSize: 150px; creditsHistoryEntryGiftStickerSpace: 105px; +creditsHistoryEntryStarGiftSkip: 10px; +creditsHistoryEntryStarGiftSize: 120px; +creditsHistoryEntryStarGiftSpace: 125px; + creditsGiftBox: Box(defaultBox) { shadowIgnoreTopSkip: true; } From 394ef139551c204eb3db8bb6a747460688754476 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 22:33:57 +0400 Subject: [PATCH 21/40] Fix code block language change. Fixes #28513. --- Telegram/lib_ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index bc5f66913dbc4e..1f2806546f2caf 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit bc5f66913dbc4e68d2d4314240d68df681284d3b +Subproject commit 1f2806546f2caf413608939c816348cc2bb9fd30 From 566f27913714a11f27765dd64301a750bec8871f Mon Sep 17 00:00:00 2001 From: K900 Date: Thu, 10 Oct 2024 21:15:57 +0300 Subject: [PATCH 22/40] Fix build without QT_IMPLICIT_QCHAR_CONSTRUCTION --- Telegram/SourceFiles/data/data_document.cpp | 16 ++++++++-------- Telegram/SourceFiles/data/data_wall_paper.cpp | 4 ++-- Telegram/SourceFiles/lang/lang_cloud_manager.cpp | 2 +- .../passport/ui/passport_details_row.cpp | 4 ++-- .../settings/business/settings_quick_replies.cpp | 8 ++++---- .../storage/details/storage_file_utilities.cpp | 2 +- Telegram/SourceFiles/ui/widgets/color_editor.cpp | 4 ++-- .../window/themes/window_theme_editor_block.cpp | 4 ++-- Telegram/codegen | 2 +- Telegram/lib_base | 2 +- Telegram/lib_ui | 2 +- cmake | 2 +- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 9c25a78613fb2a..5456ef2807afa0 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -936,14 +936,14 @@ void DocumentData::setFileName(const QString &remoteFileName) { // in filenames, because they introduce a security issue, when // an executable "Fil[x]gepj.exe" may look like "Filexe.jpeg". QChar controls[] = { - 0x200E, // LTR Mark - 0x200F, // RTL Mark - 0x202A, // LTR Embedding - 0x202B, // RTL Embedding - 0x202D, // LTR Override - 0x202E, // RTL Override - 0x2066, // LTR Isolate - 0x2067, // RTL Isolate + QChar(0x200E), // LTR Mark + QChar(0x200F), // RTL Mark + QChar(0x202A), // LTR Embedding + QChar(0x202B), // RTL Embedding + QChar(0x202D), // LTR Override + QChar(0x202E), // RTL Override + QChar(0x2066), // LTR Isolate + QChar(0x2067), // RTL Isolate }; for (const auto &ch : controls) { _filename = std::move(_filename).replace(ch, "_"); diff --git a/Telegram/SourceFiles/data/data_wall_paper.cpp b/Telegram/SourceFiles/data/data_wall_paper.cpp index 1bfd653359919f..0234bdbb410d49 100644 --- a/Telegram/SourceFiles/data/data_wall_paper.cpp +++ b/Telegram/SourceFiles/data/data_wall_paper.cpp @@ -150,8 +150,8 @@ using Ui::MaybeColorFromSerialized; const auto hex = [](int value) { value = std::clamp(value, 0, 15); return (value > 9) - ? ('a' + (value - 10)) - : ('0' + value); + ? QChar('a' + (value - 10)) + : QChar('0' + value); }; return QString() + hex(value / 16) + hex(value % 16); }; diff --git a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp index 8c98b96d13c2dc..5bbe85cedfb5ff 100644 --- a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp +++ b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp @@ -434,7 +434,7 @@ void CloudManager::requestLanguageAndSwitch( void CloudManager::sendSwitchingToLanguageRequest() { if (!_api) { - _switchingToLanguageId = -1; + _switchingToLanguageRequest = -1; return; } _api->request(_switchingToLanguageRequest).cancel(); diff --git a/Telegram/SourceFiles/passport/ui/passport_details_row.cpp b/Telegram/SourceFiles/passport/ui/passport_details_row.cpp index b50ff5164b5c17..55739b7dbb6622 100644 --- a/Telegram/SourceFiles/passport/ui/passport_details_row.cpp +++ b/Telegram/SourceFiles/passport/ui/passport_details_row.cpp @@ -527,9 +527,9 @@ void DateInput::correctValue( if (accumulated > _maxValue || (limit == _maxDigits && oldLength > _maxDigits)) { if (oldCursor > limit) { - _putNext.fire('0' + (accumulated % 10)); + _putNext.fire(QChar('0' + (accumulated % 10))); } else { - _putNext.fire(0); + _putNext.fire(QChar(0)); } } } diff --git a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp index 941409f98bafdb..e59ef7061d7020 100644 --- a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp +++ b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp @@ -171,10 +171,10 @@ void QuickReplies::setupContent( } for (const auto &ch : name) { if (!ch.isLetterOrNumber() - && (ch != '_') - && (ch != 0x200c) - && (ch != 0x00b7) - && (ch < 0x0d80 || ch > 0x0dff)) { + && (ch != QChar('_')) + && (ch.unicode() != 0x200c) + && (ch.unicode() != 0x00b7) + && (ch.unicode() < 0x0d80 || ch.unicode() > 0x0dff)) { return false; } } diff --git a/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp b/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp index 0ef6baa634735f..b4338484f8f52d 100644 --- a/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp +++ b/Telegram/SourceFiles/storage/details/storage_file_utilities.cpp @@ -243,7 +243,7 @@ QString ToFilePart(FileKey val) { result.reserve(0x10); for (int32 i = 0; i < 0x10; ++i) { uchar v = (val & 0x0F); - result.push_back((v < 0x0A) ? ('0' + v) : ('A' + (v - 0x0A))); + result.push_back((v < 0x0A) ? QChar('0' + v) : QChar('A' + (v - 0x0A))); val >>= 4; } return result; diff --git a/Telegram/SourceFiles/ui/widgets/color_editor.cpp b/Telegram/SourceFiles/ui/widgets/color_editor.cpp index bf2ba26fcfc1c9..c8fc937f8b37b1 100644 --- a/Telegram/SourceFiles/ui/widgets/color_editor.cpp +++ b/Telegram/SourceFiles/ui/widgets/color_editor.cpp @@ -997,9 +997,9 @@ void ColorEditor::updateResultField() { auto text = QString(); const auto addHex = [&text](int value) { if (value >= 0 && value <= 9) { - text.append('0' + value); + text.append(QChar('0' + value)); } else if (value >= 10 && value <= 15) { - text.append('a' + (value - 10)); + text.append(QChar('a' + (value - 10))); } }; const auto addValue = [&](int value) { diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp index 9c0c85cc346529..cd5b5d84e40fb6 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp @@ -134,9 +134,9 @@ void EditorBlock::Row::setValue(QColor value) { void EditorBlock::Row::fillValueString() { auto addHex = [=](int code) { if (code >= 0 && code < 10) { - _valueString.append('0' + code); + _valueString.append(QChar('0' + code)); } else if (code >= 10 && code < 16) { - _valueString.append('a' + (code - 10)); + _valueString.append(QChar('a' + (code - 10))); } }; auto addCode = [=](int code) { diff --git a/Telegram/codegen b/Telegram/codegen index 25301a3c1e899f..4155b9ae2d4c5a 160000 --- a/Telegram/codegen +++ b/Telegram/codegen @@ -1 +1 @@ -Subproject commit 25301a3c1e899f218e79f6727bc7dd96036da982 +Subproject commit 4155b9ae2d4c5a37b9738afa8ef9fa20d8fdcb44 diff --git a/Telegram/lib_base b/Telegram/lib_base index 168e70e390684e..21d1ac8bfcca03 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 168e70e390684e8e45d6c088c92a7cfdf822b76b +Subproject commit 21d1ac8bfcca03f67d7f6df75e265cd5597dc101 diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 1f2806546f2caf..e76eaecc9d8cae 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 1f2806546f2caf413608939c816348cc2bb9fd30 +Subproject commit e76eaecc9d8cae7e50ca24a71833bc219f750a19 diff --git a/cmake b/cmake index 82ae419da99140..3ca8fb8c91fdf5 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 82ae419da99140aa5f0e3e4e4ae214d0e948efea +Subproject commit 3ca8fb8c91fdf5b52565a8294f6cb33e8b6d6852 From f2e0e481de5d379b9542f6ff9021fab5d409c1d4 Mon Sep 17 00:00:00 2001 From: K900 Date: Fri, 11 Oct 2024 14:16:45 +0300 Subject: [PATCH 23/40] Update for lib_ui API change --- Telegram/SourceFiles/storage/storage_account.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/storage/storage_account.cpp b/Telegram/SourceFiles/storage/storage_account.cpp index 074812e138eed8..a24a6e6fc0be49 100644 --- a/Telegram/SourceFiles/storage/storage_account.cpp +++ b/Telegram/SourceFiles/storage/storage_account.cpp @@ -2709,7 +2709,7 @@ std::optional Account::saveRecentHashtags( auto found = false; auto m = QRegularExpressionMatch(); auto recent = getPack(); - for (auto i = 0, next = 0; (m = TextUtilities::RegExpHashtag().match(text, i)).hasMatch(); i = next) { + for (auto i = 0, next = 0; (m = TextUtilities::RegExpHashtag(false).match(text, i)).hasMatch(); i = next) { i = m.capturedStart(); next = m.capturedEnd(); if (m.hasMatch()) { From a88f48cd935dee313bd727c2cdc9600b6f99769d Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 12 Oct 2024 09:58:40 +0400 Subject: [PATCH 24/40] Fallback to portal on Linux if QStyleHints::colorScheme is unknown --- .../platform/linux/integration_linux.cpp | 47 +++++++++++++++---- .../platform/linux/specific_linux.cpp | 8 +--- .../window/themes/window_theme.cpp | 6 ++- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/integration_linux.cpp b/Telegram/SourceFiles/platform/linux/integration_linux.cpp index 147a9f03c66228..8a7db94ed4064c 100644 --- a/Telegram/SourceFiles/platform/linux/integration_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/integration_linux.cpp @@ -17,6 +17,7 @@ For license and copyright information please follow this link: #include "base/random.h" #include +#include #include #include @@ -189,24 +190,30 @@ class LinuxIntegration final : public Integration, public base::has_weak_ptr { const gi::ref_ptr _application; XdpInhibit::InhibitProxy _inhibitProxy; -#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) + rpl::variable> _darkMode; base::Platform::XDP::SettingWatcher _darkModeWatcher; -#endif // Qt < 6.5.0 + rpl::lifetime _lifetime; }; LinuxIntegration::LinuxIntegration() : _application(MakeApplication()) -#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) +, _darkMode([]() -> std::optional { + if (auto value = base::Platform::XDP::ReadSetting( + "org.freedesktop.appearance", + "color-scheme")) { + return value->get_uint32() == 1; + } + return std::nullopt; +}) , _darkModeWatcher( "org.freedesktop.appearance", "color-scheme", - [](GLib::Variant value) { + [=](GLib::Variant value) { Core::Sandbox::Instance().customEnterFromEventLoop([&] { - Core::App().settings().setSystemDarkMode(value.get_uint32() == 1); + _darkMode = value.get_uint32() == 1; }); -}) -#endif // Qt < 6.5.0 -{ + } +) { LOG(("Icon theme: %1").arg(QIcon::themeName())); LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName())); @@ -230,6 +237,30 @@ void LinuxIntegration::init() { initInhibit(); })); + + _darkMode.value() +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + | rpl::filter([] { + return QGuiApplication::styleHints()->colorScheme() + == Qt::ColorScheme::Unknown; + }) +#endif // Qt >= 6.5.0 + | rpl::start_with_next([](std::optional value) { + Core::App().settings().setSystemDarkMode(value); + }, _lifetime); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + Core::App().settings().systemDarkModeValue( + ) | rpl::filter([=](std::optional value) { + return !value && _darkMode.current(); + }) | rpl::start_with_next([=] { + crl::on_main(this, [=] { + if (!Core::App().settings().systemDarkMode()) { + Core::App().settings().setSystemDarkMode(_darkMode.current()); + } + }); + }, _lifetime); +#endif // Qt >= 6.5.0 } void LinuxIntegration::initInhibit() { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index b49cef3bbe6104..d4b438a4d4a255 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -536,13 +536,7 @@ QString SingleInstanceLocalServerName(const QString &hash) { #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) std::optional IsDarkMode() { - auto result = base::Platform::XDP::ReadSetting( - "org.freedesktop.appearance", - "color-scheme"); - - return result.has_value() - ? std::make_optional(result->get_uint32() == 1) - : std::nullopt; + return std::nullopt; } #endif // Qt < 6.5.0 diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 640a9b19cc9c22..899534d9e78a17 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -529,6 +529,8 @@ void ChatBackground::start() { #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) rpl::single( QGuiApplication::styleHints()->colorScheme() + ) | rpl::filter( + rpl::mappers::_1 != Qt::ColorScheme::Unknown ) | rpl::then( base::qt_signal_producer( QGuiApplication::styleHints(), @@ -542,7 +544,9 @@ void ChatBackground::start() { Core::App().settings().setSystemDarkMode(dark); }, _lifetime); #else // Qt >= 6.5.0 - Core::App().settings().setSystemDarkMode(Platform::IsDarkMode()); + if (const auto dark = Platform::IsDarkMode()) { + Core::App().settings().setSystemDarkMode(dark); + } #endif // Qt < 6.5.0 } From ba31756bf93d29868a6ecd762b75ef67ef0ed113 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 11 Oct 2024 09:47:52 +0400 Subject: [PATCH 25/40] Fix build with MSVC. --- Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp index 1c5c516e7971a8..5b094a9e80701a 100644 --- a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp @@ -757,7 +757,6 @@ void FillPeerQrBox( tr::lng_qr_box_font_size()); Ui::AddSkip(box->verticalLayout()); const auto seekSize = st::settingsScale.seekSize.height(); - const auto &labelSt = st::defaultFlatLabel; const auto slider = box->verticalLayout()->add( object_ptr( From 5767cbd0e313a34569b83a9ef440c68c6e8a1825 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 11 Oct 2024 18:19:40 +0400 Subject: [PATCH 26/40] Fix send menus with additional items. --- .../SourceFiles/boxes/sticker_set_box.cpp | 12 +- .../chat_helpers/gifs_list_widget.cpp | 13 +- .../chat_helpers/stickers_list_widget.cpp | 13 +- .../inline_bots/inline_results_inner.cpp | 15 ++- Telegram/SourceFiles/menu/menu_send.cpp | 116 ++++++++++-------- Telegram/SourceFiles/menu/menu_send.h | 7 ++ 6 files changed, 122 insertions(+), 54 deletions(-) diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index dd98ff312d8a2f..14902a9eeed641 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -1428,9 +1428,13 @@ void StickerSetBox::Inner::contextMenuEvent(QContextMenuEvent *e) { const auto send = crl::guard(this, [=](Api::SendOptions options) { chosen(index, document, options); }); + + // In case we're adding items after FillSendMenu we have + // to pass nullptr for showForEffect and attach selector later. + // Otherwise added items widths won't be respected in menu geometry. SendMenu::FillSendMenu( _menu.get(), - _show, + nullptr, // showForEffect details, SendMenu::DefaultCallback(_show, send)); @@ -1464,6 +1468,12 @@ void StickerSetBox::Inner::contextMenuEvent(QContextMenuEvent *e) { .isAttention = true, }); } + + SendMenu::AttachSendMenuEffect( + _menu.get(), + _show, + details, + SendMenu::DefaultCallback(_show, send)); } if (_menu->empty()) { _menu = nullptr; diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index c048232955240a..72865ea018acb0 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -402,9 +402,13 @@ base::unique_qptr GifsListWidget::fillContextMenu( // inline results don't have effects copyDetails.effectAllowed = false; } + + // In case we're adding items after FillSendMenu we have + // to pass nullptr for showForEffect and attach selector later. + // Otherwise added items widths won't be respected in menu geometry. SendMenu::FillSendMenu( menu, - _show, + nullptr, // showForMenu copyDetails, SendMenu::DefaultCallback(_show, send), icons); @@ -441,6 +445,13 @@ base::unique_qptr GifsListWidget::fillContextMenu( AddGifAction(std::move(callback), _show, document, icons); } } + + SendMenu::AttachSendMenuEffect( + menu, + _show, + copyDetails, + SendMenu::DefaultCallback(_show, send)); + return menu; } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index c3af5e2628cb6a..8eb165894471b5 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -1780,9 +1780,13 @@ base::unique_qptr StickersListWidget::fillContextMenu( }); }); const auto icons = &st().icons; + + // In case we're adding items after FillSendMenu we have + // to pass nullptr for showForEffect and attach selector later. + // Otherwise added items widths won't be respected in menu geometry. SendMenu::FillSendMenu( menu, - _show, + nullptr, // showForEffect details, SendMenu::DefaultCallback(_show, send), icons); @@ -1816,6 +1820,13 @@ base::unique_qptr StickersListWidget::fillContextMenu( false); }, &icons->menuRecentRemove); } + + SendMenu::AttachSendMenuEffect( + menu, + _show, + details, + SendMenu::DefaultCallback(_show, send)); + return menu; } diff --git a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp index 3caba7536f2b9a..6f1ae7916f9fe1 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp @@ -346,11 +346,16 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { const auto send = crl::guard(this, [=](Api::SendOptions options) { selectInlineResult(selected, options, false); }); + const auto show = _controller->uiShow(); + + // In case we're adding items after FillSendMenu we have + // to pass nullptr for showForEffect and attach selector later. + // Otherwise added items widths won't be respected in menu geometry. SendMenu::FillSendMenu( _menu, - _controller->uiShow(), + nullptr, // showForEffect details, - SendMenu::DefaultCallback(_controller->uiShow(), send)); + SendMenu::DefaultCallback(show, send)); const auto item = _mosaic.itemAt(_selected); if (const auto previewDocument = item->getPreviewDocument()) { @@ -366,6 +371,12 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { previewDocument); } + SendMenu::AttachSendMenuEffect( + _menu, + show, + details, + SendMenu::DefaultCallback(show, send)); + if (!_menu->empty()) { _menu->popup(QCursor::pos()); } diff --git a/Telegram/SourceFiles/menu/menu_send.cpp b/Telegram/SourceFiles/menu/menu_send.cpp index 3cf7a94dfbc3ea..fdc0ec07c5a97e 100644 --- a/Telegram/SourceFiles/menu/menu_send.cpp +++ b/Telegram/SourceFiles/menu/menu_send.cpp @@ -609,6 +609,67 @@ Fn DefaultCallback( }; } +FillMenuResult AttachSendMenuEffect( + not_null menu, + std::shared_ptr show, + Details details, + Fn action, + std::optional desiredPositionOverride) { + Expects(show != nullptr); + + using namespace HistoryView::Reactions; + const auto effect = std::make_shared>(); + const auto position = desiredPositionOverride.value_or(QCursor::pos()); + const auto selector = (show && details.effectAllowed) + ? AttachSelectorToMenu( + menu, + position, + st::reactPanelEmojiPan, + show, + LookupPossibleEffects(&show->session()), + { tr::lng_effect_add_title(tr::now) }, + nullptr, // iconFactory + [=] { return (*effect) != nullptr; }) // paused + : base::make_unexpected(AttachSelectorResult::Skipped); + if (!selector) { + if (selector.error() == AttachSelectorResult::Failed) { + return FillMenuResult::Failed; + } + menu->prepareGeometryFor(position); + return FillMenuResult::Prepared; + } + + (*selector)->chosen( + ) | rpl::start_with_next([=](ChosenReaction chosen) { + const auto &reactions = show->session().data().reactions(); + const auto &effects = reactions.list(Data::Reactions::Type::Effects); + const auto i = ranges::find(effects, chosen.id, &Data::Reaction::id); + if (i != end(effects)) { + if (const auto strong = effect->data()) { + strong->hideAnimated(); + } + const auto weak = Ui::MakeWeak(menu); + const auto done = [=] { + delete effect->data(); + if (const auto strong = weak.data()) { + strong->hideMenu(true); + } + }; + *effect = Ui::CreateChild( + menu, + show, + details, + menu->mapFromGlobal(chosen.globalGeometry.center()), + *i, + action, + crl::guard(menu, done)); + (*effect)->show(); + } + }, menu->lifetime()); + + return FillMenuResult::Prepared; +} + FillMenuResult FillSendMenu( not_null menu, std::shared_ptr showForEffect, @@ -691,57 +752,14 @@ FillMenuResult FillSendMenu( &icons.menuPrice); } - using namespace HistoryView::Reactions; - const auto effect = std::make_shared>(); - const auto position = desiredPositionOverride.value_or(QCursor::pos()); - const auto selector = (showForEffect && details.effectAllowed) - ? AttachSelectorToMenu( + return showForEffect + ? AttachSendMenuEffect( menu, - position, - st::reactPanelEmojiPan, showForEffect, - LookupPossibleEffects(&showForEffect->session()), - { tr::lng_effect_add_title(tr::now) }, - nullptr, // iconFactory - [=] { return (*effect) != nullptr; }) // paused - : base::make_unexpected(AttachSelectorResult::Skipped); - if (!selector) { - if (selector.error() == AttachSelectorResult::Failed) { - return FillMenuResult::Failed; - } - menu->prepareGeometryFor(position); - return FillMenuResult::Prepared; - } - - (*selector)->chosen( - ) | rpl::start_with_next([=](ChosenReaction chosen) { - const auto &reactions = showForEffect->session().data().reactions(); - const auto &effects = reactions.list(Data::Reactions::Type::Effects); - const auto i = ranges::find(effects, chosen.id, &Data::Reaction::id); - if (i != end(effects)) { - if (const auto strong = effect->data()) { - strong->hideAnimated(); - } - const auto weak = Ui::MakeWeak(menu); - const auto done = [=] { - delete effect->data(); - if (const auto strong = weak.data()) { - strong->hideMenu(true); - } - }; - *effect = Ui::CreateChild( - menu, - showForEffect, - details, - menu->mapFromGlobal(chosen.globalGeometry.center()), - *i, - action, - crl::guard(menu, done)); - (*effect)->show(); - } - }, menu->lifetime()); - - return FillMenuResult::Prepared; + details, + action, + desiredPositionOverride) + : FillMenuResult::Prepared; } void SetupMenuAndShortcuts( diff --git a/Telegram/SourceFiles/menu/menu_send.h b/Telegram/SourceFiles/menu/menu_send.h index 5c3a99bae9cf9b..a361dc11651a87 100644 --- a/Telegram/SourceFiles/menu/menu_send.h +++ b/Telegram/SourceFiles/menu/menu_send.h @@ -90,6 +90,13 @@ FillMenuResult FillSendMenu( const style::ComposeIcons *iconsOverride = nullptr, std::optional desiredPositionOverride = std::nullopt); +FillMenuResult AttachSendMenuEffect( + not_null menu, + std::shared_ptr show, + Details details, + Fn action, + std::optional desiredPositionOverride = std::nullopt); + void SetupMenuAndShortcuts( not_null button, std::shared_ptr show, From 73f38c896f7b55d9f735ca1e188d89e588c67eb7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 14 Oct 2024 10:48:37 +0400 Subject: [PATCH 27/40] Use new phrase for miniapp launch confirmation. --- .../inline_bots/bot_attach_web_view.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 8daa1006bb4514..a89e904e9633eb 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -821,15 +821,20 @@ void WebViewInstance::confirmOpen(Fn done) { botClose(); close(); }; + _parentShow->show(Box([=](not_null box) { FillBotUsepic(box, _bot, _context.controller); Ui::ConfirmBox(box, { - .text = tr::lng_allow_bot_webview_details_about( + .text = tr::lng_profile_open_app_about( tr::now, + lt_terms, + Ui::Text::Link( + tr::lng_profile_open_app_terms(tr::now), + tr::lng_mini_apps_tos_url(tr::now)), Ui::Text::RichLangValue), .confirmed = crl::guard(this, callback), .cancelled = crl::guard(this, cancel), - .confirmText = tr::lng_box_ok(), + .confirmText = tr::lng_view_button_bot_app(), }); })); } @@ -849,11 +854,16 @@ void WebViewInstance::confirmAppOpen( }; FillBotUsepic(box, _bot, _context.controller); Ui::ConfirmBox(box, { - tr::lng_allow_bot_webview_details_about( + tr::lng_profile_open_app_about( tr::now, + lt_terms, + Ui::Text::Link( + tr::lng_profile_open_app_terms(tr::now), + tr::lng_mini_apps_tos_url(tr::now)), Ui::Text::RichLangValue), crl::guard(this, callback), crl::guard(this, cancelled), + tr::lng_view_button_bot_app(), }); if (writeAccess) { (*allowed) = box->addRow( From e00e562b5f985e1ed1bd1ae481115bfe0a68436b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 11 Oct 2024 19:59:34 +0300 Subject: [PATCH 28/40] Fixed update of width for usernames label in profile section as well. --- Telegram/SourceFiles/info/profile/info_profile_actions.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index cc93514805cd65..4fc4d060d3916a 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -1184,6 +1184,7 @@ object_ptr DetailsFiller::setupInfo() { usernameLine.text->parentWidget(), st::infoProfileLabeledButtonQr); fitLabelToButton(qrButton, usernameLine.text); + fitLabelToButton(qrButton, usernameLine.subtext); qrButton->setClickedCallback([=] { controller->show( Box(Ui::FillPeerQrBox, user, std::nullopt, nullptr)); @@ -1260,6 +1261,7 @@ object_ptr DetailsFiller::setupInfo() { linkLine.text->parentWidget(), st::infoProfileLabeledButtonQr); fitLabelToButton(qr, linkLine.text); + fitLabelToButton(qr, linkLine.subtext); qr->setClickedCallback([=, peer = _peer] { controller->show( Box(Ui::FillPeerQrBox, peer, std::nullopt, nullptr)); From 9064f3ba4be6867b177a724ab56c637be717764e Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 11 Oct 2024 20:03:38 +0300 Subject: [PATCH 29/40] Fixed behavior of checkbox to remove background from QR in share QR box. --- Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp index 5b094a9e80701a..526b9700e38a03 100644 --- a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp @@ -819,7 +819,9 @@ void FillPeerQrBox( box->verticalLayout(), tr::lng_qr_box_transparent_background(), st::settingsButtonNoIcon)); - backgroundToggle->toggleOn(state->backgroundToggled.value(), true); + backgroundToggle->toggleOn( + state->backgroundToggled.value() | rpl::map(!rpl::mappers::_1), + true); backgroundToggle->setClickedCallback([=] { state->backgroundToggled = !state->backgroundToggled.current(); }); From 7b4bd5696bec22d26d46cfadd86c8db79e14de5f Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 11 Oct 2024 23:04:56 +0300 Subject: [PATCH 30/40] Added check views to selection mode of messages. --- .../admin_log/history_admin_log_inner.cpp | 4 +- .../admin_log/history_admin_log_inner.h | 2 +- .../history/history_inner_widget.cpp | 92 ++++++++++++++----- .../history/history_inner_widget.h | 10 +- .../history/view/history_view_element.cpp | 24 ++++- .../history/view/history_view_element.h | 13 ++- .../history/view/history_view_list_widget.cpp | 50 +++++++++- .../history/view/history_view_list_widget.h | 11 ++- .../history/view/history_view_message.cpp | 66 ++++++++++++- .../history/view/history_view_message.h | 2 + .../view/history_view_replies_section.cpp | 2 +- Telegram/SourceFiles/ui/chat/chat.style | 5 + 12 files changed, 242 insertions(+), 39 deletions(-) diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 1edf0d15809aa2..b67629f92b4598 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -662,8 +662,8 @@ bool InnerWidget::elementUnderCursor( return (Element::Hovered() == view); } -bool InnerWidget::elementInSelectionMode() { - return false; +HistoryView::SelectionModeResult InnerWidget::elementInSelectionMode() { + return {}; } bool InnerWidget::elementIntersectsRange( diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h index ed13def82c71e7..db52cac1cbd286 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h @@ -94,7 +94,7 @@ class InnerWidget final HistoryView::Context elementContext() override; bool elementUnderCursor( not_null view) override; - bool elementInSelectionMode() override; + HistoryView::SelectionModeResult elementInSelectionMode() override; bool elementIntersectsRange( not_null view, int from, diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index fe91dbf4cad5eb..22de853c0cff21 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -43,8 +43,9 @@ For license and copyright information please follow this link: #include "ui/boxes/report_box_graphics.h" #include "ui/layers/generic_box.h" #include "ui/controls/delete_message_context_action.h" -#include "ui/painter.h" #include "ui/inactive_press.h" +#include "ui/painter.h" +#include "ui/rect.h" #include "ui/ui_utility.h" #include "window/window_session_controller.h" #include "window/window_controller.h" @@ -210,8 +211,10 @@ class HistoryMainElementDelegate final not_null view) override { return (Element::Moused() == view); } - bool elementInSelectionMode() override { - return _widget ? _widget->inSelectionMode() : false; + HistoryView::SelectionModeResult elementInSelectionMode() override { + return _widget + ? _widget->inSelectionMode() + : HistoryView::SelectionModeResult(); } bool elementIntersectsRange( not_null view, @@ -599,7 +602,7 @@ void HistoryInner::setupSwipeReply() { } }, [=, show = _controller->uiShow()](int cursorTop) { auto result = HistoryView::SwipeHandlerFinishData(); - if (inSelectionMode()) { + if (inSelectionMode().inSelectionMode) { return result; } enumerateItems([&]( @@ -1369,6 +1372,18 @@ bool HistoryInner::eventHook(QEvent *e) { return RpWidget::eventHook(e); } +int HistoryInner::SelectionViewOffset( + not_null inner, + not_null view) { + if (inner->_lastInSelectionMode) { + const auto translation + = Element::AdditionalSpaceForSelectionCheckbox(view); + const auto progress = inner->_inSelectionModeAnimation.value(1.); + return translation * progress; + } + return 0; +} + HistoryInner::VideoUserpic *HistoryInner::validateVideoUserpic( not_null peer) { if (!peer->isPremium() @@ -1705,7 +1720,7 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but && (!Element::Hovered() || !Element::Hovered()->allowTextSelectionByHandler(pressed))) { _mouseAction = MouseAction::PrepareDrag; - } else if (inSelectionMode()) { + } else if (inSelectionMode().inSelectionMode) { if (_dragStateItem && _selected.find(_dragStateItem) != _selected.cend() && Element::Hovered()) { @@ -1993,7 +2008,7 @@ void HistoryInner::mouseActionFinish( // toggle selection instead of activating the pressed link if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive - && inSelectionMode() + && inSelectionMode().inSelectionMode && button != Qt::RightButton) { if (const auto view = viewByItem(_mouseActionItem)) { if (view->toggleSelectionByHandlerClick(activated)) { @@ -2026,7 +2041,7 @@ void HistoryInner::mouseActionFinish( } if ((_mouseAction == MouseAction::PrepareSelect) && !_pressWasInactive - && inSelectionMode()) { + && inSelectionMode().inSelectionMode) { changeSelectionAsGroup( &_selected, _mouseActionItem, @@ -2043,7 +2058,7 @@ void HistoryInner::mouseActionFinish( } else if ((i == _selected.cend()) && !_dragStateItem->isService() && _dragStateItem->isRegular() - && inSelectionMode()) { + && inSelectionMode().inSelectionMode) { if (_selected.size() < MaxSelectedItems) { _selected.emplace(_dragStateItem, FullSelection); repaintItem(_mouseActionItem); @@ -2127,7 +2142,7 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) { && !ClickHandler::getPressed() && (_mouseCursorState == CursorState::None || _mouseCursorState == CursorState::Date) - && !inSelectionMode() + && !inSelectionMode().inSelectionMode && !_emptyPainter && e->button() == Qt::LeftButton) { if (const auto view = Element::Moused()) { @@ -3638,17 +3653,46 @@ bool HistoryInner::canDeleteSelected() const { && (selectedState.count == selectedState.canDeleteCount); } -bool HistoryInner::inSelectionMode() const { - if (hasSelectedItems()) { - return true; - } else if (_mouseAction == MouseAction::Selecting - && _dragSelFrom - && _dragSelTo) { - return true; - } else if (_chooseForReportReason.has_value()) { - return true; +HistoryView::SelectionModeResult HistoryInner::inSelectionMode() const { + const auto inSelectionMode = [&] { + if (hasSelectedItems()) { + return true; + } else if (_mouseAction == MouseAction::Selecting + && _dragSelFrom + && _dragSelTo) { + return true; + } else if (_chooseForReportReason.has_value()) { + return true; + } + return false; + }(); + const auto now = inSelectionMode; + if (_lastInSelectionMode != now) { + _lastInSelectionMode = now; + if (_inSelectionModeAnimation.animating()) { + const auto progress = !now + ? _inSelectionModeAnimation.value(0.) + : 1. - _inSelectionModeAnimation.value(0.); + _inSelectionModeAnimation.change( + now ? 1. : 0., + st::universalDuration * (1. - progress)); + } else { + _inSelectionModeAnimation.stop(); + _inSelectionModeAnimation.start( + [this] { + const_cast(this)->update( + QRect( + 0, + _visibleAreaTop, + width(), + _visibleAreaBottom - _visibleAreaTop)); + }, + now ? 0. : 1., + now ? 1. : 0., + st::universalDuration); + } } - return false; + return { now, _inSelectionModeAnimation.value(now ? 1. : 0.) }; } bool HistoryInner::elementIntersectsRange( @@ -3835,7 +3879,7 @@ auto HistoryInner::reactionButtonParameters( || !view->data()->canReact() || _mouseAction == MouseAction::Dragging || _mouseAction == MouseAction::Selecting - || inSelectionMode()) { + || inSelectionMode().inSelectionMode) { return {}; } auto result = view->reactionButtonParameters( @@ -3856,7 +3900,7 @@ void HistoryInner::mouseActionUpdate() { auto mousePos = mapFromGlobal(_mousePosition); auto point = _widget->clampMousePosition(mousePos); - QPoint m; + auto m = QPoint(); adjustCurrent(point.y()); const auto reactionState = _reactionsManager->buttonTextState(point); @@ -3873,6 +3917,10 @@ void HistoryInner::mouseActionUpdate() { ? _curHistory->blocks[_curBlock]->messages[_curItem].get() : nullptr; const auto item = view ? view->data().get() : nullptr; + const auto selectionViewOffset = view + ? QPoint(SelectionViewOffset(this, view), 0) + : QPoint(0, 0); + point -= selectionViewOffset; if (view) { const auto changed = (Element::Moused() != view); if (changed) { @@ -3920,7 +3968,7 @@ void HistoryInner::mouseActionUpdate() { dragState = reactionState; lnkhost = reactionView; } else if (item) { - if (item != _mouseActionItem || (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { + if (item != _mouseActionItem || ((m + selectionViewOffset) - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { if (_mouseAction == MouseAction::PrepareDrag) { _mouseAction = MouseAction::Dragging; InvokeQueued(this, [=] { performDrag(); }); diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 55418843237079..c19c3b8b0c7653 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -30,6 +30,7 @@ namespace HistoryView { class ElementDelegate; class EmojiInteractions; struct TextState; +struct SelectionModeResult; struct StateRequest; enum class CursorState : char; enum class PointState : char; @@ -135,7 +136,7 @@ class HistoryInner void clearSelected(bool onlyTextSelection = false); [[nodiscard]] MessageIdsList getSelectedItems() const; [[nodiscard]] bool hasSelectedItems() const; - [[nodiscard]] bool inSelectionMode() const; + [[nodiscard]] HistoryView::SelectionModeResult inSelectionMode() const; [[nodiscard]] bool elementIntersectsRange( not_null view, int from, @@ -243,6 +244,10 @@ class HistoryInner void onTouchSelect(); void onTouchScrollTimer(); + [[nodiscard]] static int SelectionViewOffset( + not_null inner, + not_null view); + using ChosenReaction = HistoryView::Reactions::ChosenReaction; using VideoUserpic = Dialogs::Ui::VideoUserpic; using SelectedItems = std::map>; @@ -508,6 +513,9 @@ class HistoryInner bool _dragSelecting = false; bool _wasSelectedText = false; // was some text selected in current drag action + mutable bool _lastInSelectionMode = false; + mutable Ui::Animations::Simple _inSelectionModeAnimation; + // scroll by touch support (at least Windows Surface tablets) bool _touchScroll = false; bool _touchSelect = false; diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 42174145cc7a61..880b58f75a16a3 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -37,6 +37,7 @@ For license and copyright information please follow this link: #include "ui/text/text_utilities.h" #include "ui/item_text_options.h" #include "ui/painter.h" +#include "ui/rect.h" #include "data/components/sponsored_messages.h" #include "data/data_session.h" #include "data/data_forum.h" @@ -110,8 +111,8 @@ bool DefaultElementDelegate::elementUnderCursor( return false; } -bool DefaultElementDelegate::elementInSelectionMode() { - return false; +SelectionModeResult DefaultElementDelegate::elementInSelectionMode() { + return {}; } bool DefaultElementDelegate::elementIntersectsRange( @@ -740,6 +741,25 @@ not_null Element::enforcePurchasedTag() { return Get(); } +int Element::AdditionalSpaceForSelectionCheckbox( + not_null view, + QRect countedGeometry) { + if (!view->hasOutLayout() || view->delegate()->elementIsChatWide()) { + return 0; + } + if (countedGeometry.isEmpty()) { + countedGeometry = view->innerGeometry(); + } + const auto diff = view->width() + - (countedGeometry.x() + countedGeometry.width()) + - st::msgPadding.right() + - st::msgSelectionOffset + - view->rightActionSize().value_or(QSize()).width(); + return (diff < 0) + ? -(std::min(st::msgSelectionOffset, -diff)) + : 0; +} + void Element::refreshMedia(Element *replacing) { if (_flags & Flag::MediaOverriden) { return; diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index d1ef6c282d7055..be41e07dcb41b9 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -70,12 +70,17 @@ enum class OnlyEmojiAndSpaces : char { No, }; +struct SelectionModeResult { + bool inSelectionMode = false; + float64 progress = 0.0; +}; + class Element; class ElementDelegate { public: virtual Context elementContext() = 0; virtual bool elementUnderCursor(not_null view) = 0; - virtual bool elementInSelectionMode() = 0; + virtual SelectionModeResult elementInSelectionMode() = 0; virtual bool elementIntersectsRange( not_null view, int from, @@ -131,7 +136,7 @@ class ElementDelegate { class DefaultElementDelegate : public ElementDelegate { public: bool elementUnderCursor(not_null view) override; - bool elementInSelectionMode() override; + SelectionModeResult elementInSelectionMode() override; bool elementIntersectsRange( not_null view, int from, @@ -571,6 +576,10 @@ class Element [[nodiscard]] not_null enforcePurchasedTag(); + [[nodiscard]] static int AdditionalSpaceForSelectionCheckbox( + not_null view, + QRect countedGeometry = QRect()); + virtual bool consumeHorizontalScroll(QPoint position, int delta) { return false; } diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index cef7612e9131cf..d300453f8ea399 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1229,8 +1229,34 @@ bool ListWidget::hasSelectedItems() const { return !_selected.empty(); } -bool ListWidget::inSelectionMode() const { - return hasSelectedItems() || !_dragSelected.empty(); +SelectionModeResult ListWidget::inSelectionMode() const { + const auto now = hasSelectedItems() || !_dragSelected.empty(); + if (_lastInSelectionMode != now) { + _lastInSelectionMode = now; + if (_inSelectionModeAnimation.animating()) { + const auto progress = !now + ? _inSelectionModeAnimation.value(0.) + : 1. - _inSelectionModeAnimation.value(0.); + _inSelectionModeAnimation.change( + now ? 1. : 0., + st::universalDuration * (1. - progress)); + } else { + _inSelectionModeAnimation.stop(); + _inSelectionModeAnimation.start( + [this] { + const_cast(this)->update( + QRect( + 0, + _visibleTop, + width(), + _visibleBottom - _visibleTop)); + }, + now ? 0. : 1., + now ? 1. : 0., + st::universalDuration); + } + } + return { now, _inSelectionModeAnimation.value(now ? 1. : 0.) }; } bool ListWidget::overSelectedItems() const { @@ -1751,7 +1777,7 @@ bool ListWidget::elementUnderCursor( return (_overElement == view); } -bool ListWidget::elementInSelectionMode() { +SelectionModeResult ListWidget::elementInSelectionMode() { return inSelectionMode(); } @@ -3410,7 +3436,7 @@ Reactions::ButtonParameters ListWidget::reactionButtonParameters( if (top < 0 || !view->data()->canReact() || _mouseAction == MouseAction::Dragging - || inSelectionMode()) { + || inSelectionMode().inSelectionMode) { return {}; } auto result = view->reactionButtonParameters( @@ -3536,6 +3562,19 @@ ClickHandlerContext ListWidget::prepareClickHandlerContext(FullMsgId id) { }; } +int ListWidget::SelectionViewOffset( + not_null inner, + not_null view) { + if (inner->_lastInSelectionMode) { + const auto translation + = Element::AdditionalSpaceForSelectionCheckbox(view); + const auto progress = inner->_inSelectionModeAnimation.value(1.); + return translation * progress; + } + return 0; +} + + void ListWidget::mouseActionUpdate() { auto mousePosition = mapFromGlobal(_mousePosition); auto point = QPoint( @@ -3551,6 +3590,9 @@ void ListWidget::mouseActionUpdate() { ? reactionView : strictFindItemByY(point.y()); const auto item = view ? view->data().get() : nullptr; + if (view) { + point -= QPoint(SelectionViewOffset(this, view), 0); + } const auto itemPoint = mapPointToItem(point, view); _overState = MouseState( item ? item->fullId() : FullMsgId(), diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 6be42640639196..02ec9a370ba07f 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -389,7 +389,7 @@ class ListWidget final // ElementDelegate interface. Context elementContext() override; bool elementUnderCursor(not_null view) override; - bool elementInSelectionMode() override; + SelectionModeResult elementInSelectionMode() override; bool elementIntersectsRange( not_null view, int from, @@ -459,6 +459,10 @@ class ListWidget final int resizeGetHeight(int newWidth) override; private: + [[nodiscard]] static int SelectionViewOffset( + not_null inner, + not_null view); + using ScrollTopState = ListMemento::ScrollTopState; using PointState = HistoryView::PointState; using CursorState = HistoryView::CursorState; @@ -618,7 +622,7 @@ class ListWidget final const SelectedMap::const_iterator &i); bool hasSelectedText() const; bool hasSelectedItems() const; - bool inSelectionMode() const; + SelectionModeResult inSelectionMode() const; bool overSelectedItems() const; void clearTextSelection(); void clearSelected(); @@ -830,6 +834,9 @@ class ListWidget final ElementHighlighter _highlighter; + mutable bool _lastInSelectionMode = false; + mutable Ui::Animations::Simple _inSelectionModeAnimation; + // scroll by touch support (at least Windows Surface tablets) bool _touchScroll = false; bool _touchSelect = false; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 25a57950757f3f..7c189084e80809 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1100,6 +1100,14 @@ void Message::draw(Painter &p, const PaintContext &context) const { if (hasGesture) { p.translate(context.gestureHorizontal.translation, 0); } + const auto selectionModeResult = delegate()->elementInSelectionMode(); + const auto selectionTranslation = (selectionModeResult.progress > 0) + ? (selectionModeResult.progress + * AdditionalSpaceForSelectionCheckbox(this, g)) + : 0; + if (selectionTranslation) { + p.translate(selectionTranslation, 0); + } if (item->hasUnrequestedFactcheck()) { item->history()->session().factchecks().requestFor(item); @@ -1449,7 +1457,14 @@ void Message::draw(Painter &p, const PaintContext &context) const { const auto fastShareTop = data()->isSponsored() ? g.top() + fastShareSkip : g.top() + g.height() - fastShareSkip - size->height(); + const auto o = p.opacity(); + if (selectionModeResult.progress > 0) { + p.setOpacity(1. - selectionModeResult.progress); + } drawRightAction(p, context, fastShareLeft, fastShareTop, width()); + if (selectionModeResult.progress > 0) { + p.setOpacity(o); + } } if (media) { @@ -1570,6 +1585,48 @@ void Message::draw(Painter &p, const PaintContext &context) const { } p.restore(); } + if (selectionTranslation) { + p.translate(-selectionTranslation, 0); + } + if (selectionModeResult.progress) { + const auto progress = selectionModeResult.progress; + if (progress <= 1.) { + if (context.selected()) { + if (!_selectionRoundCheckbox) { + _selectionRoundCheckbox + = std::make_unique( + st::msgSelectionCheck, + [this] { repaint(); }); + } + } + if (_selectionRoundCheckbox) { + _selectionRoundCheckbox->setChecked( + context.selected(), + anim::type::normal); + } + const auto o = ScopedPainterOpacity(p, progress); + const auto &st = st::msgSelectionCheck; + const auto pos = QPoint( + (width() + - (st::msgSelectionOffset * progress - st.size) / 2 + - st::msgPadding.right() / 2 + - st.size), + g.y() + (g.height() - st.size) / 2); + { + p.setPen(QPen(st.border, st.width)); + p.setBrush(context.st->msgServiceBg()); + auto hq = PainterHighQualityEnabler(p); + p.drawEllipse(QRect(pos, Size(st.size))); + } + if (_selectionRoundCheckbox) { + _selectionRoundCheckbox->paint(p, pos.x(), pos.y(), width()); + } + } else { + _selectionRoundCheckbox = nullptr; + } + } else { + _selectionRoundCheckbox = nullptr; + } } void Message::paintCommentsButton( @@ -2959,7 +3016,9 @@ bool Message::getStateText( void Message::updatePressed(QPoint point) { const auto item = data(); const auto media = this->media(); - if (!media) return; + if (!media) { + return; + } auto g = countGeometry(); auto keyboard = item->inlineReplyKeyboard(); @@ -3792,7 +3851,7 @@ bool Message::displayFastReply() const { return hasFastReply() && data()->isRegular() && canSendAnything() - && !delegate()->elementInSelectionMode(); + && !delegate()->elementInSelectionMode().inSelectionMode; } bool Message::displayRightActionComments() const { @@ -3956,6 +4015,9 @@ void Message::drawRightAction( ClickHandlerPtr Message::rightActionLink( std::optional pressPoint) const { + if (delegate()->elementInSelectionMode().progress > 0) { + return nullptr; + } ensureRightAction(); if (!_rightAction->link) { _rightAction->link = prepareRightActionLink(); diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index af97b8b9518545..dc35277df79cbf 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -22,6 +22,7 @@ struct ReactionId; namespace Ui { struct BubbleRounding; +class RoundCheckbox; } // namespace Ui namespace HistoryView { @@ -313,6 +314,7 @@ class Message final : public Element { mutable Ui::Text::String _fromName; mutable std::unique_ptr _fromNameStatus; + mutable std::unique_ptr _selectionRoundCheckbox; Ui::Text::String _rightBadge; mutable int _fromNameVersion = 0; uint32 _bubbleWidthLimit : 28 = 0; diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 1ecf43c290af68..1ae6f36c5b69fd 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -898,7 +898,7 @@ void RepliesWidget::setupSwipeReply() { } }, [=, show = controller()->uiShow()](int cursorTop) { auto result = HistoryView::SwipeHandlerFinishData(); - if (_inner->elementInSelectionMode()) { + if (_inner->elementInSelectionMode().inSelectionMode) { return result; } const auto view = _inner->lookupItemByY(cursorTop); diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 3369b5fb265844..cb30fdf4768001 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -26,6 +26,7 @@ msgPadding: margins(11px, 8px, 11px, 8px); msgMargin: margins(16px, 6px, 56px, 2px); msgMarginTopAttached: 0px; msgShadow: 2px; +msgSelectionOffset: 30px; historyReplyTop: 2px; historyReplyBottom: 2px; @@ -1149,3 +1150,7 @@ factcheckField: InputField(defaultInputField) { style: defaultTextStyle; } purchasedTagPadding: margins(3px, 2px, 6px, 2px); + +msgSelectionCheck: RoundCheckbox(defaultPeerListCheck) { + bgActive: boxTextFgGood; +} From 54b0d965aea9fe1b861f0fa08a8ec52a89b86c3f Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 12 Oct 2024 11:04:19 +0300 Subject: [PATCH 31/40] Slightly eased conditions for selection mode to avoid shaky animations. --- Telegram/SourceFiles/history/history_inner_widget.cpp | 8 +++++--- .../SourceFiles/history/view/history_view_list_widget.cpp | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 22de853c0cff21..cae2d2698e1ac7 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -3657,12 +3657,14 @@ HistoryView::SelectionModeResult HistoryInner::inSelectionMode() const { const auto inSelectionMode = [&] { if (hasSelectedItems()) { return true; - } else if (_mouseAction == MouseAction::Selecting - && _dragSelFrom - && _dragSelTo) { + } + const auto isSelecting = _mouseAction == MouseAction::Selecting; + if (isSelecting && _dragSelFrom && _dragSelTo) { return true; } else if (_chooseForReportReason.has_value()) { return true; + } else if (_lastInSelectionMode && isSelecting) { + return true; } return false; }(); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index d300453f8ea399..2e2c087b04a933 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1230,7 +1230,9 @@ bool ListWidget::hasSelectedItems() const { } SelectionModeResult ListWidget::inSelectionMode() const { - const auto now = hasSelectedItems() || !_dragSelected.empty(); + const auto now = hasSelectedItems() + || !_dragSelected.empty() + || (_mouseAction == MouseAction::Selecting && _lastInSelectionMode); if (_lastInSelectionMode != now) { _lastInSelectionMode = now; if (_inSelectionModeAnimation.animating()) { From 9ea78f7d28d4b26c9ad7ae548dbc3e660d8abad1 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 14 Oct 2024 06:04:19 +0300 Subject: [PATCH 32/40] Fixed display of message highlights in selection mode. --- .../history/view/history_view_message.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 7c189084e80809..6e017b597772f7 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1193,10 +1193,18 @@ void Message::draw(Painter &p, const PaintContext &context) const { } } - if (customHighlight) { - media->drawHighlight(p, context, localMediaTop); - } else { - paintHighlight(p, context, fullGeometry.height()); + { + if (selectionTranslation) { + p.translate(-selectionTranslation, 0); + } + if (customHighlight) { + media->drawHighlight(p, context, localMediaTop); + } else { + paintHighlight(p, context, fullGeometry.height()); + } + if (selectionTranslation) { + p.translate(selectionTranslation, 0); + } } const auto roll = media ? media->bubbleRoll() : Media::BubbleRoll(); From c5add2fca93a387992727dba5cf1a1a86858cd78 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 14 Oct 2024 06:22:30 +0300 Subject: [PATCH 33/40] Revert "Added experimental option to disable floating reactions strip." This reverts commit a32a9aa3fcbb0adb724101ff5d233f1ef2a04b41. --- .../reactions/history_view_reactions_button.cpp | 13 ------------- .../view/reactions/history_view_reactions_button.h | 2 -- .../SourceFiles/settings/settings_experimental.cpp | 2 -- Telegram/SourceFiles/window/main_window.cpp | 3 +-- 4 files changed, 1 insertion(+), 19 deletions(-) diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp index eee39b863ec7bd..9f2759f36ba952 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp @@ -22,7 +22,6 @@ For license and copyright information please follow this link: #include "core/click_handler_types.h" #include "main/main_session.h" #include "base/event_filter.h" -#include "base/options.h" #include "styles/style_chat.h" #include "styles/style_chat_helpers.h" #include "styles/style_menu_icons.h" @@ -60,15 +59,8 @@ constexpr auto kRefreshListDelay = crl::time(100); return CountMaxSizeWithMargins(st::reactionCornerShadow); } -base::options::toggle OptionDisableFloatReactions({ - .id = kOptionDisableFloatReactions, - .name = "Disable floating reactions strip", -}); - } // namespace -const char kOptionDisableFloatReactions[] = "disable-float-reactions"; - Button::Button( Fn update, ButtonParameters parameters, @@ -453,11 +445,6 @@ void Manager::showButtonDelayed() { void Manager::applyList(const Data::PossibleItemReactionsRef &reactions) { using Button = Strip::AddedButton; - if (OptionDisableFloatReactions.value()) { - _strip.applyList({}, Button::None); - _tagsStrip = {}; - return; - } _strip.applyList( reactions.recent, (/*reactions.customAllowed diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h index fc15ec1bf681fc..4a1842d995f63b 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h @@ -38,8 +38,6 @@ class Session; namespace HistoryView::Reactions { -extern const char kOptionDisableFloatReactions[]; - enum class ExpandDirection { Up, Down, diff --git a/Telegram/SourceFiles/settings/settings_experimental.cpp b/Telegram/SourceFiles/settings/settings_experimental.cpp index 78711a7fad7adc..983497e8a14de0 100644 --- a/Telegram/SourceFiles/settings/settings_experimental.cpp +++ b/Telegram/SourceFiles/settings/settings_experimental.cpp @@ -21,7 +21,6 @@ For license and copyright information please follow this link: #include "chat_helpers/tabbed_panel.h" #include "dialogs/dialogs_widget.h" #include "info/profile/info_profile_actions.h" -#include "history/view/reactions/history_view_reactions_button.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "media/player/media_player_instance.h" @@ -158,7 +157,6 @@ void SetupExperimental( addToggle(Data::kOptionExternalVideoPlayer); addToggle(Window::kOptionNewWindowsSizeAsFirst); addToggle(Window::kOptionDisableTouchbar); - addToggle(HistoryView::Reactions::kOptionDisableFloatReactions); } } // namespace diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 1b773fd0229b6f..208ed561cdb8ef 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -76,8 +76,7 @@ base::options::toggle OptionNewWindowsSizeAsFirst({ base::options::toggle OptionDisableTouchbar({ .id = kOptionDisableTouchbar, - .name = "Disable Touch Bar.", - .description = "macOS only", + .name = "Disable Touch Bar (macOS only).", .scope = [] { #ifdef Q_OS_MAC return true; From b64c610abb0bbbaa67cc3f501ebea1a6a8e5dcf2 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 14 Oct 2024 11:23:45 +0300 Subject: [PATCH 34/40] Fixed ability to copy shared links for channels with select restriction. Fixed #28492. --- Telegram/SourceFiles/info/media/info_media_list_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 280b35589ebb09..3b68e21d569628 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -1026,7 +1026,7 @@ void ListWidget::showContextMenu( } } } - } else if (link) { + } else if (link && !_provider->hasSelectRestriction()) { const auto actionText = link->copyToClipboardContextItemText(); if (!actionText.isEmpty()) { _contextMenu->addAction( From b3dddc1dfe19687551ad3f77992096f38f7dbb8d Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 14 Oct 2024 12:41:12 +0400 Subject: [PATCH 35/40] Fix indent of RTL text with as skip block. Fixes #27748. --- Telegram/lib_ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index e76eaecc9d8cae..a58c9a41656391 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit e76eaecc9d8cae7e50ca24a71833bc219f750a19 +Subproject commit a58c9a41656391445041a2e9afad21ad44a046cc From db475ef0b40160b288ceecea7a465e40318ba709 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 2 Oct 2024 14:56:28 +0400 Subject: [PATCH 36/40] Update API scheme to layer 190. Support adding messages to gifts of Premium subscriptions. --- Telegram/SourceFiles/boxes/star_gift_box.cpp | 14 +----------- Telegram/SourceFiles/history/history_item.cpp | 22 +++++++++++++++++-- Telegram/SourceFiles/mtproto/scheme/api.tl | 8 +++---- .../SourceFiles/payments/payments_form.cpp | 11 ++++++++-- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index 70737c2c0c5136..38262bce386676 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -1083,19 +1083,7 @@ void SendGiftBox( }; button->setClickedCallback([=] { const auto star = std::get_if(&descriptor); - if (v::is(descriptor)) { - if (state->sending) { - return; - } else { - state->sending = true; - } - SendGift( - window, - peer, - api, - GiftDetails{ descriptor }, - premiumSent); - } else if (star && star->limitedCount && !star->limitedLeft) { + if (star && star->limitedCount && !star->limitedLeft) { window->showToast({ .title = tr::lng_gift_sold_out_title(tr::now), .text = tr::lng_gift_sold_out_text( diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 46e9c52e39e47e..ec57dee505504e 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -5421,8 +5421,18 @@ void HistoryItem::applyAction(const MTPMessageAction &action) { _media = std::make_unique( this, _from, - Data::GiftType::Premium, - data.vmonths().v); + Data::GiftCode{ + .message = (data.vmessage() + ? TextWithEntities{ + .text = qs(data.vmessage()->data().vtext()), + .entities = Api::EntitiesFromMTP( + &history()->session(), + data.vmessage()->data().ventities().v), + } + : TextWithEntities()), + .count = data.vmonths().v, + .type = Data::GiftType::Premium, + }); }, [&](const MTPDmessageActionSuggestProfilePhoto &data) { data.vphoto().match([&](const MTPDphoto &photo) { _flags |= MessageFlag::IsUserpicSuggestion; @@ -5453,6 +5463,14 @@ void HistoryItem::applyAction(const MTPMessageAction &action) { _from, Data::GiftCode{ .slug = qs(data.vslug()), + .message = (data.vmessage() + ? TextWithEntities{ + .text = qs(data.vmessage()->data().vtext()), + .entities = Api::EntitiesFromMTP( + &history()->session(), + data.vmessage()->data().ventities().v), + } + : TextWithEntities()), .channel = (boostedId ? history()->owner().channel(boostedId).get() : nullptr), diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index de269021f17be8..72acb3884e23f2 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -169,13 +169,13 @@ messageActionSetChatTheme#aa786345 emoticon:string = MessageAction; messageActionChatJoinedByRequest#ebbca3cb = MessageAction; messageActionWebViewDataSentMe#47dd8079 text:string data:string = MessageAction; messageActionWebViewDataSent#b4c38cb5 text:string = MessageAction; -messageActionGiftPremium#c83d6aec flags:# currency:string amount:long months:int crypto_currency:flags.0?string crypto_amount:flags.0?long = MessageAction; +messageActionGiftPremium#6c6274fa flags:# currency:string amount:long months:int crypto_currency:flags.0?string crypto_amount:flags.0?long message:flags.1?TextWithEntities = MessageAction; messageActionTopicCreate#d999256 flags:# title:string icon_color:int icon_emoji_id:flags.0?long = MessageAction; messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags.1?long closed:flags.2?Bool hidden:flags.3?Bool = MessageAction; messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction; messageActionRequestedPeer#31518e9b button_id:int peers:Vector = MessageAction; messageActionSetChatWallPaper#5060a3f4 flags:# same:flags.0?true for_both:flags.1?true wallpaper:WallPaper = MessageAction; -messageActionGiftCode#678c2e09 flags:# via_giveaway:flags.0?true unclaimed:flags.2?true boost_peer:flags.1?Peer months:int slug:string currency:flags.2?string amount:flags.2?long crypto_currency:flags.3?string crypto_amount:flags.3?long = MessageAction; +messageActionGiftCode#56d03994 flags:# via_giveaway:flags.0?true unclaimed:flags.2?true boost_peer:flags.1?Peer months:int slug:string currency:flags.2?string amount:flags.2?long crypto_currency:flags.3?string crypto_amount:flags.3?long message:flags.4?TextWithEntities = MessageAction; messageActionGiveawayLaunch#a80f51e4 flags:# stars:flags.0?long = MessageAction; messageActionGiveawayResults#87e2f155 flags:# stars:flags.0?true winners_count:int unclaimed_count:int = MessageAction; messageActionBoostApply#cc02aa6d boosts:int = MessageAction; @@ -1476,7 +1476,7 @@ help.premiumPromo#5334759c status_text:string status_entities:Vector boost_peer:flags.0?InputPeer currency:string amount:long = InputStorePaymentPurpose; +inputStorePaymentPremiumGiftCode#fb790393 flags:# users:Vector boost_peer:flags.0?InputPeer currency:string amount:long message:flags.1?TextWithEntities = InputStorePaymentPurpose; inputStorePaymentPremiumGiveaway#160544ca flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true boost_peer:InputPeer additional_peers:flags.1?Vector countries_iso2:flags.2?Vector prize_description:flags.4?string random_id:long until_date:int currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose; @@ -2565,4 +2565,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool; fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo; -// LAYER 189 +// LAYER 190 diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index 322cb6c8090feb..56d107b7d95136 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -415,7 +415,8 @@ MTPInputInvoice Form::inputInvoice() const { using Flag = MTPDinputStorePaymentPremiumGiftCode::Flag; return MTP_inputInvoicePremiumGiftCode( MTP_inputStorePaymentPremiumGiftCode( - MTP_flags(users->boostPeer ? Flag::f_boost_peer : Flag()), + MTP_flags((users->boostPeer ? Flag::f_boost_peer : Flag()) + | (users->message.empty() ? Flag(0) : Flag::f_message)), MTP_vector_from_range(ranges::views::all( users->users ) | ranges::views::transform([](not_null user) { @@ -423,7 +424,13 @@ MTPInputInvoice Form::inputInvoice() const { })), users->boostPeer ? users->boostPeer->input : MTPInputPeer(), MTP_string(giftCode.currency), - MTP_long(giftCode.amount)), + MTP_long(giftCode.amount), + MTP_textWithEntities( + MTP_string(users->message.text), + Api::EntitiesToMTP( + &users->users.front()->session(), + users->message.entities, + Api::ConvertOption::SkipLocal))), option); } else { return MTP_inputInvoicePremiumGiftCode( From 1a0fd35f3644fc12bed8fab7ee52f44e2de4a326 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 11 Oct 2024 09:47:41 +0400 Subject: [PATCH 37/40] Check gift sold out error on sending. --- Telegram/SourceFiles/boxes/star_gift_box.cpp | 1 + .../SourceFiles/payments/payments_form.cpp | 2 ++ Telegram/SourceFiles/payments/payments_form.h | 2 ++ .../payments/payments_non_panel_process.cpp | 21 ++++++++++++++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index 38262bce386676..580db09cd3c3c3 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -842,6 +842,7 @@ void SendGift( .randomId = details.randomId, .message = details.text, .user = peer->asUser(), + .limitedCount = gift.limitedCount, .anonymous = details.anonymous, }, done, processNonPanelPaymentFormFactory); }); diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index 56d107b7d95136..7941404c464f88 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -501,11 +501,13 @@ void Form::requestForm() { .currency = currency, .amount = amount, }; + const auto gift = std::get_if(&_id.value); const auto formData = CreditsFormData{ .id = _id, .formId = data.vform_id().v, .invoice = invoice, .inputInvoice = inputInvoice(), + .starGiftLimitedCount = gift ? gift->limitedCount : 0, .starGiftForm = true, }; _updates.fire(CreditsPaymentStarted{ .data = formData }); diff --git a/Telegram/SourceFiles/payments/payments_form.h b/Telegram/SourceFiles/payments/payments_form.h index 0a364a9b16b5cf..9b0d38d4d5f94e 100644 --- a/Telegram/SourceFiles/payments/payments_form.h +++ b/Telegram/SourceFiles/payments/payments_form.h @@ -177,6 +177,7 @@ struct InvoiceStarGift { uint64 randomId = 0; TextWithEntities message; not_null user; + int limitedCount = 0; bool anonymous = false; }; @@ -198,6 +199,7 @@ struct CreditsFormData { PhotoData *photo = nullptr; InvoiceCredits invoice; MTPInputInvoice inputInvoice; + int starGiftLimitedCount = 0; bool starGiftForm = false; }; diff --git a/Telegram/SourceFiles/payments/payments_non_panel_process.cpp b/Telegram/SourceFiles/payments/payments_non_panel_process.cpp index 9f3652b1a04b79..6f348df4f33560 100644 --- a/Telegram/SourceFiles/payments/payments_non_panel_process.cpp +++ b/Telegram/SourceFiles/payments/payments_non_panel_process.cpp @@ -25,6 +25,8 @@ For license and copyright information please follow this link: #include "ui/boxes/boost_box.h" // Ui::StartFireworks. #include "ui/layers/generic_box.h" #include "ui/text/format_values.h" +#include "ui/text/text_utilities.h" +#include "ui/toast/toast.h" #include "window/window_controller.h" #include "window/window_session_controller.h" @@ -59,7 +61,24 @@ void ProcessCreditsPayment( const auto done = [=](std::optional error) { const auto onstack = maybeReturnToBot; if (error) { - show->showToast(*error); + if (*error == u"STARGIFT_USAGE_LIMITED"_q) { + if (form->starGiftLimitedCount) { + show->showToast({ + .title = tr::lng_gift_sold_out_title( + tr::now), + .text = tr::lng_gift_sold_out_text( + tr::now, + lt_count_decimal, + form->starGiftLimitedCount, + Ui::Text::RichLangValue), + }); + } else { + show->showToast( + tr::lng_gift_sold_out_title(tr::now)); + } + } else { + show->showToast(*error); + } if (onstack) { onstack(CheckoutResult::Failed); } From 4492e72ffa3750839e0207baa8cfb350930b1b39 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 14 Oct 2024 13:55:29 +0400 Subject: [PATCH 38/40] Fix web app window resize on macOS. --- Telegram/lib_ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index a58c9a41656391..21b55b21cc5fcc 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit a58c9a41656391445041a2e9afad21ad44a046cc +Subproject commit 21b55b21cc5fcc243ec01a9c3201e24b24dfd458 From cfe93530b8ca279454fa900c15f037ed2f52a920 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 14 Oct 2024 13:58:27 +0400 Subject: [PATCH 39/40] Version 5.6.2. - Message selection marks. - Better copy username / public link / ID menu in profiles. - Keyboard navigation (Up/Down/PageUp/PageDown) in chat preview. - Improved QR options for profile links. - Fix calls color problems on Windows. - Fix scroll problems on Linux. --- 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 | 9 +++++++++ 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index c2a348d684147c..0ca57011540938 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -10,7 +10,7 @@ + Version="5.6.2.0" /> Telegram Desktop Telegram Messenger LLP diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index cf66287b3b3aeb..507535ac08a16b 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 5,6,1,0 - PRODUCTVERSION 5,6,1,0 + FILEVERSION 5,6,2,0 + PRODUCTVERSION 5,6,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -62,10 +62,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop" - VALUE "FileVersion", "5.6.1.0" + VALUE "FileVersion", "5.6.2.0" VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "5.6.1.0" + VALUE "ProductVersion", "5.6.2.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 17b16de046bf09..7af91c02c9c8a2 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 5,6,1,0 - PRODUCTVERSION 5,6,1,0 + FILEVERSION 5,6,2,0 + PRODUCTVERSION 5,6,2,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", "5.6.1.0" + VALUE "FileVersion", "5.6.2.0" VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "5.6.1.0" + VALUE "ProductVersion", "5.6.2.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 6b603882ddac5e..f2ec782af2a47c 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 = 5006001; -constexpr auto AppVersionStr = "5.6.1"; +constexpr auto AppVersion = 5006002; +constexpr auto AppVersionStr = "5.6.2"; constexpr auto AppBetaVersion = false; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/build/version b/Telegram/build/version index 2ac0de6a0729e5..344e0546f17c3a 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 5006001 +AppVersion 5006002 AppVersionStrMajor 5.6 -AppVersionStrSmall 5.6.1 -AppVersionStr 5.6.1 +AppVersionStrSmall 5.6.2 +AppVersionStr 5.6.2 BetaChannel 0 AlphaVersion 0 -AppVersionOriginal 5.6.1 +AppVersionOriginal 5.6.2 diff --git a/changelog.txt b/changelog.txt index b7cd736d6d8672..4e4d9ee98feab0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,12 @@ +5.6.2 (14.10.24) + +- Message selection marks. +- Better copy username / public link / ID menu in profiles. +- Keyboard navigation (Up/Down/PageUp/PageDown) in chat preview. +- Improved QR options for profile links. +- Fix calls color problems on Windows. +- Fix scroll problems on Linux. + 5.6.1 (07.10.24) - Fix media viewer sometimes blocking the app after launch. From b41ac0fc2a55fbf2edc8c90103043bc5443d3465 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 14 Oct 2024 16:34:45 +0400 Subject: [PATCH 40/40] Version 5.6.2: Fix build with GCC. --- Telegram/SourceFiles/boxes/star_gift_box.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index 580db09cd3c3c3..5a863f6050df95 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -1074,14 +1074,6 @@ void SendGiftBox( x += single.width() + st::giftBoxGiftSkip.x(); } - const auto premiumSent = [=](Payments::CheckoutResult result) { - state->sending = false; - if (result == Payments::CheckoutResult::Paid) { - window->showPeerHistory(peer); - window->showToast( - Ui::Text::Bold(tr::lng_gift_sent_title(tr::now))); - } - }; button->setClickedCallback([=] { const auto star = std::get_if(&descriptor); if (star && star->limitedCount && !star->limitedLeft) {