From 8d0fe601cf1a16eca642de05ffb78c329963ba1e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Nov 2023 16:25:55 +0400 Subject: [PATCH 01/16] Fix sending quote data with uploaded media. Fixes #27032. --- Telegram/SourceFiles/history/history_item.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 1bd5d52c2..c9391f3fa 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -2904,11 +2904,22 @@ FullStoryId HistoryItem::replyToStory() const { } FullReplyTo HistoryItem::replyTo() const { - return { - .messageId = replyToFullId(), - .storyId = replyToStory(), + auto result = FullReplyTo{ .topicRootId = topicRootId(), }; + if (const auto reply = Get()) { + const auto &fields = reply->fields(); + const auto peer = fields.externalPeerId; + const auto replyToPeer = peer ? peer : _history->peer->id; + if (const auto id = fields.messageId) { + result.messageId = { replyToPeer, id }; + result.quote = fields.quote; + } + if (const auto id = fields.storyId) { + result.storyId = { replyToPeer, id }; + } + } + return result; } void HistoryItem::setText(const TextWithEntities &textWithEntities) { From b959877598b21de0d01e641bbf70c7fc4a75b30a Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Nov 2023 13:27:26 +0400 Subject: [PATCH 02/16] Use explicit nativeVirtualKey on Windows only. --- Telegram/lib_ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 0bee95570..85b25a109 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 0bee95570e7d28afa5cee91b3d1c642051ba1da8 +Subproject commit 85b25a109dc916356d75836bff73710c846a5a40 From f7ea0e1d00764f563e6da847a4955ba2574e65e1 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Nov 2023 16:46:17 +0400 Subject: [PATCH 03/16] Fix modifications tracking in Ui::Text::String. Fixes #27031. --- Telegram/lib_ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 85b25a109..024f438ce 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 85b25a109dc916356d75836bff73710c846a5a40 +Subproject commit 024f438ce539d627717e4793479c8b727e8df29b From c530d7cc891f6eb86691d067f40dbe9dabc7238b Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Nov 2023 17:43:58 +0400 Subject: [PATCH 04/16] Apply Ui::Text::String modifications in highlighting. --- .../history/view/history_view_element.cpp | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 1ba437586..bacc1d8af 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -1673,21 +1673,27 @@ TextSelection Element::FindSelectionFromQuote( } offset = i + 1; } - //for (const auto &modification : text.modifications()) { - // if (modification.position >= selection.to) { - // break; - // } else if (modification.position <= selection.from) { - // modified.from += modification.skipped; - // if (modification.added - // && modification.position < selection.from) { - // --modified.from; - // } - // } - // modified.to += modification.skipped; - // if (modification.added && modified.to > modified.from) { - // --modified.to; - // } - //} + for (const auto &modification : text.modifications()) { + if (modification.position >= result.to) { + break; + } + if (modification.added) { + ++result.to; + } + const auto shiftTo = std::min( + int(modification.skipped), + result.to - modification.position); + result.to -= shiftTo; + if (modification.position <= result.from) { + if (modification.added) { + ++result.from; + } + const auto shiftFrom = std::min( + int(modification.skipped), + result.from - modification.position); + result.from -= shiftFrom; + } + } return result; } From 468d4c5e4f3383dcbec01b6c09d77470c4073f5c Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 Nov 2023 18:01:41 +0400 Subject: [PATCH 05/16] Don't make multiboost badge gradient. --- Telegram/SourceFiles/ui/boxes/boost_box.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/ui/boxes/boost_box.cpp b/Telegram/SourceFiles/ui/boxes/boost_box.cpp index 83bd4fa37..0be48632c 100644 --- a/Telegram/SourceFiles/ui/boxes/boost_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/boost_box.cpp @@ -98,11 +98,7 @@ namespace { auto hq = PainterHighQualityEnabler(p); const auto radius = std::min(badge->width(), badge->height()) / 2; p.setPen(Qt::NoPen); - auto brush = QLinearGradient( - QPointF(badge->width(), badge->height()), - QPointF()); - brush.setStops(Ui::Premium::ButtonGradientStops()); - p.setBrush(brush); + p.setBrush(st::premiumButtonBg2); p.drawRoundedRect(badge->rect(), radius, radius); }, badge->lifetime()); From 1e6cf839e26408b5e6dcfc391f4c0c9554985f8c Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 11 Nov 2023 14:58:44 +0300 Subject: [PATCH 06/16] Fixed Api requests for statistics with non-default DC. --- Telegram/SourceFiles/api/api_statistics.cpp | 65 +++++-------------- Telegram/SourceFiles/api/api_statistics.h | 11 +--- Telegram/SourceFiles/data/data_channel.cpp | 4 ++ Telegram/SourceFiles/data/data_session.cpp | 9 +++ Telegram/SourceFiles/data/data_session.h | 5 ++ .../info_statistics_inner_widget.cpp | 7 +- Telegram/SourceFiles/mtproto/core_types.h | 1 + 7 files changed, 41 insertions(+), 61 deletions(-) diff --git a/Telegram/SourceFiles/api/api_statistics.cpp b/Telegram/SourceFiles/api/api_statistics.cpp index 383d0973c..12c7a313e 100644 --- a/Telegram/SourceFiles/api/api_statistics.cpp +++ b/Telegram/SourceFiles/api/api_statistics.cpp @@ -187,40 +187,37 @@ namespace { } // namespace -Statistics::Statistics(not_null api) -: _api(&api->instance()) { +Statistics::Statistics(not_null channel) +: _channel(channel) +, _api(&channel->session().api().instance()) { } -rpl::producer Statistics::request( - not_null peer) { +rpl::producer Statistics::request() { return [=](auto consumer) { auto lifetime = rpl::lifetime(); - const auto channel = peer->asChannel(); - if (!channel) { - return lifetime; - } - if (!channel->isMegagroup()) { + const auto dcId = _channel->owner().statsDcId(_channel); + if (!_channel->isMegagroup()) { _api.request(MTPstats_GetBroadcastStats( MTP_flags(MTPstats_GetBroadcastStats::Flags(0)), - channel->inputChannel + _channel->inputChannel )).done([=](const MTPstats_BroadcastStats &result) { _channelStats = ChannelStatisticsFromTL(result.data()); consumer.put_done(); }).fail([=](const MTP::Error &error) { consumer.put_error_copy(error.type()); - }).send(); + }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); } else { _api.request(MTPstats_GetMegagroupStats( MTP_flags(MTPstats_GetMegagroupStats::Flags(0)), - channel->inputChannel + _channel->inputChannel )).done([=](const MTPstats_MegagroupStats &result) { _supergroupStats = SupergroupStatisticsFromTL(result.data()); - peer->owner().processUsers(result.data().vusers()); + _channel->owner().processUsers(result.data().vusers()); consumer.put_done(); }).fail([=](const MTP::Error &error) { consumer.put_error_copy(error.type()); - }).send(); + }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); } return lifetime; @@ -228,15 +225,11 @@ rpl::producer Statistics::request( } Statistics::GraphResult Statistics::requestZoom( - not_null peer, const QString &token, float64 x) { return [=](auto consumer) { auto lifetime = rpl::lifetime(); - const auto channel = peer->asChannel(); - if (!channel) { - return lifetime; - } + const auto dcId = _channel->owner().statsDcId(_channel); const auto wasEmpty = _zoomDeque.empty(); _zoomDeque.push_back([=] { _api.request(MTPstats_LoadAsyncGraph( @@ -256,7 +249,7 @@ Statistics::GraphResult Statistics::requestZoom( } }).fail([=](const MTP::Error &error) { consumer.put_error_copy(error.type()); - }).send(); + }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); }); if (wasEmpty) { _zoomDeque.front()(); @@ -266,32 +259,6 @@ Statistics::GraphResult Statistics::requestZoom( }; } -Statistics::GraphResult Statistics::requestMessage( - not_null peer, - MsgId msgId) { - return [=](auto consumer) { - auto lifetime = rpl::lifetime(); - const auto channel = peer->asChannel(); - if (!channel) { - return lifetime; - } - - _api.request(MTPstats_GetMessageStats( - MTP_flags(MTPstats_GetMessageStats::Flags(0)), - channel->inputChannel, - MTP_int(msgId.bare) - )).done([=](const MTPstats_MessageStats &result) { - consumer.put_next( - StatisticalGraphFromTL(result.data().vviews_graph())); - consumer.put_done(); - }).fail([=](const MTP::Error &error) { - consumer.put_error_copy(error.type()); - }).send(); - - return lifetime; - }; -} - Data::ChannelStatistics Statistics::channelStats() const { return _channelStats; } @@ -314,6 +281,7 @@ void PublicForwards::request( if (_requestId) { return; } + const auto dcId = _channel->owner().statsDcId(_channel); const auto offsetPeer = _channel->owner().peer(token.fullId.peer); const auto tlOffsetPeer = offsetPeer ? offsetPeer->input @@ -396,7 +364,7 @@ void PublicForwards::request( }); }).fail([=] { _requestId = 0; - }).send(); + }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); } MessageStatistics::MessageStatistics( @@ -416,6 +384,7 @@ void MessageStatistics::request(Fn done) { if (_channel->isMegagroup()) { return; } + const auto dcId = _channel->owner().statsDcId(_channel); const auto requestFirstPublicForwards = [=]( const Data::StatisticalGraph &messageGraph, @@ -484,7 +453,7 @@ void MessageStatistics::request(Fn done) { StatisticalGraphFromTL(result.data().vviews_graph())); }).fail([=](const MTP::Error &error) { requestPrivateForwards({}); - }).send(); + }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); } diff --git a/Telegram/SourceFiles/api/api_statistics.h b/Telegram/SourceFiles/api/api_statistics.h index 460c9df9d..14ec1ccf8 100644 --- a/Telegram/SourceFiles/api/api_statistics.h +++ b/Telegram/SourceFiles/api/api_statistics.h @@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_statistics.h" #include "mtproto/sender.h" -class ApiWrap; class ChannelData; class PeerData; @@ -19,23 +18,19 @@ namespace Api { class Statistics final { public: - explicit Statistics(not_null api); + explicit Statistics(not_null channel); - [[nodiscard]] rpl::producer request( - not_null peer); + [[nodiscard]] rpl::producer request(); using GraphResult = rpl::producer; [[nodiscard]] GraphResult requestZoom( - not_null peer, const QString &token, float64 x); - [[nodiscard]] GraphResult requestMessage( - not_null peer, - MsgId msgId); [[nodiscard]] Data::ChannelStatistics channelStats() const; [[nodiscard]] Data::SupergroupStatistics supergroupStats() const; private: + const not_null _channel; Data::ChannelStatistics _channelStats; Data::SupergroupStatistics _supergroupStats; MTP::Sender _api; diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 3b26c1eb9..5daff7e17 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -1120,6 +1120,10 @@ void ApplyChannelUpdate( channel, update.vnotify_settings()); + if (update.vstats_dc()) { + channel->owner().applyStatsDcId(channel, update.vstats_dc()->v); + } + if (const auto sendAs = update.vdefault_send_as()) { session->sendAsPeers().setChosen(channel, peerFromMTP(*sendAs)); } else { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 162db84c2..bfe8019de 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -4532,6 +4532,15 @@ uint64 Session::wallpapersHash() const { return _wallpapersHash; } +MTP::DcId Session::statsDcId(not_null channel) { + const auto it = _channelStatsDcIds.find(channel); + return (it == end(_channelStatsDcIds)) ? MTP::DcId(0) : it->second; +} + +void Session::applyStatsDcId(not_null channel, MTP::DcId dcId) { + _channelStatsDcIds[channel] = dcId; +} + void Session::webViewResultSent(WebViewResultSent &&sent) { return _webViewResultSent.fire(std::move(sent)); } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index c470e3a8b..df6dc5019 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -730,6 +730,9 @@ public: [[nodiscard]] auto peerDecorationsUpdated() const -> rpl::producer>; + void applyStatsDcId(not_null, MTP::DcId); + [[nodiscard]] MTP::DcId statsDcId(not_null); + void clearLocalStorage(); private: @@ -1014,6 +1017,8 @@ private: base::flat_map, TimeId> _watchingForOffline; base::Timer _watchForOfflineTimer; + base::flat_map, MTP::DcId> _channelStatsDcIds; + rpl::event_stream _webViewResultSent; rpl::event_stream> _peerDecorationsUpdated; diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp index 19704c779..237453d6e 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp @@ -91,7 +91,6 @@ void ProcessZoom( widget->zoomRequests( ) | rpl::start_with_next([=](float64 x) { d.api->requestZoom( - d.peer, zoomToken, x ) | rpl::start_with_next_error_done([=]( @@ -144,7 +143,6 @@ void FillStatistic( m); descriptor.api->requestZoom( - descriptor.peer, graphData.zoomToken, 0 ) | rpl::start_with_next_error_done([=, graphPtr = &graphData]( @@ -524,7 +522,7 @@ void InnerWidget::load() { const auto descriptor = Descriptor{ _peer, - lifetime().make_state(&_peer->session().api()), + lifetime().make_state(_peer->asChannel()), _controller->uiShow()->toastParent(), }; @@ -543,7 +541,6 @@ void InnerWidget::load() { ) | rpl::take(1) | rpl::start_with_next([=] { if (!_contextId) { descriptor.api->request( - descriptor.peer ) | rpl::start_with_done([=] { _state.stats = Data::AnyStatistics{ descriptor.api->channelStats(), @@ -575,7 +572,7 @@ void InnerWidget::fill() { const auto inner = this; const auto descriptor = Descriptor{ _peer, - lifetime().make_state(&_peer->session().api()), + lifetime().make_state(_peer->asChannel()), _controller->uiShow()->toastParent(), }; if (_state.stats.message) { diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 0437644be..fba98aeee 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -47,6 +47,7 @@ constexpr auto kUpdaterDcShift = 0x03; constexpr auto kExportDcShift = 0x04; constexpr auto kExportMediaDcShift = 0x05; constexpr auto kGroupCallStreamDcShift = 0x06; +constexpr auto kStatsDcShift = 0x06; constexpr auto kMaxMediaDcCount = 0x10; constexpr auto kBaseDownloadDcShift = 0x10; constexpr auto kBaseUploadDcShift = 0x20; From 9324ceeb247ecc8de9f8299a9e93d92926084c0f Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 11 Nov 2023 21:20:09 +0400 Subject: [PATCH 07/16] Destory stats sessions after a timeout. --- Telegram/SourceFiles/api/api_statistics.cpp | 122 ++++++++++++++------ Telegram/SourceFiles/api/api_statistics.h | 44 +++++-- Telegram/SourceFiles/apiwrap.cpp | 28 +++++ Telegram/SourceFiles/apiwrap.h | 8 ++ Telegram/SourceFiles/data/data_session.cpp | 8 +- Telegram/SourceFiles/mtproto/core_types.h | 2 +- Telegram/SourceFiles/mtproto/mtp_instance.h | 13 ++- Telegram/SourceFiles/mtproto/sender.h | 36 ++++-- 8 files changed, 199 insertions(+), 62 deletions(-) diff --git a/Telegram/SourceFiles/api/api_statistics.cpp b/Telegram/SourceFiles/api/api_statistics.cpp index 12c7a313e..09b5c5c06 100644 --- a/Telegram/SourceFiles/api/api_statistics.cpp +++ b/Telegram/SourceFiles/api/api_statistics.cpp @@ -18,6 +18,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Api { namespace { +constexpr auto kCheckRequestsTimer = 10 * crl::time(1000); + [[nodiscard]] Data::StatisticalGraph StatisticalGraphFromTL( const MTPStatsGraph &tl) { return tl.match([&](const MTPDstatsGraph &d) { @@ -188,36 +190,91 @@ namespace { } // namespace Statistics::Statistics(not_null channel) +: StatisticsRequestSender(channel) { +} + +StatisticsRequestSender::StatisticsRequestSender(not_null channel) : _channel(channel) -, _api(&channel->session().api().instance()) { +, _api(&_channel->session().api().instance()) +, _timer([=] { checkRequests(); }) { +} + +StatisticsRequestSender::~StatisticsRequestSender() { + for (const auto &[dcId, ids] : _requests) { + for (const auto id : ids) { + _channel->session().api().unregisterStatsRequest(dcId, id); + } + } +} + +void StatisticsRequestSender::checkRequests() { + const auto api = &_channel->session().api(); + for (auto i = begin(_requests); i != end(_requests);) { + for (auto j = begin(i->second); j != end(i->second);) { + if (_api.pending(*j)) { + ++j; + } else { + _channel->session().api().unregisterStatsRequest( + i->first, + *j); + j = i->second.erase(j); + } + } + if (i->second.empty()) { + i = _requests.erase(i); + } else { + ++i; + } + } + if (_requests.empty()) { + _timer.cancel(); + } +} + +template +auto StatisticsRequestSender::makeRequest(Request &&request) { + const auto id = _api.allocateRequestId(); + const auto dcId = _channel->owner().statsDcId(_channel); + if (dcId) { + _channel->session().api().registerStatsRequest(dcId, id); + _requests[dcId].emplace(id); + if (!_timer.isActive()) { + _timer.callEach(kCheckRequestsTimer); + } + } + return std::move(_api.request( + std::forward(request) + ).toDC( + dcId ? MTP::ShiftDcId(dcId, MTP::kStatsDcShift) : 0 + ).overrideId(id)); } rpl::producer Statistics::request() { return [=](auto consumer) { auto lifetime = rpl::lifetime(); - const auto dcId = _channel->owner().statsDcId(_channel); - if (!_channel->isMegagroup()) { - _api.request(MTPstats_GetBroadcastStats( + if (!channel()->isMegagroup()) { + makeRequest(MTPstats_GetBroadcastStats( MTP_flags(MTPstats_GetBroadcastStats::Flags(0)), - _channel->inputChannel + channel()->inputChannel )).done([=](const MTPstats_BroadcastStats &result) { _channelStats = ChannelStatisticsFromTL(result.data()); consumer.put_done(); }).fail([=](const MTP::Error &error) { consumer.put_error_copy(error.type()); - }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); + }).send(); } else { - _api.request(MTPstats_GetMegagroupStats( + makeRequest(MTPstats_GetMegagroupStats( MTP_flags(MTPstats_GetMegagroupStats::Flags(0)), - _channel->inputChannel + channel()->inputChannel )).done([=](const MTPstats_MegagroupStats &result) { - _supergroupStats = SupergroupStatisticsFromTL(result.data()); - _channel->owner().processUsers(result.data().vusers()); + const auto &data = result.data(); + _supergroupStats = SupergroupStatisticsFromTL(data); + channel()->owner().processUsers(data.vusers()); consumer.put_done(); }).fail([=](const MTP::Error &error) { consumer.put_error_copy(error.type()); - }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); + }).send(); } return lifetime; @@ -229,10 +286,9 @@ Statistics::GraphResult Statistics::requestZoom( float64 x) { return [=](auto consumer) { auto lifetime = rpl::lifetime(); - const auto dcId = _channel->owner().statsDcId(_channel); const auto wasEmpty = _zoomDeque.empty(); _zoomDeque.push_back([=] { - _api.request(MTPstats_LoadAsyncGraph( + makeRequest(MTPstats_LoadAsyncGraph( MTP_flags(x ? MTPstats_LoadAsyncGraph::Flag::f_x : MTPstats_LoadAsyncGraph::Flag(0)), @@ -249,7 +305,7 @@ Statistics::GraphResult Statistics::requestZoom( } }).fail([=](const MTP::Error &error) { consumer.put_error_copy(error.type()); - }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); + }).send(); }); if (wasEmpty) { _zoomDeque.front()(); @@ -270,9 +326,8 @@ Data::SupergroupStatistics Statistics::supergroupStats() const { PublicForwards::PublicForwards( not_null channel, FullMsgId fullId) -: _channel(channel) -, _fullId(fullId) -, _api(&channel->session().api().instance()) { +: StatisticsRequestSender(channel) +, _fullId(fullId) { } void PublicForwards::request( @@ -281,20 +336,19 @@ void PublicForwards::request( if (_requestId) { return; } - const auto dcId = _channel->owner().statsDcId(_channel); - const auto offsetPeer = _channel->owner().peer(token.fullId.peer); + const auto offsetPeer = channel()->owner().peer(token.fullId.peer); const auto tlOffsetPeer = offsetPeer ? offsetPeer->input : MTP_inputPeerEmpty(); constexpr auto kLimit = tl::make_int(100); - _requestId = _api.request(MTPstats_GetMessagePublicForwards( - _channel->inputChannel, + _requestId = makeRequest(MTPstats_GetMessagePublicForwards( + channel()->inputChannel, MTP_int(_fullId.msg), MTP_int(token.rate), tlOffsetPeer, MTP_int(token.fullId.msg), kLimit - )).done([=, channel = _channel](const MTPmessages_Messages &result) { + )).done([=, channel = channel()](const MTPmessages_Messages &result) { using Messages = QVector; _requestId = 0; @@ -364,16 +418,15 @@ void PublicForwards::request( }); }).fail([=] { _requestId = 0; - }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); + }).send(); } MessageStatistics::MessageStatistics( not_null channel, FullMsgId fullId) -: _publicForwards(channel, fullId) -, _channel(channel) -, _fullId(fullId) -, _api(&channel->session().api().instance()) { +: StatisticsRequestSender(channel) +, _publicForwards(channel, fullId) +, _fullId(fullId) { } Data::PublicForwardsSlice MessageStatistics::firstSlice() const { @@ -381,11 +434,9 @@ Data::PublicForwardsSlice MessageStatistics::firstSlice() const { } void MessageStatistics::request(Fn done) { - if (_channel->isMegagroup()) { + if (channel()->isMegagroup()) { return; } - const auto dcId = _channel->owner().statsDcId(_channel); - const auto requestFirstPublicForwards = [=]( const Data::StatisticalGraph &messageGraph, const Data::StatisticsMessageInteractionInfo &info) { @@ -403,8 +454,8 @@ void MessageStatistics::request(Fn done) { const auto requestPrivateForwards = [=]( const Data::StatisticalGraph &messageGraph) { - _api.request(MTPchannels_GetMessages( - _channel->inputChannel, + api().request(MTPchannels_GetMessages( + channel()->inputChannel, MTP_vector( 1, MTP_inputMessageID(MTP_int(_fullId.msg)))) @@ -444,17 +495,16 @@ void MessageStatistics::request(Fn done) { }).send(); }; - _api.request(MTPstats_GetMessageStats( + makeRequest(MTPstats_GetMessageStats( MTP_flags(MTPstats_GetMessageStats::Flags(0)), - _channel->inputChannel, + channel()->inputChannel, MTP_int(_fullId.msg.bare) )).done([=](const MTPstats_MessageStats &result) { requestPrivateForwards( StatisticalGraphFromTL(result.data().vviews_graph())); }).fail([=](const MTP::Error &error) { requestPrivateForwards({}); - }).toDC(MTP::ShiftDcId(dcId, MTP::kStatsDcShift)).send(); - + }).send(); } Boosts::Boosts(not_null peer) diff --git a/Telegram/SourceFiles/api/api_statistics.h b/Telegram/SourceFiles/api/api_statistics.h index 14ec1ccf8..dddf3654c 100644 --- a/Telegram/SourceFiles/api/api_statistics.h +++ b/Telegram/SourceFiles/api/api_statistics.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/timer.h" #include "data/data_boosts.h" #include "data/data_statistics.h" #include "mtproto/sender.h" @@ -16,7 +17,35 @@ class PeerData; namespace Api { -class Statistics final { +class StatisticsRequestSender { +protected: + explicit StatisticsRequestSender(not_null channel); + ~StatisticsRequestSender(); + + template < + typename Request, + typename = std::enable_if_t>, + typename = typename Request::Unboxed> + [[nodiscard]] auto makeRequest(Request &&request); + + [[nodiscard]] MTP::Sender &api() { + return _api; + } + [[nodiscard]] not_null channel() { + return _channel; + } + +private: + void checkRequests(); + + const not_null _channel; + MTP::Sender _api; + base::Timer _timer; + base::flat_map> _requests; + +}; + +class Statistics final : public StatisticsRequestSender { public: explicit Statistics(not_null channel); @@ -30,34 +59,29 @@ public: [[nodiscard]] Data::SupergroupStatistics supergroupStats() const; private: - const not_null _channel; Data::ChannelStatistics _channelStats; Data::SupergroupStatistics _supergroupStats; - MTP::Sender _api; std::deque> _zoomDeque; }; -class PublicForwards final { +class PublicForwards final : public StatisticsRequestSender { public: - explicit PublicForwards(not_null channel, FullMsgId fullId); + PublicForwards(not_null channel, FullMsgId fullId); void request( const Data::PublicForwardsSlice::OffsetToken &token, Fn done); private: - const not_null _channel; const FullMsgId _fullId; mtpRequestId _requestId = 0; int _lastTotal = 0; - MTP::Sender _api; - }; -class MessageStatistics final { +class MessageStatistics final : public StatisticsRequestSender { public: explicit MessageStatistics( not_null channel, @@ -69,13 +93,11 @@ public: private: PublicForwards _publicForwards; - const not_null _channel; const FullMsgId _fullId; Data::PublicForwardsSlice _firstSlice; mtpRequestId _requestId = 0; - MTP::Sender _api; }; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index c3024e991..ea150bf9b 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -114,6 +114,7 @@ constexpr auto kStickersByEmojiInvalidateTimeout = crl::time(6 * 1000); constexpr auto kNotifySettingSaveTimeout = crl::time(1000); constexpr auto kDialogsFirstLoad = 20; constexpr auto kDialogsPerPage = 500; +constexpr auto kStatsSessionKillTimeout = 10 * crl::time(1000); using PhotoFileLocationId = Data::PhotoFileLocationId; using DocumentFileLocationId = Data::DocumentFileLocationId; @@ -159,6 +160,7 @@ ApiWrap::ApiWrap(not_null session) , _fileLoader(std::make_unique(kFileLoaderQueueStopTimeout)) , _topPromotionTimer([=] { refreshTopPromotion(); }) , _updateNotifyTimer([=] { sendNotifySettingsUpdates(); }) +, _statsSessionKillTimer([=] { checkStatsSessions(); }) , _authorizations(std::make_unique(this)) , _attachedStickers(std::make_unique(this)) , _blockedPeers(std::make_unique(this)) @@ -4287,6 +4289,32 @@ void ApiWrap::saveSelfBio(const QString &text) { }).send(); } +void ApiWrap::registerStatsRequest(MTP::DcId dcId, mtpRequestId id) { + _statsRequests[dcId].emplace(id); +} + +void ApiWrap::unregisterStatsRequest(MTP::DcId dcId, mtpRequestId id) { + const auto i = _statsRequests.find(dcId); + Assert(i != end(_statsRequests)); + const auto removed = i->second.remove(id); + Assert(removed); + if (i->second.empty()) { + _statsSessionKillTimer.callOnce(kStatsSessionKillTimeout); + } +} + +void ApiWrap::checkStatsSessions() { + for (auto i = begin(_statsRequests); i != end(_statsRequests);) { + if (i->second.empty()) { + instance().killSession( + MTP::ShiftDcId(i->first, MTP::kStatsDcShift)); + i = _statsRequests.erase(i); + } else { + ++i; + } + } +} + Api::Authorizations &ApiWrap::authorizations() { return *_authorizations; } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index f61eb0957..ecb0f968a 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -369,6 +369,9 @@ public: void saveSelfBio(const QString &text); + void registerStatsRequest(MTP::DcId dcId, mtpRequestId id); + void unregisterStatsRequest(MTP::DcId dcId, mtpRequestId id); + [[nodiscard]] Api::Authorizations &authorizations(); [[nodiscard]] Api::AttachedStickers &attachedStickers(); [[nodiscard]] Api::BlockedPeers &blockedPeers(); @@ -547,6 +550,8 @@ private: not_null channel); void migrateFail(not_null peer, const QString &error); + void checkStatsSessions(); + const not_null _session; base::flat_map _modifyRequests; @@ -683,6 +688,9 @@ private: QString requestedText; } _bio; + base::flat_map> _statsRequests; + base::Timer _statsSessionKillTimer; + const std::unique_ptr _authorizations; const std::unique_ptr _attachedStickers; const std::unique_ptr _blockedPeers; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index bfe8019de..bc124d71f 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -4537,8 +4537,12 @@ MTP::DcId Session::statsDcId(not_null channel) { return (it == end(_channelStatsDcIds)) ? MTP::DcId(0) : it->second; } -void Session::applyStatsDcId(not_null channel, MTP::DcId dcId) { - _channelStatsDcIds[channel] = dcId; +void Session::applyStatsDcId( + not_null channel, + MTP::DcId dcId) { + if (dcId != channel->session().mainDcId()) { + _channelStatsDcIds[channel] = dcId; + } } void Session::webViewResultSent(WebViewResultSent &&sent) { diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index fba98aeee..75287ceba 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -47,7 +47,7 @@ constexpr auto kUpdaterDcShift = 0x03; constexpr auto kExportDcShift = 0x04; constexpr auto kExportMediaDcShift = 0x05; constexpr auto kGroupCallStreamDcShift = 0x06; -constexpr auto kStatsDcShift = 0x06; +constexpr auto kStatsDcShift = 0x07; constexpr auto kMaxMediaDcCount = 0x10; constexpr auto kBaseDownloadDcShift = 0x10; constexpr auto kBaseUploadDcShift = 0x20; diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.h b/Telegram/SourceFiles/mtproto/mtp_instance.h index 2a3bc3d4e..7dc5be49b 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.h +++ b/Telegram/SourceFiles/mtproto/mtp_instance.h @@ -150,8 +150,11 @@ public: ResponseHandler &&callbacks = {}, ShiftedDcId shiftedDcId = 0, crl::time msCanWait = 0, - mtpRequestId afterRequestId = 0) { - const auto requestId = details::GetNextRequestId(); + mtpRequestId afterRequestId = 0, + mtpRequestId overrideRequestId = 0) { + const auto requestId = overrideRequestId + ? overrideRequestId + : details::GetNextRequestId(); sendSerialized( requestId, details::SerializedRequest::Serialize(request), @@ -169,13 +172,15 @@ public: FailHandler &&onFail = nullptr, ShiftedDcId shiftedDcId = 0, crl::time msCanWait = 0, - mtpRequestId afterRequestId = 0) { + mtpRequestId afterRequestId = 0, + mtpRequestId overrideRequestId = 0) { return send( request, ResponseHandler{ std::move(onDone), std::move(onFail) }, shiftedDcId, msCanWait, - afterRequestId); + afterRequestId, + overrideRequestId); } template diff --git a/Telegram/SourceFiles/mtproto/sender.h b/Telegram/SourceFiles/mtproto/sender.h index 632f817f4..5330a0559 100644 --- a/Telegram/SourceFiles/mtproto/sender.h +++ b/Telegram/SourceFiles/mtproto/sender.h @@ -130,6 +130,9 @@ class Sender { void setToDC(ShiftedDcId dcId) noexcept { _dcId = dcId; } + void setOverrideRequestId(mtpRequestId id) noexcept { + _overrideRequestId = id; + } void setCanWait(crl::time ms) noexcept { _canWait = ms; } @@ -147,16 +150,16 @@ class Sender { _afterRequestId = requestId; } - ShiftedDcId takeDcId() const noexcept { + [[nodiscard]] ShiftedDcId takeDcId() const noexcept { return _dcId; } - crl::time takeCanWait() const noexcept { + [[nodiscard]] crl::time takeCanWait() const noexcept { return _canWait; } - DoneHandler takeOnDone() noexcept { + [[nodiscard]] DoneHandler takeOnDone() noexcept { return std::move(_done); } - FailHandler takeOnFail() { + [[nodiscard]] FailHandler takeOnFail() { return v::match(_fail, [&](auto &value) { return MakeFailHandler( _sender, @@ -164,11 +167,14 @@ class Sender { _failSkipPolicy); }); } - mtpRequestId takeAfter() const noexcept { + [[nodiscard]] mtpRequestId takeAfter() const noexcept { return _afterRequestId; } + [[nodiscard]] mtpRequestId takeOverrideRequestId() const noexcept { + return _overrideRequestId; + } - not_null sender() const noexcept { + [[nodiscard]] not_null sender() const noexcept { return _sender; } void registerRequest(mtpRequestId requestId) { @@ -187,6 +193,7 @@ class Sender { FailFullHandler> _fail; FailSkipPolicy _failSkipPolicy = FailSkipPolicy::Simple; mtpRequestId _afterRequestId = 0; + mtpRequestId _overrideRequestId = 0; }; @@ -207,9 +214,10 @@ public: : RequestBuilder(sender) , _request(std::move(request)) { } - SpecificRequestBuilder(SpecificRequestBuilder &&other) = default; public: + SpecificRequestBuilder(SpecificRequestBuilder &&other) = default; + [[nodiscard]] SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept { setToDC(dcId); return *this; @@ -218,6 +226,10 @@ public: setCanWait(ms); return *this; } + [[nodiscard]] SpecificRequestBuilder &overrideId(mtpRequestId id) noexcept { + setOverrideRequestId(id); + return *this; + } using Result = typename Request::ResponseType; [[nodiscard]] SpecificRequestBuilder &done( @@ -295,7 +307,8 @@ public: takeOnFail(), takeDcId(), takeCanWait(), - takeAfter()); + takeAfter(), + takeOverrideRequestId()); registerRequest(id); return id; } @@ -347,6 +360,13 @@ public: } } + [[nodiscard]] mtpRequestId allocateRequestId() noexcept { + return details::GetNextRequestId(); + } + [[nodiscard]] bool pending(mtpRequestId requestId) noexcept { + return _requests.contains(requestId); + } + private: class RequestWrap { public: From 617be49e552e8467441da89cc99842d240d9fd4d Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 13 Nov 2023 00:44:26 +0300 Subject: [PATCH 08/16] Fixed crash in statistics on linear charts with filtered first line. --- Telegram/SourceFiles/statistics/view/linear_chart_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/statistics/view/linear_chart_view.cpp b/Telegram/SourceFiles/statistics/view/linear_chart_view.cpp index e89be9177..23fb14d3c 100644 --- a/Telegram/SourceFiles/statistics/view/linear_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/view/linear_chart_view.cpp @@ -163,7 +163,7 @@ void LinearChartView::paintSelectedXIndex( + c.rect.topLeft(); } - if (!linePainted) { + if (!linePainted && lineAlpha) { [[maybe_unused]] const auto o = ScopedPainterOpacity( p, p.opacity() * progress * kRulerLineAlpha); From edb7cf197ac2531d31a2f6a540c2867867c04ed7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Nov 2023 10:07:46 +0400 Subject: [PATCH 09/16] Improve reply preview above the field. --- .../Resources/icons/chat/input_forward.png | Bin 402 -> 759 bytes .../Resources/icons/chat/input_forward@2x.png | Bin 858 -> 1393 bytes .../Resources/icons/chat/input_forward@3x.png | Bin 1305 -> 1881 bytes .../icons/chat/input_link_settings.png | Bin 0 -> 829 bytes .../icons/chat/input_link_settings@2x.png | Bin 0 -> 1507 bytes .../icons/chat/input_link_settings@3x.png | Bin 0 -> 2213 bytes Telegram/Resources/icons/chat/input_reply.png | Bin 593 -> 0 bytes .../Resources/icons/chat/input_reply@2x.png | Bin 1257 -> 0 bytes .../Resources/icons/chat/input_reply@3x.png | Bin 1894 -> 0 bytes .../icons/chat/input_reply_quote.png | Bin 0 -> 676 bytes .../icons/chat/input_reply_quote@2x.png | Bin 0 -> 1156 bytes .../icons/chat/input_reply_quote@3x.png | Bin 0 -> 1770 bytes .../icons/chat/input_reply_settings.png | Bin 0 -> 711 bytes .../icons/chat/input_reply_settings@2x.png | Bin 0 -> 1358 bytes .../icons/chat/input_reply_settings@3x.png | Bin 0 -> 1887 bytes Telegram/Resources/langs/lang.strings | 2 + .../chat_helpers/chat_helpers.style | 8 +- .../SourceFiles/history/history_widget.cpp | 229 ++++++++---------- Telegram/SourceFiles/history/history_widget.h | 3 - .../history_view_compose_controls.cpp | 72 +++--- .../controls/history_view_draft_options.cpp | 2 + .../history/view/history_view_reply.cpp | 82 +++++-- .../history/view/history_view_reply.h | 8 + 23 files changed, 215 insertions(+), 191 deletions(-) create mode 100644 Telegram/Resources/icons/chat/input_link_settings.png create mode 100644 Telegram/Resources/icons/chat/input_link_settings@2x.png create mode 100644 Telegram/Resources/icons/chat/input_link_settings@3x.png delete mode 100644 Telegram/Resources/icons/chat/input_reply.png delete mode 100644 Telegram/Resources/icons/chat/input_reply@2x.png delete mode 100644 Telegram/Resources/icons/chat/input_reply@3x.png create mode 100644 Telegram/Resources/icons/chat/input_reply_quote.png create mode 100644 Telegram/Resources/icons/chat/input_reply_quote@2x.png create mode 100644 Telegram/Resources/icons/chat/input_reply_quote@3x.png create mode 100644 Telegram/Resources/icons/chat/input_reply_settings.png create mode 100644 Telegram/Resources/icons/chat/input_reply_settings@2x.png create mode 100644 Telegram/Resources/icons/chat/input_reply_settings@3x.png diff --git a/Telegram/Resources/icons/chat/input_forward.png b/Telegram/Resources/icons/chat/input_forward.png index c04e20ceb36fcc112bb8177c773f554fad0ec04b..2d9c78335437873d77d777240c7cec1597533844 100644 GIT binary patch delta 701 zcmV;u0z&l|*jX4XM2Hp^qS%Oya)tl@_u;!U%hP?lK)Q2^ z$L!2E-^|XwoxQj?%m38@gTe4?e=ktJYv%%zsNHTin@w2EX7kh2(~p1h@$peEmq{dl z{WF0?A{mWFcXxLPu2d@BZg)1DEf$OAa#<)8lF1~0QYtc^&;Q;F6e?)%z}}crxM6Is zP$>Ml7buL+;c&np7K>TXKp?Q&?NX_fK=9cE7UskfXsJ{x5{VdJJRV1Xe+Gj=wOYNr zyd(p{;V=?Fvf1pR8WM0?kHun4*mk>}&*$s)IvR~C6pGDeW3$=Fm_q{KaY9#DSEQG! zqfEVCZ!(!I7K`0(e}8|+&y&eyrqiifttP`FkqA=?^DUK1GMS77@X|FJO)i%!7K``y z_e=oNghHWoI*osfOaQ%Bf2*;I;FaS5(&=>1&(Am#7B9JMwOW83LcX8`gTcvULUPgc zUaw~~8oxjdD9#gSPGdZ_4~IjQO2s#a)oSH#%W(o&Zf|dSCBU_4G#V!rEb+6G_VIZ9`ud7JVFEgxPM6C?e|j+)y&LkT)3^Oh`hfL7#_it`)Xr$B@;mtwJ z%gc-3@5c^k@tsZw_Z%-34M0tx)oRgkpU;PpM+>gk>kkhP*Z~c|Wyh1kG3zlB@EFMD jaxRLq@7#fJ>cAgk6P6JjO>|%L4TpoEqI1ryJf$ZB?6)@GoUcbI6vH zMu(gGx3k~%2^1;d+4xo1yR1o5p}h5qW9fv~4B_h~L)bO>D&A{u+AsCyXrz0O;I4Jd z$v%C*pS2#YpT2k1`)ZBTlemA%DKz`Cw|+Z$Den5R zbc3y`N$1{uy;(nj$)a!Z9Y3XQ;@$Vp%KSd4{ou{bIXkV?W-irkS9`Z>Me{3#>x}E- kj92g#$v${>G`)b`ZHm#7-75dBfg!=*>FVdQ&MBb@09tv8N&o-= diff --git a/Telegram/Resources/icons/chat/input_forward@2x.png b/Telegram/Resources/icons/chat/input_forward@2x.png index c500804d00c95acedb1168d6edb3fca389c357d8..26e435458b38ec40a6ec13bf079158b6090c20b7 100644 GIT binary patch delta 1340 zcmV-C1;hH<2Js3ZiBL{Q4GJ0x0000DNk~Le0000$0000$2m$~A03{3NiIE{le?XuE z00aO40096106+i$002f&La+b;1lvhOK~!i3?O91EZc!XJKSSm*LdFt8G87gl$wIO* zWg`nxR!U0AuuwKON-1H1l2T;Yu)qQdnL?(BEQ~$FGrjkF@6>s>d(XY!b?^PY&*I+2 z*E#?DAAjHfob&&mYhj^3Is!TZe>ws>0y+XZ0_H=&QrdK4Vq#ia8h92L7gtwTrJ29i zTU%S(-rnBdoCi}7zn7O1-n6#166b&Zd&sz@rA0!-EU(xpWMyUb@bKW|+6b&ioLx(vxLDn8Xg`_AkWOqB=0cbe`FJTSW{EO zS7iLT4b#Ns<>kl6hqbkJQc}{~+#Gn4lauia#}^hBo}Qk537)gFv%bDQrZ)2sr>3Uh zF2X?a;K2aX$;nCcc%#5-P*4y+<>m^eASzJB6$uRu?e6X_Dk|a+6f;ff*bQR8etpG4XzPcXxPr z`2PMLQyc}}-rkglIp75VsrmVNS65divnnDyK0Q4pUeaG2WRH)Je>XQb&(F^wZftCj z;vzOS_Ve=-l+w~tX{*8jAho`}?&s$xEhzT(Kd3wo9Jd}G9y}sW21iFncXxMtdwaav z-rjzDd&6LJa})4m5E2r?6Ol8Gi;KfPfelIyGml4f4IwMS!om^~5(GuVUjmQ@>KPds z{{H?K7Z-(vge^9-(wZ$_aa|&B1cyn@cfQ3vERcxrS$Qyig|&4-ezx)_kaARnIRGMgd3j=b zG^R&HMAX*Sc64-I&RaKQ7+bVfbvs71Cs|8yqkCN{E{9L7T2E|`rUyap30~Lej zRWjgC5cR1LI}Iq<)P(JhN_TnUXfRS!Q#J6FsUkl=pJz{OiX9dW18UWyqocdKJ25sM z9myFT9nCbY4G~)>&m?b(yLeP%D6rAlQIlxsPEJmEf1JW8`ikJ-U@E2k0J}c^U!h?_ z85tQtvnFPh*%NbBA#xudA2D%l=-JuXT$6N+o-idPMcRgR0Jw*BadDB>puyX=wl?ZC z8DO((XlRgAHcAA5t9)`-pn;3hD(Lkf@g55fU!tT%=v%P>@c9QTgt8fTz&*dv00agG z%D2Z1e*o>9>F!B!eM0kRd3pJ(H@?CE>g(&}$FBh={ZzBFv*YRM`BjbF0C3M&Sy}m2 z4QlygVq#$U`1m*=AV7hxrKKhE2cmDrorMAo8i?TjQ1Nvv`g8<>si_og5cm(%fp*IW6o5^A(rX)BbY*;s3`_wbg53=&KMBDM6)ovnOx= zyvg#UQTln=&yQ>KjjXG$TTY&N-d4Oi-RPLa>)ed}B0qkl%3a#W!mvVzm4PWhbAgXL zD@ByQ4=W!Vv$0&iuiE6mxJ|!HcInIfep|LXGHdhAGijS|TFlM=^D(1g|Ms6Xd7ppQ z#0X4g_n2||=_N6)Rtp6+;RyoatEcLUbq6Y|iBAwPpWUlF{dAy`n)C#L?YGyi4bciz zRFj_|P`-Qa+OXAu3d@)$2z>v&ckR`z_ijAw1x7P(oPO$b{p+B?-+v7R zFY|hI^dCRm=eBr*z-4}qjw@Dk`-+boS;M|7{%CQz%k#yDrqBP^S6^ap*ed$%hd|(i zi`QqwtrtJVvpDkG*1x}x{%@YV_tCDoOVs{#fBFAueatoO!~Xfj_x4EJFT0pABS!D} zpBv}-Ds1F@S6?-H{q_xy8C5 zq~|E}ghr3u3{$!`RxlU|WQsQg8H({cuqnM|3eYqY*X?k{w&P9ac(o ovnw!9EMwFVP5#J`LX2Vm*`L=Pi_?&QpbARYp00i_>zopr0ADj!5dZ)H diff --git a/Telegram/Resources/icons/chat/input_forward@3x.png b/Telegram/Resources/icons/chat/input_forward@3x.png index 9df3f2369c21a0899785b8ae95eeb6f50cdf51a4..488f8e1e109bc5b097eaab02c711b5829e44103e 100644 GIT binary patch delta 1831 zcmV+?2iW+T3fT@JiBL{Q4GJ0x0000DNk~Le0001B0001B2m$~A0B!oHLe_)^k z00aO4009610AK(B005~oUrqo32E$22K~#7F?ORDm98DBfiT-iJH5fNg6c-TpLqz1) zn8X!9K@brIgCTk{c=IBPSv*Qa#DfPxK`-J#A;zE=S5*8_Tq3w2;)dcHjY|Ii!-k?6 zr+ccWXL`!{YYxNfs#mYx`?~5?f4x`LHa7gn5#R`L1ULd50geDifFr;W;0SO8I0762 zjsQo%st~YMYK^b2Z&+9uTK)X_b9Z-FX>)7l4-E|+9v=Sl=g+_QKM;6Cp*7n~Z(C7O z(dFf(0FC$`g{Y#JW1XBBCVJ5kkV2Iek0UA{gsGICo-Vxn+1c6l_IA+kf8M=INJtP0 zfBg9I>eVY-TU!SQhrjgwgmN%XPEMYmp9`(5`kTEhUDR^83b z&AGWb)5@v z$=5Q}aCUZv|02`;>({SjVbvG}!`;DW|9$@hVVK*-=K1sIQBhGoe?C4m%u+nj(a{7Q zf#~Y$qTEgQk$RWhw;GmO}lW_tq+zP=)PfriAL`P3He?*}=f)GjE-Q5YGz>#-%ch}U^;GcMR)GCcOWB@`(>+9Pjdv#|rJ{=JxH|x7^%ZolaFgKA~)1Utf=07p6MaAgQdFkSW947QE)OXU|eoQwg$Z zX=#ChfkJm{YipGK3T%|yLPtl(zP`S_VCbv3IAf>l$n{S zNGF;pMmoi6e^6artw_Gs%t(C@bsrL_RjLqjEDz<#mwf#AQE4yQ@nZ+DxVWg-0F1R5AfG{83X=lQ>Zg8YMK_XryHe3JMw<8wUmka5gEA zf_yDT>%*Oz3CuH<2zPh)oSdApvNHUGmKPfr7uV9#e?qnb@|M%r4h;>txVXr7&2%l6 z=c=kIBy;I)R?0awHRa{y#WV_fm3#X1>8DShe*OBT)LT=%{LH?mW&bye_<6XFE5u+T&rT_D`Zr(U={X3NT+B8 zgG4__Zm_fK5x)%Vq+h;#DWSE7#dURcVzn5dk!)fj7Q>0_@$oSupb#|}isox;Yl&Kn z5Nzdxa21RZTm&`LWE5!+4(Z(&E+!!BPR~y`5$OMO|65*OhATy;5w`)5a>sGt`}gm0 zf4D|C6%pURe@E<&SVvJSGcqe(-LY3f;#J;v;!2xwLz2Z)4a{~*W3baNE-t1yr&n~c zN_uDUTnx8|h<-8zZmU#QRz7(`JHd?rh|!Z(gX@6! zl=n4Ku8|%f`1R7#QYkr>FUPTg6hN)5f2~GeN~Ht{_m50|Kgg7r`uX|kMF%&j;EdJu zL<5kSZkVZ2Teod?cJ@Pn5VEQd4h;eXuMZwwg;;xj=%Mi)6%NAG>nRTqZn-{=k7ji) zj{_ZC7*>xCB**~7&^>8`refnqrWoP|e4=5n2_=IRK#%OEJ-MfWBd`}QUQilOeZ!^~ zpvU*E2Esy&Agr~oU%#d?o1Vu?zV^X32XV7Gz6!w38)sN#{xbc&82xKEEhoM>#23^1 z`}?e4@ind4TpCA!Bft^h2yg^A0vrL307rl$z!BgGa0EC490861M}Q;15wIo%{sTO3 V7T;0;X<7gP002ovPDHLkV1huROdS9K literal 1305 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz1ASip>6gA{T+3Vp}Gz|!pL;uuoF z`1a05eVss&;~#hXFS?KsVztz%F-%EHii_*w2lfl6|FNn_as6ko&5DYWS|l`=jkT%e z!M>gPdveUIv&+iQo!gnde{#;Ivb1w|e*Zp``u5(;NyX>X`NbA<{xQ6zzw7Hgk6M7ruY_a$_4$f$Eo!A2+^#`*v#!kX=wwS5@`u_pe`T6qsXpW$O0r z+4JS^-@jrL7}v4N#O>a zUcN3fQ&a58qsHUMkN>@THFUA1_^!X#uTPJUjO=9GS@GaTf%f?|MLXBX0@({@O-kQmKz{zp`oH;vQzI<6*}uE_Q{EL_n$55 zy>-!t3l}Cx%gU~;Si0ArQS99BM~@Dv7Vl~4pA;we;7d+aobW$3e;*%_Z?7#&7#>WM z%ogW(zlb?+V*Un(b-9;6t$z6b!H0K0U%p)VG-|C_0?YPU30MD}R5i#;OLIHgF0(L` zA)ImRr^oN!t(!f6e)wm@r~dI={|ju^^Z)K%b9lRF>AD0RA+`SG^=sFP+IdX6IO|&5 z712!VC;zOBtz39ry3?&Bljcs|x@XUvmGz}=;nv^u<#w!KnDzIoOj@X(p58WQ_5Ngr zI~*l5#OKyrpY8tP?JCBCu!MCv9`)+i*KOXq@Nr5j@9o0epp+dC-`8DhUCph0k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSVF5FO4N|zKE$K4@1JiO(7sn6} z-nY|EduIiT9Qz!oX?w(>K%kFnmPpEr3k!oC3zRtgmUeJ_<~NYy@NIDrR1&y2^TB~- zFD*VWo?~%zcWSf!c3@u=qc?y4d}SLO zo0^)MKYupI#m9?_i7h*w7}CBqYORApLt15}r3@cXm;C(KA3qja$gHwmKILp$vC_l` zG6kv%&z?VTwMjmhv@v9L=#EF-HnP7sTwlL_{jx;rnP}R!ZQIs_tv>$vWQq|xJ9~P1 zy3+Ay&z7Bke*5m-+WPwSSF?^LZM^=Pb9I!2XF+{^eQ~ifvzYz$W5?KL23%rroN_S1 z!p^Sm_+z!nFMs}wTz|dYY2oF|mm_qhc`dzi;nt?JY1wA8WjgeY7#E0hv6@WvN=;99 zUw(PwfwyHq|1RorQM$F@u^iWyMgD4&83HvgWclauSXxXt{4n74ex3Pq<~a1VtXojP zS0pbhTPs;|h+)U0(vxYMC+&~B)t~=RHf=?0F4Mb5j~@N{6{Vp$zwuaPhKQpwBje7P zcOO0!q^7#MG}TpB?%cos{>zerDme2$gV>%yll+x zj=SvW625mtKy%kG^O9#>Q-peN&0KU*Bk|1cg4XhtWj<#_z23E3O!#nJ;M31PmoHD& zkk8-c#mCukXlB#LZ&?eH)1J++;qjg@>p00i_>zopr E00J9n(*OVf literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/input_link_settings@2x.png b/Telegram/Resources/icons/chat/input_link_settings@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0eb12d2033a21267742df7b62a3ba3d14892153f GIT binary patch literal 1507 zcmV<91swW`P)00001b5ch_0Itp) z=>Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuBO-V#SRA>e5noB5lT@=S(_xmN} zewnyMxeZP9DP~3#i2)-6rHmOUbCfA!%7lrMi4=(<$t@}5l1n7yBfjs~yKBGaJ;y%J zd7kgt&*!ak22cB}v-V#9wf5R;|M%v{5BG5+;6}iWfExjQ5vZ!Fnw*^6+}xa-o9pQ4 z&}T@?$Zc(H@9*#b7@q0rX)Tui!=NFmzL}Ys^YimjQBl{|*Hcqdc#)NrRZ>!NdV0FG zwG|#79vvMWA0MBXn3$51lAfN<*Qci^999h&XnA{kJD@*4KJxSPu^k*7yuQ9JB%hz3 zhFSU5yt%oFi;D{|&|sCloSYm!-QV9I9UajCv}oW-P*9Mn7iy|cn&hFXaksa(`IMZT z+}YVVK0eMo)YjG_VIIcD#{T~5+1uNDetuRB7-%_Jjt?R~Zf|eNCEBDobt%wLe709q zR3v=>{o~^!b;;+^G<8&Fv#`fJ)YsRSm6e^Hoh>ddUS3{Wam2*LApAzjV}+=aR99DT zY;2HSJT!P!X?{m}O-&8Be-+W6H5XxkvD&3jL_|bOOG{Exk}NrIZ*Q_aF)@*smv?n_ z)z{Yt=)u83wlfM5o1MK6RN;z>io(J|^a%lJxwEr#aByJX%a^ZRU0ucif7!-EF*FUK zkeZsRGM15%F)}i8adBZCicMxuW6GpkFUMGy)q>@2{}w_=0WBXb;+X@ zjSAh}-NFIq=mi?qgXky-yhe!jL&KvuMzcRSjJ+I%IN;5$G2d7DS5UgUT5Dw9sj8ZdU2|O>RVwRY~ux28`&@WFD+KNZ6+ZdVVV_E5Fq7 zn-HF3+^uXXrU^asfaFUYa1G%Ayw&CgX4#2&=1LUo?3>EhL zf*!5`UlQoy-X2Skw}5}sXLQN$v8v)Z&NGMo4!$JN^GkGov*-60=2sYF##J2CXY^#I z_UxA@Lvbdy2FPdhR0ZvKtW-BS*QV2n^n@xYb!=)5`tm%DKIo~-au8h&_7?$;9YeJROscH&JkNRS<}=dSzC?h;jM6QO{WvPKQUQRI+3u) zm6nzQmm3lO0CjkH$p2R0kCVQxjvE0t0&WD{2)Ge&Bk+es;9tDSDA2t=B%S~O002ov JPDHLkV1mdizZC!g literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/input_link_settings@3x.png b/Telegram/Resources/icons/chat/input_link_settings@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..851858fafd273a93da6f4f3c777f7b7542e36b7d GIT binary patch literal 2213 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%0Dk-4V%BRT182&(SH zvb;yZe*pMwEw0%>!`@Nic5M8|na*8YFZq#{L#Bd>eG&GK@;ljy1{Qht-o1NSud$|8 z*Zm-cC!(HB%^!11$WkkICmjePrz&yJoQ%U&i?|-h;yO4490Cpjhk!%CA>a^j2si{B n0uBL(fJ49`;1F;KL`L90y_~>SyPuzN00000NkvXXu0mjfp578n literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/input_reply.png b/Telegram/Resources/icons/chat/input_reply.png deleted file mode 100644 index f20b997732252fb8460a49a83b8826649e0a6243..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 593 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(k>KRV@2c%6Yf@~BLxkQ3oKHinkQIG&snv~VD?#|9WhL| zw$-+umR*oJ%fH}9p^e?S8f_^n833%blu_|R`T^YqiLQ|G7TZ@;}~LWx7moA19>1g1@Xz3afv%pVMb zMHVvqp70+QSantFN|vbsk8)tO)!e4%mHPY6rcHKtt#fFR=|Aq@dHGyY?DfRmcklhx zJ^jm0!O2f;a`hz>hc8DvZELLNChWiepDp0BNr8-d;}Qm?l*JbrY>ww&Xi48DbYDzQ ztlMDz`NX|(pH)?@wx2#O2Kj3CGiNf4+15W8CxCL%>k+y#**b NJzf1=);T3K0RSy>^9BF_ diff --git a/Telegram/Resources/icons/chat/input_reply@2x.png b/Telegram/Resources/icons/chat/input_reply@2x.png deleted file mode 100644 index e44f5f79eb0d624cb436d5b4bd0b266f074245c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1257 zcmeAS@N?(olHy`uVBq!ia0vp^0U*r51|<6gKdl8)jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-euz(rC1}QXr;N#E0z!L1~;uuoF z`1aOWZPP#rh7XV9=KtjBw0F=DD?8+ra)0- z|LVVj2@Yoi5**mBh+J56PVhv-ET&mkEtw<(f*m$nxhpVdab<)(=SXqzWjy;zrjcib z=7Pw%$`cq(Sxr_KvluN{){s`(hpxGqDIzFHDJ(qv=*N#6GxGAT%?V3d{kXd{e)^$9 zP8L>HOxCh8GC!>5S=jzLdiwO~=D&YyZ=Z{rKX)SeY>eLk#JU{pk6j<<;$1# zkN%n**sv$+-=yx3CWeNJzkdDl_^YC>&Ry9mwsYssNAKSG+1T1neDyQ*#1Gr+Cr)r^ zeo7LxvbEjn_jlSfF%M5qL%X<2g-0)y*B$z3k~39SN~-JWqpbg5znb>+_dC0~y533d z6mGk<&+sN@L^^iKE7X-S=IbE z?%m^)mzQ7mR_1MfPL6}4W8+GV;H|H96M}<<_w3zksWyE@@8rqC8v6R-zSmslZEvVJ z`o;L}{rk?ozP+3)R^(Rw>;Cfg?b`V5$zl5|-tXA6N9WY3Q$l8aD>min|15gYuwANd z`RC7{U1AsRwQUvLw`-TwhmcR!5B2Txm=*h~?lC7l-@0|Hg8achW-aH=`CaZvV-Vc9 za3Nz{TwIOoo}D`lYpav_1Oz|+{QCFr-S8t9F9uEy%n%b0+`Vg;(5Dcg*BTGM7pA2x z6Fj0aXF*KQ@_+y83@t4^Up@c%Gt#4^u(VY5iMGGue1kQnb;n%embj#*s;<=C9Z+7r zea7tBo6T)wr7ew$S_I$n@$(<&5;|UYD%$do;KId=nbXqJ9z1$|X6od$VNgR#S%qs57vEj7 zb=v)d2N{ldp877gVat{$GZyT9$g1!yFf{b(kGeazZ*%i0_!-#R+P>N^yoc$CT~}9E zLUr|RE3@g-rypcG!kLzye)!$Hb+R?rZh1SrQP$Pvt*WkGxMhn;MT5n`KYwa0Y;68? zcl^J0=&yasPkXkm@1?V6&sO-Kz}ef|YtPCr^i4%+vF3!6pW~M>uUs-igjuUVBa+7> zFlb7m11q0uH>0Lkml4m30}E3O6zopr E0NQ6L4*&oF diff --git a/Telegram/Resources/icons/chat/input_reply@3x.png b/Telegram/Resources/icons/chat/input_reply@3x.png deleted file mode 100644 index 97688789f3449d4230f8628d4b4a4dceead488eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1894 zcmd6o`#;l*AICo*n@uxP4jZvZ!virixsJqF9*lD5IPByyLRL~_8Fg3}r1MS1%uy1` z<*0Z#Q+!a{an0q-ZMltHlDU*L*YEst&VO(o-ydG@*ZcDP>HT=TAMcx|+??c4swe;e zTD z3mXsZ?Gd{8ourFK-^kiBw&80l!gsR!hr60?AUIb)}NHwIniHQeVPHsuSay}g}$m&JAGPKp?xix=NerQkOxY zdVO9_MZ`znuj>942yURy9dYSvkBy0Gnw{0PW^AjWP$)Yb!rcA``8rr#Ie~qt8iQA>ytA1AM+1 z&OOM;%gs#{3eNEl^L*Vxr8R+AKU^1DU>MhLs(NWyE z^BDiR?;D~o^W%c_=6DlqaBOUc`m`%pTSsSNx|3yT_eC4A0nE(Iw1`BNU9RqLYhS-c z4-E~CVx!kyd;{*c{0LS#vHg;_)}_6@y)Rui6*SnSG$wC-a;W8O=AQw?4q2fZbGE5zkeh*qW*q0@^`f>Fv*G@LD(e|lsi@&^p#h%qi8FzP+h3HLEzHA&|u$ALGQ!Dq}Ft zcH9C&$Rt1XtS#l}AtF&}O6#{QW`-{^FW%}Ch}EQqg*9=x>64m`No#H;2K`8aeFI~M z6dfCDrD_snSzJ;wFXe9p$^21T`e*#yL}=T{$Oszy^D|O$adE(9&4QZc2})yKop~`S z=iKvo*mmV9x3Bs{BC&EUdVFc<%e|~Dd1Es(?dIlYIBEOZ;sO+T@#3p&9S8eMAm`~o zRWQa}Uhr&Xs#Q^Q<8DO&`~7_NRsH|o)enh?h%ndpx9;L;zT97aVM`Pf!b}bd!dWM8 zVwW7|cy|us2CnvZ#Ev!Oo*l43*wTGj^Gq&%|A*e*3-=$ii6w_Zs<}D*v7m*&cDu+T zoJ!4!NyxjKn>!b`p)9VlrTnn|iLdWY(wku;mv#^{Q&V*&0@j3MXJ;q+J44I6v7W=Z zr{Qf{4v&7DcFbg0ARx;T*Ow+>FtZG+s9WwDUsqSl{0agV_d@^4Z*6T&DKfOlDJs%} z+>|D5&0N{lx6Ly4?AZf~73y@{?{t3Ap=fEV*}i%8>SFm%YX|XoJbIAO-r*HA4SoM! zSI=x)#DLh4tjx@`iHQl%$%v?^5GWkt7=>JdAV-ipxTJ7lSjCn!JB{0rW?b$!93D|i zERuR!QsUmJTC{QqJW$Q=@0Y?QWxlAb<)+BRy=DtjQpMuLmUcx?E1)Rd=??A>QOP6? z$3jk99J`*GdAtElwxB?U5SB%U9Sp3$)Yk44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSVF5FO4N|zKE$K4@0~4R8i(`lf z@7qw@6OM@@{~n$8H z)AbrP{&#o1tG)ZXaQ)YPhi_Y+uRK?LuX@k9-=CFrS2Eu(bI|iUkhJke&bG5@%_Uo- z-hTe6H~nLkVe{(iE+4hoK585Kk1Ma56jEqcvaqAnLWYNpIW^gT z`Q`OZo5DMU3oT@{rgm|a?v6ci@ZQ_9+i%OvW(QitoV)Wq!ESzgl8MyPm3iBxPgK~j zExMR->#f-x2L%V=jK|ZrS@3Sz5w!Bi<3g90`VF}zQX9*yWZ%5lcQxzi$M(aDF-d>J z9ae^zN%a<3_&hmq^<~NHue+kw9%A!d7$DMp^zzFur=GZOiOSu7|9Jal?WtZLH?^`A z9C%scW+tZ?(Pm4H3Q$G5tUC!F7bcM5gV?>8e^L%de{t1su-hZ!Fo17^7 zRyciUOwp;2jVDt+3Exy-elzD&X5ph5_EmfT&HR7u(A?~;QFEed6xMx;judm$n|?jZ z)XvgRrnyD+V`s322*=u>l__Sk-{h(mxb@R# zs-7vcnp+|Jx6VF3%0S{s$-{219akFltv|5qEahhZTKy>%ltMgR{an^LB{Ts5Q0Eys literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/input_reply_quote@2x.png b/Telegram/Resources/icons/chat/input_reply_quote@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c7bcb7d8eb746bf32d3e0fa1962bad88c36ac1d8 GIT binary patch literal 1156 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 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/input_reply_settings@2x.png b/Telegram/Resources/icons/chat/input_reply_settings@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2a4aef116e3608f9e1029df99888c99af59a5e10 GIT binary patch literal 1358 zcmV-U1+n^xP)00001b5ch_0Itp) z=>Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuAxJg7oRA>e5Sz9PAQ5Zh#&Ea^F zOC&_@N=SH+kXtE2x#vZSC|*2x5%K6n;z8t6aw*CSN}@#aAmmQUEpja!my^pm-?2_( zH?#NJvu9@Q^D^_WTWihwzyJIH`DgzBU;EoP^-?{cdO-Dn>H*aQst5j`2Q18~IwB$> zCME_N7Zw(lmzT|{TCOfDE35AA?%z5WrdX7VYc~0&rY1uE=jTPnjg5`+378{9?n>*VC5 zx3^cOUM0mRCnrG{W*~TQVSwqx#DtPMm|}T)dcvu?v4SZUgwu9kW5cc zn~K%h*{K^~c(Y-TsUXt#BQ#oDTR8?RD=R`QtyYVmcX4sCx3{;owMBB^_T=a16WQ(U z?V+I|#2cna1fXZ*QNUpD|rqTO-9q zNJz-X#|Ksl3k!|%mYWBVUy)5yQ&Z`hkZv6u9C&+>8Gd|TWPNjU^Y!%=1_mA9w0b4m^I-qd_4E|_I6WQ()S~% zN=r+>bg&yCgCczCY$V^UuC8Xs{2wyDB$D}w5v;APWorW|48>59yeBO!jiC*Ti;I$( zi4?rNymWPSWo1J^Kmes=5J}PKHnjY#3;?c&hX?u$qag#XamaTrKKgA6zSq~ zb8`$005qzrsi`SC37L1}guXc6KXgFNq>JodU-?QSy@>^ zK_)8|6%~}ql-`ly(~R*~?dO>q@a}D(dbOQ)lTwEO5U!DOtb=0ei)grpH zhld9q2~5Qp08V&4+S=N9;`n5r7QjhmY^&r zC+GC^6u%N=l@UR?fj_qJCBfOCGKeaQ>H*aQss~gLs2)%~pn5>{0M!G3010L20?tMn QLjV8(07*qoM6N<$f)1%&*Z=?k literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/input_reply_settings@3x.png b/Telegram/Resources/icons/chat/input_reply_settings@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e2f131d6aa4356e090975a845a10d10747d31a39 GIT binary patch literal 1887 zcmZ8ieK^zW8~+Z?!bnzPJ4m4wDypqID;qI+TdOATquFvziKhJ&t^E}UW-ya6S-wSGBX#fBK z)En#Hdzy96I2A*v}7GtBoN5=)y5TZ=pmBODzCE zw;TlMY8kX}R<85kY-G9a|Kf#0p=*Rc0Dxb5dtmp`L0>~d@cVsM$Y^)hAYE9EI9_2o z!E!avBqp61(Er$na7i6W4Zoy(DOjpE^-MpaL+2VSnGnI-@SS@Kv<$Y$&(Cf`5~6(j zy*Sr(1GymSb@=b9SN%R5jYvJBifG#WrHqp@|1hA0Xnj5v=eDwZ2?4T352j-P`j>Pt z0OdwUxhT!3x*^+>=9j8y9HkG=S<0I~CG|9VNv(#$! z#7OG|cEVh-p@%Oz92K(!S-4$aUq1tky}lGl9O#}6ZHRZWx6kbJs+RMBQDIBq&#&+A zua9UN&$)NQux#JMRSqmcg1YgmpG1)h5;uwQmsy;{|{`_#(>%^oSwKlog6kMw3)nPRx* zYRdeadhmq_^w!`WM@Prd;Nak(p!%fgsslMR8ciS&2ov;kENg5lX-RW48#e=ncdM(b zm$1>~#>6S+NwFOvm$Z^N_T<`zo zcCP@MY%zu72tphA=;-fmFv_t&qKM{k{N2=ieK-PvsAR@Kz-}6ihAT5>rTRwy+UeqA@WIqCpUs<;t|ci=tam(p@dEzV zvwcMKW14GuVHZ8wudJ^xj2JzxthN{vB3Vuci>5!lhS!FgR^J@ZVGsF$y8wa`91cJTTaj)?= zsf!ijCZv<$RJdeX+*kx8!QS#TMigXK$i|-Em z9_!%C>*h};EjKrBcUrukjm^@5kR;afj*f2dO)UR8?!D3>pmc*s^nP+cqFWPS)WFQn z&Q6*h`vAXt;L}`hZ1#;?w`vVR4NDDafq{WRK^7#0VUIL7;~^XE*?2~M37R44tgo+^ z$z)6>Gc^@R;$4jDtEY|3&dwUWqc*}3K~(DcIgA3_y4G!WX2u8#wLlf|9k%R6vm)wZ zC2P09yL73Nr%&}RyhgY;rTo0u^IIrtdiv?GgYyvDH|{V#Apw0RNK}@%q$%{ z_QZ6uwQOhN?uMqOJ9pYJZc1;>%s2j*J&``Jv&6TxeFV(O)!m;TG%c&AcU4EADlvf$ zw3S^#A<`MSR6ojE(cgb|vef-@^CQ2FPq2$o&`r}V9S2UAn3AVdDo=7?Da5R}wzl@f ze7xq?(}JvBPzhjm82|ONDmgDql;>$LkD#-FjHO1_8r1t7_GGHT;p5=`~p(d`e zk~OpU?%i94QsRdmpEWscbJaOa`vbU6!?8cMszP(EFfn9uM@?6zR!EbmIfFyFrO*=XEmfD0j(xbN8tT6aC?CrY3ih|R7zGc*; zU3Jvjr)&JsyCN6l%9UyJ9ab5_ngV6^U{<3dW{IJxtF*?ry1To((2o3xz`J>qxy>-+ z{&_*5r>Ez~JHF@;V;}Ve7!2my() - st::historySendPadding - st::historyReplyHeight, - width() - skip - _fieldBarCancel->width(), + width() - _fieldBarCancel->width(), st::historyReplyHeight); const auto hasWebPage = !!_previewDrawPreview; const auto inDetails = detailsRect.contains(pos) @@ -4418,10 +4418,6 @@ void HistoryWidget::leaveToChildEvent(QEvent *e, QWidget *child) { // e -- from } void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) { - if (_replyForwardPressed) { - _replyForwardPressed = false; - update(0, _field->y() - st::historySendPadding - st::historyReplyHeight, width(), st::historyReplyHeight); - } } void HistoryWidget::sendBotCommand(const Bot::SendCommandRequest &request) { @@ -6243,20 +6239,7 @@ bool HistoryWidget::cornerButtonsHas(HistoryView::CornerButtonType type) { void HistoryWidget::mousePressEvent(QMouseEvent *e) { const auto isReadyToForward = readyToForward(); - const auto hasSecondLayer = (_editMsgId - || _replyTo - || isReadyToForward - || _kbReplyTo); - _replyForwardPressed = hasSecondLayer && QRect( - 0, - _field->y() - st::historySendPadding - st::historyReplyHeight, - st::historyReplySkip, - st::historyReplyHeight).contains(e->pos()); - if (_replyForwardPressed - && !_fieldBarCancel->isHidden() - && !isReadyToForward) { - updateField(); - } else if (_inPhotoEdit && _photoEditMedia) { + if (_inPhotoEdit && _photoEditMedia) { EditCaptionBox::StartPhotoEdit( controller(), _photoEditMedia, @@ -7486,7 +7469,6 @@ void HistoryWidget::cancelEdit() { void HistoryWidget::cancelFieldAreaState() { controller()->hideLayer(); - _replyForwardPressed = false; if (_previewDrawPreview) { _preview->apply({ .removed = true }); } else if (_editMsgId) { @@ -7818,25 +7800,23 @@ void HistoryWidget::updateForwarding() { } void HistoryWidget::updateReplyToName() { - if (_editMsgId) { + if (!_history || _editMsgId) { return; } else if (!_replyEditMsg && (_replyTo || !_kbReplyTo)) { return; } - const auto from = [&] { - const auto item = _replyEditMsg ? _replyEditMsg : _kbReplyTo; - if (const auto from = item->displayFrom()) { - return from; - } - return item->author().get(); - }(); - _replyToName.setText( - st::msgNameStyle, - from->name(), - Ui::NameTextOptions()); - _replyToNameVersion = (_replyEditMsg - ? _replyEditMsg - : _kbReplyTo)->author()->nameVersion(); + const auto context = Core::MarkedTextContext{ + .session = &_history->session(), + .customEmojiRepaint = [] {}, + .customEmojiLoopLimit = 1, + }; + const auto to = _replyEditMsg ? _replyEditMsg : _kbReplyTo; + const auto replyToQuote = _replyTo && !_replyTo.quote.empty(); + _replyToName.setMarkedText( + st::fwdTextStyle, + HistoryView::Reply::ComposePreviewName(_history, to, replyToQuote), + Ui::NameTextOptions(), + context); } void HistoryWidget::updateField() { @@ -7856,12 +7836,6 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) { auto hasForward = readyToForward(); auto drawMsgText = (_editMsgId || _replyTo) ? _replyEditMsg : _kbReplyTo; if (_editMsgId || _replyTo || (!hasForward && _kbReplyTo)) { - if (!_editMsgId - && drawMsgText - && (_replyToNameVersion - < drawMsgText->author()->nameVersion())) { - updateReplyToName(); - } backy -= st::historyReplyHeight; backh += st::historyReplyHeight; } else if (hasForward) { @@ -7871,12 +7845,11 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) { backy -= st::historyReplyHeight; backh += st::historyReplyHeight; } - auto drawWebPagePreview = _previewDrawPreview && !_replyForwardPressed; p.setInactive( controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Any)); p.fillRect(myrtlrect(0, backy, width(), backh), st::historyReplyBg); - const auto media = (!drawWebPagePreview && drawMsgText) + const auto media = (!_previewDrawPreview && drawMsgText) ? drawMsgText->media() : nullptr; const auto hasPreview = media && media->hasReplyPreview(); @@ -7890,86 +7863,11 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) { }); } - if (_editMsgId || _replyTo || (!hasForward && _kbReplyTo)) { - const auto now = crl::now(); - const auto paused = p.inactive(); - const auto pausedSpoiler = paused || On(PowerSaving::kChatSpoiler); - auto replyLeft = st::historyReplySkip; - (_editMsgId ? st::historyEditIcon : st::historyReplyIcon).paint(p, st::historyReplyIconPosition + QPoint(0, backy), width()); - if (!drawWebPagePreview) { - if (drawMsgText) { - if (hasPreview) { - if (preview) { - const auto overEdit = _photoEditMedia - ? _inPhotoEditOver.value(_inPhotoEdit ? 1. : 0.) - : 0.; - auto to = QRect( - replyLeft, - backy + (st::historyReplyHeight - st::historyReplyPreview) / 2, - st::historyReplyPreview, - st::historyReplyPreview); - p.drawPixmap(to.x(), to.y(), preview->pixSingle( - preview->size() / style::DevicePixelRatio(), - { - .options = Images::Option::RoundSmall, - .outer = to.size(), - })); - if (_replySpoiler) { - if (overEdit > 0.) { - p.setOpacity(1. - overEdit); - } - Ui::FillSpoilerRect( - p, - to, - Ui::DefaultImageSpoiler().frame( - _replySpoiler->index(now, pausedSpoiler))); - } - if (overEdit > 0.) { - p.setOpacity(overEdit); - p.fillRect(to, st::historyEditMediaBg); - st::historyEditMedia.paintInCenter(p, to); - p.setOpacity(1.); - } - } - replyLeft += st::historyReplyPreview + st::msgReplyBarSkip; - } - p.setPen(st::historyReplyNameFg); - if (_editMsgId) { - paintEditHeader(p, rect, replyLeft, backy); - } else { - _replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right()); - } - p.setPen(st::historyComposeAreaFg); - _replyEditMsgText.draw(p, { - .position = QPoint( - replyLeft, - backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height), - .availableWidth = width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right(), - .palette = &st::historyComposeAreaPalette, - .spoiler = Ui::Text::DefaultSpoilerCache(), - .now = now, - .pausedEmoji = paused || On(PowerSaving::kEmojiChat), - .pausedSpoiler = pausedSpoiler, - .elisionLines = 1, - }); - } else { - p.setFont(st::msgDateFont); - p.setPen(st::historyComposeAreaFgService); - p.drawText(replyLeft, backy + (st::historyReplyHeight - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(tr::lng_profile_loading(tr::now), width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right())); - } - } - } else if (hasForward) { - st::historyForwardIcon.paint(p, st::historyReplyIconPosition + QPoint(0, backy), width()); - if (!drawWebPagePreview) { - const auto x = st::historyReplySkip; - const auto available = width() - - x - - _fieldBarCancel->width() - - st::msgReplyPadding.right(); - _forwardPanel->paint(p, x, backy, available, width()); - } - } - if (drawWebPagePreview) { + if (_previewDrawPreview) { + st::historyLinkIcon.paint( + p, + st::historyReplyIconPosition + QPoint(0, backy), + width()); const auto textTop = backy + st::msgReplyPadding.top(); auto previewLeft = st::historyReplySkip; @@ -7998,6 +7896,87 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) { previewLeft, textTop + st::msgServiceNameFont->height, elidedWidth); + } else if (_editMsgId || _replyTo || (!hasForward && _kbReplyTo)) { + const auto now = crl::now(); + const auto paused = p.inactive(); + const auto pausedSpoiler = paused || On(PowerSaving::kChatSpoiler); + auto replyLeft = st::historyReplySkip; + (_editMsgId + ? st::historyEditIcon + : (_replyTo && !_replyTo.quote.empty()) + ? st::historyQuoteIcon + : st::historyReplyIcon).paint( + p, + st::historyReplyIconPosition + QPoint(0, backy), + width()); + if (drawMsgText) { + if (hasPreview) { + if (preview) { + const auto overEdit = _photoEditMedia + ? _inPhotoEditOver.value(_inPhotoEdit ? 1. : 0.) + : 0.; + auto to = QRect( + replyLeft, + backy + (st::historyReplyHeight - st::historyReplyPreview) / 2, + st::historyReplyPreview, + st::historyReplyPreview); + p.drawPixmap(to.x(), to.y(), preview->pixSingle( + preview->size() / style::DevicePixelRatio(), + { + .options = Images::Option::RoundSmall, + .outer = to.size(), + })); + if (_replySpoiler) { + if (overEdit > 0.) { + p.setOpacity(1. - overEdit); + } + Ui::FillSpoilerRect( + p, + to, + Ui::DefaultImageSpoiler().frame( + _replySpoiler->index(now, pausedSpoiler))); + } + if (overEdit > 0.) { + p.setOpacity(overEdit); + p.fillRect(to, st::historyEditMediaBg); + st::historyEditMedia.paintInCenter(p, to); + p.setOpacity(1.); + } + } + replyLeft += st::historyReplyPreview + st::msgReplyBarSkip; + } + p.setPen(st::historyReplyNameFg); + if (_editMsgId) { + paintEditHeader(p, rect, replyLeft, backy); + } else { + _replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right()); + } + p.setPen(st::historyComposeAreaFg); + _replyEditMsgText.draw(p, { + .position = QPoint( + replyLeft, + backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height), + .availableWidth = width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right(), + .palette = &st::historyComposeAreaPalette, + .spoiler = Ui::Text::DefaultSpoilerCache(), + .now = now, + .pausedEmoji = paused || On(PowerSaving::kEmojiChat), + .pausedSpoiler = pausedSpoiler, + .elisionLines = 1, + }); + } else { + p.setFont(st::msgDateFont); + p.setPen(st::historyComposeAreaFgService); + p.drawText(replyLeft, backy + (st::historyReplyHeight - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(tr::lng_profile_loading(tr::now), width() - replyLeft - _fieldBarCancel->width() - st::msgReplyPadding.right())); + } + } else if (hasForward) { + st::historyForwardIcon.paint(p, st::historyReplyIconPosition + QPoint(0, backy), width()); + const auto x = st::historyReplySkip; + const auto available = width() + - x + - _fieldBarCancel->width() + - st::msgReplyPadding.right(); + _forwardPanel->paint(p, x, backy, available, width()); } } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 87b7edde9..10a54c858 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -647,7 +647,6 @@ private: MTP::Sender _api; FullReplyTo _replyTo; Ui::Text::String _replyToName; - int _replyToNameVersion = 0; FullReplyTo _processingReplyTo; HistoryItem *_processingReplyItem = nullptr; @@ -688,8 +687,6 @@ private: Ui::Text::String _previewTitle; Ui::Text::String _previewDescription; - bool _replyForwardPressed = false; - PeerData *_peer = nullptr; bool _canSendMessages = false; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 540d4ca5f..f697baf00 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -51,6 +51,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/controls/history_view_voice_record_bar.h" #include "history/view/controls/history_view_ttl_button.h" #include "history/view/controls/history_view_webpage_processor.h" +#include "history/view/history_view_reply.h" #include "history/view/history_view_webpage_preview.h" #include "inline_bots/bot_attach_web_view.h" #include "inline_bots/inline_results_widget.h" @@ -192,7 +193,6 @@ private: Ui::Text::String _shownMessageText; std::unique_ptr _shownPreviewSpoiler; Ui::Animations::Simple _inPhotoEditOver; - int _shownMessageNameVersion = -1; bool _shownMessageHasPreview : 1 = false; bool _inPhotoEdit : 1 = false; bool _photoEditAllowed : 1 = false; @@ -245,7 +245,6 @@ void FieldHeader::init() { updateVisible(); }, lifetime()); - const auto leftIconPressed = lifetime().make_state(false); paintRequest( ) | rpl::start_with_next([=] { Painter p(this); @@ -253,21 +252,29 @@ void FieldHeader::init() { p.fillRect(rect(), st::historyComposeAreaBg); const auto position = st::historyReplyIconPosition; - if (isEditingMessage()) { + if (_preview.parsed) { + st::historyLinkIcon.paint(p, position, width()); + } else if (isEditingMessage()) { st::historyEditIcon.paint(p, position, width()); } else if (readyToForward()) { st::historyForwardIcon.paint(p, position, width()); - } else if (replyingToMessage()) { - st::historyReplyIcon.paint(p, position, width()); + } else if (const auto reply = replyingToMessage()) { + if (!reply.quote.empty()) { + st::historyQuoteIcon.paint(p, position, width()); + } else { + st::historyReplyIcon.paint(p, position, width()); + } } - (_preview.parsed && !*leftIconPressed) - ? paintWebPage( + if (_preview.parsed) { + paintWebPage( p, - _history ? _history->peer : _data->session().user()) - : (isEditingMessage() || !readyToForward()) - ? paintEditOrReplyToMessage(p) - : paintForwardInfo(p); + _history ? _history->peer : _data->session().user()); + } else if (isEditingMessage() || !readyToForward()) { + paintEditOrReplyToMessage(p); + } else { + paintForwardInfo(p); + } }, lifetime()); _editMsgId.value( @@ -359,13 +366,9 @@ void FieldHeader::init() { updateOver(inPreviewRect, inPhotoEdit); return; } - const auto isLeftIcon = (pos.x() < st::historyReplySkip); const auto isLeftButton = (e->button() == Qt::LeftButton); if (type == QEvent::MouseButtonPress) { - if (isLeftButton && isLeftIcon && !inPreviewRect) { - *leftIconPressed = true; - update(); - } else if (isLeftButton && inPhotoEdit) { + if (isLeftButton && inPhotoEdit) { _editPhotoRequests.fire({}); } else if (isLeftButton && inPreviewRect) { const auto reply = replyingToMessage(); @@ -384,11 +387,6 @@ void FieldHeader::init() { _editOptionsRequests.fire({}); } } - } else if (type == QEvent::MouseButtonRelease) { - if (isLeftButton && *leftIconPressed) { - *leftIconPressed = false; - update(); - } } }, lifetime()); } @@ -431,9 +429,21 @@ void FieldHeader::setShownMessage(HistoryItem *item) { st::msgNameStyle, tr::lng_edit_message(tr::now), Ui::NameTextOptions()); + } else if (item) { + const auto context = Core::MarkedTextContext{ + .session = &_history->session(), + .customEmojiRepaint = [] {}, + .customEmojiLoopLimit = 1, + }; + const auto replyTo = _replyTo.current(); + const auto quote = replyTo && !replyTo.quote.empty(); + _shownMessageName.setMarkedText( + st::fwdTextStyle, + HistoryView::Reply::ComposePreviewName(_history, item, quote), + Ui::NameTextOptions(), + context); } else { _shownMessageName.clear(); - _shownMessageNameVersion = -1; } updateVisible(); update(); @@ -545,19 +555,6 @@ void FieldHeader::paintEditOrReplyToMessage(Painter &p) { return; } - if (!isEditingMessage()) { - const auto user = _shownMessage->displayFrom() - ? _shownMessage->displayFrom() - : _shownMessage->author().get(); - if (_shownMessageNameVersion < user->nameVersion()) { - _shownMessageName.setText( - st::msgNameStyle, - user->name(), - Ui::NameTextOptions()); - _shownMessageNameVersion = user->nameVersion(); - } - } - const auto media = _shownMessage->media(); _shownMessageHasPreview = media && media->hasReplyPreview(); const auto preview = _shownMessageHasPreview @@ -692,12 +689,11 @@ FullReplyTo FieldHeader::getDraftReply() const { void FieldHeader::updateControlsGeometry(QSize size) { const auto isReadyToForward = readyToForward(); - const auto skip = isReadyToForward ? 0 : st::historyReplySkip; _cancel->moveToRight(0, 0); _clickableRect = QRect( - skip, 0, - width() - skip - _cancel->width(), + 0, + width() - _cancel->width(), height()); _shownMessagePreviewRect = QRect( st::historyReplySkip, diff --git a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp index 850ecfe6b..6812cb273 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp @@ -642,6 +642,8 @@ void DraftOptionsBox( if (const auto current = state->quote.current()) { result.messageId = current.item->fullId(); result.quote = current.text; + } else { + result.quote = {}; } return result; }; diff --git a/Telegram/SourceFiles/history/view/history_view_reply.cpp b/Telegram/SourceFiles/history/view/history_view_reply.cpp index 6899a0832..10877d5c1 100644 --- a/Telegram/SourceFiles/history/view/history_view_reply.cpp +++ b/Telegram/SourceFiles/history/view/history_view_reply.cpp @@ -394,10 +394,11 @@ void Reply::updateName( viaBotUsername = bot->username(); } } + const auto history = view->history(); const auto &fields = data->fields(); const auto sender = resolvedSender.value_or(this->sender(view, data)); const auto externalPeer = fields.externalPeerId - ? view->history()->owner().peer(fields.externalPeerId).get() + ? history->owner().peer(fields.externalPeerId).get() : nullptr; const auto displayAsExternal = data->displayAsExternal(view->data()); const auto groupNameAdded = displayAsExternal @@ -415,38 +416,20 @@ void Reply::updateName( + st::historyReplyPreviewMargin.right() - st::historyReplyPadding.left()) : 0; - const auto peerIcon = [](PeerData *peer) { - using namespace std; - return !peer - ? pair(&st::historyReplyUser, st::historyReplyUserPadding) - : peer->isBroadcast() - ? pair(&st::historyReplyChannel, st::historyReplyChannelPadding) - : (peer->isChannel() || peer->isChat()) - ? pair(&st::historyReplyGroup, st::historyReplyGroupPadding) - : pair(&st::historyReplyUser, st::historyReplyUserPadding); - }; - const auto peerEmoji = [&](PeerData *peer) { - const auto owner = &view->history()->owner(); - const auto icon = peerIcon(peer); - return Ui::Text::SingleCustomEmoji( - owner->customEmojiManager().registerInternalEmoji( - *icon.first, - icon.second)); - }; auto nameFull = TextWithEntities(); if (displayAsExternal && !groupNameAdded && !fields.storyId) { - nameFull.append(peerEmoji(sender)); + nameFull.append(PeerEmoji(history, sender)); } nameFull.append(name); if (groupNameAdded) { - nameFull.append(' ').append(peerEmoji(externalPeer)); + nameFull.append(' ').append(PeerEmoji(history, externalPeer)); nameFull.append(externalPeer->name()); } if (!viaBotUsername.isEmpty()) { nameFull.append(u" @"_q).append(viaBotUsername); } const auto context = Core::MarkedTextContext{ - .session = &view->history()->session(), + .session = &history->session(), .customEmojiRepaint = [] {}, .customEmojiLoopLimit = 1, }; @@ -813,6 +796,61 @@ void Reply::stopLastRipple() { } } +TextWithEntities Reply::PeerEmoji( + not_null history, + PeerData *peer) { + using namespace std; + const auto icon = !peer + ? pair(&st::historyReplyUser, st::historyReplyUserPadding) + : peer->isBroadcast() + ? pair(&st::historyReplyChannel, st::historyReplyChannelPadding) + : (peer->isChannel() || peer->isChat()) + ? pair(&st::historyReplyGroup, st::historyReplyGroupPadding) + : pair(&st::historyReplyUser, st::historyReplyUserPadding); + const auto owner = &history->owner(); + return Ui::Text::SingleCustomEmoji( + owner->customEmojiManager().registerInternalEmoji( + *icon.first, + icon.second)); +} + +TextWithEntities Reply::ComposePreviewName( + not_null history, + not_null to, + bool quote) { + const auto sender = [&] { + if (const auto from = to->displayFrom()) { + return not_null(from); + } + return to->author(); + }(); + const auto toPeer = to->history()->peer; + const auto displayAsExternal = (to->history() != history); + const auto groupNameAdded = displayAsExternal + && (toPeer != sender) + && (toPeer->isChat() || toPeer->isMegagroup()); + const auto shorten = groupNameAdded || quote; + + auto nameFull = TextWithEntities(); + using namespace HistoryView; + if (displayAsExternal && !groupNameAdded) { + nameFull.append(Reply::PeerEmoji(history, sender)); + } + nameFull.append(shorten ? sender->shortName() : sender->name()); + if (groupNameAdded) { + nameFull.append(' ').append(Reply::PeerEmoji(history, toPeer)); + nameFull.append(toPeer->name()); + } + return (quote + ? tr::lng_preview_reply_to_quote + : tr::lng_preview_reply_to)( + tr::now, + lt_name, + nameFull, + Ui::Text::WithEntities); + +} + void Reply::unloadPersistentAnimation() { _text.unloadPersistentAnimation(); } diff --git a/Telegram/SourceFiles/history/view/history_view_reply.h b/Telegram/SourceFiles/history/view/history_view_reply.h index 5322d5c09..4b30a842d 100644 --- a/Telegram/SourceFiles/history/view/history_view_reply.h +++ b/Telegram/SourceFiles/history/view/history_view_reply.h @@ -63,6 +63,14 @@ public: return _link; } + [[nodiscard]] static TextWithEntities PeerEmoji( + not_null history, + PeerData *peer); + [[nodiscard]] static TextWithEntities ComposePreviewName( + not_null history, + not_null to, + bool quote); + private: [[nodiscard]] Ui::Text::GeometryDescriptor textGeometry( int available, From 98bd5757b0d8262a1aaf2aee5fee0b39f193d5b4 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 13 Nov 2023 09:18:51 +0300 Subject: [PATCH 10/16] Increased pagination limits for recent messages in statistics info. --- .../info/statistics/info_statistics_inner_widget.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp index 237453d6e..694c67fb5 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp @@ -702,8 +702,9 @@ void InnerWidget::fillRecentPosts() { container, tr::lng_stories_show_more()))); - constexpr auto kPerPage = int(10); - const auto max = stats.recentMessageInteractions.size(); + constexpr auto kFirstPage = int(10); + constexpr auto kPerPage = int(30); + const auto max = int(stats.recentMessageInteractions.size()); if (_state.recentPostsExpanded) { _state.recentPostsExpanded = std::max( _state.recentPostsExpanded - kPerPage, @@ -712,8 +713,10 @@ void InnerWidget::fillRecentPosts() { const auto showMore = [=] { const auto from = _state.recentPostsExpanded; _state.recentPostsExpanded = std::min( - int(max), - _state.recentPostsExpanded + kPerPage); + max, + _state.recentPostsExpanded + ? (_state.recentPostsExpanded + kPerPage) + : kFirstPage); if (_state.recentPostsExpanded == max) { buttonWrap->toggle(false, anim::type::instant); } From d4d2eef2915315e04a2ba63a7aff3b081cb67f6a Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Nov 2023 10:40:44 +0400 Subject: [PATCH 11/16] Fix clearing cloud draft on message send. Regression was introduced in 20ba417ddd. --- Telegram/SourceFiles/apiwrap.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index ea150bf9b..82c819051 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3582,11 +3582,12 @@ void ApiWrap::sendMessage(MessageToSend &&message) { sendAction(action); const auto clearCloudDraft = action.clearDraft; + const auto draftTopicRootId = action.replyTo.topicRootId; const auto replyTo = action.replyTo.messageId ? peer->owner().message(action.replyTo.messageId) : nullptr; - const auto topicRootId = action.replyTo.topicRootId - ? action.replyTo.topicRootId + const auto topicRootId = draftTopicRootId + ? draftTopicRootId : replyTo ? replyTo->topicRootId() : Data::ForumTopic::kGeneralId; @@ -3626,7 +3627,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) { TextUtilities::Trim(sending); _session->data().registerMessageRandomId(randomId, newId); - _session->data().registerMessageSentData(randomId, peer->id, sending.text); + _session->data().registerMessageSentData( + randomId, + peer->id, + sending.text); MTPstring msgText(MTP_string(sending.text)); auto flags = NewMessageFlags(peer); @@ -3688,8 +3692,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) { if (clearCloudDraft) { sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft; mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; - history->clearCloudDraft(topicRootId); - history->startSavingCloudDraft(topicRootId); + history->clearCloudDraft(draftTopicRootId); + history->startSavingCloudDraft(draftTopicRootId); } const auto sendAs = action.options.sendAs; const auto messageFromId = sendAs @@ -3726,7 +3730,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) { const MTP::Response &response) { if (clearCloudDraft) { history->finishSavingCloudDraft( - topicRootId, + draftTopicRootId, UnixtimeFromMsgId(response.outerMsgId)); } }; @@ -3740,7 +3744,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) { } if (clearCloudDraft) { history->finishSavingCloudDraft( - topicRootId, + draftTopicRootId, UnixtimeFromMsgId(response.outerMsgId)); } }; From 22cedbc9cc85dcb3f83d1aa85fe924a147f9f6f0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Nov 2023 11:38:37 +0400 Subject: [PATCH 12/16] Don't show full albums in search results. --- Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index e71c3cefd..5299b648c 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -879,7 +879,7 @@ void RowPainter::Paint( } return nullptr; }(); - const auto previewOptions = [&]() -> HistoryView::ToPreviewOptions { + auto previewOptions = [&]() -> HistoryView::ToPreviewOptions { if (topic) { return {}; } else if (const auto searchChat = row->searchInChat()) { @@ -891,6 +891,7 @@ void RowPainter::Paint( } return {}; }(); + previewOptions.ignoreGroup = true; const auto badgesState = context.displayUnreadInfo ? entry->chatListBadgesState() From 69efd127eb1eb181e42849bc3b0fc00381c17e1b Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Nov 2023 10:43:34 +0400 Subject: [PATCH 13/16] Update submodules. --- Telegram/SourceFiles/platform/win/integration_win.h | 2 +- Telegram/SourceFiles/platform/win/windows_app_user_model_id.h | 2 ++ Telegram/SourceFiles/platform/win/windows_dlls.h | 1 + Telegram/ThirdParty/libtgvoip | 2 +- Telegram/lib_base | 2 +- Telegram/lib_ui | 2 +- Telegram/lib_webview | 2 +- cmake | 2 +- 8 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/platform/win/integration_win.h b/Telegram/SourceFiles/platform/win/integration_win.h index b51184e1d..5e559b69a 100644 --- a/Telegram/SourceFiles/platform/win/integration_win.h +++ b/Telegram/SourceFiles/platform/win/integration_win.h @@ -7,11 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/platform/win/base_windows_winrt.h" #include "platform/platform_integration.h" #include -#include #include namespace Platform { diff --git a/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h b/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h index 92d6c2b7d..4f69019eb 100644 --- a/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h +++ b/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h @@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/platform/win/base_windows_h.h" +#include + namespace Platform { namespace AppUserModelId { diff --git a/Telegram/SourceFiles/platform/win/windows_dlls.h b/Telegram/SourceFiles/platform/win/windows_dlls.h index eef6e9bc7..d97eeab92 100644 --- a/Telegram/SourceFiles/platform/win/windows_dlls.h +++ b/Telegram/SourceFiles/platform/win/windows_dlls.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/platform/win/base_windows_h.h" +#include #include #include #include diff --git a/Telegram/ThirdParty/libtgvoip b/Telegram/ThirdParty/libtgvoip index c2e718049..e286ab661 160000 --- a/Telegram/ThirdParty/libtgvoip +++ b/Telegram/ThirdParty/libtgvoip @@ -1 +1 @@ -Subproject commit c2e718049cf11bbbe7b6d78b78b2d21f0e0affa0 +Subproject commit e286ab66141a2f986803177e4cbb7b14002664cb diff --git a/Telegram/lib_base b/Telegram/lib_base index bb5e7fafd..fe4f0a72d 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit bb5e7fafd7aca5808217baeeb9ee3af8c3be6b1b +Subproject commit fe4f0a72d2041a860c67a81a70f2e4b6f845d9fb diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 024f438ce..f9b24c755 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 024f438ce539d627717e4793479c8b727e8df29b +Subproject commit f9b24c75512bc5f73b9ec5e6612858394582a328 diff --git a/Telegram/lib_webview b/Telegram/lib_webview index f5fe3afcf..aab27269f 160000 --- a/Telegram/lib_webview +++ b/Telegram/lib_webview @@ -1 +1 @@ -Subproject commit f5fe3afcf5bc5edf07a78ad18b9e8d33c3fbfdb2 +Subproject commit aab27269ff8aad5dfaf7372db10bff700fdb5fe9 diff --git a/cmake b/cmake index 78098ede7..c373a0a01 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 78098ede77a09e41da6233d765d02b43a60e7138 +Subproject commit c373a0a0141bbe146a9507f02b8515183748eb51 From d2b6012bfd787edeeba19892c35d44be809e668c Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sun, 12 Nov 2023 13:43:13 +0400 Subject: [PATCH 14/16] Mark code unneeded after Qt 6.6.0 --- Telegram/SourceFiles/platform/mac/main_window_mac.mm | 11 +++++++++++ Telegram/SourceFiles/platform/mac/specific_mac_p.mm | 10 ++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index d30a65809..92c948549 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -40,7 +40,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include + +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) #include +#endif // Qt < 6.6.0 #include #include @@ -52,7 +55,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL - (id) init:(MainWindow::Private*)window; - (void) activeSpaceDidChange:(NSNotification *)aNotification; +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) - (void) darkModeChanged:(NSNotification *)aNotification; +#endif // Qt < 6.6.0 - (void) screenIsLocked:(NSNotification *)aNotification; - (void) screenIsUnlocked:(NSNotification *)aNotification; @@ -113,6 +118,7 @@ private: - (void) activeSpaceDidChange:(NSNotification *)aNotification { } +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) - (void) darkModeChanged:(NSNotification *)aNotification { Core::Sandbox::Instance().customEnterFromEventLoop([&] { #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) @@ -122,6 +128,7 @@ private: #endif // Qt < 6.5.0 }); } +#endif // Qt < 6.6.0 - (void) screenIsLocked:(NSNotification *)aNotification { Core::App().setScreenIsLocked(true); @@ -156,10 +163,12 @@ void ForceDisabled(QAction *action, bool disabled) { } } +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) QString strNotificationAboutThemeChange() { const uint32 letters[] = { 0x75E86256, 0xD03E11B1, 0x4D92201D, 0xA2144987, 0x99D5B34F, 0x037589C3, 0x38ED2A7C, 0xD2371ABC, 0xDC98BB02, 0x27964E1B, 0x01748AED, 0xE06679F8, 0x761C9580, 0x4F2595BF, 0x6B5FCBF4, 0xE4D9C24E, 0xBA2F6AB5, 0xE6E3FA71, 0xF2CFC255, 0x56A50C19, 0x43AE1239, 0x77CA4254, 0x7D189A89, 0xEA7663EE, 0x84CEB554, 0xA0ADF236, 0x886512D4, 0x7D3FBDAF, 0x85C4BE4F, 0x12C8255E, 0x9AD8BD41, 0xAC154683, 0xB117598B, 0xDFD9F947, 0x63F06C7B, 0x6340DCD6, 0x3AAE6B3E, 0x26CB125A }; return Platform::MakeFromLetters(letters); } +#endif // Qt < 6.6.0 QString strNotificationAboutScreenLocked() { const uint32 letters[] = { 0x34B47F28, 0x47E95179, 0x73D05C42, 0xB4E2A933, 0x924F22D1, 0x4265D8EA, 0x9E4D2CC2, 0x02E8157B, 0x35BF7525, 0x75901A41, 0xB0400FCC, 0xE801169D, 0x4E04B589, 0xC1CEF054, 0xAB2A7EB0, 0x5C67C4F6, 0xA4E2B954, 0xB35E12D2, 0xD598B22B, 0x4E3B8AAB, 0xBEA5E439, 0xFDA8AA3C, 0x1632DBA8, 0x88FE8965 }; @@ -181,7 +190,9 @@ MainWindow::Private::Private(not_null window) @autoreleasepool { [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:_observer selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil]; +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) [[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(darkModeChanged:) name:Q2NSString(strNotificationAboutThemeChange()) object:nil]; +#endif // Qt < 6.6.0 [[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsLocked:) name:Q2NSString(strNotificationAboutScreenLocked()) object:nil]; [[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil]; diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm index 984643871..de1f1d1ec 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm @@ -30,7 +30,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #if __has_include() #include #endif // __has_include() +#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) #include +#endif // Qt < 6.6.0 #include #include #include @@ -201,11 +203,11 @@ ApplicationDelegate *_sharedDelegate = nil; "-receiveWakeNote: received, scheduling detach from audio device")); Media::Audio::ScheduleDetachFromDeviceSafe(); -#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) - QWindowSystemInterface::handleThemeChange(); -#else // Qt >= 6.5.0 +#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) Core::App().settings().setSystemDarkMode(Platform::IsDarkMode()); -#endif // Qt < 6.5.0 +#elif QT_VERSION < QT_VERSION_CHECK(6, 6, 0) // Qt < 6.5.0 + QWindowSystemInterface::handleThemeChange(); +#endif // Qt < 6.6.0 }); } From 53b342f72293e5ee7194e195042650675408b878 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Nov 2023 11:46:07 +0400 Subject: [PATCH 15/16] Version 4.11.7. - Fix sending media files with quote replies. - Fix quoted text highlighting in some cases. - Fix loading statistics for some channels. - Fix Ctrl+Shift+. shortcut on X11. - Fix a crash in statistics. --- 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 | 8 ++++++++ 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index 87d43e603..b206163a2 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -10,7 +10,7 @@ + Version="4.11.7.0" /> Telegram Desktop Telegram Messenger LLP diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index d4c42a1cf..aeacecdf8 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,11,6,0 - PRODUCTVERSION 4,11,6,0 + FILEVERSION 4,11,7,0 + PRODUCTVERSION 4,11,7,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -62,10 +62,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop" - VALUE "FileVersion", "4.11.6.0" + VALUE "FileVersion", "4.11.7.0" VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "4.11.6.0" + VALUE "ProductVersion", "4.11.7.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 0ceaffbf2..768f1d460 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,11,6,0 - PRODUCTVERSION 4,11,6,0 + FILEVERSION 4,11,7,0 + PRODUCTVERSION 4,11,7,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -53,10 +53,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop Updater" - VALUE "FileVersion", "4.11.6.0" + VALUE "FileVersion", "4.11.7.0" VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "4.11.6.0" + VALUE "ProductVersion", "4.11.7.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 59219d9c3..7e21b5238 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 = 4011006; -constexpr auto AppVersionStr = "4.11.6"; +constexpr auto AppVersion = 4011007; +constexpr auto AppVersionStr = "4.11.7"; constexpr auto AppBetaVersion = false; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/build/version b/Telegram/build/version index 447ef2247..065ee5c80 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 4011006 +AppVersion 4011007 AppVersionStrMajor 4.11 -AppVersionStrSmall 4.11.6 -AppVersionStr 4.11.6 +AppVersionStrSmall 4.11.7 +AppVersionStr 4.11.7 BetaChannel 0 AlphaVersion 0 -AppVersionOriginal 4.11.6 +AppVersionOriginal 4.11.7 diff --git a/changelog.txt b/changelog.txt index 245ef9c1e..c7e56597b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,11 @@ +4.11.7 (13.11.23) + +- Fix sending media files with quote replies. +- Fix quoted text highlighting in some cases. +- Fix loading statistics for some channels. +- Fix Ctrl+Shift+. shortcut on X11. +- Fix a crash in statistics. + 4.11.6 (09.11.23) - Support multiple boosts and reassignment. From df8c80226baba5a546435b052b6baabb4d0b37f7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Nov 2023 12:24:29 +0400 Subject: [PATCH 16/16] Version 4.11.7: Fix build with GCC. --- Telegram/SourceFiles/api/api_statistics.cpp | 1 - .../history/view/controls/history_view_compose_controls.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/Telegram/SourceFiles/api/api_statistics.cpp b/Telegram/SourceFiles/api/api_statistics.cpp index 09b5c5c06..1f5c093a6 100644 --- a/Telegram/SourceFiles/api/api_statistics.cpp +++ b/Telegram/SourceFiles/api/api_statistics.cpp @@ -208,7 +208,6 @@ StatisticsRequestSender::~StatisticsRequestSender() { } void StatisticsRequestSender::checkRequests() { - const auto api = &_channel->session().api(); for (auto i = begin(_requests); i != end(_requests);) { for (auto j = begin(i->second); j != end(i->second);) { if (_api.pending(*j)) { diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index f697baf00..8b9ac3393 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -688,7 +688,6 @@ FullReplyTo FieldHeader::getDraftReply() const { } void FieldHeader::updateControlsGeometry(QSize size) { - const auto isReadyToForward = readyToForward(); _cancel->moveToRight(0, 0); _clickableRect = QRect( 0,