Allocate 64 bits for message ids.

This commit is contained in:
John Preston 2021-09-30 10:04:55 +04:00
parent 6adf791b3b
commit 1e660fc2a2
29 changed files with 337 additions and 162 deletions

View file

@ -415,6 +415,7 @@ PRIVATE
data/data_media_types.h data/data_media_types.h
data/data_messages.cpp data/data_messages.cpp
data/data_messages.h data/data_messages.h
data/data_msg_id.h
data/data_notify_settings.cpp data/data_notify_settings.cpp
data/data_notify_settings.h data/data_notify_settings.h
data/data_peer.cpp data/data_peer.cpp

View file

@ -662,8 +662,8 @@ QString ApiWrap::exportDirectMessageLink(
const auto fallback = [&] { const auto fallback = [&] {
auto linkChannel = channel; auto linkChannel = channel;
auto linkItemId = item->id; auto linkItemId = item->id;
auto linkCommentId = 0; auto linkCommentId = MsgId();
auto linkThreadId = 0; auto linkThreadId = MsgId();
if (inRepliesContext) { if (inRepliesContext) {
if (const auto rootId = item->replyToTop()) { if (const auto rootId = item->replyToTop()) {
const auto root = item->history()->owner().message( const auto root = item->history()->owner().message(
@ -693,11 +693,11 @@ QString ApiWrap::exportDirectMessageLink(
: "c/" + QString::number(peerToChannel(linkChannel->id).bare); : "c/" + QString::number(peerToChannel(linkChannel->id).bare);
const auto query = base const auto query = base
+ '/' + '/'
+ QString::number(linkItemId) + QString::number(linkItemId.bare)
+ (linkCommentId + (linkCommentId
? "?comment=" + QString::number(linkCommentId) ? "?comment=" + QString::number(linkCommentId.bare)
: linkThreadId : linkThreadId
? "?thread=" + QString::number(linkThreadId) ? "?thread=" + QString::number(linkThreadId.bare)
: ""); : "");
if (linkChannel->hasUsername() if (linkChannel->hasUsername()
&& !linkChannel->isMegagroup() && !linkChannel->isMegagroup()

View file

@ -288,7 +288,6 @@ bool ServiceCheck::checkRippleStartPosition(QPoint position) const {
bool out) { bool out) {
Expects(history->peer->isUser()); Expects(history->peer->isUser());
static auto id = ServerMaxMsgId + (ServerMaxMsgId / 3);
const auto flags = MessageFlag::FakeHistoryItem const auto flags = MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId | MessageFlag::HasFromId
| (out ? MessageFlag::Outgoing : MessageFlag(0)); | (out ? MessageFlag::Outgoing : MessageFlag(0));
@ -296,7 +295,7 @@ bool ServiceCheck::checkRippleStartPosition(QPoint position) const {
const auto viaBotId = UserId(); const auto viaBotId = UserId();
const auto groupedId = uint64(); const auto groupedId = uint64();
const auto item = history->makeMessage( const auto item = history->makeMessage(
++id, history->owner().nextNonHistoryEntryId(),
flags, flags,
replyTo, replyTo,
viaBotId, viaBotId,

View file

@ -1113,7 +1113,7 @@ QString AppendShareGameScoreUrl(
auto channelAccessHash = uint64(channel ? channel->access : 0); auto channelAccessHash = uint64(channel ? channel->access : 0);
shareHashDataInts[0] = session->userId().bare; shareHashDataInts[0] = session->userId().bare;
shareHashDataInts[1] = fullId.channel.bare; shareHashDataInts[1] = fullId.channel.bare;
shareHashDataInts[2] = fullId.msg; shareHashDataInts[2] = uint64(fullId.msg.bare);
shareHashDataInts[3] = channelAccessHash; shareHashDataInts[3] = channelAccessHash;
// Count SHA1() of data. // Count SHA1() of data.
@ -1200,7 +1200,6 @@ void ShareGameScoreByHash(
//} //}
if (((hashDataInts[1] >> 40) != 0) if (((hashDataInts[1] >> 40) != 0)
|| ((hashDataInts[2] >> 32) != 0)
|| (!hashDataInts[1] && channelAccessHash)) { || (!hashDataInts[1] && channelAccessHash)) {
// If there is no channel id, there should be no channel access_hash. // If there is no channel id, there should be no channel access_hash.
Ui::show(Box<InformBox>(tr::lng_share_wrong_user(tr::now))); Ui::show(Box<InformBox>(tr::lng_share_wrong_user(tr::now)));
@ -1208,7 +1207,7 @@ void ShareGameScoreByHash(
} }
auto channelId = ChannelId(hashDataInts[1]); auto channelId = ChannelId(hashDataInts[1]);
auto msgId = MsgId(hashDataInts[2]); auto msgId = MsgId(int64(hashDataInts[2]));
if (const auto item = session->data().message(channelId, msgId)) { if (const auto item = session->data().message(channelId, msgId)) {
FastShareMessage(item); FastShareMessage(item);
} else { } else {

View file

@ -141,7 +141,7 @@ private:
}; };
BoxController::Row::Row(not_null<HistoryItem*> item) BoxController::Row::Row(not_null<HistoryItem*> item)
: PeerListRow(item->history()->peer, item->id) : PeerListRow(item->history()->peer, item->id.bare)
, _items(1, item) , _items(1, item)
, _date(ItemDateTime(item).date()) , _date(ItemDateTime(item).date())
, _type(ComputeType(item)) , _type(ComputeType(item))

View file

@ -16,7 +16,7 @@ struct SendCommandRequest {
not_null<PeerData*> peer; not_null<PeerData*> peer;
QString command; QString command;
FullMsgId context; FullMsgId context;
int replyTo = 0; MsgId replyTo = 0;
}; };
[[nodiscard]] QString WrapCommandInChat( [[nodiscard]] QString WrapCommandInChat(

View file

@ -19,6 +19,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data { namespace Data {
DraftKey DraftKey::FromSerializedOld(int32 value) {
return !value
? DraftKey::None()
: (value == kLocalDraftIndex + kEditDraftShiftOld)
? DraftKey::LocalEdit()
: (value == kScheduledDraftIndex + kEditDraftShiftOld)
? DraftKey::ScheduledEdit()
: (value > 0 && value < 0x4000'0000)
? DraftKey::Replies(int64(value))
: (value > kEditDraftShiftOld
&& value < kEditDraftShiftOld + 0x4000'000)
? DraftKey::RepliesEdit(int64(value - kEditDraftShiftOld))
: DraftKey::None();
}
Draft::Draft( Draft::Draft(
const TextWithTags &textWithTags, const TextWithTags &textWithTags,
MsgId msgId, MsgId msgId,

View file

@ -75,19 +75,21 @@ public:
return kScheduledDraftIndex + kEditDraftShift; return kScheduledDraftIndex + kEditDraftShift;
} }
[[nodiscard]] static DraftKey Replies(MsgId rootId) { [[nodiscard]] static DraftKey Replies(MsgId rootId) {
return rootId; return rootId.bare;
} }
[[nodiscard]] static DraftKey RepliesEdit(MsgId rootId) { [[nodiscard]] static DraftKey RepliesEdit(MsgId rootId) {
return rootId + kEditDraftShift; return rootId.bare + kEditDraftShift;
} }
[[nodiscard]] static DraftKey FromSerialized(int32 value) { [[nodiscard]] static DraftKey FromSerialized(qint64 value) {
return value; return value;
} }
[[nodiscard]] int32 serialize() const { [[nodiscard]] qint64 serialize() const {
return _value; return _value;
} }
[[nodiscard]] static DraftKey FromSerializedOld(int32 value);
inline bool operator<(const DraftKey &other) const { inline bool operator<(const DraftKey &other) const {
return _value < other._value; return _value < other._value;
} }
@ -111,15 +113,16 @@ public:
} }
private: private:
DraftKey(int value) : _value(value) { DraftKey(int64 value) : _value(value) {
} }
static constexpr auto kLocalDraftIndex = -1; static constexpr auto kLocalDraftIndex = -1;
static constexpr auto kCloudDraftIndex = -2; static constexpr auto kCloudDraftIndex = -2;
static constexpr auto kScheduledDraftIndex = -3; static constexpr auto kScheduledDraftIndex = -3;
static constexpr auto kEditDraftShift = ServerMaxMsgId; static constexpr auto kEditDraftShift = ServerMaxMsgId.bare;
static constexpr auto kEditDraftShiftOld = 0x3FFF'FFFF;
int _value = 0; int64 _value = 0;
}; };

View file

@ -72,13 +72,13 @@ void Histories::readInbox(not_null<History*> history) {
if (history->lastServerMessageKnown()) { if (history->lastServerMessageKnown()) {
const auto last = history->lastServerMessage(); const auto last = history->lastServerMessage();
DEBUG_LOG(("Reading: last known, reading till %1." DEBUG_LOG(("Reading: last known, reading till %1."
).arg(last ? last->id : 0)); ).arg(last ? last->id.bare : 0));
readInboxTill(history, last ? last->id : 0); readInboxTill(history, last ? last->id : 0);
return; return;
} else if (history->loadedAtBottom()) { } else if (history->loadedAtBottom()) {
if (const auto lastId = history->maxMsgId()) { if (const auto lastId = history->maxMsgId()) {
DEBUG_LOG(("Reading: loaded at bottom, maxMsgId %1." DEBUG_LOG(("Reading: loaded at bottom, maxMsgId %1."
).arg(lastId)); ).arg(lastId.bare));
readInboxTill(history, lastId); readInboxTill(history, lastId);
return; return;
} else if (history->loadedAtTop()) { } else if (history->loadedAtTop()) {
@ -93,7 +93,7 @@ void Histories::readInbox(not_null<History*> history) {
const auto last = history->lastServerMessage(); const auto last = history->lastServerMessage();
DEBUG_LOG(("Reading: got entry, reading till %1." DEBUG_LOG(("Reading: got entry, reading till %1."
).arg(last ? last->id : 0)); ).arg(last ? last->id.bare : 0));
readInboxTill(history, last ? last->id : 0); readInboxTill(history, last ? last->id : 0);
}); });
} }
@ -147,7 +147,7 @@ void Histories::readInboxTill(
Expects(IsServerMsgId(tillId) || (!tillId && !force)); Expects(IsServerMsgId(tillId) || (!tillId && !force));
DEBUG_LOG(("Reading: readInboxTill %1, force %2." DEBUG_LOG(("Reading: readInboxTill %1, force %2."
).arg(tillId ).arg(tillId.bare
).arg(Logs::b(force))); ).arg(Logs::b(force)));
const auto syncGuard = gsl::finally([&] { const auto syncGuard = gsl::finally([&] {
@ -156,8 +156,8 @@ void Histories::readInboxTill(
if (history->unreadCount() > 0) { if (history->unreadCount() > 0) {
if (const auto last = history->lastServerMessage()) { if (const auto last = history->lastServerMessage()) {
DEBUG_LOG(("Reading: checking last %1 and %2." DEBUG_LOG(("Reading: checking last %1 and %2."
).arg(last->id ).arg(last->id.bare
).arg(tillId)); ).arg(tillId.bare));
if (last->id == tillId) { if (last->id == tillId) {
DEBUG_LOG(("Reading: locally marked as read.")); DEBUG_LOG(("Reading: locally marked as read."));
history->setUnreadCount(0); history->setUnreadCount(0);
@ -180,11 +180,11 @@ void Histories::readInboxTill(
const auto maybeState = lookup(history); const auto maybeState = lookup(history);
if (maybeState && maybeState->sentReadTill >= tillId) { if (maybeState && maybeState->sentReadTill >= tillId) {
DEBUG_LOG(("Reading: readInboxTill finish 3 with %1." DEBUG_LOG(("Reading: readInboxTill finish 3 with %1."
).arg(maybeState->sentReadTill)); ).arg(maybeState->sentReadTill.bare));
return; return;
} else if (maybeState && maybeState->willReadTill >= tillId) { } else if (maybeState && maybeState->willReadTill >= tillId) {
DEBUG_LOG(("Reading: readInboxTill finish 4 with %1 and force %2." DEBUG_LOG(("Reading: readInboxTill finish 4 with %1 and force %2."
).arg(maybeState->sentReadTill ).arg(maybeState->sentReadTill.bare
).arg(Logs::b(force))); ).arg(Logs::b(force)));
if (force) { if (force) {
sendPendingReadInbox(history); sendPendingReadInbox(history);
@ -200,7 +200,7 @@ void Histories::readInboxTill(
&& history->unreadCountKnown() && history->unreadCountKnown()
&& *stillUnread == history->unreadCount()) { && *stillUnread == history->unreadCount()) {
DEBUG_LOG(("Reading: count didn't change so just update till %1" DEBUG_LOG(("Reading: count didn't change so just update till %1"
).arg(tillId)); ).arg(tillId.bare));
history->setInboxReadTill(tillId); history->setInboxReadTill(tillId);
return; return;
} }
@ -208,7 +208,7 @@ void Histories::readInboxTill(
state.willReadTill = tillId; state.willReadTill = tillId;
if (force || !stillUnread || !*stillUnread) { if (force || !stillUnread || !*stillUnread) {
DEBUG_LOG(("Reading: will read till %1 with still unread %2" DEBUG_LOG(("Reading: will read till %1 with still unread %2"
).arg(tillId ).arg(tillId.bare
).arg(stillUnread.value_or(-666))); ).arg(stillUnread.value_or(-666)));
state.willReadWhen = 0; state.willReadWhen = 0;
sendReadRequests(); sendReadRequests();
@ -216,17 +216,18 @@ void Histories::readInboxTill(
return; return;
} }
} else if (!state.willReadWhen) { } else if (!state.willReadWhen) {
DEBUG_LOG(("Reading: will read till %1 with postponed").arg(tillId)); DEBUG_LOG(("Reading: will read till %1 with postponed"
).arg(tillId.bare));
state.willReadWhen = crl::now() + kReadRequestTimeout; state.willReadWhen = crl::now() + kReadRequestTimeout;
if (!_readRequestsTimer.isActive()) { if (!_readRequestsTimer.isActive()) {
_readRequestsTimer.callOnce(kReadRequestTimeout); _readRequestsTimer.callOnce(kReadRequestTimeout);
} }
} else { } else {
DEBUG_LOG(("Reading: will read till %1 postponed already" DEBUG_LOG(("Reading: will read till %1 postponed already"
).arg(tillId)); ).arg(tillId.bare));
} }
DEBUG_LOG(("Reading: marking now with till %1 and still %2" DEBUG_LOG(("Reading: marking now with till %1 and still %2"
).arg(tillId ).arg(tillId.bare
).arg(*stillUnread)); ).arg(*stillUnread));
history->setInboxReadTill(tillId); history->setInboxReadTill(tillId);
history->setUnreadCount(*stillUnread); history->setUnreadCount(*stillUnread);
@ -440,7 +441,7 @@ void Histories::requestFakeChatListMessage(
void Histories::sendPendingReadInbox(not_null<History*> history) { void Histories::sendPendingReadInbox(not_null<History*> history) {
if (const auto state = lookup(history)) { if (const auto state = lookup(history)) {
DEBUG_LOG(("Reading: send pending now with till %1 and when %2" DEBUG_LOG(("Reading: send pending now with till %1 and when %2"
).arg(state->willReadTill ).arg(state->willReadTill.bare
).arg(state->willReadWhen)); ).arg(state->willReadWhen));
if (state->willReadTill && state->willReadWhen) { if (state->willReadTill && state->willReadWhen) {
state->willReadWhen = 0; state->willReadWhen = 0;
@ -462,7 +463,7 @@ void Histories::sendReadRequests() {
continue; continue;
} else if (state.willReadWhen <= now) { } else if (state.willReadWhen <= now) {
DEBUG_LOG(("Reading: sending with till %1." DEBUG_LOG(("Reading: sending with till %1."
).arg(state.willReadTill)); ).arg(state.willReadTill.bare));
sendReadRequest(history, state); sendReadRequest(history, state);
} else if (!next || *next > state.willReadWhen) { } else if (!next || *next > state.willReadWhen) {
DEBUG_LOG(("Reading: scheduling for later send.")); DEBUG_LOG(("Reading: scheduling for later send."));
@ -483,10 +484,10 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
state.willReadWhen = 0; state.willReadWhen = 0;
state.sentReadDone = false; state.sentReadDone = false;
DEBUG_LOG(("Reading: sending request now with till %1." DEBUG_LOG(("Reading: sending request now with till %1."
).arg(tillId)); ).arg(tillId.bare));
sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) { sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) {
DEBUG_LOG(("Reading: sending request invoked with till %1." DEBUG_LOG(("Reading: sending request invoked with till %1."
).arg(tillId)); ).arg(tillId.bare));
const auto finished = [=] { const auto finished = [=] {
const auto state = lookup(history); const auto state = lookup(history);
Assert(state != nullptr); Assert(state != nullptr);

View file

@ -0,0 +1,187 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "data/data_peer_id.h"
struct MsgId {
constexpr MsgId() noexcept = default;
constexpr MsgId(int64 value) noexcept : bare(value) {
}
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return (bare != 0);
}
[[nodiscard]] constexpr bool operator!() const noexcept {
return !bare;
}
[[nodiscard]] constexpr MsgId operator-() const noexcept {
return -bare;
}
constexpr MsgId operator++() noexcept {
return ++bare;
}
constexpr MsgId operator++(int) noexcept {
return bare++;
}
constexpr MsgId operator--() noexcept {
return --bare;
}
constexpr MsgId operator--(int) noexcept {
return bare--;
}
int64 bare = 0;
};
Q_DECLARE_METATYPE(MsgId);
[[nodiscard]] inline constexpr MsgId operator+(MsgId a, MsgId b) noexcept {
return MsgId(a.bare + b.bare);
}
[[nodiscard]] inline constexpr MsgId operator-(MsgId a, MsgId b) noexcept {
return MsgId(a.bare - b.bare);
}
[[nodiscard]] inline constexpr bool operator==(MsgId a, MsgId b) noexcept {
return (a.bare == b.bare);
}
[[nodiscard]] inline constexpr bool operator!=(MsgId a, MsgId b) noexcept {
return (a.bare != b.bare);
}
[[nodiscard]] inline constexpr bool operator<(MsgId a, MsgId b) noexcept {
return (a.bare < b.bare);
}
[[nodiscard]] inline constexpr bool operator>(MsgId a, MsgId b) noexcept {
return (a.bare > b.bare);
}
[[nodiscard]] inline constexpr bool operator<=(MsgId a, MsgId b) noexcept {
return (a.bare <= b.bare);
}
[[nodiscard]] inline constexpr bool operator>=(MsgId a, MsgId b) noexcept {
return (a.bare >= b.bare);
}
constexpr auto StartClientMsgId = MsgId(-0x7FFFFFFF);
constexpr auto EndClientMsgId = MsgId(-0x40000000);
constexpr auto ShowAtTheEndMsgId = MsgId(-0x40000000);
constexpr auto SwitchAtTopMsgId = MsgId(-0x3FFFFFFF);
constexpr auto ShowAtProfileMsgId = MsgId(-0x3FFFFFFE);
constexpr auto ShowAndStartBotMsgId = MsgId(-0x3FFFFFFD);
constexpr auto ShowAtGameShareMsgId = MsgId(-0x3FFFFFFC);
constexpr auto ShowForChooseMessagesMsgId = MsgId(-0x3FFFFFFB);
constexpr auto ServerMaxMsgId = MsgId(1LL << 56);
constexpr auto ShowAtUnreadMsgId = MsgId(0);
[[nodiscard]] constexpr inline bool IsClientMsgId(MsgId id) noexcept {
return (id >= StartClientMsgId && id < EndClientMsgId);
}
[[nodiscard]] constexpr inline bool IsServerMsgId(MsgId id) noexcept {
return (id > 0 && id < ServerMaxMsgId);
}
struct MsgRange {
constexpr MsgRange() noexcept = default;
constexpr MsgRange(MsgId from, MsgId till) noexcept
: from(from)
, till(till) {
}
MsgId from = 0;
MsgId till = 0;
};
[[nodiscard]] inline constexpr bool operator==(
MsgRange a,
MsgRange b) noexcept {
return (a.from == b.from) && (a.till == b.till);
}
[[nodiscard]] inline constexpr bool operator!=(
MsgRange a,
MsgRange b) noexcept {
return !(a == b);
}
struct FullMsgId {
constexpr FullMsgId() noexcept = default;
constexpr FullMsgId(ChannelId channel, MsgId msg) noexcept
: channel(channel), msg(msg) {
}
constexpr explicit operator bool() const noexcept {
return msg != 0;
}
constexpr bool operator!() const noexcept {
return msg == 0;
}
ChannelId channel = NoChannel;
MsgId msg = 0;
};
[[nodiscard]] inline constexpr bool operator<(
const FullMsgId &a,
const FullMsgId &b) noexcept {
if (a.channel < b.channel) {
return true;
} else if (a.channel > b.channel) {
return false;
}
return a.msg < b.msg;
}
[[nodiscard]] inline constexpr bool operator>(
const FullMsgId &a,
const FullMsgId &b) noexcept {
return b < a;
}
[[nodiscard]] inline constexpr bool operator<=(
const FullMsgId &a,
const FullMsgId &b) noexcept {
return !(b < a);
}
[[nodiscard]] inline constexpr bool operator>=(
const FullMsgId &a,
const FullMsgId &b) noexcept {
return !(a < b);
}
[[nodiscard]] inline constexpr bool operator==(
const FullMsgId &a,
const FullMsgId &b) noexcept {
return (a.channel == b.channel) && (a.msg == b.msg);
}
[[nodiscard]] inline constexpr bool operator!=(
const FullMsgId &a,
const FullMsgId &b) noexcept {
return !(a == b);
}
Q_DECLARE_METATYPE(FullMsgId);
namespace std {
template <>
struct hash<MsgId> : private hash<int64> {
size_t operator()(MsgId value) const noexcept {
return hash<int64>::operator()(value.bare);
}
};
} // namespace std

View file

@ -546,7 +546,7 @@ uint64 ScheduledMessages::countListHash(const List &list) const {
}) | ranges::views::reverse; }) | ranges::views::reverse;
for (const auto &item : serverside) { for (const auto &item : serverside) {
const auto j = list.idByItem.find(item.get()); const auto j = list.idByItem.find(item.get());
HashUpdate(hash, j->second); HashUpdate(hash, j->second.bare);
if (const auto edited = item->Get<HistoryMessageEdited>()) { if (const auto edited = item->Get<HistoryMessageEdited>()) {
HashUpdate(hash, edited->date); HashUpdate(hash, edited->date);
} else { } else {

View file

@ -1838,8 +1838,8 @@ void Session::processMessages(
continue; continue;
} }
} }
const auto id = IdFromMessage(message); const auto id = IdFromMessage(message); // Only 32 bit values here.
indices.emplace((uint64(uint32(id)) << 32) | uint64(i), i); indices.emplace((uint64(uint32(id.bare)) << 32) | uint64(i), i);
} }
for (const auto &[position, index] : indices) { for (const auto &[position, index] : indices) {
addNewMessage( addNewMessage(

View file

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

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/value_ordering.h" #include "base/value_ordering.h"
#include "ui/text/text.h" // For QFIXED_MAX #include "ui/text/text.h" // For QFIXED_MAX
#include "data/data_peer_id.h" #include "data/data_peer_id.h"
#include "data/data_msg_id.h"
class HistoryItem; class HistoryItem;
using HistoryItemsList = std::vector<not_null<HistoryItem*>>; using HistoryItemsList = std::vector<not_null<HistoryItem*>>;
@ -100,80 +101,6 @@ class Folder;
using FolderId = int32; using FolderId = int32;
using FilterId = int32; using FilterId = int32;
using MsgId = int32;
constexpr auto StartClientMsgId = MsgId(-0x7FFFFFFF);
constexpr auto EndClientMsgId = MsgId(-0x40000000);
constexpr auto ShowAtTheEndMsgId = MsgId(-0x40000000);
constexpr auto SwitchAtTopMsgId = MsgId(-0x3FFFFFFF);
constexpr auto ShowAtProfileMsgId = MsgId(-0x3FFFFFFE);
constexpr auto ShowAndStartBotMsgId = MsgId(-0x3FFFFFFD);
constexpr auto ShowAtGameShareMsgId = MsgId(-0x3FFFFFFC);
constexpr auto ShowForChooseMessagesMsgId = MsgId(-0x3FFFFFFB);
constexpr auto ServerMaxMsgId = MsgId(0x3FFFFFFF);
constexpr auto ShowAtUnreadMsgId = MsgId(0);
constexpr inline bool IsClientMsgId(MsgId id) {
return (id >= StartClientMsgId && id < EndClientMsgId);
}
constexpr inline bool IsServerMsgId(MsgId id) {
return (id > 0 && id < ServerMaxMsgId);
}
struct MsgRange {
MsgRange() = default;
MsgRange(MsgId from, MsgId till) : from(from), till(till) {
}
MsgId from = 0;
MsgId till = 0;
};
inline bool operator==(const MsgRange &a, const MsgRange &b) {
return (a.from == b.from) && (a.till == b.till);
}
inline bool operator!=(const MsgRange &a, const MsgRange &b) {
return !(a == b);
}
struct FullMsgId {
constexpr FullMsgId() = default;
constexpr FullMsgId(ChannelId channel, MsgId msg)
: channel(channel), msg(msg) {
}
explicit operator bool() const {
return msg != 0;
}
inline constexpr bool operator<(const FullMsgId &other) const {
if (channel < other.channel) {
return true;
} else if (channel > other.channel) {
return false;
}
return msg < other.msg;
}
inline constexpr bool operator>(const FullMsgId &other) const {
return other < *this;
}
inline constexpr bool operator<=(const FullMsgId &other) const {
return !(other < *this);
}
inline constexpr bool operator>=(const FullMsgId &other) const {
return !(*this < other);
}
inline constexpr bool operator==(const FullMsgId &other) const {
return (channel == other.channel) && (msg == other.msg);
}
inline constexpr bool operator!=(const FullMsgId &other) const {
return !(*this == other);
}
ChannelId channel = NoChannel;
MsgId msg = 0;
};
Q_DECLARE_METATYPE(FullMsgId);
using MessageIdsList = std::vector<FullMsgId>; using MessageIdsList = std::vector<FullMsgId>;
@ -182,6 +109,10 @@ MTPDmessage::Flags FlagsFromMessage(const MTPmessage &message);
MsgId IdFromMessage(const MTPmessage &message); MsgId IdFromMessage(const MTPmessage &message);
TimeId DateFromMessage(const MTPmessage &message); TimeId DateFromMessage(const MTPmessage &message);
[[nodiscard]] inline MTPint MTP_int(MsgId id) noexcept {
return MTP_int(id.bare);
}
class DocumentData; class DocumentData;
class PhotoData; class PhotoData;
struct WebPageData; struct WebPageData;

View file

@ -1173,7 +1173,7 @@ HistoryItem *History::latestSendingMessage() const {
}); });
const auto i = ranges::max_element(sending, ranges::less(), []( const auto i = ranges::max_element(sending, ranges::less(), [](
not_null<HistoryItem*> item) { not_null<HistoryItem*> item) {
return uint64(item->date()) << 32 | uint32(item->id); return std::pair(item->date(), item->id.bare);
}); });
return (i == sending.end()) ? nullptr : i->get(); return (i == sending.end()) ? nullptr : i->get();
} }
@ -1466,7 +1466,7 @@ bool History::readInboxTillNeedsRequest(MsgId tillId) {
} }
DEBUG_LOG(("Reading: readInboxTillNeedsRequest is_server %1, before %2." DEBUG_LOG(("Reading: readInboxTillNeedsRequest is_server %1, before %2."
).arg(Logs::b(IsServerMsgId(tillId)) ).arg(Logs::b(IsServerMsgId(tillId))
).arg(_inboxReadBefore.value_or(-666))); ).arg(_inboxReadBefore.value_or(-666).bare));
return IsServerMsgId(tillId) && (_inboxReadBefore.value_or(1) <= tillId); return IsServerMsgId(tillId) && (_inboxReadBefore.value_or(1) <= tillId);
} }
@ -1492,9 +1492,9 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
if (_inboxReadBefore) { if (_inboxReadBefore) {
const auto before = *_inboxReadBefore; const auto before = *_inboxReadBefore;
DEBUG_LOG(("Reading: check before %1 with min %2 and max %3." DEBUG_LOG(("Reading: check before %1 with min %2 and max %3."
).arg(before ).arg(before.bare
).arg(minMsgId() ).arg(minMsgId().bare
).arg(maxMsgId())); ).arg(maxMsgId().bare));
if (minMsgId() <= before && maxMsgId() >= readTillId) { if (minMsgId() <= before && maxMsgId() >= readTillId) {
auto result = 0; auto result = 0;
for (const auto &block : blocks) { for (const auto &block : blocks) {
@ -1520,7 +1520,7 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
} }
const auto minimalServerId = minMsgId(); const auto minimalServerId = minMsgId();
DEBUG_LOG(("Reading: check at end loaded from %1 loaded %2 - %3").arg( DEBUG_LOG(("Reading: check at end loaded from %1 loaded %2 - %3").arg(
QString::number(minimalServerId), QString::number(minimalServerId.bare),
Logs::b(loadedAtBottom()), Logs::b(loadedAtBottom()),
Logs::b(loadedAtTop()))); Logs::b(loadedAtTop())));
if (!loadedAtBottom() if (!loadedAtBottom()

View file

@ -477,7 +477,7 @@ HistoryMessage::HistoryMessage(
} }
config.replyTo = data.vreply_to_msg_id().v; config.replyTo = data.vreply_to_msg_id().v;
config.replyToTop = data.vreply_to_top_id().value_or( config.replyToTop = data.vreply_to_top_id().value_or(
config.replyTo); data.vreply_to_msg_id().v);
}); });
} }
config.viaBotId = data.vvia_bot_id().value_or_empty(); config.viaBotId = data.vvia_bot_id().value_or_empty();
@ -527,7 +527,7 @@ HistoryMessage::HistoryMessage(
if (!peer || peer == history->peer->id) { if (!peer || peer == history->peer->id) {
config.replyTo = data.vreply_to_msg_id().v; config.replyTo = data.vreply_to_msg_id().v;
config.replyToTop = data.vreply_to_top_id().value_or( config.replyToTop = data.vreply_to_top_id().value_or(
config.replyTo); data.vreply_to_msg_id().v);
} }
}); });
} }
@ -820,7 +820,7 @@ void HistoryMessage::setRepliesInboxReadTill(
MsgId readTillId, MsgId readTillId,
std::optional<int> unreadCount) { std::optional<int> unreadCount) {
if (const auto views = Get<HistoryMessageViews>()) { if (const auto views = Get<HistoryMessageViews>()) {
const auto newReadTillId = std::max(readTillId, 1); const auto newReadTillId = std::max(readTillId.bare, int64(1));
const auto ignore = (newReadTillId < views->repliesInboxReadTillId); const auto ignore = (newReadTillId < views->repliesInboxReadTillId);
if (ignore) { if (ignore) {
return; return;
@ -870,7 +870,7 @@ MsgId HistoryMessage::repliesOutboxReadTill() const {
void HistoryMessage::setRepliesOutboxReadTill(MsgId readTillId) { void HistoryMessage::setRepliesOutboxReadTill(MsgId readTillId) {
if (const auto views = Get<HistoryMessageViews>()) { if (const auto views = Get<HistoryMessageViews>()) {
const auto newReadTillId = std::max(readTillId, 1); const auto newReadTillId = std::max(readTillId.bare, int64(1));
if (newReadTillId > views->repliesOutboxReadTillId) { if (newReadTillId > views->repliesOutboxReadTillId) {
views->repliesOutboxReadTillId = newReadTillId; views->repliesOutboxReadTillId = newReadTillId;
if (!repliesAreComments()) { if (!repliesAreComments()) {
@ -1747,10 +1747,15 @@ void HistoryMessage::setReplies(const MTPMessageReplies &data) {
const auto channelId = ChannelId( const auto channelId = ChannelId(
data.vchannel_id().value_or_empty()); data.vchannel_id().value_or_empty());
const auto readTillId = data.vread_max_id() const auto readTillId = data.vread_max_id()
? std::max( ? std::max({
{ views->repliesInboxReadTillId, data.vread_max_id()->v, 1 }) views->repliesInboxReadTillId.bare,
int64(data.vread_max_id()->v),
int64(1),
})
: views->repliesInboxReadTillId; : views->repliesInboxReadTillId;
const auto maxId = data.vmax_id().value_or(views->repliesMaxId); const auto maxId = data.vmax_id()
? data.vmax_id()->v
: views->repliesMaxId;
const auto countsChanged = (views->replies.count != count) const auto countsChanged = (views->replies.count != count)
|| (views->repliesInboxReadTillId != readTillId) || (views->repliesInboxReadTillId != readTillId)
|| (views->repliesMaxId != maxId); || (views->repliesMaxId != maxId);

View file

@ -1172,7 +1172,7 @@ void HistoryWidget::checkNextHighlight() {
return msgId; return msgId;
} }
} }
return 0; return MsgId();
}(); }();
if (!nextHighlight) { if (!nextHighlight) {
return; return;
@ -2844,7 +2844,7 @@ void HistoryWidget::firstLoadMessages() {
} }
auto from = _history; auto from = _history;
auto offsetId = 0; auto offsetId = MsgId();
auto offset = 0; auto offset = 0;
auto loadCount = kMessagesPerPage; auto loadCount = kMessagesPerPage;
if (_showAtMsgId == ShowAtUnreadMsgId) { if (_showAtMsgId == ShowAtUnreadMsgId) {
@ -3018,7 +3018,7 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
_delayedShowAtMsgId = showAtMsgId; _delayedShowAtMsgId = showAtMsgId;
auto from = _history; auto from = _history;
auto offsetId = 0; auto offsetId = MsgId();
auto offset = 0; auto offset = 0;
auto loadCount = kMessagesPerPage; auto loadCount = kMessagesPerPage;
if (_delayedShowAtMsgId == ShowAtUnreadMsgId) { if (_delayedShowAtMsgId == ShowAtUnreadMsgId) {

View file

@ -60,7 +60,7 @@ namespace {
PinnedMemento::PinnedMemento( PinnedMemento::PinnedMemento(
not_null<History*> history, not_null<History*> history,
MsgId highlightId) UniversalMsgId highlightId)
: _history(history) : _history(history)
, _highlightId(highlightId) { , _highlightId(highlightId) {
_list.setAroundPosition({ _list.setAroundPosition({

View file

@ -166,7 +166,7 @@ private:
class PinnedMemento : public Window::SectionMemento { class PinnedMemento : public Window::SectionMemento {
public: public:
using UniversalMsgId = int32; using UniversalMsgId = MsgId;
explicit PinnedMemento( explicit PinnedMemento(
not_null<History*> history, not_null<History*> history,

View file

@ -153,7 +153,7 @@ void PinnedTracker::clear() {
_current = PinnedId(); _current = PinnedId();
} }
void PinnedTracker::trackAround(MsgId messageId) { void PinnedTracker::trackAround(UniversalMsgId messageId) {
if (_aroundId == messageId) { if (_aroundId == messageId) {
return; return;
} }

View file

@ -19,7 +19,7 @@ namespace HistoryView {
class PinnedTracker final { class PinnedTracker final {
public: public:
using UniversalMsgId = int32; using UniversalMsgId = MsgId;
explicit PinnedTracker(not_null<History*> history); explicit PinnedTracker(not_null<History*> history);
~PinnedTracker(); ~PinnedTracker();

View file

@ -49,7 +49,7 @@ QString DocumentTimestampLinkBase(
FullMsgId context) { FullMsgId context) {
return QString( return QString(
"doc%1_%2_%3" "doc%1_%2_%3"
).arg(document->id).arg(context.channel.bare).arg(context.msg); ).arg(document->id).arg(context.channel.bare).arg(context.msg.bare);
} }
TextWithEntities AddTimestampLinks( TextWithEntities AddTimestampLinks(

View file

@ -986,7 +986,7 @@ SparseIdsMergedSlice::Key ListWidget::sliceKey(
} }
if (universalId < 0) { if (universalId < 0) {
// Convert back to plain id for non-migrated histories. // Convert back to plain id for non-migrated histories.
universalId += ServerMaxMsgId; universalId = universalId + ServerMaxMsgId;
} }
return Key(_peer->id, 0, universalId); return Key(_peer->id, 0, universalId);
} }

View file

@ -46,7 +46,7 @@ class AbstractController;
namespace Media { namespace Media {
using BaseLayout = Overview::Layout::ItemBase; using BaseLayout = Overview::Layout::ItemBase;
using UniversalMsgId = int32; using UniversalMsgId = MsgId;
class ListWidget final class ListWidget final
: public Ui::RpWidget : public Ui::RpWidget

View file

@ -64,13 +64,14 @@ QByteArray SessionSettings::serialize() const {
for (const auto &[id, time] : _mediaLastPlaybackPosition) { for (const auto &[id, time] : _mediaLastPlaybackPosition) {
stream << quint64(id) << qint64(time); stream << quint64(id) << qint64(time);
} }
stream << qint32(_hiddenPinnedMessages.size()); stream << qint32(0);
for (const auto &[key, value] : _hiddenPinnedMessages) {
stream << SerializePeerId(key) << qint32(value);
}
stream << qint32(_dialogsFiltersEnabled ? 1 : 0); stream << qint32(_dialogsFiltersEnabled ? 1 : 0);
stream << qint32(_supportAllSilent ? 1 : 0); stream << qint32(_supportAllSilent ? 1 : 0);
stream << qint32(_photoEditorHintShowsCount); stream << qint32(_photoEditorHintShowsCount);
stream << qint32(_hiddenPinnedMessages.size());
for (const auto &[key, value] : _hiddenPinnedMessages) {
stream << SerializePeerId(key) << qint64(value.bare);
}
} }
return result; return result;
} }
@ -310,6 +311,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
auto count = qint32(0); auto count = qint32(0);
stream >> count; stream >> count;
if (stream.status() == QDataStream::Ok) { if (stream.status() == QDataStream::Ok) {
// Legacy.
for (auto i = 0; i != count; ++i) { for (auto i = 0; i != count; ++i) {
auto key = quint64(); auto key = quint64();
auto value = qint32(); auto value = qint32();
@ -332,6 +334,23 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) { if (!stream.atEnd()) {
stream >> photoEditorHintShowsCount; stream >> photoEditorHintShowsCount;
} }
if (!stream.atEnd()) {
auto count = qint32(0);
stream >> count;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != count; ++i) {
auto key = quint64();
auto value = qint64();
stream >> key >> value;
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for SessionSettings::addFromSerialized()"));
return;
}
hiddenPinnedMessages.emplace(DeserializePeerId(key), value);
}
}
}
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("App Error: " LOG(("App Error: "
"Bad data for SessionSettings::addFromSerialized()")); "Bad data for SessionSettings::addFromSerialized()"));

View file

@ -133,12 +133,10 @@ AdminLog::OwnedItem GenerateForwardedItem(
Expects(history->peer->isUser()); Expects(history->peer->isUser());
using Flag = MTPDmessage::Flag; using Flag = MTPDmessage::Flag;
// #TODO common global incrementable id for fake items, like clientMsgId.
static auto id = ServerMaxMsgId + (ServerMaxMsgId / 6);
const auto flags = Flag::f_from_id | Flag::f_fwd_from; const auto flags = Flag::f_from_id | Flag::f_fwd_from;
const auto item = MTP_message( const auto item = MTP_message(
MTP_flags(flags), MTP_flags(flags),
MTP_int(++id), MTP_int(history->owner().nextNonHistoryEntryId()),
peerToMTP(history->peer->id), peerToMTP(history->peer->id),
peerToMTP(history->peer->id), peerToMTP(history->peer->id),
MTP_messageFwdHeader( MTP_messageFwdHeader(

View file

@ -1074,14 +1074,14 @@ bool ReadSetting(
} break; } break;
case dbiHiddenPinnedMessagesOld: { case dbiHiddenPinnedMessagesOld: {
auto v = QMap<uint64, MsgId>(); auto v = QMap<uint64, int32>();
stream >> v; stream >> v;
if (!CheckStreamStatus(stream)) return false; if (!CheckStreamStatus(stream)) return false;
for (auto i = v.begin(), e = v.end(); i != e; ++i) { for (auto i = v.begin(), e = v.end(); i != e; ++i) {
context.sessionSettings().setHiddenPinnedMessageId( context.sessionSettings().setHiddenPinnedMessageId(
DeserializePeerId(i.key()), DeserializePeerId(i.key()),
i.value()); MsgId(i.value()));
} }
context.legacyRead = true; context.legacyRead = true;
} break; } break;

View file

@ -54,8 +54,10 @@ constexpr auto kSinglePeerTypeChat = qint32(8 + 2);
constexpr auto kSinglePeerTypeChannel = qint32(8 + 3); constexpr auto kSinglePeerTypeChannel = qint32(8 + 3);
constexpr auto kSinglePeerTypeSelf = qint32(4); constexpr auto kSinglePeerTypeSelf = qint32(4);
constexpr auto kSinglePeerTypeEmpty = qint32(0); constexpr auto kSinglePeerTypeEmpty = qint32(0);
constexpr auto kMultiDraftTag = quint64(0xFFFFFFFFFFFFFF01ULL); constexpr auto kMultiDraftTagOld = quint64(0xFFFF'FFFF'FFFF'FF01ULL);
constexpr auto kMultiDraftCursorsTag = quint64(0xFFFFFFFFFFFFFF02ULL); constexpr auto kMultiDraftCursorsTagOld = quint64(0xFFFF'FFFF'FFFF'FF02ULL);
constexpr auto kMultiDraftTag = quint64(0xFFFF'FFFF'FFFF'FF03ULL);
constexpr auto kMultiDraftCursorsTag = quint64(0xFFFF'FFFF'FFFF'FF04ULL);
enum { // Local Storage Keys enum { // Local Storage Keys
lskUserMap = 0x00, lskUserMap = 0x00,
@ -1068,10 +1070,10 @@ void Account::writeDrafts(not_null<History*> history) {
const TextWithTags &text, const TextWithTags &text,
Data::PreviewState, Data::PreviewState,
auto&&) { // cursor auto&&) { // cursor
size += sizeof(qint32) // key size += sizeof(qint64) // key
+ Serialize::stringSize(text.text) + Serialize::stringSize(text.text)
+ sizeof(quint32) + TextUtilities::SerializeTagsSize(text.tags) + sizeof(qint64) + TextUtilities::SerializeTagsSize(text.tags)
+ 2 * sizeof(qint32); // msgId, previewState + sizeof(qint64) + sizeof(qint32); // msgId, previewState
}; };
EnumerateDrafts( EnumerateDrafts(
map, map,
@ -1096,7 +1098,7 @@ void Account::writeDrafts(not_null<History*> history) {
<< key.serialize() << key.serialize()
<< text.text << text.text
<< TextUtilities::SerializeTags(text.tags) << TextUtilities::SerializeTags(text.tags)
<< qint32(msgId) << qint64(msgId.bare)
<< qint32(previewState); << qint32(previewState);
}; };
EnumerateDrafts( EnumerateDrafts(
@ -1143,7 +1145,7 @@ void Account::writeDraftCursors(not_null<History*> history) {
auto size = int(sizeof(quint64) * 2 auto size = int(sizeof(quint64) * 2
+ sizeof(quint32) + sizeof(quint32)
+ sizeof(qint32) * 4 * count); + (sizeof(qint64) + sizeof(qint32) * 3) * count);
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
data.stream data.stream
@ -1196,7 +1198,9 @@ void Account::readDraftCursors(PeerId peerId, Data::HistoryDrafts &map) {
} }
quint64 tag = 0; quint64 tag = 0;
draft.stream >> tag; draft.stream >> tag;
if (tag != kMultiDraftTag && tag != kMultiDraftCursorsTag) { if (tag != kMultiDraftCursorsTag
&& tag != kMultiDraftCursorsTagOld
&& tag != kMultiDraftTagOld) {
readDraftCursorsLegacy(peerId, draft, tag, map); readDraftCursorsLegacy(peerId, draft, tag, map);
return; return;
} }
@ -1209,13 +1213,19 @@ void Account::readDraftCursors(PeerId peerId, Data::HistoryDrafts &map) {
return; return;
} }
const auto keysWritten = (tag == kMultiDraftCursorsTag); const auto keysWritten = (tag == kMultiDraftCursorsTag);
const auto keysOld = (tag == kMultiDraftCursorsTagOld);
for (auto i = 0; i != count; ++i) { for (auto i = 0; i != count; ++i) {
qint32 keyValue = 0; qint64 keyValue = 0;
qint32 keyValueOld = 0;
if (keysWritten) { if (keysWritten) {
draft.stream >> keyValue; draft.stream >> keyValue;
} else if (keysOld) {
draft.stream >> keyValueOld;
} }
const auto key = keysWritten const auto key = keysWritten
? Data::DraftKey::FromSerialized(keyValue) ? Data::DraftKey::FromSerialized(keyValue)
: keysOld
? Data::DraftKey::FromSerializedOld(keyValueOld)
: Data::DraftKey::Local(); : Data::DraftKey::Local();
qint32 position = 0, anchor = 0, scroll = QFIXED_MAX; qint32 position = 0, anchor = 0, scroll = QFIXED_MAX;
draft.stream >> position >> anchor >> scroll; draft.stream >> position >> anchor >> scroll;
@ -1287,7 +1297,7 @@ void Account::readDraftsWithCursors(not_null<History*> history) {
quint64 tag = 0; quint64 tag = 0;
draft.stream >> tag; draft.stream >> tag;
if (tag != kMultiDraftTag) { if (tag != kMultiDraftTag && tag != kMultiDraftTagOld) {
readDraftsWithCursorsLegacy(history, draft, tag); readDraftsWithCursorsLegacy(history, draft, tag);
return; return;
} }
@ -1302,12 +1312,18 @@ void Account::readDraftsWithCursors(not_null<History*> history) {
return; return;
} }
auto map = Data::HistoryDrafts(); auto map = Data::HistoryDrafts();
const auto keysOld = (tag == kMultiDraftTagOld);
for (auto i = 0; i != count; ++i) { for (auto i = 0; i != count; ++i) {
TextWithTags data; TextWithTags data;
QByteArray tagsSerialized; QByteArray tagsSerialized;
qint32 keyValue = 0, messageId = 0, uncheckedPreviewState = 0; qint64 keyValue = 0;
qint32 keyValueOld = 0, messageId = 0, uncheckedPreviewState = 0;
if (keysOld) {
draft.stream >> keyValueOld;
} else {
draft.stream >> keyValue;
}
draft.stream draft.stream
>> keyValue
>> data.text >> data.text
>> tagsSerialized >> tagsSerialized
>> messageId >> messageId
@ -1321,7 +1337,9 @@ void Account::readDraftsWithCursors(not_null<History*> history) {
case Data::PreviewState::EmptyOnEdit: case Data::PreviewState::EmptyOnEdit:
previewState = Data::PreviewState(uncheckedPreviewState); previewState = Data::PreviewState(uncheckedPreviewState);
} }
const auto key = Data::DraftKey::FromSerialized(keyValue); const auto key = keysOld
? Data::DraftKey::FromSerializedOld(keyValueOld)
: Data::DraftKey::FromSerialized(keyValue);
if (key && key != Data::DraftKey::Cloud()) { if (key && key != Data::DraftKey::Cloud()) {
map.emplace(key, std::make_unique<Data::Draft>( map.emplace(key, std::make_unique<Data::Draft>(
data, data,

View file

@ -274,7 +274,6 @@ AdminLog::OwnedItem GenerateCommentItem(
if (data.comment.isEmpty()) { if (data.comment.isEmpty()) {
return nullptr; return nullptr;
} }
const auto id = ServerMaxMsgId + (ServerMaxMsgId / 2);
const auto flags = MessageFlag::HasFromId const auto flags = MessageFlag::HasFromId
| MessageFlag::Outgoing | MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem; | MessageFlag::FakeHistoryItem;
@ -282,7 +281,7 @@ AdminLog::OwnedItem GenerateCommentItem(
const auto viaBotId = UserId(); const auto viaBotId = UserId();
const auto groupedId = uint64(); const auto groupedId = uint64();
const auto item = history->makeMessage( const auto item = history->makeMessage(
id, history->owner().nextNonHistoryEntryId(),
flags, flags,
replyTo, replyTo,
viaBotId, viaBotId,
@ -305,7 +304,7 @@ AdminLog::OwnedItem GenerateContactItem(
const auto postAuthor = QString(); const auto postAuthor = QString();
const auto groupedId = uint64(); const auto groupedId = uint64();
const auto item = history->makeMessage( const auto item = history->makeMessage(
(ServerMaxMsgId + (ServerMaxMsgId / 2) + 1), history->owner().nextNonHistoryEntryId(),
(MessageFlag::HasFromId (MessageFlag::HasFromId
| MessageFlag::Outgoing | MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem), | MessageFlag::FakeHistoryItem),