Merge tag 'v4.11.7' into dev

# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/lib_ui
This commit is contained in:
ZavaruKitsu 2023-11-19 00:27:58 +03:00
commit 98b8840019
54 changed files with 537 additions and 353 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -2714,6 +2714,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_forwarding_from_two" = "{user} and {second_user}"; "lng_forwarding_from_two" = "{user} and {second_user}";
"lng_inline_switch_choose" = "Choose conversation..."; "lng_inline_switch_choose" = "Choose conversation...";
"lng_inline_switch_cant" = "Sorry, no way to write here :("; "lng_inline_switch_cant" = "Sorry, no way to write here :(";
"lng_preview_reply_to" = "Reply to {name}";
"lng_preview_reply_to_quote" = "Reply to quote by {name}";
"lng_reply_in_another_title" = "Reply in..."; "lng_reply_in_another_title" = "Reply in...";
"lng_reply_in_another_chat" = "Reply in Another Chat"; "lng_reply_in_another_chat" = "Reply in Another Chat";

View file

@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.11.6.0" /> Version="4.11.7.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName> <PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,11,6,0 FILEVERSION 4,11,7,0
PRODUCTVERSION 4,11,6,0 PRODUCTVERSION 4,11,7,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop" VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "4.11.6.0" VALUE "FileVersion", "4.11.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.11.6.0" VALUE "ProductVersion", "4.11.7.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,11,6,0 FILEVERSION 4,11,7,0
PRODUCTVERSION 4,11,6,0 PRODUCTVERSION 4,11,7,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater" VALUE "FileDescription", "AyuGram Desktop Updater"
VALUE "FileVersion", "4.11.6.0" VALUE "FileVersion", "4.11.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.11.6.0" VALUE "ProductVersion", "4.11.7.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -18,6 +18,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Api { namespace Api {
namespace { namespace {
constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
[[nodiscard]] Data::StatisticalGraph StatisticalGraphFromTL( [[nodiscard]] Data::StatisticalGraph StatisticalGraphFromTL(
const MTPStatsGraph &tl) { const MTPStatsGraph &tl) {
return tl.match([&](const MTPDstatsGraph &d) { return tl.match([&](const MTPDstatsGraph &d) {
@ -187,23 +189,73 @@ namespace {
} // namespace } // namespace
Statistics::Statistics(not_null<ApiWrap*> api) Statistics::Statistics(not_null<ChannelData*> channel)
: _api(&api->instance()) { : StatisticsRequestSender(channel) {
} }
rpl::producer<rpl::no_value, QString> Statistics::request( StatisticsRequestSender::StatisticsRequestSender(not_null<ChannelData *> channel)
not_null<PeerData*> peer) { : _channel(channel)
, _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() {
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 <typename Request, typename, typename>
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>(request)
).toDC(
dcId ? MTP::ShiftDcId(dcId, MTP::kStatsDcShift) : 0
).overrideId(id));
}
rpl::producer<rpl::no_value, QString> Statistics::request() {
return [=](auto consumer) { return [=](auto consumer) {
auto lifetime = rpl::lifetime(); auto lifetime = rpl::lifetime();
const auto channel = peer->asChannel();
if (!channel) {
return lifetime;
}
if (!channel->isMegagroup()) { if (!channel()->isMegagroup()) {
_api.request(MTPstats_GetBroadcastStats( makeRequest(MTPstats_GetBroadcastStats(
MTP_flags(MTPstats_GetBroadcastStats::Flags(0)), MTP_flags(MTPstats_GetBroadcastStats::Flags(0)),
channel->inputChannel channel()->inputChannel
)).done([=](const MTPstats_BroadcastStats &result) { )).done([=](const MTPstats_BroadcastStats &result) {
_channelStats = ChannelStatisticsFromTL(result.data()); _channelStats = ChannelStatisticsFromTL(result.data());
consumer.put_done(); consumer.put_done();
@ -211,12 +263,13 @@ rpl::producer<rpl::no_value, QString> Statistics::request(
consumer.put_error_copy(error.type()); consumer.put_error_copy(error.type());
}).send(); }).send();
} else { } else {
_api.request(MTPstats_GetMegagroupStats( makeRequest(MTPstats_GetMegagroupStats(
MTP_flags(MTPstats_GetMegagroupStats::Flags(0)), MTP_flags(MTPstats_GetMegagroupStats::Flags(0)),
channel->inputChannel channel()->inputChannel
)).done([=](const MTPstats_MegagroupStats &result) { )).done([=](const MTPstats_MegagroupStats &result) {
_supergroupStats = SupergroupStatisticsFromTL(result.data()); const auto &data = result.data();
peer->owner().processUsers(result.data().vusers()); _supergroupStats = SupergroupStatisticsFromTL(data);
channel()->owner().processUsers(data.vusers());
consumer.put_done(); consumer.put_done();
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
consumer.put_error_copy(error.type()); consumer.put_error_copy(error.type());
@ -228,18 +281,13 @@ rpl::producer<rpl::no_value, QString> Statistics::request(
} }
Statistics::GraphResult Statistics::requestZoom( Statistics::GraphResult Statistics::requestZoom(
not_null<PeerData*> peer,
const QString &token, const QString &token,
float64 x) { float64 x) {
return [=](auto consumer) { return [=](auto consumer) {
auto lifetime = rpl::lifetime(); auto lifetime = rpl::lifetime();
const auto channel = peer->asChannel();
if (!channel) {
return lifetime;
}
const auto wasEmpty = _zoomDeque.empty(); const auto wasEmpty = _zoomDeque.empty();
_zoomDeque.push_back([=] { _zoomDeque.push_back([=] {
_api.request(MTPstats_LoadAsyncGraph( makeRequest(MTPstats_LoadAsyncGraph(
MTP_flags(x MTP_flags(x
? MTPstats_LoadAsyncGraph::Flag::f_x ? MTPstats_LoadAsyncGraph::Flag::f_x
: MTPstats_LoadAsyncGraph::Flag(0)), : MTPstats_LoadAsyncGraph::Flag(0)),
@ -266,32 +314,6 @@ Statistics::GraphResult Statistics::requestZoom(
}; };
} }
Statistics::GraphResult Statistics::requestMessage(
not_null<PeerData*> 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 { Data::ChannelStatistics Statistics::channelStats() const {
return _channelStats; return _channelStats;
} }
@ -303,9 +325,8 @@ Data::SupergroupStatistics Statistics::supergroupStats() const {
PublicForwards::PublicForwards( PublicForwards::PublicForwards(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
FullMsgId fullId) FullMsgId fullId)
: _channel(channel) : StatisticsRequestSender(channel)
, _fullId(fullId) , _fullId(fullId) {
, _api(&channel->session().api().instance()) {
} }
void PublicForwards::request( void PublicForwards::request(
@ -314,19 +335,19 @@ void PublicForwards::request(
if (_requestId) { if (_requestId) {
return; return;
} }
const auto offsetPeer = _channel->owner().peer(token.fullId.peer); const auto offsetPeer = channel()->owner().peer(token.fullId.peer);
const auto tlOffsetPeer = offsetPeer const auto tlOffsetPeer = offsetPeer
? offsetPeer->input ? offsetPeer->input
: MTP_inputPeerEmpty(); : MTP_inputPeerEmpty();
constexpr auto kLimit = tl::make_int(100); constexpr auto kLimit = tl::make_int(100);
_requestId = _api.request(MTPstats_GetMessagePublicForwards( _requestId = makeRequest(MTPstats_GetMessagePublicForwards(
_channel->inputChannel, channel()->inputChannel,
MTP_int(_fullId.msg), MTP_int(_fullId.msg),
MTP_int(token.rate), MTP_int(token.rate),
tlOffsetPeer, tlOffsetPeer,
MTP_int(token.fullId.msg), MTP_int(token.fullId.msg),
kLimit kLimit
)).done([=, channel = _channel](const MTPmessages_Messages &result) { )).done([=, channel = channel()](const MTPmessages_Messages &result) {
using Messages = QVector<FullMsgId>; using Messages = QVector<FullMsgId>;
_requestId = 0; _requestId = 0;
@ -402,10 +423,9 @@ void PublicForwards::request(
MessageStatistics::MessageStatistics( MessageStatistics::MessageStatistics(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
FullMsgId fullId) FullMsgId fullId)
: _publicForwards(channel, fullId) : StatisticsRequestSender(channel)
, _channel(channel) , _publicForwards(channel, fullId)
, _fullId(fullId) , _fullId(fullId) {
, _api(&channel->session().api().instance()) {
} }
Data::PublicForwardsSlice MessageStatistics::firstSlice() const { Data::PublicForwardsSlice MessageStatistics::firstSlice() const {
@ -413,10 +433,9 @@ Data::PublicForwardsSlice MessageStatistics::firstSlice() const {
} }
void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) { void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
if (_channel->isMegagroup()) { if (channel()->isMegagroup()) {
return; return;
} }
const auto requestFirstPublicForwards = [=]( const auto requestFirstPublicForwards = [=](
const Data::StatisticalGraph &messageGraph, const Data::StatisticalGraph &messageGraph,
const Data::StatisticsMessageInteractionInfo &info) { const Data::StatisticsMessageInteractionInfo &info) {
@ -434,8 +453,8 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
const auto requestPrivateForwards = [=]( const auto requestPrivateForwards = [=](
const Data::StatisticalGraph &messageGraph) { const Data::StatisticalGraph &messageGraph) {
_api.request(MTPchannels_GetMessages( api().request(MTPchannels_GetMessages(
_channel->inputChannel, channel()->inputChannel,
MTP_vector<MTPInputMessage>( MTP_vector<MTPInputMessage>(
1, 1,
MTP_inputMessageID(MTP_int(_fullId.msg)))) MTP_inputMessageID(MTP_int(_fullId.msg))))
@ -475,9 +494,9 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
}).send(); }).send();
}; };
_api.request(MTPstats_GetMessageStats( makeRequest(MTPstats_GetMessageStats(
MTP_flags(MTPstats_GetMessageStats::Flags(0)), MTP_flags(MTPstats_GetMessageStats::Flags(0)),
_channel->inputChannel, channel()->inputChannel,
MTP_int(_fullId.msg.bare) MTP_int(_fullId.msg.bare)
)).done([=](const MTPstats_MessageStats &result) { )).done([=](const MTPstats_MessageStats &result) {
requestPrivateForwards( requestPrivateForwards(
@ -485,7 +504,6 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
requestPrivateForwards({}); requestPrivateForwards({});
}).send(); }).send();
} }
Boosts::Boosts(not_null<PeerData*> peer) Boosts::Boosts(not_null<PeerData*> peer)

View file

@ -7,30 +7,53 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "base/timer.h"
#include "data/data_boosts.h" #include "data/data_boosts.h"
#include "data/data_statistics.h" #include "data/data_statistics.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
class ApiWrap;
class ChannelData; class ChannelData;
class PeerData; class PeerData;
namespace Api { namespace Api {
class Statistics final { class StatisticsRequestSender {
public: protected:
explicit Statistics(not_null<ApiWrap*> api); explicit StatisticsRequestSender(not_null<ChannelData*> channel);
~StatisticsRequestSender();
[[nodiscard]] rpl::producer<rpl::no_value, QString> request( template <
not_null<PeerData*> peer); typename Request,
typename = std::enable_if_t<!std::is_reference_v<Request>>,
typename = typename Request::Unboxed>
[[nodiscard]] auto makeRequest(Request &&request);
[[nodiscard]] MTP::Sender &api() {
return _api;
}
[[nodiscard]] not_null<ChannelData*> channel() {
return _channel;
}
private:
void checkRequests();
const not_null<ChannelData*> _channel;
MTP::Sender _api;
base::Timer _timer;
base::flat_map<MTP::DcId, base::flat_set<mtpRequestId>> _requests;
};
class Statistics final : public StatisticsRequestSender {
public:
explicit Statistics(not_null<ChannelData*> channel);
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
using GraphResult = rpl::producer<Data::StatisticalGraph, QString>; using GraphResult = rpl::producer<Data::StatisticalGraph, QString>;
[[nodiscard]] GraphResult requestZoom( [[nodiscard]] GraphResult requestZoom(
not_null<PeerData*> peer,
const QString &token, const QString &token,
float64 x); float64 x);
[[nodiscard]] GraphResult requestMessage(
not_null<PeerData*> peer,
MsgId msgId);
[[nodiscard]] Data::ChannelStatistics channelStats() const; [[nodiscard]] Data::ChannelStatistics channelStats() const;
[[nodiscard]] Data::SupergroupStatistics supergroupStats() const; [[nodiscard]] Data::SupergroupStatistics supergroupStats() const;
@ -38,31 +61,27 @@ public:
private: private:
Data::ChannelStatistics _channelStats; Data::ChannelStatistics _channelStats;
Data::SupergroupStatistics _supergroupStats; Data::SupergroupStatistics _supergroupStats;
MTP::Sender _api;
std::deque<Fn<void()>> _zoomDeque; std::deque<Fn<void()>> _zoomDeque;
}; };
class PublicForwards final { class PublicForwards final : public StatisticsRequestSender {
public: public:
explicit PublicForwards(not_null<ChannelData*> channel, FullMsgId fullId); PublicForwards(not_null<ChannelData*> channel, FullMsgId fullId);
void request( void request(
const Data::PublicForwardsSlice::OffsetToken &token, const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done); Fn<void(Data::PublicForwardsSlice)> done);
private: private:
const not_null<ChannelData*> _channel;
const FullMsgId _fullId; const FullMsgId _fullId;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
int _lastTotal = 0; int _lastTotal = 0;
MTP::Sender _api;
}; };
class MessageStatistics final { class MessageStatistics final : public StatisticsRequestSender {
public: public:
explicit MessageStatistics( explicit MessageStatistics(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
@ -74,13 +93,11 @@ public:
private: private:
PublicForwards _publicForwards; PublicForwards _publicForwards;
const not_null<ChannelData*> _channel;
const FullMsgId _fullId; const FullMsgId _fullId;
Data::PublicForwardsSlice _firstSlice; Data::PublicForwardsSlice _firstSlice;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
MTP::Sender _api;
}; };

View file

@ -118,6 +118,7 @@ constexpr auto kStickersByEmojiInvalidateTimeout = crl::time(6 * 1000);
constexpr auto kNotifySettingSaveTimeout = crl::time(1000); constexpr auto kNotifySettingSaveTimeout = crl::time(1000);
constexpr auto kDialogsFirstLoad = 20; constexpr auto kDialogsFirstLoad = 20;
constexpr auto kDialogsPerPage = 500; constexpr auto kDialogsPerPage = 500;
constexpr auto kStatsSessionKillTimeout = 10 * crl::time(1000);
using PhotoFileLocationId = Data::PhotoFileLocationId; using PhotoFileLocationId = Data::PhotoFileLocationId;
using DocumentFileLocationId = Data::DocumentFileLocationId; using DocumentFileLocationId = Data::DocumentFileLocationId;
@ -163,6 +164,7 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
, _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout)) , _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout))
, _topPromotionTimer([=] { refreshTopPromotion(); }) , _topPromotionTimer([=] { refreshTopPromotion(); })
, _updateNotifyTimer([=] { sendNotifySettingsUpdates(); }) , _updateNotifyTimer([=] { sendNotifySettingsUpdates(); })
, _statsSessionKillTimer([=] { checkStatsSessions(); })
, _authorizations(std::make_unique<Api::Authorizations>(this)) , _authorizations(std::make_unique<Api::Authorizations>(this))
, _attachedStickers(std::make_unique<Api::AttachedStickers>(this)) , _attachedStickers(std::make_unique<Api::AttachedStickers>(this))
, _blockedPeers(std::make_unique<Api::BlockedPeers>(this)) , _blockedPeers(std::make_unique<Api::BlockedPeers>(this))
@ -3614,11 +3616,12 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
sendAction(action); sendAction(action);
const auto clearCloudDraft = action.clearDraft; const auto clearCloudDraft = action.clearDraft;
const auto draftTopicRootId = action.replyTo.topicRootId;
const auto replyTo = action.replyTo.messageId const auto replyTo = action.replyTo.messageId
? peer->owner().message(action.replyTo.messageId) ? peer->owner().message(action.replyTo.messageId)
: nullptr; : nullptr;
const auto topicRootId = action.replyTo.topicRootId const auto topicRootId = draftTopicRootId
? action.replyTo.topicRootId ? draftTopicRootId
: replyTo : replyTo
? replyTo->topicRootId() ? replyTo->topicRootId()
: Data::ForumTopic::kGeneralId; : Data::ForumTopic::kGeneralId;
@ -3658,7 +3661,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
TextUtilities::Trim(sending); TextUtilities::Trim(sending);
_session->data().registerMessageRandomId(randomId, newId); _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)); MTPstring msgText(MTP_string(sending.text));
auto flags = NewMessageFlags(peer); auto flags = NewMessageFlags(peer);
@ -3720,8 +3726,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (clearCloudDraft) { if (clearCloudDraft) {
sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft; sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft;
mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
history->clearCloudDraft(topicRootId); history->clearCloudDraft(draftTopicRootId);
history->startSavingCloudDraft(topicRootId); history->startSavingCloudDraft(draftTopicRootId);
} }
const auto sendAs = action.options.sendAs; const auto sendAs = action.options.sendAs;
const auto messageFromId = sendAs const auto messageFromId = sendAs
@ -3758,7 +3764,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
const MTP::Response &response) { const MTP::Response &response) {
if (clearCloudDraft) { if (clearCloudDraft) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, draftTopicRootId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
} }
}; };
@ -3772,7 +3778,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
} }
if (clearCloudDraft) { if (clearCloudDraft) {
history->finishSavingCloudDraft( history->finishSavingCloudDraft(
topicRootId, draftTopicRootId,
UnixtimeFromMsgId(response.outerMsgId)); UnixtimeFromMsgId(response.outerMsgId));
} }
}; };
@ -4340,6 +4346,32 @@ void ApiWrap::saveSelfBio(const QString &text) {
}).send(); }).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() { Api::Authorizations &ApiWrap::authorizations() {
return *_authorizations; return *_authorizations;
} }

View file

@ -369,6 +369,9 @@ public:
void saveSelfBio(const QString &text); 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::Authorizations &authorizations();
[[nodiscard]] Api::AttachedStickers &attachedStickers(); [[nodiscard]] Api::AttachedStickers &attachedStickers();
[[nodiscard]] Api::BlockedPeers &blockedPeers(); [[nodiscard]] Api::BlockedPeers &blockedPeers();
@ -547,6 +550,8 @@ private:
not_null<ChannelData*> channel); not_null<ChannelData*> channel);
void migrateFail(not_null<PeerData*> peer, const QString &error); void migrateFail(not_null<PeerData*> peer, const QString &error);
void checkStatsSessions();
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
base::flat_map<QString, int> _modifyRequests; base::flat_map<QString, int> _modifyRequests;
@ -683,6 +688,9 @@ private:
QString requestedText; QString requestedText;
} _bio; } _bio;
base::flat_map<MTP::DcId, base::flat_set<mtpRequestId>> _statsRequests;
base::Timer _statsSessionKillTimer;
const std::unique_ptr<Api::Authorizations> _authorizations; const std::unique_ptr<Api::Authorizations> _authorizations;
const std::unique_ptr<Api::AttachedStickers> _attachedStickers; const std::unique_ptr<Api::AttachedStickers> _attachedStickers;
const std::unique_ptr<Api::BlockedPeers> _blockedPeers; const std::unique_ptr<Api::BlockedPeers> _blockedPeers;

View file

@ -827,11 +827,13 @@ historyEmojiStatusInfoLabel: FlatLabel(historyContactStatusLabel) {
} }
historyContactStatusMinSkip: 16px; historyContactStatusMinSkip: 16px;
historyReplySkip: 51px; historyReplySkip: 53px;
historyReplyNameFg: windowActiveTextFg; historyReplyNameFg: windowActiveTextFg;
historyReplyHeight: 49px; historyReplyHeight: 49px;
historyReplyIconPosition: point(5px, 5px); historyReplyIconPosition: point(7px, 7px);
historyReplyIcon: icon {{ "chat/input_reply", historyReplyIconFg }}; historyReplyIcon: icon {{ "chat/input_reply_settings", historyReplyIconFg }};
historyLinkIcon: icon {{ "chat/input_link_settings", historyReplyIconFg }};
historyQuoteIcon: icon {{ "chat/input_reply_quote", historyReplyIconFg }};
historyForwardIcon: icon {{ "chat/input_forward", historyReplyIconFg }}; historyForwardIcon: icon {{ "chat/input_forward", historyReplyIconFg }};
historyEditIcon: icon {{ "chat/input_edit", historyReplyIconFg }}; historyEditIcon: icon {{ "chat/input_edit", historyReplyIconFg }};
historyReplyCancel: IconButton { historyReplyCancel: IconButton {

View file

@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
constexpr auto AppNameOld = "AyuGram for Windows"_cs; constexpr auto AppNameOld = "AyuGram for Windows"_cs;
constexpr auto AppName = "AyuGram Desktop"_cs; constexpr auto AppName = "AyuGram Desktop"_cs;
constexpr auto AppFile = "AyuGram"_cs; constexpr auto AppFile = "AyuGram"_cs;
constexpr auto AppVersion = 4011006; constexpr auto AppVersion = 4011007;
constexpr auto AppVersionStr = "4.11.6"; constexpr auto AppVersionStr = "4.11.7";
constexpr auto AppBetaVersion = false; constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

@ -1120,6 +1120,10 @@ void ApplyChannelUpdate(
channel, channel,
update.vnotify_settings()); update.vnotify_settings());
if (update.vstats_dc()) {
channel->owner().applyStatsDcId(channel, update.vstats_dc()->v);
}
if (const auto sendAs = update.vdefault_send_as()) { if (const auto sendAs = update.vdefault_send_as()) {
session->sendAsPeers().setChosen(channel, peerFromMTP(*sendAs)); session->sendAsPeers().setChosen(channel, peerFromMTP(*sendAs));
} else { } else {

View file

@ -4567,6 +4567,19 @@ uint64 Session::wallpapersHash() const {
return _wallpapersHash; return _wallpapersHash;
} }
MTP::DcId Session::statsDcId(not_null<ChannelData*> channel) {
const auto it = _channelStatsDcIds.find(channel);
return (it == end(_channelStatsDcIds)) ? MTP::DcId(0) : it->second;
}
void Session::applyStatsDcId(
not_null<ChannelData*> channel,
MTP::DcId dcId) {
if (dcId != channel->session().mainDcId()) {
_channelStatsDcIds[channel] = dcId;
}
}
void Session::webViewResultSent(WebViewResultSent &&sent) { void Session::webViewResultSent(WebViewResultSent &&sent) {
return _webViewResultSent.fire(std::move(sent)); return _webViewResultSent.fire(std::move(sent));
} }

View file

@ -730,6 +730,9 @@ public:
[[nodiscard]] auto peerDecorationsUpdated() const [[nodiscard]] auto peerDecorationsUpdated() const
-> rpl::producer<not_null<PeerData*>>; -> rpl::producer<not_null<PeerData*>>;
void applyStatsDcId(not_null<ChannelData*>, MTP::DcId);
[[nodiscard]] MTP::DcId statsDcId(not_null<ChannelData*>);
void clearLocalStorage(); void clearLocalStorage();
private: private:
@ -1014,6 +1017,8 @@ private:
base::flat_map<not_null<UserData*>, TimeId> _watchingForOffline; base::flat_map<not_null<UserData*>, TimeId> _watchingForOffline;
base::Timer _watchForOfflineTimer; base::Timer _watchForOfflineTimer;
base::flat_map<not_null<ChannelData*>, MTP::DcId> _channelStatsDcIds;
rpl::event_stream<WebViewResultSent> _webViewResultSent; rpl::event_stream<WebViewResultSent> _webViewResultSent;
rpl::event_stream<not_null<PeerData*>> _peerDecorationsUpdated; rpl::event_stream<not_null<PeerData*>> _peerDecorationsUpdated;

View file

@ -879,7 +879,7 @@ void RowPainter::Paint(
} }
return nullptr; return nullptr;
}(); }();
const auto previewOptions = [&]() -> HistoryView::ToPreviewOptions { auto previewOptions = [&]() -> HistoryView::ToPreviewOptions {
if (topic) { if (topic) {
return {}; return {};
} else if (const auto searchChat = row->searchInChat()) { } else if (const auto searchChat = row->searchInChat()) {
@ -891,6 +891,7 @@ void RowPainter::Paint(
} }
return {}; return {};
}(); }();
previewOptions.ignoreGroup = true;
const auto badgesState = context.displayUnreadInfo const auto badgesState = context.displayUnreadInfo
? entry->chatListBadgesState() ? entry->chatListBadgesState()

View file

@ -2956,11 +2956,22 @@ FullStoryId HistoryItem::replyToStory() const {
} }
FullReplyTo HistoryItem::replyTo() const { FullReplyTo HistoryItem::replyTo() const {
return { auto result = FullReplyTo{
.messageId = replyToFullId(),
.storyId = replyToStory(),
.topicRootId = topicRootId(), .topicRootId = topicRootId(),
}; };
if (const auto reply = Get<HistoryMessageReply>()) {
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) { void HistoryItem::setText(const TextWithEntities &textWithEntities) {

View file

@ -101,6 +101,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_pinned_bar.h" #include "history/view/history_view_pinned_bar.h"
#include "history/view/history_view_group_call_bar.h" #include "history/view/history_view_group_call_bar.h"
#include "history/view/history_view_item_preview.h" #include "history/view/history_view_item_preview.h"
#include "history/view/history_view_reply.h"
#include "history/view/history_view_requests_bar.h" #include "history/view/history_view_requests_bar.h"
#include "history/view/history_view_sticker_toast.h" #include "history/view/history_view_sticker_toast.h"
#include "history/view/history_view_translate_bar.h" #include "history/view/history_view_translate_bar.h"
@ -4395,11 +4396,10 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
void HistoryWidget::updateOverStates(QPoint pos) { void HistoryWidget::updateOverStates(QPoint pos) {
const auto isReadyToForward = readyToForward(); const auto isReadyToForward = readyToForward();
const auto skip = isReadyToForward ? 0 : st::historyReplySkip;
const auto detailsRect = QRect( const auto detailsRect = QRect(
skip, 0,
_field->y() - st::historySendPadding - st::historyReplyHeight, _field->y() - st::historySendPadding - st::historyReplyHeight,
width() - skip - _fieldBarCancel->width(), width() - _fieldBarCancel->width(),
st::historyReplyHeight); st::historyReplyHeight);
const auto hasWebPage = !!_previewDrawPreview; const auto hasWebPage = !!_previewDrawPreview;
const auto inDetails = detailsRect.contains(pos) const auto inDetails = detailsRect.contains(pos)
@ -4439,10 +4439,6 @@ void HistoryWidget::leaveToChildEvent(QEvent *e, QWidget *child) { // e -- from
} }
void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) { 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) { void HistoryWidget::sendBotCommand(const Bot::SendCommandRequest &request) {
@ -6264,20 +6260,7 @@ bool HistoryWidget::cornerButtonsHas(HistoryView::CornerButtonType type) {
void HistoryWidget::mousePressEvent(QMouseEvent *e) { void HistoryWidget::mousePressEvent(QMouseEvent *e) {
const auto isReadyToForward = readyToForward(); const auto isReadyToForward = readyToForward();
const auto hasSecondLayer = (_editMsgId if (_inPhotoEdit && _photoEditMedia) {
|| _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) {
EditCaptionBox::StartPhotoEdit( EditCaptionBox::StartPhotoEdit(
controller(), controller(),
_photoEditMedia, _photoEditMedia,
@ -7507,7 +7490,6 @@ void HistoryWidget::cancelEdit() {
void HistoryWidget::cancelFieldAreaState() { void HistoryWidget::cancelFieldAreaState() {
controller()->hideLayer(); controller()->hideLayer();
_replyForwardPressed = false;
if (_previewDrawPreview) { if (_previewDrawPreview) {
_preview->apply({ .removed = true }); _preview->apply({ .removed = true });
} else if (_editMsgId) { } else if (_editMsgId) {
@ -7839,25 +7821,23 @@ void HistoryWidget::updateForwarding() {
} }
void HistoryWidget::updateReplyToName() { void HistoryWidget::updateReplyToName() {
if (_editMsgId) { if (!_history || _editMsgId) {
return; return;
} else if (!_replyEditMsg && (_replyTo || !_kbReplyTo)) { } else if (!_replyEditMsg && (_replyTo || !_kbReplyTo)) {
return; return;
} }
const auto from = [&] { const auto context = Core::MarkedTextContext{
const auto item = _replyEditMsg ? _replyEditMsg : _kbReplyTo; .session = &_history->session(),
if (const auto from = item->displayFrom()) { .customEmojiRepaint = [] {},
return from; .customEmojiLoopLimit = 1,
} };
return item->author().get(); const auto to = _replyEditMsg ? _replyEditMsg : _kbReplyTo;
}(); const auto replyToQuote = _replyTo && !_replyTo.quote.empty();
_replyToName.setText( _replyToName.setMarkedText(
st::msgNameStyle, st::fwdTextStyle,
from->name(), HistoryView::Reply::ComposePreviewName(_history, to, replyToQuote),
Ui::NameTextOptions()); Ui::NameTextOptions(),
_replyToNameVersion = (_replyEditMsg context);
? _replyEditMsg
: _kbReplyTo)->author()->nameVersion();
} }
void HistoryWidget::updateField() { void HistoryWidget::updateField() {
@ -7877,12 +7857,6 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
auto hasForward = readyToForward(); auto hasForward = readyToForward();
auto drawMsgText = (_editMsgId || _replyTo) ? _replyEditMsg : _kbReplyTo; auto drawMsgText = (_editMsgId || _replyTo) ? _replyEditMsg : _kbReplyTo;
if (_editMsgId || _replyTo || (!hasForward && _kbReplyTo)) { if (_editMsgId || _replyTo || (!hasForward && _kbReplyTo)) {
if (!_editMsgId
&& drawMsgText
&& (_replyToNameVersion
< drawMsgText->author()->nameVersion())) {
updateReplyToName();
}
backy -= st::historyReplyHeight; backy -= st::historyReplyHeight;
backh += st::historyReplyHeight; backh += st::historyReplyHeight;
} else if (hasForward) { } else if (hasForward) {
@ -7892,12 +7866,11 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
backy -= st::historyReplyHeight; backy -= st::historyReplyHeight;
backh += st::historyReplyHeight; backh += st::historyReplyHeight;
} }
auto drawWebPagePreview = _previewDrawPreview && !_replyForwardPressed;
p.setInactive( p.setInactive(
controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Any)); controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Any));
p.fillRect(myrtlrect(0, backy, width(), backh), st::historyReplyBg); p.fillRect(myrtlrect(0, backy, width(), backh), st::historyReplyBg);
const auto media = (!drawWebPagePreview && drawMsgText) const auto media = (!_previewDrawPreview && drawMsgText)
? drawMsgText->media() ? drawMsgText->media()
: nullptr; : nullptr;
const auto hasPreview = media && media->hasReplyPreview(); const auto hasPreview = media && media->hasReplyPreview();
@ -7911,86 +7884,11 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
}); });
} }
if (_editMsgId || _replyTo || (!hasForward && _kbReplyTo)) { if (_previewDrawPreview) {
const auto now = crl::now(); st::historyLinkIcon.paint(
const auto paused = p.inactive(); p,
const auto pausedSpoiler = paused || On(PowerSaving::kChatSpoiler); st::historyReplyIconPosition + QPoint(0, backy),
auto replyLeft = st::historyReplySkip; width());
(_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) {
const auto textTop = backy + st::msgReplyPadding.top(); const auto textTop = backy + st::msgReplyPadding.top();
auto previewLeft = st::historyReplySkip; auto previewLeft = st::historyReplySkip;
@ -8019,6 +7917,87 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
previewLeft, previewLeft,
textTop + st::msgServiceNameFont->height, textTop + st::msgServiceNameFont->height,
elidedWidth); 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());
} }
} }

View file

@ -647,7 +647,6 @@ private:
MTP::Sender _api; MTP::Sender _api;
FullReplyTo _replyTo; FullReplyTo _replyTo;
Ui::Text::String _replyToName; Ui::Text::String _replyToName;
int _replyToNameVersion = 0;
FullReplyTo _processingReplyTo; FullReplyTo _processingReplyTo;
HistoryItem *_processingReplyItem = nullptr; HistoryItem *_processingReplyItem = nullptr;
@ -688,8 +687,6 @@ private:
Ui::Text::String _previewTitle; Ui::Text::String _previewTitle;
Ui::Text::String _previewDescription; Ui::Text::String _previewDescription;
bool _replyForwardPressed = false;
PeerData *_peer = nullptr; PeerData *_peer = nullptr;
bool _canSendMessages = false; bool _canSendMessages = false;

View file

@ -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_voice_record_bar.h"
#include "history/view/controls/history_view_ttl_button.h" #include "history/view/controls/history_view_ttl_button.h"
#include "history/view/controls/history_view_webpage_processor.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 "history/view/history_view_webpage_preview.h"
#include "inline_bots/bot_attach_web_view.h" #include "inline_bots/bot_attach_web_view.h"
#include "inline_bots/inline_results_widget.h" #include "inline_bots/inline_results_widget.h"
@ -192,7 +193,6 @@ private:
Ui::Text::String _shownMessageText; Ui::Text::String _shownMessageText;
std::unique_ptr<Ui::SpoilerAnimation> _shownPreviewSpoiler; std::unique_ptr<Ui::SpoilerAnimation> _shownPreviewSpoiler;
Ui::Animations::Simple _inPhotoEditOver; Ui::Animations::Simple _inPhotoEditOver;
int _shownMessageNameVersion = -1;
bool _shownMessageHasPreview : 1 = false; bool _shownMessageHasPreview : 1 = false;
bool _inPhotoEdit : 1 = false; bool _inPhotoEdit : 1 = false;
bool _photoEditAllowed : 1 = false; bool _photoEditAllowed : 1 = false;
@ -245,7 +245,6 @@ void FieldHeader::init() {
updateVisible(); updateVisible();
}, lifetime()); }, lifetime());
const auto leftIconPressed = lifetime().make_state<bool>(false);
paintRequest( paintRequest(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
Painter p(this); Painter p(this);
@ -253,21 +252,29 @@ void FieldHeader::init() {
p.fillRect(rect(), st::historyComposeAreaBg); p.fillRect(rect(), st::historyComposeAreaBg);
const auto position = st::historyReplyIconPosition; 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()); st::historyEditIcon.paint(p, position, width());
} else if (readyToForward()) { } else if (readyToForward()) {
st::historyForwardIcon.paint(p, position, width()); st::historyForwardIcon.paint(p, position, width());
} else if (replyingToMessage()) { } else if (const auto reply = replyingToMessage()) {
st::historyReplyIcon.paint(p, position, width()); if (!reply.quote.empty()) {
st::historyQuoteIcon.paint(p, position, width());
} else {
st::historyReplyIcon.paint(p, position, width());
}
} }
(_preview.parsed && !*leftIconPressed) if (_preview.parsed) {
? paintWebPage( paintWebPage(
p, p,
_history ? _history->peer : _data->session().user()) _history ? _history->peer : _data->session().user());
: (isEditingMessage() || !readyToForward()) } else if (isEditingMessage() || !readyToForward()) {
? paintEditOrReplyToMessage(p) paintEditOrReplyToMessage(p);
: paintForwardInfo(p); } else {
paintForwardInfo(p);
}
}, lifetime()); }, lifetime());
_editMsgId.value( _editMsgId.value(
@ -359,13 +366,9 @@ void FieldHeader::init() {
updateOver(inPreviewRect, inPhotoEdit); updateOver(inPreviewRect, inPhotoEdit);
return; return;
} }
const auto isLeftIcon = (pos.x() < st::historyReplySkip);
const auto isLeftButton = (e->button() == Qt::LeftButton); const auto isLeftButton = (e->button() == Qt::LeftButton);
if (type == QEvent::MouseButtonPress) { if (type == QEvent::MouseButtonPress) {
if (isLeftButton && isLeftIcon && !inPreviewRect) { if (isLeftButton && inPhotoEdit) {
*leftIconPressed = true;
update();
} else if (isLeftButton && inPhotoEdit) {
_editPhotoRequests.fire({}); _editPhotoRequests.fire({});
} else if (isLeftButton && inPreviewRect) { } else if (isLeftButton && inPreviewRect) {
const auto reply = replyingToMessage(); const auto reply = replyingToMessage();
@ -384,11 +387,6 @@ void FieldHeader::init() {
_editOptionsRequests.fire({}); _editOptionsRequests.fire({});
} }
} }
} else if (type == QEvent::MouseButtonRelease) {
if (isLeftButton && *leftIconPressed) {
*leftIconPressed = false;
update();
}
} }
}, lifetime()); }, lifetime());
} }
@ -431,9 +429,21 @@ void FieldHeader::setShownMessage(HistoryItem *item) {
st::msgNameStyle, st::msgNameStyle,
tr::lng_edit_message(tr::now), tr::lng_edit_message(tr::now),
Ui::NameTextOptions()); 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 { } else {
_shownMessageName.clear(); _shownMessageName.clear();
_shownMessageNameVersion = -1;
} }
updateVisible(); updateVisible();
update(); update();
@ -545,19 +555,6 @@ void FieldHeader::paintEditOrReplyToMessage(Painter &p) {
return; 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(); const auto media = _shownMessage->media();
_shownMessageHasPreview = media && media->hasReplyPreview(); _shownMessageHasPreview = media && media->hasReplyPreview();
const auto preview = _shownMessageHasPreview const auto preview = _shownMessageHasPreview
@ -691,13 +688,11 @@ FullReplyTo FieldHeader::getDraftReply() const {
} }
void FieldHeader::updateControlsGeometry(QSize size) { void FieldHeader::updateControlsGeometry(QSize size) {
const auto isReadyToForward = readyToForward();
const auto skip = isReadyToForward ? 0 : st::historyReplySkip;
_cancel->moveToRight(0, 0); _cancel->moveToRight(0, 0);
_clickableRect = QRect( _clickableRect = QRect(
skip,
0, 0,
width() - skip - _cancel->width(), 0,
width() - _cancel->width(),
height()); height());
_shownMessagePreviewRect = QRect( _shownMessagePreviewRect = QRect(
st::historyReplySkip, st::historyReplySkip,

View file

@ -642,6 +642,8 @@ void DraftOptionsBox(
if (const auto current = state->quote.current()) { if (const auto current = state->quote.current()) {
result.messageId = current.item->fullId(); result.messageId = current.item->fullId();
result.quote = current.text; result.quote = current.text;
} else {
result.quote = {};
} }
return result; return result;
}; };

View file

@ -1676,21 +1676,27 @@ TextSelection Element::FindSelectionFromQuote(
} }
offset = i + 1; offset = i + 1;
} }
//for (const auto &modification : text.modifications()) { for (const auto &modification : text.modifications()) {
// if (modification.position >= selection.to) { if (modification.position >= result.to) {
// break; break;
// } else if (modification.position <= selection.from) { }
// modified.from += modification.skipped; if (modification.added) {
// if (modification.added ++result.to;
// && modification.position < selection.from) { }
// --modified.from; const auto shiftTo = std::min(
// } int(modification.skipped),
// } result.to - modification.position);
// modified.to += modification.skipped; result.to -= shiftTo;
// if (modification.added && modified.to > modified.from) { if (modification.position <= result.from) {
// --modified.to; if (modification.added) {
// } ++result.from;
//} }
const auto shiftFrom = std::min(
int(modification.skipped),
result.from - modification.position);
result.from -= shiftFrom;
}
}
return result; return result;
} }

View file

@ -398,10 +398,11 @@ void Reply::updateName(
viaBotUsername = bot->username(); viaBotUsername = bot->username();
} }
} }
const auto history = view->history();
const auto &fields = data->fields(); const auto &fields = data->fields();
const auto sender = resolvedSender.value_or(this->sender(view, data)); const auto sender = resolvedSender.value_or(this->sender(view, data));
const auto externalPeer = fields.externalPeerId const auto externalPeer = fields.externalPeerId
? view->history()->owner().peer(fields.externalPeerId).get() ? history->owner().peer(fields.externalPeerId).get()
: nullptr; : nullptr;
const auto displayAsExternal = data->displayAsExternal(view->data()); const auto displayAsExternal = data->displayAsExternal(view->data());
const auto groupNameAdded = displayAsExternal const auto groupNameAdded = displayAsExternal
@ -419,38 +420,20 @@ void Reply::updateName(
+ st::historyReplyPreviewMargin.right() + st::historyReplyPreviewMargin.right()
- st::historyReplyPadding.left()) - st::historyReplyPadding.left())
: 0; : 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(); auto nameFull = TextWithEntities();
if (displayAsExternal && !groupNameAdded && !fields.storyId) { if (displayAsExternal && !groupNameAdded && !fields.storyId) {
nameFull.append(peerEmoji(sender)); nameFull.append(PeerEmoji(history, sender));
} }
nameFull.append(name); nameFull.append(name);
if (groupNameAdded) { if (groupNameAdded) {
nameFull.append(' ').append(peerEmoji(externalPeer)); nameFull.append(' ').append(PeerEmoji(history, externalPeer));
nameFull.append(externalPeer->name()); nameFull.append(externalPeer->name());
} }
if (!viaBotUsername.isEmpty()) { if (!viaBotUsername.isEmpty()) {
nameFull.append(u" @"_q).append(viaBotUsername); nameFull.append(u" @"_q).append(viaBotUsername);
} }
const auto context = Core::MarkedTextContext{ const auto context = Core::MarkedTextContext{
.session = &view->history()->session(), .session = &history->session(),
.customEmojiRepaint = [] {}, .customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1, .customEmojiLoopLimit = 1,
}; };
@ -819,6 +802,61 @@ void Reply::stopLastRipple() {
} }
} }
TextWithEntities Reply::PeerEmoji(
not_null<History*> 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*> history,
not_null<HistoryItem*> 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() { void Reply::unloadPersistentAnimation() {
_text.unloadPersistentAnimation(); _text.unloadPersistentAnimation();
} }

View file

@ -63,6 +63,14 @@ public:
return _link; return _link;
} }
[[nodiscard]] static TextWithEntities PeerEmoji(
not_null<History*> history,
PeerData *peer);
[[nodiscard]] static TextWithEntities ComposePreviewName(
not_null<History*> history,
not_null<HistoryItem*> to,
bool quote);
private: private:
[[nodiscard]] Ui::Text::GeometryDescriptor textGeometry( [[nodiscard]] Ui::Text::GeometryDescriptor textGeometry(
int available, int available,

View file

@ -91,7 +91,6 @@ void ProcessZoom(
widget->zoomRequests( widget->zoomRequests(
) | rpl::start_with_next([=](float64 x) { ) | rpl::start_with_next([=](float64 x) {
d.api->requestZoom( d.api->requestZoom(
d.peer,
zoomToken, zoomToken,
x x
) | rpl::start_with_next_error_done([=]( ) | rpl::start_with_next_error_done([=](
@ -144,7 +143,6 @@ void FillStatistic(
m); m);
descriptor.api->requestZoom( descriptor.api->requestZoom(
descriptor.peer,
graphData.zoomToken, graphData.zoomToken,
0 0
) | rpl::start_with_next_error_done([=, graphPtr = &graphData]( ) | rpl::start_with_next_error_done([=, graphPtr = &graphData](
@ -524,7 +522,7 @@ void InnerWidget::load() {
const auto descriptor = Descriptor{ const auto descriptor = Descriptor{
_peer, _peer,
lifetime().make_state<Api::Statistics>(&_peer->session().api()), lifetime().make_state<Api::Statistics>(_peer->asChannel()),
_controller->uiShow()->toastParent(), _controller->uiShow()->toastParent(),
}; };
@ -543,7 +541,6 @@ void InnerWidget::load() {
) | rpl::take(1) | rpl::start_with_next([=] { ) | rpl::take(1) | rpl::start_with_next([=] {
if (!_contextId) { if (!_contextId) {
descriptor.api->request( descriptor.api->request(
descriptor.peer
) | rpl::start_with_done([=] { ) | rpl::start_with_done([=] {
_state.stats = Data::AnyStatistics{ _state.stats = Data::AnyStatistics{
descriptor.api->channelStats(), descriptor.api->channelStats(),
@ -575,7 +572,7 @@ void InnerWidget::fill() {
const auto inner = this; const auto inner = this;
const auto descriptor = Descriptor{ const auto descriptor = Descriptor{
_peer, _peer,
lifetime().make_state<Api::Statistics>(&_peer->session().api()), lifetime().make_state<Api::Statistics>(_peer->asChannel()),
_controller->uiShow()->toastParent(), _controller->uiShow()->toastParent(),
}; };
if (_state.stats.message) { if (_state.stats.message) {
@ -705,8 +702,9 @@ void InnerWidget::fillRecentPosts() {
container, container,
tr::lng_stories_show_more()))); tr::lng_stories_show_more())));
constexpr auto kPerPage = int(10); constexpr auto kFirstPage = int(10);
const auto max = stats.recentMessageInteractions.size(); constexpr auto kPerPage = int(30);
const auto max = int(stats.recentMessageInteractions.size());
if (_state.recentPostsExpanded) { if (_state.recentPostsExpanded) {
_state.recentPostsExpanded = std::max( _state.recentPostsExpanded = std::max(
_state.recentPostsExpanded - kPerPage, _state.recentPostsExpanded - kPerPage,
@ -715,8 +713,10 @@ void InnerWidget::fillRecentPosts() {
const auto showMore = [=] { const auto showMore = [=] {
const auto from = _state.recentPostsExpanded; const auto from = _state.recentPostsExpanded;
_state.recentPostsExpanded = std::min( _state.recentPostsExpanded = std::min(
int(max), max,
_state.recentPostsExpanded + kPerPage); _state.recentPostsExpanded
? (_state.recentPostsExpanded + kPerPage)
: kFirstPage);
if (_state.recentPostsExpanded == max) { if (_state.recentPostsExpanded == max) {
buttonWrap->toggle(false, anim::type::instant); buttonWrap->toggle(false, anim::type::instant);
} }

View file

@ -47,6 +47,7 @@ constexpr auto kUpdaterDcShift = 0x03;
constexpr auto kExportDcShift = 0x04; constexpr auto kExportDcShift = 0x04;
constexpr auto kExportMediaDcShift = 0x05; constexpr auto kExportMediaDcShift = 0x05;
constexpr auto kGroupCallStreamDcShift = 0x06; constexpr auto kGroupCallStreamDcShift = 0x06;
constexpr auto kStatsDcShift = 0x07;
constexpr auto kMaxMediaDcCount = 0x10; constexpr auto kMaxMediaDcCount = 0x10;
constexpr auto kBaseDownloadDcShift = 0x10; constexpr auto kBaseDownloadDcShift = 0x10;
constexpr auto kBaseUploadDcShift = 0x20; constexpr auto kBaseUploadDcShift = 0x20;

View file

@ -150,8 +150,11 @@ public:
ResponseHandler &&callbacks = {}, ResponseHandler &&callbacks = {},
ShiftedDcId shiftedDcId = 0, ShiftedDcId shiftedDcId = 0,
crl::time msCanWait = 0, crl::time msCanWait = 0,
mtpRequestId afterRequestId = 0) { mtpRequestId afterRequestId = 0,
const auto requestId = details::GetNextRequestId(); mtpRequestId overrideRequestId = 0) {
const auto requestId = overrideRequestId
? overrideRequestId
: details::GetNextRequestId();
sendSerialized( sendSerialized(
requestId, requestId,
details::SerializedRequest::Serialize(request), details::SerializedRequest::Serialize(request),
@ -169,13 +172,15 @@ public:
FailHandler &&onFail = nullptr, FailHandler &&onFail = nullptr,
ShiftedDcId shiftedDcId = 0, ShiftedDcId shiftedDcId = 0,
crl::time msCanWait = 0, crl::time msCanWait = 0,
mtpRequestId afterRequestId = 0) { mtpRequestId afterRequestId = 0,
mtpRequestId overrideRequestId = 0) {
return send( return send(
request, request,
ResponseHandler{ std::move(onDone), std::move(onFail) }, ResponseHandler{ std::move(onDone), std::move(onFail) },
shiftedDcId, shiftedDcId,
msCanWait, msCanWait,
afterRequestId); afterRequestId,
overrideRequestId);
} }
template <typename Request> template <typename Request>

View file

@ -130,6 +130,9 @@ class Sender {
void setToDC(ShiftedDcId dcId) noexcept { void setToDC(ShiftedDcId dcId) noexcept {
_dcId = dcId; _dcId = dcId;
} }
void setOverrideRequestId(mtpRequestId id) noexcept {
_overrideRequestId = id;
}
void setCanWait(crl::time ms) noexcept { void setCanWait(crl::time ms) noexcept {
_canWait = ms; _canWait = ms;
} }
@ -147,16 +150,16 @@ class Sender {
_afterRequestId = requestId; _afterRequestId = requestId;
} }
ShiftedDcId takeDcId() const noexcept { [[nodiscard]] ShiftedDcId takeDcId() const noexcept {
return _dcId; return _dcId;
} }
crl::time takeCanWait() const noexcept { [[nodiscard]] crl::time takeCanWait() const noexcept {
return _canWait; return _canWait;
} }
DoneHandler takeOnDone() noexcept { [[nodiscard]] DoneHandler takeOnDone() noexcept {
return std::move(_done); return std::move(_done);
} }
FailHandler takeOnFail() { [[nodiscard]] FailHandler takeOnFail() {
return v::match(_fail, [&](auto &value) { return v::match(_fail, [&](auto &value) {
return MakeFailHandler( return MakeFailHandler(
_sender, _sender,
@ -164,11 +167,14 @@ class Sender {
_failSkipPolicy); _failSkipPolicy);
}); });
} }
mtpRequestId takeAfter() const noexcept { [[nodiscard]] mtpRequestId takeAfter() const noexcept {
return _afterRequestId; return _afterRequestId;
} }
[[nodiscard]] mtpRequestId takeOverrideRequestId() const noexcept {
return _overrideRequestId;
}
not_null<Sender*> sender() const noexcept { [[nodiscard]] not_null<Sender*> sender() const noexcept {
return _sender; return _sender;
} }
void registerRequest(mtpRequestId requestId) { void registerRequest(mtpRequestId requestId) {
@ -187,6 +193,7 @@ class Sender {
FailFullHandler> _fail; FailFullHandler> _fail;
FailSkipPolicy _failSkipPolicy = FailSkipPolicy::Simple; FailSkipPolicy _failSkipPolicy = FailSkipPolicy::Simple;
mtpRequestId _afterRequestId = 0; mtpRequestId _afterRequestId = 0;
mtpRequestId _overrideRequestId = 0;
}; };
@ -207,9 +214,10 @@ public:
: RequestBuilder(sender) : RequestBuilder(sender)
, _request(std::move(request)) { , _request(std::move(request)) {
} }
SpecificRequestBuilder(SpecificRequestBuilder &&other) = default;
public: public:
SpecificRequestBuilder(SpecificRequestBuilder &&other) = default;
[[nodiscard]] SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept { [[nodiscard]] SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept {
setToDC(dcId); setToDC(dcId);
return *this; return *this;
@ -218,6 +226,10 @@ public:
setCanWait(ms); setCanWait(ms);
return *this; return *this;
} }
[[nodiscard]] SpecificRequestBuilder &overrideId(mtpRequestId id) noexcept {
setOverrideRequestId(id);
return *this;
}
using Result = typename Request::ResponseType; using Result = typename Request::ResponseType;
[[nodiscard]] SpecificRequestBuilder &done( [[nodiscard]] SpecificRequestBuilder &done(
@ -295,7 +307,8 @@ public:
takeOnFail(), takeOnFail(),
takeDcId(), takeDcId(),
takeCanWait(), takeCanWait(),
takeAfter()); takeAfter(),
takeOverrideRequestId());
registerRequest(id); registerRequest(id);
return 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: private:
class RequestWrap { class RequestWrap {
public: public:

View file

@ -40,7 +40,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QLineEdit> #include <QtWidgets/QLineEdit>
#include <QtWidgets/QTextEdit> #include <QtWidgets/QTextEdit>
#include <QtGui/QClipboard> #include <QtGui/QClipboard>
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
#endif // Qt < 6.6.0
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <CoreFoundation/CFURL.h> #include <CoreFoundation/CFURL.h>
@ -52,7 +55,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- (id) init:(MainWindow::Private*)window; - (id) init:(MainWindow::Private*)window;
- (void) activeSpaceDidChange:(NSNotification *)aNotification; - (void) activeSpaceDidChange:(NSNotification *)aNotification;
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
- (void) darkModeChanged:(NSNotification *)aNotification; - (void) darkModeChanged:(NSNotification *)aNotification;
#endif // Qt < 6.6.0
- (void) screenIsLocked:(NSNotification *)aNotification; - (void) screenIsLocked:(NSNotification *)aNotification;
- (void) screenIsUnlocked:(NSNotification *)aNotification; - (void) screenIsUnlocked:(NSNotification *)aNotification;
@ -113,6 +118,7 @@ private:
- (void) activeSpaceDidChange:(NSNotification *)aNotification { - (void) activeSpaceDidChange:(NSNotification *)aNotification {
} }
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
- (void) darkModeChanged:(NSNotification *)aNotification { - (void) darkModeChanged:(NSNotification *)aNotification {
Core::Sandbox::Instance().customEnterFromEventLoop([&] { Core::Sandbox::Instance().customEnterFromEventLoop([&] {
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
@ -122,6 +128,7 @@ private:
#endif // Qt < 6.5.0 #endif // Qt < 6.5.0
}); });
} }
#endif // Qt < 6.6.0
- (void) screenIsLocked:(NSNotification *)aNotification { - (void) screenIsLocked:(NSNotification *)aNotification {
Core::App().setScreenIsLocked(true); 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() { 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 }; 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); return Platform::MakeFromLetters(letters);
} }
#endif // Qt < 6.6.0
QString strNotificationAboutScreenLocked() { 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 }; 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<MainWindow*> window)
@autoreleasepool { @autoreleasepool {
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:_observer selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil]; [[[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]; [[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(screenIsLocked:) name:Q2NSString(strNotificationAboutScreenLocked()) object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil]; [[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil];

View file

@ -30,7 +30,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#if __has_include(<QtCore/QOperatingSystemVersion>) #if __has_include(<QtCore/QOperatingSystemVersion>)
#include <QtCore/QOperatingSystemVersion> #include <QtCore/QOperatingSystemVersion>
#endif // __has_include(<QtCore/QOperatingSystemVersion>) #endif // __has_include(<QtCore/QOperatingSystemVersion>)
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
#endif // Qt < 6.6.0
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <CoreFoundation/CFURL.h> #include <CoreFoundation/CFURL.h>
#include <IOKit/IOKitLib.h> #include <IOKit/IOKitLib.h>
@ -201,11 +203,11 @@ ApplicationDelegate *_sharedDelegate = nil;
"-receiveWakeNote: received, scheduling detach from audio device")); "-receiveWakeNote: received, scheduling detach from audio device"));
Media::Audio::ScheduleDetachFromDeviceSafe(); Media::Audio::ScheduleDetachFromDeviceSafe();
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
QWindowSystemInterface::handleThemeChange();
#else // Qt >= 6.5.0
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode()); 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
}); });
} }

View file

@ -7,11 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "base/platform/win/base_windows_winrt.h"
#include "platform/platform_integration.h" #include "platform/platform_integration.h"
#include <QAbstractNativeEventFilter> #include <QAbstractNativeEventFilter>
#include <winrt/base.h>
#include <ShlObj.h> #include <ShlObj.h>
namespace Platform { namespace Platform {

View file

@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/win/base_windows_h.h" #include "base/platform/win/base_windows_h.h"
#include <wtypes.h>
namespace Platform { namespace Platform {
namespace AppUserModelId { namespace AppUserModelId {

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/win/base_windows_h.h" #include "base/platform/win/base_windows_h.h"
#include <shellapi.h>
#include <shlobj.h> #include <shlobj.h>
#include <dwmapi.h> #include <dwmapi.h>
#include <RestartManager.h> #include <RestartManager.h>

View file

@ -163,7 +163,7 @@ void LinearChartView::paintSelectedXIndex(
+ c.rect.topLeft(); + c.rect.topLeft();
} }
if (!linePainted) { if (!linePainted && lineAlpha) {
[[maybe_unused]] const auto o = ScopedPainterOpacity( [[maybe_unused]] const auto o = ScopedPainterOpacity(
p, p,
p.opacity() * progress * kRulerLineAlpha); p.opacity() * progress * kRulerLineAlpha);

View file

@ -98,11 +98,7 @@ namespace {
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
const auto radius = std::min(badge->width(), badge->height()) / 2; const auto radius = std::min(badge->width(), badge->height()) / 2;
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
auto brush = QLinearGradient( p.setBrush(st::premiumButtonBg2);
QPointF(badge->width(), badge->height()),
QPointF());
brush.setStops(Ui::Premium::ButtonGradientStops());
p.setBrush(brush);
p.drawRoundedRect(badge->rect(), radius, radius); p.drawRoundedRect(badge->rect(), radius, radius);
}, badge->lifetime()); }, badge->lifetime());

@ -1 +1 @@
Subproject commit c2e718049cf11bbbe7b6d78b78b2d21f0e0affa0 Subproject commit e286ab66141a2f986803177e4cbb7b14002664cb

View file

@ -1,7 +1,7 @@
AppVersion 4011006 AppVersion 4011007
AppVersionStrMajor 4.11 AppVersionStrMajor 4.11
AppVersionStrSmall 4.11.6 AppVersionStrSmall 4.11.7
AppVersionStr 4.11.6 AppVersionStr 4.11.7
BetaChannel 0 BetaChannel 0
AlphaVersion 0 AlphaVersion 0
AppVersionOriginal 4.11.6 AppVersionOriginal 4.11.7

@ -1 +1 @@
Subproject commit bb5e7fafd7aca5808217baeeb9ee3af8c3be6b1b Subproject commit fe4f0a72d2041a860c67a81a70f2e4b6f845d9fb

@ -1 +1 @@
Subproject commit f5fe3afcf5bc5edf07a78ad18b9e8d33c3fbfdb2 Subproject commit aab27269ff8aad5dfaf7372db10bff700fdb5fe9

View file

@ -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) 4.11.6 (09.11.23)
- Support multiple boosts and reassignment. - Support multiple boosts and reassignment.

2
cmake

@ -1 +1 @@
Subproject commit 78098ede77a09e41da6233d765d02b43a60e7138 Subproject commit c373a0a0141bbe146a9507f02b8515183748eb51