Compare commits

..

34 Commits

Author SHA1 Message Date
John Preston
ede4c0f781 Beta version 3.3.1.
- Switch between contacts list sorting modes.
- Sort contacts list by last seen time by default.
- Fix disappearing Send As Channel button after message editing.
- Fix file upload cancelling.
- Fix crash in video capture on macOS.
- Fix labels in the About box.
- Use Qt 6.2.2 for macOS and Linux builds.
- Allow installing x64 Windows version on Windows ARM.
2021-12-23 00:07:26 +00:00
John Preston
75337ad1c2 Fix shared media list in migrated groups. 2021-12-23 00:07:26 +00:00
John Preston
e05b2f3b38 Fix build on Linux. 2021-12-22 17:32:35 +00:00
John Preston
0f15adb208 Sort contacts by last seen by default.
Fixes #5515.
2021-12-22 15:14:16 +00:00
John Preston
a7e552ccab Fix assertion violation in media overview.
Regression was introduced in 5e7e7eaa83.
2021-12-22 13:05:54 +00:00
John Preston
797433ebe9 Fix disappearing Send As Channel button.
Fixes #17359.
2021-12-22 12:32:09 +00:00
John Preston
633532b88d Fix build on Windows. 2021-12-22 11:47:17 +00:00
John Preston
a0dcade9d8 Remove redundant freedesktop.org.xml. 2021-12-22 10:42:32 +00:00
John Preston
2a0babe5ab Fix file upload cancelling.
Fixes #17408.
2021-12-22 10:34:00 +00:00
23rd
dd92f7fb9d Slightly refactored AddContactBox. 2021-12-22 10:27:43 +00:00
John Preston
7ad08b3ef8 Update submodules. 2021-12-22 10:23:54 +00:00
John Preston
73917e8a4b Re-apply crash fix on macOS video capture. 2021-12-22 10:17:50 +00:00
Ilya Fedin
dc7aef3f86 Move HFLAGS to other variables in Dockerfile 2021-12-22 14:15:48 +04:00
Ilya Fedin
d89597bf64 Activate crl dispatch backend on Linux
Linux is the only platform where slow QThreadPool is used, let's use dispatch here as well
2021-12-22 14:15:48 +04:00
Magnus Groß
c2b2d0a92a Do not destroy drag after launchDrag()
On X11 we need to keep the QDrag around a little longer.

Right now, drag is scoped local to launchDrag() and will be destroyed
immediately when launchDrag() finishes. However for X11 we must keep the
drag object alive a little longer. It may only be destroyed once the
drag operation has been accepted by another window, otherwise drag and
drop is broken on Linux and no action happens when something is dragged
from Telegram into another window.

This is because there is still communication happening in the XDND
protocol once QDrag::exec() finishes. See the documentation for
reference: https://freedesktop.org/wiki/Specifications/XDND/

Fixes #17291
2021-12-22 14:15:36 +04:00
John Preston
b341dddbb9 Move macOS and Linux builds to Qt 6.2.2. 2021-12-22 10:13:31 +00:00
John Preston
999e4264c5 Move macOS and Linux builds to Qt 6.2.2. 2021-12-22 10:13:29 +00:00
John Preston
aee11469c4 Fix crash in video capture on macOS.
Fixes #17420.
2021-12-22 10:11:57 +00:00
John Preston
651cfe5b7e Fix about box text labels layout. 2021-12-22 10:11:57 +00:00
John Preston
a34b2a5472 Fix build with DESKTOP_APP_USE_PACKAGED_RLOTTIE. 2021-12-22 10:11:57 +00:00
John Preston
5e7e7eaa83 FullMsgId rely on PeerId instead of ChannelId. 2021-12-22 10:11:57 +00:00
Ilya Fedin
a8f05a01ed Build kwayland as external project
This will simplify packaged Qt 6 build
2021-12-22 14:09:32 +04:00
Ilya Fedin
fedd21b0a6 Use QFontMetrics::height in PreLaunchWindow 2021-12-22 14:08:22 +04:00
Ilya Fedin
7ff7473db6 Auto-check for many instance
This option was invented when single instance check wasn't adapted for -workdir. Now, -workdir can work without -many and this option is redudant, but auto-update prevention is helpful. Let's autodetect whether the binary is already running with a lock file.
2021-12-22 14:07:22 +04:00
Vitaly Zaitsev
d89aab08bf Fixed build against OpenSSL 3.0.
Deprecated function FIPS_mode_set() was removed in OpenSSL 3.0.

Switched to EVP_default_properties_enable_fips() as described in OpenSSL
3.0 migration guide.

Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org>
2021-12-19 16:35:13 +04:00
Ilya Fedin
b2fb5424ed Get rid of deprecated OpenSSL <1.1 functions 2021-12-16 13:05:53 +04:00
John Preston
e7e34d50ba Fix building on Windows. 2021-12-14 16:27:57 +04:00
John Preston
19320cc5d8 Fix dependencies build on M1. 2021-12-14 11:33:59 +04:00
k1ee
107a87c7ce Add support to build on M1 Mac
On M1 mac, some dependencies build two `arm64` builds and makes `lipo` fail.
2021-12-14 11:32:13 +04:00
RadRussianRus
2cb1d2c0bc Removed explicit definition of cmake generator
Even though TDesktop build migrated to VS 2022, dependencies script still had "Visual Studio 16 2019" for mozjpeg and openal-soft as a generator. Removing these lines allows to use latest Visual Studio without changing the script.
2021-12-13 14:26:05 +04:00
Ilya Fedin
48ab88a9ca Don't use QPlatformNativeInterface for native window handle on Windows 2021-12-13 14:24:34 +04:00
Ilya Fedin
33b7ac209e Don't use QPlatformNativeInterface-based XCB::GetRootWindowFromQt 2021-12-13 14:24:34 +04:00
Ilya Fedin
4a0ffdc9f5 Result binary shouldn't be in bin subfolder with any generator on macOS
Since MACOSX_BUNDLE is used
2021-12-11 07:29:02 +04:00
Ilya Fedin
1ec2c16d27 Fix path to result binary in Linux action 2021-12-11 07:29:02 +04:00
111 changed files with 771 additions and 34911 deletions

View File

@@ -107,7 +107,7 @@ jobs:
- name: Check.
run: |
filePath="$REPO_NAME/out/Debug/bin/Telegram"
filePath="$REPO_NAME/out/Debug/Telegram"
if test -f "$filePath"; then
echo "Build successfully done! :)"
@@ -121,7 +121,7 @@ jobs:
- name: Move artifact.
if: env.UPLOAD_ARTIFACT == 'true'
run: |
cd $REPO_NAME/out/Debug/bin
cd $REPO_NAME/out/Debug
mkdir artifact
mv Telegram artifact/
- uses: actions/upload-artifact@master
@@ -129,4 +129,4 @@ jobs:
name: Upload artifact.
with:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.REPO_NAME }}/out/Debug/bin/artifact/
path: ${{ env.REPO_NAME }}/out/Debug/artifact/

6
.gitmodules vendored
View File

@@ -94,3 +94,9 @@
[submodule "Telegram/ThirdParty/jemalloc"]
path = Telegram/ThirdParty/jemalloc
url = https://github.com/jemalloc/jemalloc
[submodule "Telegram/ThirdParty/kwayland"]
path = Telegram/ThirdParty/kwayland
url = https://github.com/KDE/kwayland.git
[submodule "Telegram/ThirdParty/dispatch"]
path = Telegram/ThirdParty/dispatch
url = https://github.com/apple/swift-corelibs-libdispatch

View File

@@ -1407,7 +1407,7 @@ PRIVATE
G_LOG_DOMAIN="Telegram"
)
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode"
if (APPLE
OR "${CMAKE_GENERATOR}" STREQUAL "Ninja Multi-Config"
OR NOT CMAKE_EXECUTABLE_SUFFIX STREQUAL ""
OR NOT "${output_name}" STREQUAL "Telegram")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

File diff suppressed because it is too large Load Diff

View File

@@ -83,9 +83,6 @@
<file alias="settings/devices/device_web_firefox.lottie">../../icons/settings/devices/device_web_firefox.lottie</file>
<file alias="settings/devices/device_web_safari.lottie">../../icons/settings/devices/device_web_safari.lottie</file>
</qresource>
<qresource prefix="/qt-project.org">
<file>../qmime/freedesktop.org.xml</file>
</qresource>
<qresource prefix="/misc">
<file alias="default_shortcuts-custom.json">../../default_shortcuts-custom.json</file>
<file alias="telegramdesktop.desktop">../../../../lib/xdg/telegramdesktop.desktop</file>

View File

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

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,3,0,0
PRODUCTVERSION 3,3,0,0
FILEVERSION 3,3,1,0
PRODUCTVERSION 3,3,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "3.3.0.0"
VALUE "FileVersion", "3.3.1.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.3.0.0"
VALUE "ProductVersion", "3.3.1.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,3,0,0
PRODUCTVERSION 3,3,0,0
FILEVERSION 3,3,1,0
PRODUCTVERSION 3,3,1,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", "3.3.0.0"
VALUE "FileVersion", "3.3.1.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.3.0.0"
VALUE "ProductVersion", "3.3.1.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -118,7 +118,7 @@ void PeerPhoto::upload(not_null<PeerData*> peer, QImage &&image) {
std::move(image));
const auto fakeId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
const auto already = ranges::find(
_uploads,

View File

@@ -74,7 +74,7 @@ void SendExistingMedia(
api->sendAction(message.action);
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();
@@ -255,7 +255,7 @@ bool SendDice(MessageToSend &message) {
api->sendAction(message.action);
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();
@@ -346,10 +346,8 @@ void SendConfirmedFile(
const std::shared_ptr<FileLoadResult> &file) {
const auto isEditing = (file->type != SendMediaType::Audio)
&& (file->to.replaceMediaOf != 0);
const auto channelId = peerToChannel(file->to.peer);
const auto newId = FullMsgId(
channelId,
file->to.peer,
isEditing
? file->to.replaceMediaOf
: session->data().nextLocalMessageId());

View File

@@ -87,7 +87,7 @@ std::optional<HistoryItem*> SingleMessageSearch::performLookupByChannel(
Expects(!_requestKey.empty());
const auto postId = _requestKey.postId;
if (const auto item = _session->data().message(channel, postId)) {
if (const auto item = _session->data().message(channel->id, postId)) {
_cache.emplace(_requestKey, item->fullId());
return item;
} else if (!ready) {
@@ -112,7 +112,7 @@ std::optional<HistoryItem*> SingleMessageSearch::performLookupByChannel(
&& received.messageIds.front() == postId) {
_cache.emplace(
_requestKey,
FullMsgId(peerToChannel(channel->id), postId));
FullMsgId(channel->id, postId));
ready();
} else {
fail();

View File

@@ -730,7 +730,7 @@ void Updates::addActiveChat(rpl::producer<PeerData*> chat) {
}
void Updates::requestChannelRangeDifference(not_null<History*> history) {
Expects(history->isChannel());
Expects(history->peer->isChannel());
const auto channel = history->peer->asChannel();
if (const auto requestId = _rangeDifferenceRequests.take(channel)) {
@@ -1181,7 +1181,7 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
const auto &d = update.c_updateReadMessagesContents();
auto possiblyReadMentions = base::flat_set<MsgId>();
for (const auto &msgId : d.vmessages().v) {
if (const auto item = _session->data().message(NoChannel, msgId.v)) {
if (const auto item = _session->data().nonChannelMessage(msgId.v)) {
if (item->isUnreadMedia() || item->isUnreadMention()) {
item->markMediaRead();
_session->data().requestItemRepaint(item);
@@ -1249,7 +1249,7 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updateDeleteMessages: {
auto &d = update.c_updateDeleteMessages();
_session->data().processMessagesDeleted(NoChannel, d.vmessages().v);
_session->data().processNonChannelMessagesDeleted(d.vmessages().v);
} break;
case mtpc_updateNewChannelMessage: {
@@ -1278,9 +1278,9 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updatePinnedChannelMessages: {
const auto &d = update.c_updatePinnedChannelMessages();
const auto channelId = d.vchannel_id().v;
const auto peerId = peerFromChannel(d.vchannel_id());
for (const auto &msgId : d.vmessages().v) {
const auto item = session().data().message(channelId, msgId.v);
const auto item = session().data().message(peerId, msgId.v);
if (item) {
item->setIsPinned(d.is_pinned());
}
@@ -1299,13 +1299,16 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updateDeleteChannelMessages: {
auto &d = update.c_updateDeleteChannelMessages();
_session->data().processMessagesDeleted(d.vchannel_id().v, d.vmessages().v);
_session->data().processMessagesDeleted(
peerFromChannel(d.vchannel_id().v),
d.vmessages().v);
} break;
case mtpc_updatePinnedMessages: {
const auto &d = update.c_updatePinnedMessages();
const auto peerId = peerFromMTP(d.vpeer());
for (const auto &msgId : d.vmessages().v) {
const auto item = session().data().message(0, msgId.v);
const auto item = session().data().message(peerId, msgId.v);
if (item) {
item->setIsPinned(d.is_pinned());
}
@@ -1424,7 +1427,7 @@ void Updates::applyUpdates(
const auto sent = owner.messageSentData(randomId);
const auto lookupMessage = [&] {
return sent.peerId
? owner.message(peerToChannel(sent.peerId), d.vid().v)
? owner.message(sent.peerId, d.vid().v)
: nullptr;
};
if (const auto id = owner.messageIdByRandomId(randomId)) {
@@ -1439,9 +1442,9 @@ void Updates::applyUpdates(
const auto list = d.ventities();
if (list && !MentionUsersLoaded(&session(), *list)) {
session().api().requestMessageData(
item->history()->peer->asChannel(),
item->history()->peer,
item->id,
ApiWrap::RequestMessageDataCallback());
nullptr);
}
item->applySentMessage(sent.text, d, wasAlready);
}
@@ -1527,9 +1530,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
if (local->isScheduled()) {
session().data().scheduledMessages().apply(d, local);
} else {
const auto channel = id.channel;
const auto existing = session().data().message(
channel,
id.peer,
newId);
if (existing && !local->mainView()) {
const auto history = local->history();
@@ -1566,7 +1568,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
auto possiblyReadMentions = base::flat_set<MsgId>();
for (const auto &msgId : d.vmessages().v) {
if (auto item = session().data().message(channel, msgId.v)) {
if (auto item = session().data().message(channel->id, msgId.v)) {
if (item->isUnreadMedia() || item->isUnreadMention()) {
item->markMediaRead();
session().data().requestItemRepaint(item);
@@ -2146,24 +2148,26 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateChannelMessageViews: {
const auto &d = update.c_updateChannelMessageViews();
if (const auto item = session().data().message(d.vchannel_id().v, d.vid().v)) {
const auto peerId = peerFromChannel(d.vchannel_id());
if (const auto item = session().data().message(peerId, d.vid().v)) {
item->setViewsCount(d.vviews().v);
}
} break;
case mtpc_updateChannelMessageForwards: {
const auto &d = update.c_updateChannelMessageForwards();
if (const auto item = session().data().message(d.vchannel_id().v, d.vid().v)) {
const auto peerId = peerFromChannel(d.vchannel_id());
if (const auto item = session().data().message(peerId, d.vid().v)) {
item->setForwardsCount(d.vforwards().v);
}
} break;
case mtpc_updateReadChannelDiscussionInbox: {
const auto &d = update.c_updateReadChannelDiscussionInbox();
const auto channelId = d.vchannel_id().v;
const auto peerId = peerFromChannel(d.vchannel_id());
const auto msgId = d.vtop_msg_id().v;
const auto readTillId = d.vread_max_id().v;
const auto item = session().data().message(channelId, msgId);
const auto item = session().data().message(peerId, msgId);
const auto unreadCount = item
? session().data().countUnreadRepliesLocally(item, readTillId)
: std::nullopt;
@@ -2175,7 +2179,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
if (const auto broadcastId = d.vbroadcast_id()) {
if (const auto post = session().data().message(
broadcastId->v,
peerFromChannel(*broadcastId),
d.vbroadcast_post()->v)) {
post->setRepliesInboxReadTill(readTillId, unreadCount);
}
@@ -2184,10 +2188,10 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadChannelDiscussionOutbox: {
const auto &d = update.c_updateReadChannelDiscussionOutbox();
const auto channelId = d.vchannel_id().v;
const auto peerId = peerFromChannel(d.vchannel_id());
const auto msgId = d.vtop_msg_id().v;
const auto readTillId = d.vread_max_id().v;
const auto item = session().data().message(channelId, msgId);
const auto item = session().data().message(peerId, msgId);
if (item) {
item->setRepliesOutboxReadTill(readTillId);
if (const auto post = item->lookupDiscussionPostOriginal()) {

View File

@@ -95,9 +95,8 @@ void ViewsManager::done(
if (id != requestId) {
continue;
}
const auto channel = peerToChannel(peer->id);
for (auto j = 0, l = int(ids.size()); j < l; ++j) {
if (const auto item = owner.message(channel, ids[j].v)) {
if (const auto item = owner.message(peer->id, ids[j].v)) {
v[j].match([&](const MTPDmessageViews &data) {
if (const auto views = data.vviews()) {
item->setViewsCount(views->v);

View File

@@ -510,14 +510,14 @@ void ApiWrap::sendMessageFail(
}
void ApiWrap::requestMessageData(
ChannelData *channel,
PeerData *peer,
MsgId msgId,
RequestMessageDataCallback callback) {
auto &requests = channel
? _channelMessageDataRequests[channel][msgId]
Fn<void()> done) {
auto &requests = (peer && peer->isChannel())
? _channelMessageDataRequests[peer->asChannel()][msgId]
: _messageDataRequests[msgId];
if (callback) {
requests.callbacks.push_back(callback);
if (done) {
requests.callbacks.push_back(std::move(done));
}
if (!requests.requestId) {
_messageDataResolveDelayed.call();
@@ -539,19 +539,19 @@ QVector<MTPInputMessage> ApiWrap::collectMessageIds(
auto ApiWrap::messageDataRequests(ChannelData *channel, bool onlyExisting)
-> MessageDataRequests* {
if (channel) {
auto i = _channelMessageDataRequests.find(channel);
if (i == end(_channelMessageDataRequests)) {
if (onlyExisting) {
return nullptr;
}
i = _channelMessageDataRequests.emplace(
channel,
MessageDataRequests()).first;
}
return &i->second;
if (!channel) {
return &_messageDataRequests;
}
return &_messageDataRequests;
const auto i = _channelMessageDataRequests.find(channel);
if (i != end(_channelMessageDataRequests)) {
return &i->second;
} else if (onlyExisting) {
return nullptr;
}
return &_channelMessageDataRequests.emplace(
channel,
MessageDataRequests()
).first->second;
}
void ApiWrap::resolveMessageDatas() {
@@ -614,20 +614,31 @@ void ApiWrap::finalizeMessageDataRequest(
ChannelData *channel,
mtpRequestId requestId) {
auto requests = messageDataRequests(channel, true);
if (requests) {
for (auto i = requests->begin(); i != requests->cend();) {
if (i->second.requestId == requestId) {
for (const auto &callback : i->second.callbacks) {
callback(channel, i->first);
}
i = requests->erase(i);
if (!requests) {
return;
}
auto callbacks = std::vector<Fn<void()>>();
for (auto i = requests->begin(); i != requests->cend();) {
if (i->second.requestId == requestId) {
auto &list = i->second.callbacks;
if (callbacks.empty()) {
callbacks = std::move(list);
} else {
++i;
callbacks.insert(
end(callbacks),
std::make_move_iterator(begin(list)),
std::make_move_iterator(end(list)));
}
i = requests->erase(i);
} else {
++i;
}
if (channel && requests->empty()) {
_channelMessageDataRequests.remove(channel);
}
}
if (channel && requests->empty()) {
_channelMessageDataRequests.remove(channel);
}
for (const auto &callback : callbacks) {
callback();
}
}
@@ -646,7 +657,7 @@ QString ApiWrap::exportDirectMessageLink(
if (inRepliesContext) {
if (const auto rootId = item->replyToTop()) {
const auto root = item->history()->owner().message(
peerToChannel(channel->id),
channel->id,
rootId);
const auto sender = root
? root->discussionPostOriginalSender()
@@ -1388,9 +1399,8 @@ void ApiWrap::deleteAllFromParticipant(
const auto ids = history
? history->collectMessagesFromParticipantToDelete(from)
: std::vector<MsgId>();
const auto channelId = peerToChannel(channel->id);
for (const auto &msgId : ids) {
if (const auto item = _session->data().message(channelId, msgId)) {
if (const auto item = _session->data().message(channel->id, msgId)) {
item->destroy();
}
}
@@ -2225,11 +2235,7 @@ void ApiWrap::resolveWebPages() {
if (i.key()->pendingTill <= t) {
const auto item = _session->data().findWebPageItem(i.key());
if (item) {
if (item->channelId() == NoChannel) {
ids.push_back(MTP_inputMessageID(MTP_int(item->id)));
i.value() = -1;
} else {
auto channel = item->history()->peer->asChannel();
if (const auto channel = item->history()->peer->asChannel()) {
auto channelMap = idsByChannel.find(channel);
if (channelMap == idsByChannel.cend()) {
channelMap = idsByChannel.emplace(
@@ -2244,6 +2250,9 @@ void ApiWrap::resolveWebPages() {
MTP_inputMessageID(MTP_int(item->id)));
}
i.value() = -channelMap->second.first - 2;
} else {
ids.push_back(MTP_inputMessageID(MTP_int(item->id)));
i.value() = -1;
}
}
} else {
@@ -2927,14 +2936,13 @@ void ApiWrap::preloadEnoughUnreadMentions(not_null<History*> history) {
void ApiWrap::checkForUnreadMentions(
const base::flat_set<MsgId> &possiblyReadMentions,
ChannelData *channel) {
for (auto msgId : possiblyReadMentions) {
requestMessageData(channel, msgId, [=](
ChannelData *channel,
MsgId msgId) {
if (const auto item = _session->data().message(channel, msgId)) {
if (item->mentionsMe()) {
item->markMediaRead();
}
for (const auto msgId : possiblyReadMentions) {
requestMessageData(channel, msgId, [=] {
const auto item = channel
? _session->data().message(channel->id, msgId)
: _session->data().nonChannelMessage(msgId);
if (item && item->mentionsMe()) {
item->markMediaRead();
}
});
}
@@ -3206,7 +3214,7 @@ void ApiWrap::forwardMessages(
const auto randomId = base::RandomValue<uint64>();
if (genClientSideMessage) {
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
const auto self = _session->user();
const auto messageFromId = sendAs
@@ -3279,7 +3287,7 @@ void ApiWrap::sendSharedContact(
const auto peer = history->peer;
const auto newId = FullMsgId(
history->channelId(),
peer->id,
_session->data().nextLocalMessageId());
const auto anonymousPost = peer->amAnonymous();
@@ -3505,7 +3513,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
auto randomId = base::RandomValue<uint64>();
@@ -3663,7 +3671,7 @@ void ApiWrap::sendInlineResult(
const auto history = action.history;
const auto peer = history->peer;
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();

View File

@@ -147,11 +147,7 @@ public:
bool archived,
Fn<void()> callback);
using RequestMessageDataCallback = Fn<void(ChannelData*, MsgId)>;
void requestMessageData(
ChannelData *channel,
MsgId msgId,
RequestMessageDataCallback callback);
void requestMessageData(PeerData *peer, MsgId msgId, Fn<void()> done);
QString exportDirectMessageLink(
not_null<HistoryItem*> item,
bool inRepliesContext);
@@ -365,7 +361,7 @@ public:
private:
struct MessageDataRequest {
using Callbacks = std::vector<RequestMessageDataCallback>;
using Callbacks = std::vector<Fn<void()>>;
mtpRequestId requestId = 0;
Callbacks callbacks;
@@ -520,7 +516,7 @@ private:
MessageDataRequests _messageDataRequests;
base::flat_map<
ChannelData*,
not_null<ChannelData*>,
MessageDataRequests> _channelMessageDataRequests;
SingleQueuedInvokation _messageDataResolveDelayed;

View File

@@ -80,9 +80,15 @@ void AboutBox::prepare() {
void AboutBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
const auto available = width()
- st::boxPadding.left()
- st::boxPadding.right();
_version->moveToLeft(st::boxPadding.left(), st::aboutVersionTop);
_text1->resizeToWidth(available);
_text1->moveToLeft(st::boxPadding.left(), st::aboutTextTop);
_text2->resizeToWidth(available);
_text2->moveToLeft(st::boxPadding.left(), _text1->y() + _text1->height() + st::aboutSkip);
_text3->resizeToWidth(available);
_text3->moveToLeft(st::boxPadding.left(), _text2->y() + _text2->height() + st::aboutSkip);
}

View File

@@ -418,32 +418,34 @@ void AddContactBox::save() {
MTP_string(lastName)))
)).done(crl::guard(this, [=](
const MTPcontacts_ImportedContacts &result) {
result.match([&](const MTPDcontacts_importedContacts &data) {
_session->data().processUsers(data.vusers());
const auto extractUser = [&](const MTPImportedContact &data) {
return data.match([&](const MTPDimportedContact &data) {
return (data.vclient_id().v == _contactId)
? _session->data().userLoaded(data.vuser_id())
: nullptr;
});
};
const auto &list = data.vimported().v;
const auto user = list.isEmpty()
? nullptr
: extractUser(list.front());
if (user) {
if (user->isContact() || user->session().supportMode()) {
Ui::showPeerHistory(user, ShowAtTheEndMsgId);
}
Ui::hideLayer();
} else if (isBoxShown()) {
hideChildren();
_retrying = true;
updateButtons();
update();
}
const auto &data = result.match([](
const auto &data) -> const MTPDcontacts_importedContacts& {
return data;
});
_session->data().processUsers(data.vusers());
const auto extractUser = [&](const MTPImportedContact &data) {
return data.match([&](const MTPDimportedContact &data) {
return (data.vclient_id().v == _contactId)
? _session->data().userLoaded(data.vuser_id())
: nullptr;
});
};
const auto &list = data.vimported().v;
const auto user = list.isEmpty()
? nullptr
: extractUser(list.front());
if (user) {
if (user->isContact() || user->session().supportMode()) {
Ui::showPeerHistory(user, ShowAtTheEndMsgId);
}
Ui::hideLayer();
} else if (isBoxShown()) {
hideChildren();
_retrying = true;
updateButtons();
update();
}
})).send();
}

View File

@@ -160,6 +160,21 @@ contactsAboutFg: windowSubTextFgOver;
contactsAboutTop: 60px;
contactsAboutBottom: 19px;
contactsSortButton: IconButton(defaultIconButton) {
width: 48px;
height: 54px;
icon: icon{{ "contacts_alphabet", boxTitleCloseFg }};
iconOver: icon{{ "contacts_alphabet", boxTitleCloseFgOver }};
iconPosition: point(10px, -1px);
rippleAreaPosition: point(1px, 6px);
rippleAreaSize: 42px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
}
contactsSortOnlineIcon: icon{{ "contacts_online", boxTitleCloseFg }};
contactsSortOnlineIconOver: icon{{ "contacts_online", boxTitleCloseFgOver }};
contactsMarginTop: 4px;
contactsMarginBottom: 4px;
membersMarginTop: 10px;

View File

@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_folder.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "mainwindow.h"
@@ -26,12 +27,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "dialogs/dialogs_main_list.h"
#include "window/window_session_controller.h" // showAddContact()
#include "base/unixtime.h"
#include "facades.h"
#include "styles/style_boxes.h"
#include "styles/style_profile.h"
namespace {
constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000);
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().history(chat);
auto &histories = history->owner().histories();
@@ -110,17 +114,31 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
object_ptr<Ui::BoxContent> PrepareContactsBox(
not_null<Window::SessionController*> sessionController) {
const auto controller = sessionController;
auto delegate = [=](not_null<PeerListBox*> box) {
using Mode = ContactsBoxController::SortMode;
auto controller = std::make_unique<ContactsBoxController>(
&sessionController->session());
const auto raw = controller.get();
auto init = [=](not_null<PeerListBox*> box) {
struct State {
QPointer<Ui::IconButton> toggleSort;
Mode mode = ContactsBoxController::SortMode::Online;
};
const auto state = box->lifetime().make_state<State>();
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
box->addLeftButton(
tr::lng_profile_add_contact(),
[=] { controller->showAddContact(); });
[=] { sessionController->showAddContact(); });
state->toggleSort = box->addTopButton(st::contactsSortButton, [=] {
const auto online = (state->mode == Mode::Online);
state->mode = online ? Mode::Alphabet : Mode::Online;
raw->setSortMode(state->mode);
state->toggleSort->setIconOverride(
online ? &st::contactsSortOnlineIcon : nullptr,
online ? &st::contactsSortOnlineIconOver : nullptr);
});
raw->setSortMode(Mode::Online);
};
return Box<PeerListBox>(
std::make_unique<ContactsBoxController>(
&sessionController->session()),
std::move(delegate));
return Box<PeerListBox>(std::move(controller), std::move(init));
}
void PeerListRowWithLink::setActionLink(const QString &action) {
@@ -368,7 +386,8 @@ ContactsBoxController::ContactsBoxController(
not_null<Main::Session*> session,
std::unique_ptr<PeerListSearchController> searchController)
: PeerListController(std::move(searchController))
, _session(session) {
, _session(session)
, _sortByOnlineTimer([=] { sort(); }) {
}
Main::Session &ContactsBoxController::session() const {
@@ -404,6 +423,7 @@ void ContactsBoxController::rebuildRows() {
};
appendList(session().data().contactsList());
checkForEmptyRows();
sort();
delegate()->peerListRefreshRows();
}
@@ -427,6 +447,66 @@ void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
Ui::showPeerHistory(row->peer(), ShowAtUnreadMsgId);
}
void ContactsBoxController::setSortMode(SortMode mode) {
if (_sortMode == mode) {
return;
}
_sortMode = mode;
sort();
if (_sortMode == SortMode::Online) {
session().changes().peerUpdates(
Data::PeerUpdate::Flag::OnlineStatus
) | rpl::filter([=](const Data::PeerUpdate &update) {
return !_sortByOnlineTimer.isActive()
&& delegate()->peerListFindRow(update.peer->id.value);
}) | rpl::start_with_next([=] {
_sortByOnlineTimer.callOnce(kSortByOnlineThrottle);
}, _sortByOnlineLifetime);
} else {
_sortByOnlineTimer.cancel();
_sortByOnlineLifetime.destroy();
}
}
void ContactsBoxController::sort() {
switch (_sortMode) {
case SortMode::Alphabet: sortByName(); break;
case SortMode::Online: sortByOnline(); break;
default: Unexpected("SortMode in ContactsBoxController.");
}
}
void ContactsBoxController::sortByName() {
auto keys = base::flat_map<PeerListRowId, QString>();
keys.reserve(delegate()->peerListFullRowsCount());
const auto key = [&](const PeerListRow &row) {
const auto id = row.id();
const auto i = keys.find(id);
if (i != end(keys)) {
return i->second;
}
const auto peer = row.peer();
const auto history = peer->owner().history(peer);
return keys.emplace(id, history->chatListNameSortKey()).first->second;
};
const auto predicate = [&](const PeerListRow &a, const PeerListRow &b) {
return (key(a).compare(key(b)) < 0);
};
delegate()->peerListSortRows(predicate);
}
void ContactsBoxController::sortByOnline() {
const auto now = base::unixtime::now();
const auto key = [&](const PeerListRow &row) {
const auto user = row.peer()->asUser();
return user ? (std::min(user->onlineTill, now) + 1) : TimeId();
};
const auto predicate = [&](const PeerListRow &a, const PeerListRow &b) {
return key(a) > key(b);
};
delegate()->peerListSortRows(predicate);
}
bool ContactsBoxController::appendRow(not_null<UserData*> user) {
if (auto row = delegate()->peerListFindRow(user->id.value)) {
updateRowHook(row);

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_box.h"
#include "base/flat_set.h"
#include "base/weak_ptr.h"
#include "base/timer.h"
// Not used for now.
//
@@ -136,6 +137,12 @@ public:
not_null<PeerData*> peer) override final;
void rowClicked(not_null<PeerListRow*> row) override;
enum class SortMode {
Alphabet,
Online,
};
void setSortMode(SortMode mode);
protected:
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
virtual void prepareViewHook() {
@@ -144,11 +151,17 @@ protected:
}
private:
void sort();
void sortByName();
void sortByOnline();
void rebuildRows();
void checkForEmptyRows();
bool appendRow(not_null<UserData*> user);
const not_null<Main::Session*> _session;
SortMode _sortMode = SortMode::Alphabet;
base::Timer _sortByOnlineTimer;
rpl::lifetime _sortByOnlineLifetime;
};

View File

@@ -26,9 +26,9 @@ namespace {
if (!top) {
return false;
} else if (peer == migrated) {
return top.channel || (id < top.msg);
return peerIsChannel(top.peer) || (id < top.msg);
} else if (migrated) {
return top.channel && (id < top.msg);
return peerIsChannel(top.peer) && (id < top.msg);
} else {
return (id < top.msg);
}

View File

@@ -1105,12 +1105,14 @@ QString AppendShareGameScoreUrl(
const FullMsgId &fullId) {
auto shareHashData = QByteArray(0x20, Qt::Uninitialized);
auto shareHashDataInts = reinterpret_cast<uint64*>(shareHashData.data());
auto channel = fullId.channel
? session->data().channelLoaded(fullId.channel)
: static_cast<ChannelData*>(nullptr);
auto channelAccessHash = uint64(channel ? channel->access : 0);
const auto peer = fullId.peer
? session->data().peerLoaded(fullId.peer)
: static_cast<PeerData*>(nullptr);
const auto channelAccessHash = uint64((peer && peer->isChannel())
? peer->asChannel()->access
: 0);
shareHashDataInts[0] = session->userId().bare;
shareHashDataInts[1] = fullId.channel.bare;
shareHashDataInts[1] = fullId.peer.value;
shareHashDataInts[2] = uint64(fullId.msg.bare);
shareHashDataInts[3] = channelAccessHash;
@@ -1190,31 +1192,22 @@ void ShareGameScoreByHash(
return;
}
// Check first 32 bits of channel access hash.
auto channelAccessHash = hashDataInts[3];
//auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
//if (channelAccessHashInts[0] != hashDataInts[3]) {
// Ui::show(Box<Ui::InformBox>(tr::lng_share_wrong_user(tr::now)));
// return;
//}
if (((hashDataInts[1] >> 40) != 0)
|| (!hashDataInts[1] && channelAccessHash)) {
const auto peerId = PeerId(hashDataInts[1]);
const auto channelAccessHash = hashDataInts[3];
if (!peerIsChannel(peerId) && channelAccessHash) {
// If there is no channel id, there should be no channel access_hash.
Ui::show(Box<Ui::InformBox>(tr::lng_share_wrong_user(tr::now)));
return;
}
auto channelId = ChannelId(hashDataInts[1]);
auto msgId = MsgId(int64(hashDataInts[2]));
if (const auto item = session->data().message(channelId, msgId)) {
const auto msgId = MsgId(int64(hashDataInts[2]));
if (const auto item = session->data().message(peerId, msgId)) {
FastShareMessage(item);
} else {
auto resolveMessageAndShareScore = [=](ChannelData *channel) {
session->api().requestMessageData(channel, msgId, [=](
ChannelData *channel,
MsgId msgId) {
if (const auto item = session->data().message(channel, msgId)) {
auto resolveMessageAndShareScore = [=](PeerData *peer) {
session->api().requestMessageData(peer, msgId, [=] {
const auto item = session->data().message(peerId, msgId);
if (item) {
FastShareMessage(item);
} else {
Ui::show(Box<Ui::InformBox>(
@@ -1223,24 +1216,24 @@ void ShareGameScoreByHash(
});
};
const auto channel = channelId
? session->data().channelLoaded(channelId)
const auto peer = peerIsChannel(peerId)
? session->data().peerLoaded(peerId)
: nullptr;
if (channel || !channelId) {
resolveMessageAndShareScore(channel);
if (peer || !peerIsChannel(peerId)) {
resolveMessageAndShareScore(peer);
} else {
session->api().request(MTPchannels_GetChannels(
MTP_vector<MTPInputChannel>(
1,
MTP_inputChannel(
MTP_long(channelId.bare),
MTP_long(peerToChannel(peerId).bare),
MTP_long(channelAccessHash)))
)).done([=](const MTPmessages_Chats &result) {
result.match([&](const auto &data) {
session->data().processChats(data.vchats());
});
if (const auto channel = session->data().channelLoaded(channelId)) {
resolveMessageAndShareScore(channel);
if (const auto peer = session->data().peerLoaded(peerId)) {
resolveMessageAndShareScore(peer);
}
}).send();
}

View File

@@ -245,11 +245,12 @@ bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
return false;
}
if (_wasForMsgId == FullMsgId(to->channelId(), to->id) && !force) {
const auto peerId = to->history()->peer->id;
if (_wasForMsgId == FullMsgId(peerId, to->id) && !force) {
return false;
}
_wasForMsgId = FullMsgId(to->channelId(), to->id);
_wasForMsgId = FullMsgId(peerId, to->id);
auto markupFlags = to->replyKeyboardFlags();
_forceReply = markupFlags & ReplyMarkupFlag::ForceReply;

View File

@@ -164,7 +164,7 @@ void EmojiInteractions::startIncoming(
if (!peer->isUser() || bunch.interactions.empty()) {
return;
}
const auto item = _session->data().message(nullptr, messageId);
const auto item = _session->data().message(peer->id, messageId);
if (!item || !item->isRegular()) {
return;
}

View File

@@ -22,109 +22,6 @@ namespace {
std::map<int, const char*> BetaLogs() {
return {
{
2009004,
"- Choose one from dozens of new gorgeous animated backgrounds"
" in Chat Settings > Chat background.\n"
},
{
2009005,
"- Tile chat background patterns horizontally.\n"
"- Fix a rare crash in spellchecker on Windows.\n"
"- Fix animated chat backgrounds in Saved Messages.\n"
"- Fix \"Sorry, group is inaccessible\" message "
"in scheduled voice chats.\n",
},
{
2009013,
"- See unread comments count when scrolling discussions in channels."
},
{
3000002,
"- Check who've seen your message in small groups "
"from the context menu.\n"
"- Enable recording with video in live streams and video chats."
},
{
3000004,
"- Fix a crash when joining video chat or live broadcast.\n"
"- Add a \"Close to Taskbar\" option when tray icon is disabled "
"(Windows and Linux)."
},
{
3000005,
"- Add support for Emoji 13.1."
},
{
3001002,
"- Control video in fullscreen mode using arrows and numbers.\n"
"- Open locations in browser if default Bing Maps is not installed.\n"
"- Reconnect without timeout when network availability changes.\n"
"- Crash fixes."
},
{
3001005,
"- Choose one of 8 new preset themes for any individual private chat.\n"
"- Click on '...' menu > 'Change Colors' to pick a theme.\n"
"- Both chat participants will see the same theme in that chat "
" on all their devices.\n"
"- Each new theme features colorful gradient message bubbles, "
"beautifully animated backgrounds and unique background patterns.\n"
"- All chat themes have day and night versions and will follow "
"your overall dark mode settings.\n"
"- Implement main window rounded corners on Windows 11.\n"
"- Fix audio capture from AirPods on macOS.\n"
},
{
3001006,
"- Show small media previews in chats list.\n"
"- Show media album previews and caption text in chats list.\n"
"- Add \"Quick Reply\" and \"Mark as Read\" "
"to native Windows notifications.\n"
},
{
3001012,
"- Create special invite links that require admins "
"to approve users before they become members.\n"
"- Admins can view the applicants' profiles and bios "
"by tapping the Join Requests bar at the top of the chat.\n"
"- Add internal labels to your chat's Invite Links "
"to keep them organized.\n"
"- Run natively on Apple Silicon (macOS only).\n"
},
{
3001013,
"- Fix requests to groups / channels processing.\n"
"- Fix internal link previews with View Content button layout.\n"
"- Fix crash in messages search with imported messages results.\n"
"- Don't use fractional system UI scaling on Linux.\n"
"- Fix invite link icons on macOS.\n"
"- Several crash fixes.\n"
},
{
3002006,
"- Try out the new audio player with playlist shuffle and repeat.\n"
@@ -141,6 +38,24 @@ std::map<int, const char*> BetaLogs() {
"- Fix a crash in archived stickers loading.\n"
"- Fix a crash in calls to old Telegram versions.\n"
},
{
3003001,
"- Switch between contacts list sorting modes.\n"
"- Sort contacts list by last seen time by default.\n"
"- Fix disappearing Send As Channel button after message editing.\n"
"- Fix file upload cancelling.\n"
"- Fix crash in video capture on macOS.\n"
"- Fix labels in the About box.\n"
"- Use Qt 6.2.2 for macOS and Linux builds.\n"
"- Allow installing x64 Windows version on Windows ARM.\n"
}
};
};

View File

@@ -43,9 +43,7 @@ PreLaunchWindow::PreLaunchWindow(QString title) {
p.setColor(QPalette::Window, QColor(255, 255, 255));
setPalette(p);
QLabel tmp(this);
tmp.setText(qsl("Tmp"));
_size = tmp.sizeHint().height();
_size = QFontMetrics(QGuiApplication::font()).height();
int paddingVertical = (_size / 2);
int paddingHorizontal = _size;

View File

@@ -460,7 +460,6 @@ void Launcher::processArguments() {
auto parseMap = std::map<QByteArray, KeyFormat> {
{ "-debug" , KeyFormat::NoValues },
{ "-freetype" , KeyFormat::NoValues },
{ "-many" , KeyFormat::NoValues },
{ "-key" , KeyFormat::OneValue },
{ "-autostart" , KeyFormat::NoValues },
{ "-fixprevious" , KeyFormat::NoValues },
@@ -499,7 +498,6 @@ void Launcher::processArguments() {
gUseFreeType = parseResult.contains("-freetype");
gDebugMode = parseResult.contains("-debug");
gManyInstance = parseResult.contains("-many");
gKeyFile = parseResult.value("-key", {}).join(QString()).toLower();
gKeyFile = gKeyFile.replace(QRegularExpression("[^a-z0-9\\-_]"), {});
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart

View File

@@ -439,8 +439,8 @@ bool OpenMediaTimestamp(
const auto parts = base.mid(3).split('_');
const auto documentId = parts.value(0).toULongLong();
const auto itemId = FullMsgId(
parts.value(1).toInt(),
parts.value(2).toInt());
PeerId(parts.value(1).toULongLong()),
MsgId(parts.value(2).toLongLong()));
const auto session = &controller->session();
const auto document = session->data().document(documentId);
session->settings().setMediaLastPlaybackPosition(

View File

@@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h"
#include "app.h"
#include <QtCore/QLockFile>
#include <QtGui/QSessionManager>
#include <QtGui/QScreen>
#include <qpa/qplatformscreen.h>
@@ -99,10 +100,35 @@ int Sandbox::start() {
if (!Core::UpdaterDisabled()) {
_updateChecker = std::make_unique<Core::UpdateChecker>();
}
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
char h[33] = { 0 };
hashMd5Hex(d.constData(), d.size(), h);
_localServerName = Platform::SingleInstanceLocalServerName(h);
{
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
char h[33] = { 0 };
hashMd5Hex(d.constData(), d.size(), h);
_localServerName = Platform::SingleInstanceLocalServerName(h);
}
{
const auto d = QFile::encodeName(cExeDir() + cExeName());
QByteArray h;
h.resize(32);
hashMd5Hex(d.constData(), d.size(), h.data());
_lockFile = std::make_unique<QLockFile>(QDir::tempPath() + '/' + h + '-' + cGUIDStr());
_lockFile->setStaleLockTime(0);
if (!_lockFile->tryLock() && _launcher->customWorkingDir()) {
// On Windows, QLockFile has problems detecting a stale lock
// if the machine's hostname contains characters outside the US-ASCII character set.
if constexpr (Platform::IsWindows()) {
// QLockFile::removeStaleLockFile returns false on Windows,
// when the application owning the lock is still running.
if (!_lockFile->removeStaleLockFile()) {
gManyInstance = true;
}
} else {
gManyInstance = true;
}
}
}
connect(
&_localSocket,
@@ -149,13 +175,8 @@ int Sandbox::start() {
restartHint,
Qt::DirectConnection);
if (cManyInstance()) {
LOG(("Many instance allowed, starting..."));
singleInstanceChecked();
} else {
LOG(("Connecting local socket to %1...").arg(_localServerName));
_localSocket.connectToServer(_localServerName);
}
LOG(("Connecting local socket to %1...").arg(_localServerName));
_localSocket.connectToServer(_localServerName);
if (QuitOnStartRequested) {
closeApplication();
@@ -339,12 +360,12 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) {
void Sandbox::singleInstanceChecked() {
if (cManyInstance()) {
Logs::multipleInstances();
LOG(("App Info: Detected another instance"));
}
Ui::DisableCustomScaling();
refreshGlobalProxy();
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
if (!Logs::started() || !Logs::instanceChecked()) {
new NotStartedWindow();
return;
}

View File

@@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtNetwork/QLocalSocket>
#include <QtCore/QAbstractNativeEventFilter>
class QLockFile;
namespace Core {
class Launcher;
@@ -119,6 +121,7 @@ private:
QLocalServer _localServer;
QLocalSocket _localSocket;
LocalClients _localClients;
std::unique_ptr<QLockFile> _lockFile;
bool _secondInstance = false;
bool _started = false;
static bool QuitOnStartRequested;

View File

@@ -30,8 +30,6 @@ extern "C" {
#include <time.h>
#endif
#include <QtNetwork/QSslSocket>
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
// Base types compile-time check
@@ -56,15 +54,6 @@ static_assert(sizeof(int) >= 4, "Basic types size check failed");
// Precise timing functions / rand init
struct CRYPTO_dynlock_value {
QMutex mutex;
};
namespace {
bool _sslInited = false;
QMutex *_sslLocks = nullptr;
}
namespace ThirdParty {
void start() {
@@ -94,45 +83,15 @@ namespace ThirdParty {
LOG(("MTP Error: Could not init OpenSSL rand, RAND_status() is 0..."));
}
}
// Force OpenSSL loading if it is linked in Qt,
// so that we won't mess with our OpenSSL locking with Qt OpenSSL locking.
auto sslSupported = QSslSocket::supportsSsl();
if (!sslSupported) {
LOG(("Error: current Qt build doesn't support SSL requests."));
}
if (!CRYPTO_get_locking_callback()) {
// Qt didn't initialize OpenSSL, so we will.
auto numLocks = CRYPTO_num_locks();
if (numLocks) {
_sslLocks = new QMutex[numLocks];
CRYPTO_set_locking_callback(_sslLockingCallback);
} else {
LOG(("MTP Error: Could not init OpenSSL threads, CRYPTO_num_locks() returned zero!"));
}
}
if (!CRYPTO_get_dynlock_create_callback()) {
CRYPTO_set_dynlock_create_callback(_sslCreateFunction);
CRYPTO_set_dynlock_lock_callback(_sslLockFunction);
CRYPTO_set_dynlock_destroy_callback(_sslDestroyFunction);
} else if (!CRYPTO_get_dynlock_lock_callback()) {
LOG(("MTP Error: dynlock_create callback is set without dynlock_lock callback!"));
}
_sslInited = true;
}
void finish() {
CRYPTO_cleanup_all_ex_data();
#ifndef LIBRESSL_VERSION_NUMBER
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_default_properties_enable_fips(nullptr, 0);
#else
FIPS_mode_set(0);
#endif
ENGINE_cleanup();
CONF_modules_unload(1);
ERR_free_strings();
EVP_cleanup();
delete[] base::take(_sslLocks);
Platform::ThirdParty::finish();
}

View File

@@ -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 = 3003000;
constexpr auto AppVersionStr = "3.3";
constexpr auto AppBetaVersion = false;
constexpr auto AppVersion = 3003001;
constexpr auto AppVersionStr = "3.3.1";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -1221,7 +1221,10 @@ bool DocumentData::hasWebLocation() const {
}
bool DocumentData::isNull() const {
return !hasRemoteLocation() && !hasWebLocation() && _url.isEmpty();
return !hasRemoteLocation()
&& !hasWebLocation()
&& _url.isEmpty()
&& !uploading();
}
MTPInputDocument DocumentData::mtpInput() const {

View File

@@ -300,9 +300,7 @@ void Folder::applyDialog(const MTPDdialogFolder &data) {
_chatsList.updateCloudUnread(data);
if (const auto peerId = peerFromMTP(data.vpeer())) {
const auto history = owner().history(peerId);
const auto fullId = FullMsgId(
peerToChannel(peerId),
data.vtop_message().v);
const auto fullId = FullMsgId(peerId, data.vtop_message().v);
history->setFolder(this, owner().message(fullId));
} else {
_chatsList.clear();

View File

@@ -469,7 +469,7 @@ void Histories::requestGroupAround(not_null<HistoryItem*> item) {
result);
_chatListGroupRequests.remove(history);
history->migrateToOrMe()->applyChatListGroup(
history->channelId(),
history->peer->id,
result);
finish();
}).fail([=] {

View File

@@ -157,26 +157,6 @@ void MessagesList::removeOne(MessagePosition messageId) {
}
}
void MessagesList::removeAll(ChannelId channelId) {
auto removed = 0;
for (auto i = begin(_slices); i != end(_slices); ++i) {
_slices.modify(i, [&](Slice &slice) {
auto &messages = slice.messages;
for (auto j = begin(messages); j != end(messages);) {
if (j->fullId.channel == channelId) {
j = messages.erase(j);
++removed;
} else {
++j;
}
}
});
}
if (removed && _count) {
*_count -= removed;
}
}
void MessagesList::removeLessThan(MessagePosition messageId) {
auto removed = 0;
for (auto i = begin(_slices); i != end(_slices);) {
@@ -390,22 +370,6 @@ bool MessagesSliceBuilder::removeAll() {
return true;
}
bool MessagesSliceBuilder::removeFromChannel(ChannelId channelId) {
for (auto i = _ids.begin(); i != _ids.end();) {
if ((*i).fullId.channel == channelId) {
i = _ids.erase(i);
if (_fullCount) {
--*_fullCount;
}
} else {
++i;
}
}
_skippedBefore = _skippedAfter = std::nullopt;
checkInsufficient();
return true;
}
bool MessagesSliceBuilder::invalidated() {
_fullCount = _skippedBefore = _skippedAfter = std::nullopt;
_ids.clear();

View File

@@ -65,11 +65,11 @@ struct MessagesRange {
constexpr auto MinDate = TimeId(0);
constexpr auto MaxDate = std::numeric_limits<TimeId>::max();
constexpr auto MinMessagePosition = MessagePosition{
.fullId = FullMsgId(NoChannel, 1),
.fullId = FullMsgId(PeerId(), 1),
.date = MinDate,
};
constexpr auto MaxMessagePosition = MessagePosition{
.fullId = FullMsgId(NoChannel, ServerMaxMsgId - 1),
.fullId = FullMsgId(PeerId(), ServerMaxMsgId - 1),
.date = MaxDate,
};
constexpr auto FullMessagesRange = MessagesRange{
@@ -77,7 +77,7 @@ constexpr auto FullMessagesRange = MessagesRange{
.till = MaxMessagePosition,
};
constexpr auto UnreadMessagePosition = MessagePosition{
.fullId = FullMsgId(NoChannel, ShowAtUnreadMsgId),
.fullId = FullMsgId(PeerId(), ShowAtUnreadMsgId),
.date = MinDate,
};
@@ -117,7 +117,6 @@ public:
MessagesRange noSkipRange,
std::optional<int> count);
void removeOne(MessagePosition messageId);
void removeAll(ChannelId channelId);
void removeLessThan(MessagePosition messageId);
void invalidate();
void invalidateBottom();
@@ -191,7 +190,6 @@ public:
bool applyInitial(const MessagesResult &result);
bool applyUpdate(const MessagesSliceUpdate &update);
bool removeOne(MessagePosition messageId);
bool removeFromChannel(ChannelId channelId);
bool removeAll();
bool invalidated();
bool bottomInvalidated();

View File

@@ -122,9 +122,10 @@ struct MsgRange {
struct FullMsgId {
constexpr FullMsgId() noexcept = default;
constexpr FullMsgId(ChannelId channel, MsgId msg) noexcept
: channel(channel), msg(msg) {
constexpr FullMsgId(PeerId peer, MsgId msg) noexcept
: peer(peer), msg(msg) {
}
FullMsgId(ChannelId channelId, MsgId msgId) = delete;
constexpr explicit operator bool() const noexcept {
return msg != 0;
@@ -133,16 +134,16 @@ struct FullMsgId {
return msg == 0;
}
ChannelId channel = NoChannel;
PeerId peer = 0;
MsgId msg = 0;
};
[[nodiscard]] inline constexpr bool operator<(
const FullMsgId &a,
const FullMsgId &b) noexcept {
if (a.channel < b.channel) {
if (a.peer < b.peer) {
return true;
} else if (a.channel > b.channel) {
} else if (a.peer > b.peer) {
return false;
}
return a.msg < b.msg;
@@ -169,7 +170,7 @@ struct FullMsgId {
[[nodiscard]] inline constexpr bool operator==(
const FullMsgId &a,
const FullMsgId &b) noexcept {
return (a.channel == b.channel) && (a.msg == b.msg);
return (a.peer == b.peer) && (a.msg == b.msg);
}
[[nodiscard]] inline constexpr bool operator!=(

View File

@@ -1193,11 +1193,11 @@ FullMsgId ResolveTopPinnedId(
.skippedAfter = 0,
};
if (!slice.messageIds.empty()) {
return FullMsgId(peerToChannel(peer->id), slice.messageIds.back());
return FullMsgId(peer->id, slice.messageIds.back());
} else if (!migrated || slice.count != 0 || old.messageIds.empty()) {
return FullMsgId();
} else {
return FullMsgId(0, old.messageIds.back());
return FullMsgId(migrated->id, old.messageIds.back());
}
}
@@ -1227,9 +1227,9 @@ FullMsgId ResolveMinPinnedId(
.skippedAfter = 0,
};
if (!old.messageIds.empty()) {
return FullMsgId(0, old.messageIds.front());
return FullMsgId(migrated->id, old.messageIds.front());
} else if (old.count == 0 && !slice.messageIds.empty()) {
return FullMsgId(peerToChannel(peer->id), slice.messageIds.front());
return FullMsgId(peer->id, slice.messageIds.front());
} else {
return FullMsgId();
}

View File

@@ -136,8 +136,6 @@ using ChatId = ChatIdType<1>;
using ChannelId = ChatIdType<2>;
using FakeChatId = ChatIdType<0x7F>;
inline constexpr auto NoChannel = ChannelId(0);
struct PeerIdHelper {
BareId value = 0;
constexpr PeerIdHelper(BareId value) noexcept : value(value) {

View File

@@ -193,10 +193,10 @@ std::optional<int> RepliesList::fullUnreadCountAfter(
|| (fullLoaded && _list.empty());
const auto countIncoming = [&](auto from, auto till) {
auto &owner = _history->owner();
const auto channelId = _history->channelId();
const auto peerId = _history->peer->id;
auto count = 0;
for (auto i = from; i != till; ++i) {
if (!owner.message(channelId, *i)->out()) {
if (!owner.message(peerId, *i)->out()) {
++count;
}
}
@@ -336,7 +336,7 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
= (*_skippedAfter + (availableAfter - useAfter));
}
const auto channelId = _history->channelId();
const auto peerId = _history->peer->id;
slice->ids.clear();
auto nearestToAround = std::optional<MsgId>();
slice->ids.reserve(useAfter + useBefore);
@@ -346,10 +346,10 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
? *j
: *(j - 1);
}
slice->ids.emplace_back(channelId, *j);
slice->ids.emplace_back(peerId, *j);
}
slice->nearestToAround = FullMsgId(
channelId,
peerId,
nearestToAround.value_or(
slice->ids.empty() ? 0 : slice->ids.back().msg));
slice->fullCount = _fullCount.current();
@@ -418,7 +418,7 @@ Histories &RepliesList::histories() {
}
HistoryItem *RepliesList::lookupRoot() {
return _history->owner().message(_history->channelId(), _rootId);
return _history->owner().message(_history->peer->id, _rootId);
}
void RepliesList::loadAround(MsgId id) {

View File

@@ -145,7 +145,7 @@ HistoryItem *ScheduledMessages::lookupItem(PeerId peer, MsgId msg) const {
}
HistoryItem *ScheduledMessages::lookupItem(FullMsgId itemId) const {
return lookupItem(peerFromChannel(itemId.channel), itemId.msg);
return lookupItem(itemId.peer, itemId.msg);
}
int ScheduledMessages::count(not_null<History*> history) const {

View File

@@ -285,7 +285,7 @@ void Session::clear() {
_sponsoredMessages = nullptr;
_dependentMessages.clear();
base::take(_messages);
base::take(_channelMessages);
base::take(_nonChannelMessages);
_messageByRandomId.clear();
_sentMessagesData.clear();
cSetRecentInlineBots(RecentInlineBots());
@@ -1334,20 +1334,31 @@ rpl::producer<not_null<HistoryItem*>> Session::newItemAdded() const {
return _newItemAdded.events();
}
void Session::changeMessageId(ChannelId channel, MsgId wasId, MsgId nowId) {
const auto list = messagesListForInsert(channel);
void Session::changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId) {
const auto list = messagesListForInsert(peerId);
auto i = list->find(wasId);
Assert(i != list->end());
auto owned = std::move(i->second);
const auto item = i->second;
list->erase(i);
const auto [j, ok] = list->emplace(nowId, std::move(owned));
const auto [j, ok] = list->emplace(nowId, item);
if (!peerIsChannel(peerId)) {
if (IsServerMsgId(wasId)) {
const auto k = _nonChannelMessages.find(wasId);
Assert(k != end(_nonChannelMessages));
_nonChannelMessages.erase(k);
}
if (IsServerMsgId(nowId)) {
_nonChannelMessages.emplace(nowId, item);
}
}
Ensures(ok);
}
void Session::notifyItemIdChange(IdChange event) {
const auto item = event.item;
changeMessageId(item->history()->channelId(), event.oldId, item->id);
changeMessageId(item->history()->peer->id, event.oldId, item->id);
_itemIdChanges.fire_copy(event);
@@ -1797,7 +1808,7 @@ void Session::reorderTwoPinnedChats(
bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
const auto peer = peerFromMTP(data.vpeer_id());
const auto existing = message(peerToChannel(peer), data.vid().v);
const auto existing = message(peer, data.vid().v);
if (!existing) {
return false;
}
@@ -1817,8 +1828,7 @@ void Session::updateEditedMessage(const MTPMessage &data) {
-> HistoryItem* {
return nullptr;
}, [&](const auto &data) {
const auto peer = peerFromMTP(data.vpeer_id());
return message(peerToChannel(peer), data.vid().v);
return message(peerFromMTP(data.vpeer_id()), data.vid().v);
});
if (!existing) {
return;
@@ -1885,23 +1895,19 @@ void Session::processExistingMessages(
});
}
const Session::Messages *Session::messagesList(ChannelId channelId) const {
if (channelId == NoChannel) {
return &_messages;
}
const auto i = _channelMessages.find(channelId);
return (i != end(_channelMessages)) ? &i->second : nullptr;
const Session::Messages *Session::messagesList(PeerId peerId) const {
const auto i = _messages.find(peerId);
return (i != end(_messages)) ? &i->second : nullptr;
}
auto Session::messagesListForInsert(ChannelId channelId)
auto Session::messagesListForInsert(PeerId peerId)
-> not_null<Messages*> {
return (channelId == NoChannel)
? &_messages
: &_channelMessages[channelId];
return &_messages[peerId];
}
void Session::registerMessage(not_null<HistoryItem*> item) {
const auto list = messagesListForInsert(item->channelId());
const auto peerId = item->history()->peer->id;
const auto list = messagesListForInsert(peerId);
const auto itemId = item->id;
const auto i = list->find(itemId);
if (i != list->end()) {
@@ -1909,6 +1915,10 @@ void Session::registerMessage(not_null<HistoryItem*> item) {
i->second->destroy();
}
list->emplace(itemId, item);
if (!peerIsChannel(peerId) && IsServerMsgId(itemId)) {
_nonChannelMessages.emplace(itemId, item);
}
}
void Session::registerMessageTTL(TimeId when, not_null<HistoryItem*> item) {
@@ -1963,12 +1973,10 @@ void Session::checkTTLs() {
}
void Session::processMessagesDeleted(
ChannelId channelId,
PeerId peerId,
const QVector<MTPint> &data) {
const auto list = messagesList(channelId);
const auto affected = (channelId != NoChannel)
? historyLoaded(peerFromChannel(channelId))
: nullptr;
const auto list = messagesList(peerId);
const auto affected = historyLoaded(peerId);
if (!list && !affected) {
return;
}
@@ -1991,6 +1999,22 @@ void Session::processMessagesDeleted(
}
}
void Session::processNonChannelMessagesDeleted(const QVector<MTPint> &data) {
auto historiesToCheck = base::flat_set<not_null<History*>>();
for (const auto &messageId : data) {
if (const auto item = nonChannelMessage(messageId.v)) {
const auto history = item->history();
item->destroy();
if (!history->chatListMessageKnown()) {
historiesToCheck.emplace(history);
}
}
}
for (const auto &history : historiesToCheck) {
history->requestChatListMessage();
}
}
void Session::removeDependencyMessage(not_null<HistoryItem*> item) {
const auto i = _dependentMessages.find(item);
if (i == end(_dependentMessages)) {
@@ -2006,13 +2030,18 @@ void Session::removeDependencyMessage(not_null<HistoryItem*> item) {
void Session::unregisterMessage(not_null<HistoryItem*> item) {
const auto peerId = item->history()->peer->id;
const auto itemId = item->id;
_itemRemoved.fire_copy(item);
session().changes().messageUpdated(
item,
Data::MessageUpdate::Flag::Destroyed);
groups().unregisterMessage(item);
removeDependencyMessage(item);
messagesListForInsert(peerToChannel(peerId))->erase(item->id);
messagesListForInsert(peerId)->erase(itemId);
if (!peerIsChannel(peerId) && IsServerMsgId(itemId)) {
_nonChannelMessages.erase(itemId);
}
}
MsgId Session::nextLocalMessageId() {
@@ -2035,12 +2064,12 @@ bool Session::suggestToGigagroup(not_null<ChannelData*> group) const {
return _suggestToGigagroup.contains(group);
}
HistoryItem *Session::message(ChannelId channelId, MsgId itemId) const {
HistoryItem *Session::message(PeerId peerId, MsgId itemId) const {
if (!itemId) {
return nullptr;
}
const auto data = messagesList(channelId);
const auto data = messagesList(peerId);
if (!data) {
return nullptr;
}
@@ -2050,13 +2079,21 @@ HistoryItem *Session::message(ChannelId channelId, MsgId itemId) const {
}
HistoryItem *Session::message(
const ChannelData *channel,
not_null<const PeerData*> peer,
MsgId itemId) const {
return message(channel ? peerToChannel(channel->id) : 0, itemId);
return message(peer->id, itemId);
}
HistoryItem *Session::message(FullMsgId itemId) const {
return message(itemId.channel, itemId.msg);
return message(itemId.peer, itemId.msg);
}
HistoryItem *Session::nonChannelMessage(MsgId itemId) const {
if (!IsServerMsgId(itemId)) {
return nullptr;
}
const auto i = _nonChannelMessages.find(itemId);
return (i != end(_nonChannelMessages)) ? i->second.get() : nullptr;
}
void Session::updateDependentMessages(not_null<HistoryItem*> item) {

View File

@@ -348,19 +348,22 @@ public:
void processExistingMessages(
ChannelData *channel,
const MTPmessages_Messages &data);
void processNonChannelMessagesDeleted(const QVector<MTPint> &data);
void processMessagesDeleted(
ChannelId channelId,
PeerId peerId,
const QVector<MTPint> &data);
[[nodiscard]] MsgId nextLocalMessageId();
[[nodiscard]] HistoryItem *message(
ChannelId channelId,
PeerId peerId,
MsgId itemId) const;
[[nodiscard]] HistoryItem *message(
const ChannelData *channel,
not_null<const PeerData*> peer,
MsgId itemId) const;
[[nodiscard]] HistoryItem *message(FullMsgId itemId) const;
[[nodiscard]] HistoryItem *nonChannelMessage(MsgId itemId) const;
void updateDependentMessages(not_null<HistoryItem*> item);
void registerDependentMessage(
not_null<HistoryItem*> dependent,
@@ -698,11 +701,11 @@ private:
Data::Folder *requestFolder,
const MTPDdialogFolder &data);
const Messages *messagesList(ChannelId channelId) const;
not_null<Messages*> messagesListForInsert(ChannelId channelId);
const Messages *messagesList(PeerId peerId) const;
not_null<Messages*> messagesListForInsert(PeerId peerId);
not_null<HistoryItem*> registerMessage(
std::unique_ptr<HistoryItem> item);
void changeMessageId(ChannelId channel, MsgId wasId, MsgId nowId);
void changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId);
void removeDependencyMessage(not_null<HistoryItem*> item);
void photoApplyFields(
@@ -848,14 +851,15 @@ private:
Dialogs::IndexedList _contactsNoChatsList;
MsgId _localMessageIdCounter = StartClientMsgId;
Messages _messages;
std::map<ChannelId, Messages> _channelMessages;
std::unordered_map<PeerId, Messages> _messages;
std::map<
not_null<HistoryItem*>,
base::flat_set<not_null<HistoryItem*>>> _dependentMessages;
std::map<TimeId, base::flat_set<not_null<HistoryItem*>>> _ttlMessages;
base::Timer _ttlCheckTimer;
std::unordered_map<MsgId, not_null<HistoryItem*>> _nonChannelMessages;
base::flat_map<uint64, FullMsgId> _messageByRandomId;
base::flat_map<uint64, SentData> _sentMessagesData;

View File

@@ -365,7 +365,7 @@ std::optional<int> SharedMediaWithLastSlice::indexOf(Value value) const {
? QString::number(*_ending->skippedAfter())
: QString("-"));
if (const auto msgId = std::get_if<FullMsgId>(&value)) {
info.push_back("value:" + QString::number(msgId->channel.bare));
info.push_back("value:" + QString::number(msgId->peer.value));
info.push_back(QString::number(msgId->msg.bare));
const auto index = _slice.indexOf(*std::get_if<FullMsgId>(&value));
info.push_back("index:" + (index

View File

@@ -164,7 +164,7 @@ private:
return (a && b) ? base::make_optional(*a + *b) : std::nullopt;
}
static Value ComputeId(PeerId peerId, MsgId msgId) {
return FullMsgId(peerToChannel(peerId), msgId);
return FullMsgId(peerId, msgId);
}
static Value ComputeId(const Key &key) {
if (const auto messageId = std::get_if<MessageId>(&key.universalId)) {

View File

@@ -100,12 +100,10 @@ private:
}
static bool IsFromSlice(PeerId peerId, FullMsgId fullId) {
return peerIsChannel(peerId)
? (peerId == peerFromChannel(fullId.channel))
: !fullId.channel;
return (peerId == fullId.peer);
}
static FullMsgId ComputeId(PeerId peerId, MsgId msgId) {
return FullMsgId(peerToChannel(peerId), msgId);
return FullMsgId(peerId, msgId);
}
static FullMsgId ComputeId(const Key &key) {
return (key.universalId >= 0)

View File

@@ -72,7 +72,7 @@ bool SponsoredMessages::append(not_null<History*> history) {
}
const auto flags = MessageFlags(0)
| (history->isChannel() ? MessageFlag::Post : MessageFlags(0))
| (history->peer->isChannel() ? MessageFlag::Post : MessageFlags(0))
| MessageFlag::HasFromId
| MessageFlag::IsSponsored
| MessageFlag::Local;
@@ -93,7 +93,7 @@ bool SponsoredMessages::append(not_null<History*> history) {
}
bool SponsoredMessages::canHaveFor(not_null<History*> history) const {
return history->isChannel();
return history->peer->isChannel();
}
void SponsoredMessages::request(not_null<History*> history) {
@@ -189,11 +189,10 @@ void SponsoredMessages::clearItems(not_null<History*> history) {
const SponsoredMessages::Entry *SponsoredMessages::find(
const FullMsgId &fullId) const {
if (!fullId.channel) {
if (!peerIsChannel(fullId.peer)) {
return nullptr;
}
const auto history = _session->data().history(
peerFromChannel(fullId.channel));
const auto history = _session->data().history(fullId.peer);
const auto it = _data.find(history);
if (it == end(_data)) {
return nullptr;

View File

@@ -695,7 +695,7 @@ bool InnerWidget::isSearchResultActive(
const auto peer = item->history()->peer;
return (item->fullId() == entry.fullId)
|| (peer->migrateTo()
&& (peerToChannel(peer->migrateTo()->id) == entry.fullId.channel)
&& (peer->migrateTo()->id == entry.fullId.peer)
&& (item->id == -entry.fullId.msg))
|| (uniqueSearchResults() && peer == entry.key.peer());
}
@@ -1552,7 +1552,7 @@ void InnerWidget::updateDialogRow(
if (const auto migrated = from->owner().historyLoaded(from)) {
row = RowDescriptor(
migrated,
FullMsgId(0, -row.fullId.msg));
FullMsgId(from->id, -row.fullId.msg));
}
}
}
@@ -2712,7 +2712,7 @@ RowDescriptor InnerWidget::chatListEntryBefore(
if (i != list->cbegin()) {
return RowDescriptor(
(*(i - 1))->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
}
return RowDescriptor();
@@ -2738,11 +2738,11 @@ RowDescriptor InnerWidget::chatListEntryBefore(
}
return RowDescriptor(
_filterResults.back()->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
return RowDescriptor(
session().data().history(_peerSearchResults.back()->peer),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
}
if (!_peerSearchResults.empty()
@@ -2752,14 +2752,14 @@ RowDescriptor InnerWidget::chatListEntryBefore(
}
return RowDescriptor(
_filterResults.back()->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
if (!_peerSearchResults.empty()) {
for (auto b = _peerSearchResults.cbegin(), i = b + 1, e = _peerSearchResults.cend(); i != e; ++i) {
if ((*i)->peer == whichHistory->peer) {
return RowDescriptor(
session().data().history((*(i - 1))->peer),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
}
}
@@ -2771,7 +2771,7 @@ RowDescriptor InnerWidget::chatListEntryBefore(
if ((*i)->key() == which.key) {
return RowDescriptor(
(*(i - 1))->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
}
return RowDescriptor();
@@ -2789,7 +2789,7 @@ RowDescriptor InnerWidget::chatListEntryAfter(
if (i != list->cend()) {
return RowDescriptor(
(*i)->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
}
return RowDescriptor();
@@ -2815,7 +2815,7 @@ RowDescriptor InnerWidget::chatListEntryAfter(
if (i != e) {
return RowDescriptor(
session().data().history((*i)->peer),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
} else if (!_searchResults.empty()) {
return RowDescriptor(
_searchResults.front()->item()->history(),
@@ -2830,11 +2830,11 @@ RowDescriptor InnerWidget::chatListEntryAfter(
if (i != e) {
return RowDescriptor(
(*i)->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
} else if (!_peerSearchResults.empty()) {
return RowDescriptor(
session().data().history(_peerSearchResults.front()->peer),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
} else if (!_searchResults.empty()) {
return RowDescriptor(
_searchResults.front()->item()->history(),
@@ -2853,17 +2853,17 @@ RowDescriptor InnerWidget::chatListEntryFirst() const {
if (i != list->cend()) {
return RowDescriptor(
(*i)->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
return RowDescriptor();
} else if (!_filterResults.empty()) {
return RowDescriptor(
_filterResults.front()->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
} else if (!_peerSearchResults.empty()) {
return RowDescriptor(
session().data().history(_peerSearchResults.front()->peer),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
} else if (!_searchResults.empty()) {
return RowDescriptor(
_searchResults.front()->item()->history(),
@@ -2879,7 +2879,7 @@ RowDescriptor InnerWidget::chatListEntryLast() const {
if (i != list->cbegin()) {
return RowDescriptor(
(*(i - 1))->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
return RowDescriptor();
} else if (!_searchResults.empty()) {
@@ -2889,11 +2889,11 @@ RowDescriptor InnerWidget::chatListEntryLast() const {
} else if (!_peerSearchResults.empty()) {
return RowDescriptor(
session().data().history(_peerSearchResults.back()->peer),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
} else if (!_filterResults.empty()) {
return RowDescriptor(
_filterResults.back()->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
FullMsgId(PeerId(), ShowAtUnreadMsgId));
}
return RowDescriptor();
}

View File

@@ -358,7 +358,7 @@ not_null<ChannelData*> Widget::channel() const {
Dialogs::RowDescriptor Widget::activeChat() const {
return {
channel()->owner().history(channel()),
FullMsgId(peerToChannel(channel()->id), ShowAtUnreadMsgId)
FullMsgId(channel()->id, ShowAtUnreadMsgId)
};
}

View File

@@ -366,7 +366,7 @@ not_null<HistoryItem*> History::createItem(
const MTPMessage &message,
MessageFlags localFlags,
bool detachExistingItem) {
if (const auto result = owner().message(channelId(), id)) {
if (const auto result = owner().message(peer, id)) {
if (detachExistingItem) {
result->removeMainView();
}
@@ -2174,7 +2174,7 @@ bool History::isReadyFor(MsgId msgId) {
}
return loadedAtBottom();
}
const auto item = owner().message(channelId(), msgId);
const auto item = owner().message(peer, msgId);
return item && (item->history() == this) && item->mainView();
}
@@ -2446,15 +2446,15 @@ void History::setFakeChatListMessageFrom(const MTPmessages_Messages &data) {
}
void History::applyChatListGroup(
ChannelId channelId,
PeerId dataPeerId,
const MTPmessages_Messages &data) {
if (!isEmpty()
|| !_chatListMessage
|| !*_chatListMessage
|| (*_chatListMessage)->history()->channelId() != channelId
|| (*_chatListMessage)->history() != this
|| !_lastMessage
|| !*_lastMessage) {
|| !*_lastMessage
|| dataPeerId != peer->id) {
return;
}
// Apply loaded album as a last slice.
@@ -2463,7 +2463,7 @@ void History::applyChatListGroup(
items.reserve(messages.v.size());
for (const auto &message : messages.v) {
const auto id = IdFromMessage(message);
if (const auto message = owner().message(channelId, id)) {
if (const auto message = owner().message(dataPeerId, id)) {
items.push_back(message);
}
}
@@ -2584,7 +2584,7 @@ void History::applyDialog(
}
if (!channel->amCreator()) {
const auto topMessageId = FullMsgId(
peerToChannel(channel->id),
channel->id,
data.vtop_message().v);
if (const auto item = owner().message(topMessageId)) {
if (item->date() <= channel->date) {
@@ -2719,9 +2719,7 @@ void History::applyDialogFields(
void History::applyDialogTopMessage(MsgId topMessageId) {
if (topMessageId) {
const auto itemId = FullMsgId(
channelId(),
topMessageId);
const auto itemId = FullMsgId(peer->id, topMessageId);
if (const auto item = owner().message(itemId)) {
setLastServerMessage(item);
} else {
@@ -2826,18 +2824,6 @@ void History::forceFullResize() {
_flags |= Flag::f_has_pending_resized_items;
}
ChannelId History::channelId() const {
return peerToChannel(peer->id);
}
bool History::isChannel() const {
return peerIsChannel(peer->id);
}
bool History::isMegagroup() const {
return peer->isMegagroup();
}
not_null<History*> History::migrateToOrMe() const {
if (const auto to = peer->migrateTo()) {
return owner().history(to);
@@ -2964,7 +2950,7 @@ void History::checkLocalMessages() {
insertMessageToBlocks(item);
}
}
if (isChannel()
if (peer->isChannel()
&& !_joinedMessage
&& peer->asChannel()->inviter
&& goodDate(peer->asChannel()->inviteDate)) {

View File

@@ -83,16 +83,12 @@ public:
History &operator=(const History &) = delete;
~History();
ChannelId channelId() const;
bool isChannel() const;
bool isMegagroup() const;
not_null<History*> migrateToOrMe() const;
History *migrateFrom() const;
MsgRange rangeForDifferenceRequest() const;
void checkLocalMessages();
void removeJoinedMessage();
bool isEmpty() const;
bool isDisplayedEmpty() const;
Element *findFirstNonEmpty() const;
@@ -411,7 +407,7 @@ public:
void checkChatListMessageRemoved(not_null<HistoryItem*> item);
void applyChatListGroup(
ChannelId channelId,
PeerId dataPeerId,
const MTPmessages_Messages &data);
void forgetScrollState() {

View File

@@ -2892,7 +2892,9 @@ MessageIdsList HistoryInner::getSelectedItems() const {
}) | to_vector;
result |= actions::sort(less{}, [](const FullMsgId &msgId) {
return msgId.channel ? msgId.msg : (msgId.msg - ServerMaxMsgId);
return peerIsChannel(msgId.peer)
? msgId.msg
: (msgId.msg - ServerMaxMsgId);
});
return result;
}

View File

@@ -285,7 +285,7 @@ HistoryItem *HistoryItem::lookupDiscussionPostOriginal() const {
return nullptr;
}
return _history->owner().message(
forwarded->savedFromPeer->asChannel(),
forwarded->savedFromPeer->id,
forwarded->savedFromMsgId);
}
@@ -745,8 +745,8 @@ bool HistoryItem::hasDirectLink() const {
return isRegular() && _history->peer->isChannel();
}
ChannelId HistoryItem::channelId() const {
return _history->channelId();
FullMsgId HistoryItem::fullId() const {
return FullMsgId(_history->peer->id, id);
}
Data::MessagePosition HistoryItem::position() const {

View File

@@ -391,10 +391,7 @@ public:
[[nodiscard]] bool hasDirectLink() const;
[[nodiscard]] ChannelId channelId() const;
[[nodiscard]] FullMsgId fullId() const {
return FullMsgId(channelId(), id);
}
[[nodiscard]] FullMsgId fullId() const;
[[nodiscard]] Data::MessagePosition position() const;
[[nodiscard]] TimeId date() const;

View File

@@ -236,8 +236,8 @@ bool HistoryMessageReply::updateData(
if (!replyToMsg) {
replyToMsg = holder->history()->owner().message(
(replyToPeerId
? peerToChannel(replyToPeerId)
: holder->channelId()),
? replyToPeerId
: holder->history()->peer->id),
replyToMsgId);
if (replyToMsg) {
if (replyToMsg->isEmpty()) {

View File

@@ -356,16 +356,15 @@ void RequestDependentMessageData(
const auto fullId = item->fullId();
const auto history = item->history();
const auto session = &history->session();
const auto done = [=] {
if (const auto item = session->data().message(fullId)) {
item->updateDependencyItem();
}
};
history->session().api().requestMessageData(
(peerIsChannel(peerId)
? history->owner().channel(peerToChannel(peerId)).get()
: history->peer->asChannel()),
(peerId ? history->owner().peer(peerId) : history->peer),
msgId,
[=](ChannelData *channel, MsgId msgId) {
if (const auto item = session->data().message(fullId)) {
item->updateDependencyItem();
}
});
done);
}
MessageFlags NewMessageFlags(not_null<PeerData*> peer) {
@@ -384,7 +383,7 @@ bool ShouldSendSilent(
MsgId LookupReplyToTop(not_null<History*> history, MsgId replyToId) {
const auto &owner = history->owner();
if (const auto item = owner.message(history->channelId(), replyToId)) {
if (const auto item = owner.message(history->peer, replyToId)) {
return item->replyToTop();
}
return 0;
@@ -977,25 +976,28 @@ bool HistoryMessage::areRepliesUnread() const {
FullMsgId HistoryMessage::commentsItemId() const {
if (const auto views = Get<HistoryMessageViews>()) {
return FullMsgId(views->commentsMegagroupId, views->commentsRootId);
return FullMsgId(
PeerId(views->commentsMegagroupId),
views->commentsRootId);
}
return FullMsgId();
}
void HistoryMessage::setCommentsItemId(FullMsgId id) {
if (id.channel == _history->channelId()) {
if (id.peer == _history->peer->id) {
if (id.msg != this->id) {
if (const auto reply = Get<HistoryMessageReply>()) {
reply->replyToMsgTop = id.msg;
}
}
return;
} else if (const auto views = Get<HistoryMessageViews>()) {
if (views->commentsMegagroupId != id.channel) {
views->commentsMegagroupId = id.channel;
history()->owner().requestItemResize(this);
if (const auto channelId = peerToChannel(id.peer)) {
if (views->commentsMegagroupId != channelId) {
views->commentsMegagroupId = channelId;
history()->owner().requestItemResize(this);
}
views->commentsRootId = id.msg;
}
views->commentsRootId = id.msg;
}
}
@@ -1966,13 +1968,11 @@ void HistoryMessage::changeReplyToTopCounter(
if (!isRegular() || !reply->replyToTop()) {
return;
}
const auto channelId = history()->channelId();
if (!channelId) {
const auto peerId = _history->peer->id;
if (!peerIsChannel(peerId)) {
return;
}
const auto top = history()->owner().message(
channelId,
reply->replyToTop());
const auto top = _history->owner().message(peerId, reply->replyToTop());
if (!top) {
return;
}

View File

@@ -605,8 +605,8 @@ bool HistoryService::updateDependent(bool force) {
if (!dependent->msg) {
dependent->msg = history()->owner().message(
(dependent->peerId
? peerToChannel(dependent->peerId)
: channelId()),
? dependent->peerId
: _history->peer->id),
dependent->msgId);
if (dependent->msg) {
if (dependent->msg->isEmpty()) {
@@ -1245,14 +1245,14 @@ HistoryService::PreparedText GenerateJoinedText(
if (inviter->id != history->session().userPeerId()) {
auto result = HistoryService::PreparedText{};
result.links.push_back(inviter->createOpenLink());
result.text = (history->isMegagroup()
result.text = (history->peer->isMegagroup()
? tr::lng_action_add_you_group
: tr::lng_action_add_you)(
tr::now,
lt_from,
textcmdLink(1, inviter->name));
return result;
} else if (history->isMegagroup()) {
} else if (history->peer->isMegagroup()) {
if (viaRequest) {
return { tr::lng_action_you_joined_by_request(tr::now) };
}

View File

@@ -777,7 +777,7 @@ HistoryWidget::HistoryWidget(
return (action.history == _history);
}) | rpl::start_with_next([=](const Api::SendAction &action) {
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
action.history->channelId(),
action.history->peer->id,
action.replyTo));
if (action.options.scheduled) {
cancelReply(lastKeyboardUsed);
@@ -1088,7 +1088,7 @@ void HistoryWidget::animatedScrollToItem(MsgId msgId) {
updateListSize();
}
auto to = session().data().message(_channel, msgId);
auto to = session().data().message(_history->peer, msgId);
if (_list->itemTop(to) < 0) {
return;
}
@@ -1767,18 +1767,22 @@ void HistoryWidget::setReplyReturns(PeerId peer, const QList<MsgId> &replyReturn
if (_replyReturns.isEmpty()) {
_replyReturn = nullptr;
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
_replyReturn = session().data().message(0, -_replyReturns.back());
_replyReturn = _migrated
? session().data().message(_migrated->peer, -_replyReturns.back())
: nullptr;
} else {
_replyReturn = session().data().message(_channel, _replyReturns.back());
_replyReturn = session().data().message(peer, _replyReturns.back());
}
while (!_replyReturns.isEmpty() && !_replyReturn) {
_replyReturns.pop_back();
if (_replyReturns.isEmpty()) {
_replyReturn = nullptr;
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
_replyReturn = session().data().message(0, -_replyReturns.back());
_replyReturn = _migrated
? session().data().message(_migrated->peer, -_replyReturns.back())
: nullptr;
} else {
_replyReturn = session().data().message(_channel, _replyReturns.back());
_replyReturn = session().data().message(peer, _replyReturns.back());
}
}
}
@@ -1790,9 +1794,13 @@ void HistoryWidget::calcNextReplyReturn() {
if (_replyReturns.isEmpty()) {
_replyReturn = nullptr;
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
_replyReturn = session().data().message(0, -_replyReturns.back());
_replyReturn = _migrated
? session().data().message(_migrated->peer, -_replyReturns.back())
: nullptr;
} else {
_replyReturn = session().data().message(_channel, _replyReturns.back());
_replyReturn = _peer
? session().data().message(_peer, _replyReturns.back())
: nullptr;
}
}
if (!_replyReturn) {
@@ -2026,7 +2034,6 @@ void HistoryWidget::showHistory(
setHistory(nullptr);
_list = nullptr;
_peer = nullptr;
_channel = NoChannel;
_canSendMessages = false;
_silent.destroy();
updateBotKeyboard();
@@ -2057,7 +2064,6 @@ void HistoryWidget::showHistory(
if (peerId) {
_peer = session().data().peer(peerId);
_channel = peerToChannel(_peer->id);
_canSendMessages = _peer->canWrite();
_contactStatus = std::make_unique<HistoryView::ContactStatus>(
controller(),
@@ -2110,7 +2116,7 @@ void HistoryWidget::showHistory(
refreshTopBarActiveChat();
updateTopBarSelection();
if (_channel) {
if (_peer->isChannel()) {
updateNotifyControls();
session().data().requestNotifySettings(_peer);
refreshSilentToggle();
@@ -2215,7 +2221,7 @@ void HistoryWidget::showHistory(
if (_history) {
controller()->setActiveChatEntry({
_history,
FullMsgId(_history->channelId(), _showAtMsgId) });
FullMsgId(_history->peer->id, _showAtMsgId) });
}
update();
controller()->floatPlayerAreaUpdated();
@@ -2949,7 +2955,7 @@ void HistoryWidget::firstLoadMessages() {
_history->getReadyFor(_showAtMsgId);
offset = -loadCount / 2;
offsetId = _showAtMsgId;
} else if (_showAtMsgId < 0 && _history->isChannel()) {
} else if (_showAtMsgId < 0 && _history->peer->isChannel()) {
if (_showAtMsgId < 0 && -_showAtMsgId < ServerMaxMsgId && _migrated) {
_history->getReadyFor(_showAtMsgId);
from = _migrated;
@@ -3120,7 +3126,7 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
} else if (_delayedShowAtMsgId > 0) {
offset = -loadCount / 2;
offsetId = _delayedShowAtMsgId;
} else if (_delayedShowAtMsgId < 0 && _history->isChannel()) {
} else if (_delayedShowAtMsgId < 0 && _history->peer->isChannel()) {
if (_delayedShowAtMsgId < 0 && -_delayedShowAtMsgId < ServerMaxMsgId && _migrated) {
from = _migrated;
offset = -loadCount / 2;
@@ -3307,7 +3313,7 @@ void HistoryWidget::showNextUnreadMention() {
// See https://github.com/telegramdesktop/tdesktop/issues/5623
if (msgId && already) {
const auto item = _history->owner().message(
_history->channelId(),
_history->peer->id,
msgId);
if (const auto media = item ? item->media() : nullptr) {
if (const auto document = media->document()) {
@@ -3329,7 +3335,7 @@ void HistoryWidget::saveEditMsg() {
return;
}
const auto item = session().data().message(_channel, _editMsgId);
const auto item = session().data().message(_history->peer, _editMsgId);
if (!item) {
cancelEdit();
return;
@@ -3643,7 +3649,7 @@ void HistoryWidget::setMsgId(MsgId showAtMsgId) {
if (_history) {
controller()->setActiveChatEntry({
_history,
FullMsgId(_history->channelId(), _showAtMsgId) });
FullMsgId(_history->peer->id, _showAtMsgId) });
}
}
}
@@ -3894,8 +3900,8 @@ void HistoryWidget::sendBotCommand(const Bot::SendCommandRequest &request) {
}
const auto lastKeyboardUsed = (_keyboard->forMsgId()
== FullMsgId(_channel, _history->lastKeyboardId))
&& (_keyboard->forMsgId() == FullMsgId(_channel, request.replyTo));
== FullMsgId(_peer->id, _history->lastKeyboardId))
&& (_keyboard->forMsgId() == FullMsgId(_peer->id, request.replyTo));
// 'bot' may be nullptr in case of sending from FieldAutocomplete.
const auto toSend = (request.replyTo/* || !bot*/)
@@ -3927,7 +3933,8 @@ void HistoryWidget::sendBotCommand(const Bot::SendCommandRequest &request) {
void HistoryWidget::hideSingleUseKeyboard(PeerData *peer, MsgId replyTo) {
if (!_peer || _peer != peer) return;
bool lastKeyboardUsed = (_keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard->forMsgId() == FullMsgId(_channel, replyTo));
bool lastKeyboardUsed = (_keyboard->forMsgId() == FullMsgId(_peer->id, _history->lastKeyboardId))
&& (_keyboard->forMsgId() == FullMsgId(_peer->id, replyTo));
if (replyTo) {
if (_replyToId == replyTo) {
cancelReply();
@@ -4181,7 +4188,11 @@ bool HistoryWidget::updateCmdStartShown() {
}
bool HistoryWidget::kbWasHidden() const {
return _history && (_keyboard->forMsgId() == FullMsgId(_history->channelId(), _history->lastKeyboardHiddenId));
return _history
&& (_keyboard->forMsgId()
== FullMsgId(
_history->peer->id,
_history->lastKeyboardHiddenId));
}
void HistoryWidget::toggleKeyboard(bool manual) {
@@ -5308,7 +5319,9 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) {
changed = _keyboard->updateMarkup(_replyEditMsg, force);
} else {
const auto keyboardItem = _history->lastKeyboardId
? session().data().message(_channel, _history->lastKeyboardId)
? session().data().message(
_history->peer,
_history->lastKeyboardId)
: nullptr;
changed = _keyboard->updateMarkup(keyboardItem, force);
}
@@ -5319,7 +5332,11 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) {
bool hasMarkup = _keyboard->hasMarkup(), forceReply = _keyboard->forceReply() && (!_replyToId || !_replyEditMsg);
if (hasMarkup || forceReply) {
if (_keyboard->singleUse() && _keyboard->hasMarkup() && _keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId) && _history->lastKeyboardUsed) {
if (_keyboard->singleUse()
&& _keyboard->hasMarkup()
&& (_keyboard->forMsgId()
== FullMsgId(_history->peer->id, _history->lastKeyboardId))
&& _history->lastKeyboardUsed) {
_history->lastKeyboardHiddenId = _history->lastKeyboardId;
}
if (!isBotStart() && !isBlocked() && _canSendMessages && (wasVisible || (_replyToId && _replyEditMsg) || (!HasSendText(_field) && !kbWasHidden()))) {
@@ -5391,8 +5408,8 @@ void HistoryWidget::botCallbackSent(not_null<HistoryItem*> item) {
}
const auto keyId = _keyboard->forMsgId();
const auto lastKeyboardUsed = (keyId == FullMsgId(_channel, item->id))
&& (keyId == FullMsgId(_channel, _history->lastKeyboardId));
const auto lastKeyboardUsed = (keyId == FullMsgId(_peer->id, item->id))
&& (keyId == FullMsgId(_peer->id, _history->lastKeyboardId));
session().data().requestItemRepaint(item);
@@ -5706,9 +5723,7 @@ bool HistoryWidget::replyToPreviousMessage() {
if (!_history || _editMsgId) {
return false;
}
const auto fullId = FullMsgId(
_history->channelId(),
_replyToId);
const auto fullId = FullMsgId(_history->peer->id, _replyToId);
if (const auto item = session().data().message(fullId)) {
if (const auto view = item->mainView()) {
if (const auto previousView = view->previousDisplayedInBlocks()) {
@@ -5731,9 +5746,7 @@ bool HistoryWidget::replyToNextMessage() {
if (!_history || _editMsgId) {
return false;
}
const auto fullId = FullMsgId(
_history->channelId(),
_replyToId);
const auto fullId = FullMsgId(_history->peer->id, _replyToId);
if (const auto item = session().data().message(fullId)) {
if (const auto view = item->mainView()) {
if (const auto nextView = view->nextDisplayedInBlocks()) {
@@ -5841,7 +5854,7 @@ void HistoryWidget::updatePinnedViewer() {
: (view->data()->id + (offset > 0 ? 1 : 0));
const auto lastClickedId = !_pinnedClickedId
? (ServerMaxMsgId - 1)
: (!_migrated || _pinnedClickedId.channel)
: (!_migrated || peerIsChannel(_pinnedClickedId.peer))
? _pinnedClickedId.msg
: (_pinnedClickedId.msg - ServerMaxMsgId);
if (_pinnedClickedId
@@ -5899,7 +5912,7 @@ void HistoryWidget::checkPinnedBarState() {
_migrated ? _migrated->peer.get() : nullptr);
const auto universalPinnedId = !currentPinnedId
? int32(0)
: (_migrated && !currentPinnedId.channel)
: (_migrated && !peerIsChannel(currentPinnedId.peer))
? (currentPinnedId.msg - ServerMaxMsgId)
: currentPinnedId.msg;
if (universalPinnedId == hiddenId) {
@@ -6046,7 +6059,7 @@ void HistoryWidget::refreshPinnedBarButton(bool many) {
controller()->showSection(
std::make_shared<HistoryView::PinnedMemento>(
_history,
((!_migrated || id.message.channel)
((!_migrated || peerIsChannel(id.message.peer))
? id.message.msg
: (id.message.msg - ServerMaxMsgId))));
}
@@ -6154,13 +6167,14 @@ void HistoryWidget::setupRequestsBar() {
}
void HistoryWidget::requestMessageData(MsgId msgId) {
const auto callback = [=](ChannelData *channel, MsgId msgId) {
messageDataReceived(channel, msgId);
};
session().api().requestMessageData(
_peer->asChannel(),
msgId,
crl::guard(this, callback));
if (!_peer) {
return;
}
const auto peer = _peer;
const auto callback = crl::guard(this, [=] {
messageDataReceived(peer, msgId);
});
session().api().requestMessageData(_peer, msgId, callback);
}
bool HistoryWidget::sendExistingDocument(
@@ -6437,17 +6451,17 @@ void HistoryWidget::hidePinnedMessage() {
}
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
if (replyTo.channel != _channel) {
return false;
}
return _keyboard->forceReply()
&& _keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)
return _peer
&& (replyTo.peer == _peer->id)
&& _keyboard->forceReply()
&& _keyboard->forMsgId() == FullMsgId(_peer->id, _history->lastKeyboardId)
&& _keyboard->forMsgId().msg == replyTo.msg;
}
bool HistoryWidget::lastForceReplyReplied() const {
return _keyboard->forceReply()
&& _keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)
return _peer
&& _keyboard->forceReply()
&& _keyboard->forMsgId() == FullMsgId(_peer->id, _history->lastKeyboardId)
&& _keyboard->forMsgId().msg == replyToId();
}
@@ -6536,9 +6550,7 @@ void HistoryWidget::cancelEdit() {
fieldChanged();
_textUpdateEvents = old;
if (!canWriteMessage()) {
updateControlsVisibility();
}
updateControlsVisibility();
updateBotKeyboard();
updateFieldPlaceholder();
@@ -6840,10 +6852,11 @@ void HistoryWidget::clearSelected() {
}
HistoryItem *HistoryWidget::getItemFromHistoryOrMigrated(MsgId genericMsgId) const {
if (genericMsgId < 0 && -genericMsgId < ServerMaxMsgId && _migrated) {
return session().data().message(_migrated->channelId(), -genericMsgId);
}
return session().data().message(_channel, genericMsgId);
return (genericMsgId < 0 && -genericMsgId < ServerMaxMsgId && _migrated)
? session().data().message(_migrated->peer, -genericMsgId)
: _peer
? session().data().message(_peer, genericMsgId)
: nullptr;
}
MessageIdsList HistoryWidget::getSelectedItems() const {
@@ -6906,11 +6919,12 @@ void HistoryWidget::updateTopBarSelection() {
update();
}
void HistoryWidget::messageDataReceived(ChannelData *channel, MsgId msgId) {
if (!_peer || _peer->asChannel() != channel || !msgId) {
void HistoryWidget::messageDataReceived(
not_null<PeerData*> peer,
MsgId msgId) {
if (!_peer || _peer != peer || !msgId) {
return;
}
if (_editMsgId == msgId || _replyToId == msgId) {
} else if (_editMsgId == msgId || _replyToId == msgId) {
updateReplyEditTexts(true);
}
}
@@ -6932,8 +6946,10 @@ void HistoryWidget::updateReplyEditTexts(bool force) {
return;
}
}
if (!_replyEditMsg) {
_replyEditMsg = session().data().message(_channel, _editMsgId ? _editMsgId : _replyToId);
if (!_replyEditMsg && _peer) {
_replyEditMsg = session().data().message(
_peer->id,
_editMsgId ? _editMsgId : _replyToId);
}
if (_replyEditMsg) {
updateReplyEditText(_replyEditMsg);

View File

@@ -369,7 +369,7 @@ private:
void refreshTopBarActiveChat();
void requestMessageData(MsgId msgId);
void messageDataReceived(ChannelData *channel, MsgId msgId);
void messageDataReceived(not_null<PeerData*> peer, MsgId msgId);
[[nodiscard]] Api::SendAction prepareSendAction(
Api::SendOptions options) const;
@@ -666,7 +666,6 @@ private:
PeerData *_peer = nullptr;
ChannelId _channel = NoChannel;
bool _canSendMessages = false;
MsgId _showAtMsgId = ShowAtUnreadMsgId;

View File

@@ -368,15 +368,14 @@ void FieldHeader::resolveMessageData() {
if (!id) {
return;
}
const auto channel = id.channel
? _data->channel(id.channel).get()
: nullptr;
const auto callback = [=](ChannelData *channel, MsgId msgId) {
const auto peer = _data->peer(id.peer);
const auto itemId = id.msg;
const auto callback = crl::guard(this, [=] {
const auto now = (isEditingMessage()
? _editMsgId
: _replyToId).current();
if (now == id && !_shownMessage) {
if (const auto message = _data->message(channel, msgId)) {
if (const auto message = _data->message(peer, itemId)) {
setShownMessage(message);
} else if (isEditingMessage()) {
_editCancelled.fire({});
@@ -384,11 +383,8 @@ void FieldHeader::resolveMessageData() {
_replyCancelled.fire({});
}
}
};
_data->session().api().requestMessageData(
channel,
id.msg,
crl::guard(this, callback));
});
_data->session().api().requestMessageData(peer, itemId, callback);
}
void FieldHeader::previewRequested(
@@ -1537,10 +1533,10 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) {
_previewSetState(draft->previewState);
if (draft == editDraft) {
_header->editMessage({ _history->channelId(), draft->msgId });
_header->editMessage({ _history->peer->id, draft->msgId });
_header->replyToMessage({});
} else {
_header->replyToMessage({ _history->channelId(), draft->msgId });
_header->replyToMessage({ _history->peer->id, draft->msgId });
_header->editMessage({});
}
}

View File

@@ -986,7 +986,7 @@ void CopyPostLink(
Assert(channel != nullptr);
if (const auto rootId = item->replyToTop()) {
const auto root = item->history()->owner().message(
peerToChannel(channel->id),
channel->id,
rootId);
const auto sender = root
? root->discussionPostOriginalSender()

View File

@@ -2318,7 +2318,9 @@ ClickHandlerPtr Message::rightActionLink() const {
const auto owner = &data()->history()->owner();
const auto itemId = data()->fullId();
const auto forwarded = data()->Get<HistoryMessageForwarded>();
const auto savedFromPeer = forwarded ? forwarded->savedFromPeer : nullptr;
const auto savedFromPeer = forwarded
? forwarded->savedFromPeer
: nullptr;
const auto savedFromMsgId = forwarded ? forwarded->savedFromMsgId : 0;
using Callback = FnMut<void(not_null<Window::SessionController*>)>;
@@ -2328,7 +2330,7 @@ ClickHandlerPtr Message::rightActionLink() const {
*showByThread = [=, requested = 0](
not_null<Window::SessionController*> controller) mutable {
const auto original = savedFromPeer->owner().message(
savedFromPeer->asChannel(),
savedFromPeer,
savedFromMsgId);
if (original && original->replyToTop()) {
controller->showRepliesForMessage(
@@ -2337,14 +2339,12 @@ ClickHandlerPtr Message::rightActionLink() const {
original->id,
Window::SectionShow::Way::Forward);
} else if (!requested) {
const auto channel = savedFromPeer->asChannel();
const auto prequested = &requested;
requested = 1;
channel->session().api().requestMessageData(
channel,
savedFromPeer->session().api().requestMessageData(
savedFromPeer,
savedFromMsgId,
[=, weak = base::make_weak(controller.get())](
ChannelData *gotChannel, MsgId gotId) {
[=, weak = base::make_weak(controller.get())] {
if (const auto strong = showByThreadWeak.lock()) {
if (const auto strongController = weak.get()) {
*prequested = 2;

View File

@@ -101,13 +101,9 @@ namespace {
consumer.put_next(Ui::MessageBarContent{
.text = { tr::lng_contacts_loading(tr::now) },
});
const auto channel = id.channel
? session->data().channel(id.channel).get()
: nullptr;
const auto callback = [=](ChannelData *channel, MsgId id) {
consumer.put_done();
};
session->api().requestMessageData(channel, id.msg, callback);
const auto peer = session->data().peer(id.peer);
const auto callback = [=] { consumer.put_done(); };
session->api().requestMessageData(peer, id.msg, callback);
return rpl::lifetime();
});
return std::move(

View File

@@ -64,9 +64,7 @@ PinnedMemento::PinnedMemento(
: _history(history)
, _highlightId(highlightId) {
_list.setAroundPosition({
.fullId = FullMsgId(
history->channelId(),
highlightId),
.fullId = FullMsgId(history->peer->id, highlightId),
.date = TimeId(0),
});
}
@@ -332,7 +330,7 @@ not_null<History*> PinnedWidget::history() const {
Dialogs::RowDescriptor PinnedWidget::activeChat() const {
return {
_history,
FullMsgId(_history->channelId(), ShowAtUnreadMsgId)
FullMsgId(_history->peer->id, ShowAtUnreadMsgId)
};
}
@@ -391,8 +389,8 @@ void PinnedWidget::restoreState(not_null<PinnedMemento*> memento) {
if (const auto highlight = memento->getHighlightId()) {
const auto position = Data::MessagePosition{
.fullId = ((highlight > 0 || !_migratedPeer)
? FullMsgId(_history->channelId(), highlight)
: FullMsgId(0, -highlight)),
? FullMsgId(_history->peer->id, highlight)
: FullMsgId(_migratedPeer->id, -highlight)),
.date = TimeId(0),
};
_inner->showAroundPosition(position, [=] {

View File

@@ -110,7 +110,7 @@ void PinnedTracker::refreshViewer() {
void PinnedTracker::refreshCurrentFromSlice() {
const auto proj1 = [](FullMsgId id) {
return id.channel ? id.msg : (id.msg - ServerMaxMsgId);
return peerIsChannel(id.peer) ? id.msg : (id.msg - ServerMaxMsgId);
};
const auto proj2 = [](FullMsgId id) {
return id.msg;

View File

@@ -90,11 +90,9 @@ rpl::producer<Ui::MessageBarContent> RootViewContent(
MsgId rootId) {
return MessageBarContentByItemId(
&history->session(),
FullMsgId{ history->channelId(), rootId }
FullMsgId(history->peer->id, rootId)
) | rpl::map([=](Ui::MessageBarContent &&content) {
const auto item = history->owner().message(
history->channelId(),
rootId);
const auto item = history->owner().message(history->peer, rootId);
if (!item) {
content.text = Ui::Text::Link(tr::lng_deleted_message(tr::now));
}
@@ -115,7 +113,7 @@ RepliesMemento::RepliesMemento(
if (commentId) {
_list.setAroundPosition({
.fullId = FullMsgId(
commentsItem->history()->channelId(),
commentsItem->history()->peer->id,
commentId),
.date = TimeId(0),
});
@@ -361,8 +359,7 @@ void RepliesWidget::sendReadTillRequest() {
void RepliesWidget::setupRoot() {
if (!_root) {
const auto channel = _history->peer->asChannel();
const auto done = crl::guard(this, [=](ChannelData*, MsgId) {
const auto done = crl::guard(this, [=] {
_root = lookupRoot();
if (_root) {
_areComments = computeAreComments();
@@ -374,7 +371,10 @@ void RepliesWidget::setupRoot() {
}
updatePinnedVisibility();
});
_history->session().api().requestMessageData(channel, _rootId, done);
_history->session().api().requestMessageData(
_history->peer,
_rootId,
done);
}
}
@@ -413,7 +413,7 @@ void RepliesWidget::setupRootView() {
}
HistoryItem *RepliesWidget::lookupRoot() const {
return _history->owner().message(_history->channelId(), _rootId);
return _history->owner().message(_history->peer, _rootId);
}
bool RepliesWidget::computeAreComments() const {
@@ -831,9 +831,7 @@ void RepliesWidget::restoreReplyReturns(const std::vector<MsgId> &list) {
void RepliesWidget::computeCurrentReplyReturn() {
_replyReturn = _replyReturns.empty()
? nullptr
: _history->owner().message(
_history->channelId(),
_replyReturns.back());
: _history->owner().message(_history->peer, _replyReturns.back());
}
void RepliesWidget::calculateNextReplyReturn() {
@@ -1408,7 +1406,7 @@ not_null<History*> RepliesWidget::history() const {
Dialogs::RowDescriptor RepliesWidget::activeChat() const {
return {
_history,
FullMsgId(_history->channelId(), ShowAtUnreadMsgId)
FullMsgId(_history->peer->id, ShowAtUnreadMsgId)
};
}
@@ -1478,10 +1476,7 @@ bool RepliesWidget::showMessage(
if (peerId != _history->peer->id) {
return false;
}
const auto id = FullMsgId{
_history->channelId(),
messageId
};
const auto id = FullMsgId(_history->peer->id, messageId);
const auto message = _history->owner().message(id);
if (!message || message->replyToTop() != _rootId) {
return false;
@@ -1558,7 +1553,7 @@ void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
_inner->restoreState(memento->list());
if (const auto highlight = memento->getHighlightId()) {
const auto position = Data::MessagePosition{
.fullId = FullMsgId(_history->channelId(), highlight),
.fullId = FullMsgId(_history->peer->id, highlight),
.date = TimeId(0),
};
_inner->showAroundPosition(position, [=] {

View File

@@ -905,7 +905,7 @@ not_null<History*> ScheduledWidget::history() const {
Dialogs::RowDescriptor ScheduledWidget::activeChat() const {
return {
_history,
FullMsgId(_history->channelId(), ShowAtUnreadMsgId)
FullMsgId(_history->peer->id, ShowAtUnreadMsgId)
};
}

View File

@@ -59,7 +59,7 @@ QString TimestampLinkBase(
FullMsgId context) {
return QString(
"media_timestamp?base=doc%1_%2_%3&t="
).arg(document->id).arg(context.channel.bare).arg(context.msg.bare);
).arg(document->id).arg(context.peer.value).arg(context.msg.bare);
}
TimeId DurationForTimestampLinks(not_null<WebPageData*> webpage) {

View File

@@ -71,8 +71,8 @@ rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource(
Expects(peer() != nullptr);
const auto isScheduled = [&] {
const auto channelId = peerToChannel(peer()->id);
if (const auto item = session().data().message(channelId, aroundId)) {
const auto peerId = peer()->id;
if (const auto item = session().data().message(peerId, aroundId)) {
return item->isScheduled();
}
return false;

View File

@@ -61,7 +61,7 @@ constexpr auto kPreloadedScreensCountFull
constexpr auto kMediaCountForSearch = 10;
UniversalMsgId GetUniversalId(FullMsgId itemId) {
return (itemId.channel != 0)
return peerIsChannel(itemId.peer)
? UniversalMsgId(itemId.msg)
: UniversalMsgId(itemId.msg - ServerMaxMsgId);
}
@@ -855,8 +855,10 @@ FullMsgId ListWidget::computeFullId(
Expects(universalId != 0);
return (universalId > 0)
? FullMsgId(peerToChannel(_peer->id), universalId)
: FullMsgId(NoChannel, ServerMaxMsgId + universalId);
? FullMsgId(_peer->id, universalId)
: FullMsgId(
(_migrated ? _migrated : _peer.get())->id,
ServerMaxMsgId + universalId);
}
auto ListWidget::collectSelectedItems() const -> SelectedItems {
@@ -964,9 +966,8 @@ bool ListWidget::isMyItem(not_null<const HistoryItem*> item) const {
}
bool ListWidget::isPossiblyMyId(FullMsgId fullId) const {
return fullId.channel
? (_peer->isChannel() && peerToChannel(_peer->id) == fullId.channel)
: (!_peer->isChannel() || _migrated);
return (fullId.peer == _peer->id)
|| (_migrated && fullId.peer == _migrated->id);
}
bool ListWidget::isItemLayout(

View File

@@ -1429,7 +1429,7 @@ void MainWidget::ui_showPeerHistory(
if (const auto history = _history->history()) {
_dialogs->scrollToEntry(Dialogs::RowDescriptor(
history,
FullMsgId(history->channelId(), showAtMsgId)));
FullMsgId(history->peer->id, showAtMsgId)));
}
}
_dialogs->update();

View File

@@ -386,7 +386,7 @@ auto Instance::playlistKey(not_null<const Data*> data) const
return {};
}
const auto universalId = (contextId.channel == history->channelId())
const auto universalId = (contextId.peer == history->peer->id)
? contextId.msg
: (contextId.msg - ServerMaxMsgId);
return SliceKey(
@@ -506,9 +506,9 @@ bool Instance::moveInPlaylist(
}
const auto universal = computeCurrentUniversalId(data);
const auto byUniversal = [&](ShuffleData::UniversalMsgId id) {
return (id < 0)
? jumpById({ ChannelId(), id + ServerMaxMsgId })
: jumpById({ raw->history->channelId(), id });
return (id < 0 && raw->migrated)
? jumpById({ raw->migrated->peer->id, id + ServerMaxMsgId })
: jumpById({ raw->history->peer->id, id });
};
if (universal && raw->indexInPlayedIds == raw->playedIds.size()) {
raw->playedIds.push_back(universal);
@@ -906,12 +906,12 @@ void Instance::validateShuffleData(not_null<Data*> data) {
raw->nextSliceLifetime.destroy();
const auto size = update.size();
const auto channel = raw->history->channelId();
const auto peer = raw->history->peer->id;
raw->playlist.reserve(raw->playlist.size() + size);
raw->nonPlayedIds.reserve(raw->nonPlayedIds.size() + size);
for (auto i = size; i != 0;) {
const auto fullId = update[--i];
const auto universal = (fullId.channel == channel)
const auto universal = (fullId.peer == peer)
? fullId.msg
: (fullId.msg - ServerMaxMsgId);
if (raw->playlist.empty() || raw->playlist.back() > universal) {

View File

@@ -4742,7 +4742,7 @@ void OverlayWidget::updateHeader() {
_headerText = tr::lng_mediaview_single_photo(tr::now);
} else if (_user) {
_headerText = tr::lng_mediaview_profile_photo(tr::now);
} else if ((_history && _history->channelId() && !_history->isMegagroup())
} else if ((_history && _history->peer->isBroadcast())
|| (_peer && _peer->isChannel() && !_peer->isMegagroup())) {
_headerText = tr::lng_mediaview_channel_photo(tr::now);
} else if (_peer) {

View File

@@ -11,42 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace MTP::details {
namespace {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
// This is a key setter for compatibility with OpenSSL 1.0
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
if ((r->n == nullptr && n == nullptr) || (r->e == nullptr && e == nullptr)) {
return 0;
}
if (n != nullptr) {
BN_free(r->n);
r->n = n;
}
if (e != nullptr) {
BN_free(r->e);
r->e = e;
}
if (d != nullptr) {
BN_free(r->d);
r->d = d;
}
return 1;
}
// This is a key getter for compatibility with OpenSSL 1.0
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) {
if (n != nullptr) {
*n = r->n;
}
if (e != nullptr) {
*e = r->e;
}
if (d != nullptr) {
*d = r->d;
}
}
#endif
enum class Format {
RSAPublicKey,
@@ -168,7 +132,7 @@ bytes::vector RSAPublicKey::Private::encrypt(bytes::const_span data) const {
auto result = bytes::vector(kEncryptSize, gsl::byte{});
auto res = RSA_public_encrypt(kEncryptSize, reinterpret_cast<const unsigned char*>(data.data()), reinterpret_cast<unsigned char*>(result.data()), _rsa, RSA_NO_PADDING);
if (res < 0 || res > kEncryptSize) {
ERR_load_crypto_strings();
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nullptr);
LOG(("RSA Error: RSA_public_encrypt failed, key fp: %1, result: %2, error: %3").arg(fingerprint()).arg(res).arg(ERR_error_string(ERR_get_error(), 0)));
return {};
} else if (auto zeroBytes = kEncryptSize - res) {
@@ -186,7 +150,7 @@ bytes::vector RSAPublicKey::Private::decrypt(bytes::const_span data) const {
auto result = bytes::vector(kDecryptSize, gsl::byte{});
auto res = RSA_public_decrypt(kDecryptSize, reinterpret_cast<const unsigned char*>(data.data()), reinterpret_cast<unsigned char*>(result.data()), _rsa, RSA_NO_PADDING);
if (res < 0 || res > kDecryptSize) {
ERR_load_crypto_strings();
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nullptr);
LOG(("RSA Error: RSA_public_encrypt failed, key fp: %1, result: %2, error: %3").arg(fingerprint()).arg(res).arg(ERR_error_string(ERR_get_error(), 0)));
return {};
} else if (auto zeroBytes = kDecryptSize - res) {
@@ -209,7 +173,7 @@ bytes::vector RSAPublicKey::Private::encryptOAEPpadding(bytes::const_span data)
_rsa,
RSA_PKCS1_OAEP_PADDING);
if (encryptedSize != resultSize) {
ERR_load_crypto_strings();
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, nullptr);
LOG(("RSA Error: RSA_public_encrypt failed, "
"key fp: %1, result: %2, error: %3"
).arg(fingerprint()

View File

@@ -1592,7 +1592,7 @@ void FormController::uploadEncryptedFile(
prepared->filemd5 = file.uploadData->md5checksum;
file.uploadData->fullId = FullMsgId(
0,
session().userPeerId(),
session().data().nextLocalMessageId());
file.uploadData->status.set(LoadStatus::Status::InProgress, 0);
session().uploader().upload(

View File

@@ -69,7 +69,7 @@ void CheckoutProcess::Start(
return;
}
const auto id = (invoice && invoice->receiptMsgId)
? FullMsgId(item->history()->channelId(), invoice->receiptMsgId)
? FullMsgId(item->history()->peer->id, invoice->receiptMsgId)
: item->fullId();
if (invoice) {
mode = invoice->receiptMsgId ? Mode::Receipt : Mode::Payment;

View File

@@ -147,7 +147,7 @@ Form::Form(not_null<PeerData*> peer, MsgId itemId, bool receipt)
Form::~Form() = default;
void Form::fillInvoiceFromMessage() {
const auto id = FullMsgId(peerToChannel(_peer->id), _msgId);
const auto id = FullMsgId(_peer->id, _msgId);
if (const auto item = _session->data().message(id)) {
const auto media = [&] {
if (const auto payment = item->Get<HistoryServicePayment>()) {
@@ -194,9 +194,7 @@ void Form::loadThumbnail(not_null<PhotoData*> photo) {
_invoice.cover.thumbnail = prepareEmptyThumbnail();
}
_thumbnailLoadProcess->view = std::move(view);
photo->load(
Data::PhotoSize::Thumbnail,
FullMsgId(peerToChannel(_peer->id), _msgId));
photo->load(Data::PhotoSize::Thumbnail, FullMsgId(_peer->id, _msgId));
_session->downloaderTaskFinished(
) | rpl::start_with_next([=] {
const auto &view = _thumbnailLoadProcess->view;

View File

@@ -94,7 +94,7 @@ void XCBSkipTaskbar(QWindow *window, bool skip) {
return;
}
const auto root = base::Platform::XCB::GetRootWindowFromQt();
const auto root = base::Platform::XCB::GetRootWindow(connection);
if (!root.has_value()) {
return;
}

View File

@@ -32,7 +32,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QApplication>
#include <QtGui/QWindow>
#include <QtGui/QScreen>
#include <qpa/qplatformnativeinterface.h>
#include <Shobjidl.h>
#include <shellapi.h>
@@ -429,11 +428,7 @@ void MainWindow::updateIconCounters() {
}
void MainWindow::initHook() {
if (const auto native = QGuiApplication::platformNativeInterface()) {
ps_hWnd = static_cast<HWND>(native->nativeResourceForWindow(
QByteArrayLiteral("handle"),
windowHandle()));
}
ps_hWnd = reinterpret_cast<HWND>(winId());
if (!ps_hWnd) {
return;
}

View File

@@ -31,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QDesktopWidget>
#include <QtGui/QDesktopServices>
#include <QtGui/QWindow>
#include <qpa/qplatformnativeinterface.h>
#include <Shobjidl.h>
#include <ShObjIdl_core.h>

View File

@@ -964,7 +964,9 @@ int MainWindow::tryToExtendWidthBy(int addToWidth) {
void MainWindow::launchDrag(
std::unique_ptr<QMimeData> data,
Fn<void()> &&callback) {
auto drag = std::make_unique<QDrag>(this);
// Qt destroys this QDrag automatically after the drag is finished
// We must not delete this at the end of this function, as this breaks DnD on Linux
auto drag = new QDrag(this);
drag->setMimeData(data.release());
drag->exec(Qt::CopyAction);

View File

@@ -296,9 +296,7 @@ void System::checkDelayed() {
}
}
if (loaded) {
const auto fullId = FullMsgId(
history->channelId(),
i->second.msg);
const auto fullId = FullMsgId(history->peer->id, i->second.msg);
if (const auto item = peer->owner().message(fullId)) {
if (!item->notificationReady()) {
loaded = false;
@@ -677,9 +675,7 @@ void Manager::openNotificationMessage(
if (history->peer->isUser() || history->peer->isChannel()) {
return false;
}
const auto item = history->owner().message(
history->channelId(),
messageId);
const auto item = history->owner().message(history->peer, messageId);
if (!item || !item->isRegular() || !item->mentionsMe()) {
return false;
}
@@ -714,9 +710,7 @@ void Manager::notificationReplied(
message.action.clearDraft = false;
history->session().api().sendMessage(std::move(message));
const auto item = history->owner().message(
history->channelId(),
id.msgId);
const auto item = history->owner().message(history->peer, id.msgId);
if (item && item->isUnreadMention() && !item->isUnreadMedia()) {
history->session().api().markMediaRead(item);
}

View File

@@ -602,7 +602,9 @@ void ChatBackground::checkUploadWallPaper() {
const auto ready = PrepareWallPaper(_session->mainDcId(), _original);
const auto documentId = ready.id;
_wallPaperUploadId = FullMsgId(0, _session->data().nextLocalMessageId());
_wallPaperUploadId = FullMsgId(
_session->userPeerId(),
_session->data().nextLocalMessageId());
_session->uploader().uploadMedia(_wallPaperUploadId, ready);
if (_wallPaperUploadLifetime) {
return;

View File

@@ -479,7 +479,7 @@ Fn<void()> SavePreparedTheme(
const auto api = &session->api();
const auto state = std::make_shared<State>();
state->id = FullMsgId(
0,
session->userPeerId(),
session->data().nextLocalMessageId());
const auto creating = !fields.id

View File

@@ -1153,8 +1153,8 @@ void HidePinnedBar(
const auto migrated = peer->migrateFrom();
const auto top = Data::ResolveTopPinnedId(peer, migrated);
const auto universal = !top
? int32(0)
: (migrated && !top.channel)
? MsgId(0)
: (migrated && !peerIsChannel(top.peer))
? (top.msg - ServerMaxMsgId)
: top.msg;
if (universal) {

View File

@@ -376,8 +376,8 @@ void SessionNavigation::showRepliesForMessage(
}
_session->api().request(base::take(_showingRepliesRequestId)).cancel();
const auto channelId = history->channelId();
//const auto item = _session->data().message(channelId, rootId);
const auto postPeer = history->peer;
//const auto item = _session->data().message(postPeer, rootId);
//if (!commentId && (!item || !item->repliesAreComments())) {
// showSection(std::make_shared<HistoryView::RepliesMemento>(history, rootId));
// return;
@@ -411,9 +411,7 @@ void SessionNavigation::showRepliesForMessage(
if (!peer || !id) {
return;
}
auto item = _session->data().message(
peerToChannel(peer),
id);
auto item = _session->data().message(peer, id);
if (const auto group = _session->data().groups().find(item)) {
item = group->items.front();
}
@@ -426,8 +424,8 @@ void SessionNavigation::showRepliesForMessage(
data.vunread_count().v);
item->setRepliesOutboxReadTill(
data.vread_outbox_max_id().value_or_empty());
const auto post = _session->data().message(channelId, rootId);
if (post && item->history()->channelId() != channelId) {
const auto post = _session->data().message(postPeer, rootId);
if (post && item->history()->peer != postPeer) {
post->setCommentsItemId(item->fullId());
if (const auto maxId = data.vmax_id()) {
post->setRepliesMaxId(maxId->v);

1
Telegram/ThirdParty/dispatch vendored Submodule

1
Telegram/ThirdParty/kwayland vendored Submodule

View File

@@ -9,9 +9,9 @@ ENV QT5_VER 5_15_2
ENV QT5_TAG v5.15.2
ENV QT5_PREFIX /usr/local/desktop-app/Qt-5.15.2
ENV Qt5_DIR ${QT5_PREFIX}
ENV QT6_VER 6_2_0
ENV QT6_TAG v6.2.0
ENV QT6_PREFIX /usr/local/desktop-app/Qt-6.2.0
ENV QT6_VER 6_2_2
ENV QT6_TAG v6.2.2
ENV QT6_PREFIX /usr/local/desktop-app/Qt-6.2.2
ENV Qt6_DIR ${QT6_PREFIX}
ENV OPENSSL_VER 1_1_1
ENV OPENSSL_PREFIX /usr/local/desktop-app/openssl-1.1.1
@@ -19,12 +19,14 @@ ENV OPENSSL_ROOT_DIR ${OPENSSL_PREFIX}
ENV CMAKE_VER 3.21.3
ENV CMAKE_FILE cmake-$CMAKE_VER-Linux-x86_64.sh
ENV PATH ${PATH}:${QT5_PREFIX}/bin:${QT6_PREFIX}/bin
ENV HFLAGS_DEBUG "-fstack-protector-all -fstack-clash-protection -fPIC"
ENV HFLAGS "$HFLAGS_DEBUG -D_FORTIFY_SOURCE=2"
RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && yum clean all
RUN yum -y install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm && yum clean all
RUN yum -y install centos-release-scl && yum clean all
RUN yum -y install git meson ninja-build autoconf automake libtool \
RUN yum -y install git meson ninja-build autoconf automake libtool patch \
fontconfig-devel freetype-devel libX11-devel at-spi2-core-devel alsa-lib-devel \
pulseaudio-libs-devel mesa-libGL-devel mesa-libEGL-devel gtk3-devel \
perl-XML-Parser pkgconfig bison yasm file which xorg-x11-util-macros \
@@ -32,11 +34,12 @@ RUN yum -y install git meson ninja-build autoconf automake libtool \
devtoolset-10-binutils llvm-toolset-7.0 llvm-toolset-7.0-clang-devel \
llvm-toolset-7.0-llvm-devel && yum clean all
# Fix a bug with argument naming in CentOS 7 glibc
RUN sed -i 's/char \*__block/char */' /usr/include/unistd.h
SHELL [ "bash", "-c", ". /opt/rh/devtoolset-10/enable; exec bash -c \"$@\"", "-s"]
ENV LibrariesPath /usr/src/Libraries
ENV HFLAGS_DEBUG "-fstack-protector-all -fstack-clash-protection -fPIC"
ENV HFLAGS "$HFLAGS_DEBUG -D_FORTIFY_SOURCE=2"
WORKDIR $LibrariesPath
RUN mkdir /opt/cmake
@@ -46,7 +49,7 @@ RUN ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake
RUN rm $CMAKE_FILE
FROM builder AS patches
RUN git clone $GIT/desktop-app/patches.git && cd patches && git checkout b6c29e99da
RUN git clone $GIT/desktop-app/patches.git && cd patches && git checkout 5368789dc7
FROM builder AS extra-cmake-modules
@@ -766,38 +769,6 @@ RUN [ -z "${QT6}" ] || DESTDIR="$LibrariesPath/qt-cache" cmake --install .
WORKDIR ..
RUN [ -z "${QT6}" ] || rm -rf qt_${QT6_VER}
FROM patches AS kwayland
ARG QT6
COPY --from=extra-cmake-modules ${LibrariesPath}/extra-cmake-modules-cache /
COPY --from=libffi ${LibrariesPath}/libffi-cache /
COPY --from=zlib ${LibrariesPath}/zlib-cache /
COPY --from=libproxy ${LibrariesPath}/libproxy-cache /
COPY --from=mozjpeg ${LibrariesPath}/mozjpeg-cache /
COPY --from=xcb ${LibrariesPath}/xcb-cache /
COPY --from=xcb-wm ${LibrariesPath}/xcb-wm-cache /
COPY --from=xcb-util ${LibrariesPath}/xcb-util-cache /
COPY --from=xcb-image ${LibrariesPath}/xcb-image-cache /
COPY --from=xcb-keysyms ${LibrariesPath}/xcb-keysyms-cache /
COPY --from=xcb-render-util ${LibrariesPath}/xcb-render-util-cache /
COPY --from=wayland ${LibrariesPath}/wayland-cache /
COPY --from=wayland-protocols ${LibrariesPath}/wayland-protocols-cache /
COPY --from=plasma-wayland-protocols ${LibrariesPath}/plasma-wayland-protocols-cache /
COPY --from=openssl ${LibrariesPath}/openssl-cache /
COPY --from=xkbcommon ${LibrariesPath}/xkbcommon-cache /
COPY --from=qt ${LibrariesPath}/qt-cache /
RUN git clone -b v5.87.0 --depth=1 $GIT/KDE/kwayland.git
WORKDIR kwayland
RUN [ -z "${QT6}" ] || git apply ../patches/kwayland-qt6.patch
RUN cmake -GNinja -B build . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF
RUN cmake --build build --target KF5WaylandClient --parallel
RUN DESTDIR="$LibrariesPath/kwayland-cache" cmake --install build/src/client
WORKDIR ..
RUN rm -rf kwayland
FROM patches AS breakpad
RUN git clone https://chromium.googlesource.com/breakpad/breakpad.git
@@ -880,6 +851,8 @@ COPY --from=libXrender ${LibrariesPath}/libXrender-cache /
COPY --from=libXdamage ${LibrariesPath}/libXdamage-cache /
COPY --from=libXcomposite ${LibrariesPath}/libXcomposite-cache /
COPY --from=wayland ${LibrariesPath}/wayland-cache /
COPY --from=wayland-protocols ${LibrariesPath}/wayland-protocols-cache /
COPY --from=plasma-wayland-protocols ${LibrariesPath}/plasma-wayland-protocols-cache /
COPY --from=libpciaccess ${LibrariesPath}/libpciaccess-cache /
COPY --from=drm ${LibrariesPath}/drm-cache /
COPY --from=libva ${LibrariesPath}/libva-cache /
@@ -892,7 +865,6 @@ COPY --from=xkbcommon ${LibrariesPath}/xkbcommon-cache /
COPY --from=libsigcplusplus ${LibrariesPath}/libsigcplusplus-cache /
COPY --from=glibmm ${LibrariesPath}/glibmm-cache /
COPY --from=qt ${LibrariesPath}/qt-cache /
COPY --from=kwayland ${LibrariesPath}/kwayland-cache /
COPY --from=breakpad ${LibrariesPath}/breakpad breakpad
COPY --from=breakpad ${LibrariesPath}/breakpad-cache /
COPY --from=webrtc ${LibrariesPath}/tg_owt tg_owt

Some files were not shown because too many files have changed in this diff Show More