Some internal HistoryItem refactoring.

Replace most IsServerMsgId / id <=> 0 with isRegular().
Track isLocal / isHistoryEntry in flags.
Remove toHistoryMessage.
This commit is contained in:
John Preston 2021-11-07 12:06:00 +04:00
parent 22b37c4bf8
commit c534f3f22e
52 changed files with 460 additions and 524 deletions

View file

@ -36,7 +36,7 @@ void SendBotCallbackData(
int column, int column,
std::optional<MTPInputCheckPasswordSRP> password = std::nullopt, std::optional<MTPInputCheckPasswordSRP> password = std::nullopt,
Fn<void(const MTP::Error &)> handleError = nullptr) { Fn<void(const MTP::Error &)> handleError = nullptr) {
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
return; return;
} }
const auto history = item->history(); const auto history = item->history();
@ -150,7 +150,7 @@ void SendBotCallbackDataWithPassword(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
int row, int row,
int column) { int column) {
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
return; return;
} }
const auto history = item->history(); const auto history = item->history();

View file

@ -182,8 +182,7 @@ void Polls::close(not_null<HistoryItem*> item) {
void Polls::reloadResults(not_null<HistoryItem*> item) { void Polls::reloadResults(not_null<HistoryItem*> item) {
const auto itemId = item->fullId(); const auto itemId = item->fullId();
if (!IsServerMsgId(item->id) if (!item->isRegular() || _pollReloadRequestIds.contains(itemId)) {
|| _pollReloadRequestIds.contains(itemId)) {
return; return;
} }
const auto requestId = _api.request(MTPmessages_GetPollResults( const auto requestId = _api.request(MTPmessages_GetPollResults(

View file

@ -111,8 +111,6 @@ void SendExistingMedia(
if (message.action.options.scheduled) { if (message.action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled; flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
session->data().registerMessageRandomId(randomId, newId); session->data().registerMessageRandomId(randomId, newId);
@ -271,8 +269,6 @@ bool SendDice(Api::MessageToSend &message) {
if (message.action.options.scheduled) { if (message.action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled; flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
session->data().registerMessageRandomId(randomId, newId); session->data().registerMessageRandomId(randomId, newId);
@ -387,8 +383,6 @@ void SendConfirmedFile(
// Scheduled messages have no the 'edited' badge. // Scheduled messages have no the 'edited' badge.
flags |= MessageFlag::HideEdited; flags |= MessageFlag::HideEdited;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
if (file->type == SendMediaType::Audio) { if (file->type == SendMediaType::Audio) {
if (!peer->isChannel() || peer->isMegagroup()) { if (!peer->isChannel() || peer->isMegagroup()) {

View file

@ -1288,7 +1288,7 @@ void ApiWrap::markMediaRead(
continue; continue;
} }
item->markMediaRead(); item->markMediaRead();
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
continue; continue;
} }
if (const auto channel = item->history()->peer->asChannel()) { if (const auto channel = item->history()->peer->asChannel()) {
@ -1318,7 +1318,7 @@ void ApiWrap::markMediaRead(not_null<HistoryItem*> item) {
return; return;
} }
item->markMediaRead(); item->markMediaRead();
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
return; return;
} }
const auto ids = MTP_vector<MTPint>(1, MTP_int(item->id)); const auto ids = MTP_vector<MTPint>(1, MTP_int(item->id));
@ -2329,7 +2329,7 @@ void ApiWrap::deleteHistory(
if (!last) { if (!last) {
// History is empty. // History is empty.
return; return;
} else if (!IsServerMsgId(last->id)) { } else if (!last->isRegular()) {
// Destroy client-side message locally. // Destroy client-side message locally.
last->destroy(); last->destroy();
} else { } else {
@ -2354,7 +2354,7 @@ void ApiWrap::deleteHistory(
if (const auto migrated = peer->migrateFrom()) { if (const auto migrated = peer->migrateFrom()) {
deleteHistory(migrated, justClear, revoke); deleteHistory(migrated, justClear, revoke);
} }
if (IsServerMsgId(deleteTillId) || (!justClear && revoke)) { if (deleteTillId || (!justClear && revoke)) {
history->owner().histories().deleteAllMessages( history->owner().histories().deleteAllMessages(
history, history,
deleteTillId, deleteTillId,
@ -3681,8 +3681,6 @@ void ApiWrap::forwardMessages(
if (action.options.scheduled) { if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled; flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_ForwardMessages::Flag::f_schedule_date; sendFlags |= MTPmessages_ForwardMessages::Flag::f_schedule_date;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
if (draft.options != Data::ForwardOptions::PreserveInfo) { if (draft.options != Data::ForwardOptions::PreserveInfo) {
sendFlags |= MTPmessages_ForwardMessages::Flag::f_drop_author; sendFlags |= MTPmessages_ForwardMessages::Flag::f_drop_author;
@ -3741,30 +3739,28 @@ void ApiWrap::forwardMessages(
for (const auto item : draft.items) { for (const auto item : draft.items) {
const auto randomId = base::RandomValue<uint64>(); const auto randomId = base::RandomValue<uint64>();
if (genClientSideMessage) { if (genClientSideMessage) {
if (const auto message = item->toHistoryMessage()) { const auto newId = FullMsgId(
const auto newId = FullMsgId( peerToChannel(peer->id),
peerToChannel(peer->id), _session->data().nextLocalMessageId());
_session->data().nextLocalMessageId()); const auto self = _session->user();
const auto self = _session->user(); const auto messageFromId = anonymousPost
const auto messageFromId = anonymousPost ? PeerId(0)
? PeerId(0) : self->id;
: self->id; const auto messagePostAuthor = peer->isBroadcast()
const auto messagePostAuthor = peer->isBroadcast() ? self->name
? self->name : QString();
: QString(); history->addNewLocalMessage(
history->addNewLocalMessage( newId.msg,
newId.msg, flags,
flags, HistoryItem::NewMessageDate(action.options.scheduled),
HistoryItem::NewMessageDate(action.options.scheduled), messageFromId,
messageFromId, messagePostAuthor,
messagePostAuthor, item);
message); _session->data().registerMessageRandomId(randomId, newId);
_session->data().registerMessageRandomId(randomId, newId); if (!localIds) {
if (!localIds) { localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();
localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();
}
localIds->emplace(randomId, newId);
} }
localIds->emplace(randomId, newId);
} }
const auto newFrom = item->history()->peer; const auto newFrom = item->history()->peer;
if (forwardFrom != newFrom) { if (forwardFrom != newFrom) {
@ -3827,8 +3823,6 @@ void ApiWrap::sendSharedContact(
FillMessagePostFlags(action, peer, flags); FillMessagePostFlags(action, peer, flags);
if (action.options.scheduled) { if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled; flags |= MessageFlag::IsOrWasScheduled;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
const auto messageFromId = anonymousPost ? 0 : _session->userPeerId(); const auto messageFromId = anonymousPost ? 0 : _session->userPeerId();
const auto messagePostAuthor = peer->isBroadcast() const auto messagePostAuthor = peer->isBroadcast()
@ -4009,7 +4003,7 @@ void ApiWrap::sendUploadedDocument(
} }
void ApiWrap::cancelLocalItem(not_null<HistoryItem*> item) { void ApiWrap::cancelLocalItem(not_null<HistoryItem*> item) {
Expects(!IsServerMsgId(item->id)); Expects(item->isSending());
if (const auto groupId = item->groupId()) { if (const auto groupId = item->groupId()) {
sendAlbumWithCancelled(item, groupId); sendAlbumWithCancelled(item, groupId);
@ -4100,8 +4094,6 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (action.options.scheduled) { if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled; flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date; sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
const auto viaBotId = UserId(); const auto viaBotId = UserId();
lastMessage = history->addNewLocalMessage( lastMessage = history->addNewLocalMessage(
@ -4219,8 +4211,6 @@ void ApiWrap::sendInlineResult(
if (action.options.scheduled) { if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled; flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendInlineBotResult::Flag::f_schedule_date; sendFlags |= MTPmessages_SendInlineBotResult::Flag::f_schedule_date;
} else {
flags |= MessageFlag::LocalHistoryEntry;
} }
const auto messageFromId = anonymousPost ? 0 : _session->userPeerId(); const auto messageFromId = anonymousPost ? 0 : _session->userPeerId();

View file

@ -32,7 +32,7 @@ void UrlAuthBox::Activate(
itemId, itemId,
row, row,
column); column);
if (button->requestId || !IsServerMsgId(itemId.msg)) { if (button->requestId || !message->isRegular()) {
return; return;
} }
const auto session = &message->history()->session(); const auto session = &message->history()->session();
@ -121,7 +121,7 @@ void UrlAuthBox::Request(
itemId, itemId,
row, row,
column); column);
if (button->requestId || !IsServerMsgId(itemId.msg)) { if (button->requestId || !message->isRegular()) {
return; return;
} }
const auto session = &message->history()->session(); const auto session = &message->history()->session();

View file

@ -114,7 +114,7 @@ EmojiPtr EmojiInteractions::chooseInteractionEmoji(
void EmojiInteractions::startOutgoing( void EmojiInteractions::startOutgoing(
not_null<const HistoryView::Element*> view) { not_null<const HistoryView::Element*> view) {
const auto item = view->data(); const auto item = view->data();
if (!IsServerMsgId(item->id) || !item->history()->peer->isUser()) { if (!item->isRegular() || !item->history()->peer->isUser()) {
return; return;
} }
const auto emoticon = item->originalText().text; const auto emoticon = item->originalText().text;
@ -161,13 +161,11 @@ void EmojiInteractions::startIncoming(
MsgId messageId, MsgId messageId,
const QString &emoticon, const QString &emoticon,
EmojiInteractionsBunch &&bunch) { EmojiInteractionsBunch &&bunch) {
if (!peer->isUser() if (!peer->isUser() || bunch.interactions.empty()) {
|| bunch.interactions.empty()
|| !IsServerMsgId(messageId)) {
return; return;
} }
const auto item = _session->data().message(nullptr, messageId); const auto item = _session->data().message(nullptr, messageId);
if (!item) { if (!item || !item->isRegular()) {
return; return;
} }
const auto emoji = chooseInteractionEmoji(item); const auto emoji = chooseInteractionEmoji(item);

View file

@ -110,23 +110,23 @@ struct HistoryUpdate {
enum class Flag : uint32 { enum class Flag : uint32 {
None = 0, None = 0,
IsPinned = (1U << 0), IsPinned = (1U << 0),
UnreadView = (1U << 1), UnreadView = (1U << 1),
TopPromoted = (1U << 2), TopPromoted = (1U << 2),
Folder = (1U << 3), Folder = (1U << 3),
UnreadMentions = (1U << 4), UnreadMentions = (1U << 4),
LocalMessages = (1U << 5), ClientSideMessages = (1U << 5),
ChatOccupied = (1U << 6), ChatOccupied = (1U << 6),
MessageSent = (1U << 7), MessageSent = (1U << 7),
ScheduledSent = (1U << 8), ScheduledSent = (1U << 8),
ForwardDraft = (1U << 9), ForwardDraft = (1U << 9),
OutboxRead = (1U << 10), OutboxRead = (1U << 10),
BotKeyboard = (1U << 11), BotKeyboard = (1U << 11),
CloudDraft = (1U << 12), CloudDraft = (1U << 12),
LocalDraftSet = (1U << 13), LocalDraftSet = (1U << 13),
PinnedMessages = (1U << 14), PinnedMessages = (1U << 14),
LastUsedBit = (1U << 14), LastUsedBit = (1U << 14),
}; };
using Flags = base::flags<Flag>; using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; } friend inline constexpr auto is_flag_type(Flag) { return true; }

View file

@ -73,7 +73,7 @@ void Groups::refreshMessage(
unregisterMessage(item); unregisterMessage(item);
return; return;
} }
if (!IsServerMsgId(item->id) && !item->isScheduled()) { if (!item->isRegular() && !item->isScheduled()) {
return; return;
} }
const auto groupId = item->groupId(); const auto groupId = item->groupId();
@ -112,14 +112,13 @@ void Groups::refreshMessage(
HistoryItemsList::const_iterator Groups::findPositionForItem( HistoryItemsList::const_iterator Groups::findPositionForItem(
const HistoryItemsList &group, const HistoryItemsList &group,
not_null<HistoryItem*> item) { not_null<HistoryItem*> item) {
const auto itemId = item->id;
const auto last = end(group); const auto last = end(group);
if (!IsServerMsgId(itemId)) { if (!item->isRegular()) {
return last; return last;
} }
const auto itemId = item->id;
for (auto result = begin(group); result != last; ++result) { for (auto result = begin(group); result != last; ++result) {
const auto alreadyId = (*result)->id; if ((*result)->isRegular() && (*result)->id > itemId) {
if (IsServerMsgId(alreadyId) && alreadyId > itemId) {
return result; return result;
} }
} }

View file

@ -100,7 +100,7 @@ void Histories::readInbox(not_null<History*> history) {
void Histories::readInboxTill(not_null<HistoryItem*> item) { void Histories::readInboxTill(not_null<HistoryItem*> item) {
const auto history = item->history(); const auto history = item->history();
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
readClientSideMessage(item); readClientSideMessage(item);
auto view = item->mainView(); auto view = item->mainView();
if (!view) { if (!view) {
@ -123,11 +123,11 @@ void Histories::readInboxTill(not_null<HistoryItem*> item) {
} }
} }
item = view->data(); item = view->data();
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
break; break;
} }
} }
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
LOG(("App Error: " LOG(("App Error: "
"Can't read history till unknown local message.")); "Can't read history till unknown local message."));
return; return;
@ -235,7 +235,7 @@ void Histories::readInboxTill(
} }
void Histories::readInboxOnNewMessage(not_null<HistoryItem*> item) { void Histories::readInboxOnNewMessage(not_null<HistoryItem*> item) {
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
readClientSideMessage(item); readClientSideMessage(item);
} else { } else {
readInboxTill(item->history(), item->id, true); readInboxTill(item->history(), item->id, true);
@ -728,7 +728,7 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) {
continue; continue;
} }
remove.push_back(item); remove.push_back(item);
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
idsByPeer[history].push_back(MTP_int(itemId.msg)); idsByPeer[history].push_back(MTP_int(itemId.msg));
} }
} }

View file

@ -528,7 +528,7 @@ bool PeerData::canExportChatHistory() const {
} }
for (const auto &block : _owner->history(id)->blocks) { for (const auto &block : _owner->history(id)->blocks) {
for (const auto &message : block->messages) { for (const auto &message : block->messages) {
if (!message->data()->serviceMsg()) { if (!message->data()->isService()) {
return true; return true;
} }
} }

View file

@ -71,7 +71,7 @@ rpl::producer<MessagesSlice> RepliesList::source(
const auto push = [=] { const auto push = [=] {
viewer->scheduled = false; viewer->scheduled = false;
if (buildFromData(viewer)) { if (buildFromData(viewer)) {
appendLocalMessages(viewer->slice); appendClientSideMessages(viewer->slice);
consumer.put_next_copy(viewer->slice); consumer.put_next_copy(viewer->slice);
} }
}; };
@ -95,7 +95,7 @@ rpl::producer<MessagesSlice> RepliesList::source(
_history->session().changes().historyUpdates( _history->session().changes().historyUpdates(
_history, _history,
Data::HistoryUpdate::Flag::LocalMessages Data::HistoryUpdate::Flag::ClientSideMessages
) | rpl::start_with_next(pushDelayed, lifetime); ) | rpl::start_with_next(pushDelayed, lifetime);
_partLoaded.events( _partLoaded.events(
@ -115,16 +115,16 @@ rpl::producer<MessagesSlice> RepliesList::source(
}; };
} }
void RepliesList::appendLocalMessages(MessagesSlice &slice) { void RepliesList::appendClientSideMessages(MessagesSlice &slice) {
const auto &local = _history->localMessages(); const auto &messages = _history->clientSideMessages();
if (local.empty()) { if (messages.empty()) {
return; return;
} else if (slice.ids.empty()) { } else if (slice.ids.empty()) {
if (slice.skippedBefore != 0 || slice.skippedAfter != 0) { if (slice.skippedBefore != 0 || slice.skippedAfter != 0) {
return; return;
} }
slice.ids.reserve(local.size()); slice.ids.reserve(messages.size());
for (const auto &item : local) { for (const auto &item : messages) {
if (item->replyToTop() != _rootId) { if (item->replyToTop() != _rootId) {
continue; continue;
} }
@ -142,7 +142,7 @@ void RepliesList::appendLocalMessages(MessagesSlice &slice) {
dates.push_back(message->date()); dates.push_back(message->date());
} }
for (const auto &item : local) { for (const auto &item : messages) {
if (item->replyToTop() != _rootId) { if (item->replyToTop() != _rootId) {
continue; continue;
} }
@ -369,8 +369,7 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
bool RepliesList::applyUpdate( bool RepliesList::applyUpdate(
not_null<Viewer*> viewer, not_null<Viewer*> viewer,
const MessageUpdate &update) { const MessageUpdate &update) {
if (update.item->history() != _history if (update.item->history() != _history || !update.item->isRegular()) {
|| !IsServerMsgId(update.item->id)) {
return false; return false;
} }
if (update.flags & MessageUpdate::Flag::Destroyed) { if (update.flags & MessageUpdate::Flag::Destroyed) {
@ -454,7 +453,7 @@ void RepliesList::loadAround(MsgId id) {
_list.clear(); _list.clear();
if (processMessagesIsEmpty(result)) { if (processMessagesIsEmpty(result)) {
_fullCount = _skippedBefore = _skippedAfter = 0; _fullCount = _skippedBefore = _skippedAfter = 0;
} else if (id > 0) { } else if (id) {
Assert(!_list.empty()); Assert(!_list.empty());
if (_list.front() <= id) { if (_list.front() <= id) {
_skippedAfter = 0; _skippedAfter = 0;

View file

@ -46,7 +46,7 @@ private:
MessagePosition aroundId, MessagePosition aroundId,
int limitBefore, int limitBefore,
int limitAfter); int limitAfter);
void appendLocalMessages(MessagesSlice &slice); void appendClientSideMessages(MessagesSlice &slice);
[[nodiscard]] bool buildFromData(not_null<Viewer*> viewer); [[nodiscard]] bool buildFromData(not_null<Viewer*> viewer);
[[nodiscard]] bool applyUpdate( [[nodiscard]] bool applyUpdate(

View file

@ -176,8 +176,7 @@ void ScheduledMessages::sendNowSimpleMessage(
auto action = Api::SendAction(history); auto action = Api::SendAction(history);
action.replyTo = local->replyToId(); action.replyTo = local->replyToId();
const auto replyHeader = NewMessageReplyHeader(action); const auto replyHeader = NewMessageReplyHeader(action);
const auto localFlags = NewMessageFlags(history->peer) const auto localFlags = NewMessageFlags(history->peer);
| MessageFlag::LocalHistoryEntry;
const auto flags = MTPDmessage::Flag::f_entities const auto flags = MTPDmessage::Flag::f_entities
| MTPDmessage::Flag::f_from_id | MTPDmessage::Flag::f_from_id
| (local->replyToId() | (local->replyToId()

View file

@ -3496,7 +3496,7 @@ HistoryItem *Session::findWebPageItem(not_null<WebPageData*> page) const {
const auto i = _webpageItems.find(page); const auto i = _webpageItems.find(page);
if (i != _webpageItems.end()) { if (i != _webpageItems.end()) {
for (const auto &item : i->second) { for (const auto &item : i->second) {
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
return item; return item;
} }
} }
@ -3983,7 +3983,7 @@ void Session::insertCheckedServiceNotification(
| MTPDmessage::Flag::f_from_id | MTPDmessage::Flag::f_from_id
| MTPDmessage::Flag::f_media; | MTPDmessage::Flag::f_media;
const auto localFlags = MessageFlag::ClientSideUnread const auto localFlags = MessageFlag::ClientSideUnread
| MessageFlag::LocalHistoryEntry; | MessageFlag::Local;
auto sending = TextWithEntities(), left = message; auto sending = TextWithEntities(), left = message;
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) { while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
const auto id = nextLocalMessageId(); const auto id = nextLocalMessageId();

View file

@ -75,7 +75,7 @@ bool SponsoredMessages::append(not_null<History*> history) {
| (history->isChannel() ? MessageFlag::Post : MessageFlags(0)) | (history->isChannel() ? MessageFlag::Post : MessageFlags(0))
| MessageFlag::HasFromId | MessageFlag::HasFromId
| MessageFlag::IsSponsored | MessageFlag::IsSponsored
| MessageFlag::LocalHistoryEntry; | MessageFlag::Local;
auto local = history->addNewLocalMessage( auto local = history->addNewLocalMessage(
_session->data().nextLocalMessageId(), _session->data().nextLocalMessageId(),
flags, flags,

View file

@ -268,17 +268,20 @@ enum class MessageFlag : uint32 {
// No media and only a several emoji text. // No media and only a several emoji text.
IsolatedEmoji = (1U << 25), IsolatedEmoji = (1U << 25),
// Local message existing in the message history. // Message existing in the message history.
LocalHistoryEntry = (1U << 26), HistoryEntry = (1U << 26),
// Local message, not existing on the server.
Local = (1U << 27),
// Fake message for some UI element. // Fake message for some UI element.
FakeHistoryItem = (1U << 27), FakeHistoryItem = (1U << 28),
// Contact sign-up message, notification should be skipped for Silent. // Contact sign-up message, notification should be skipped for Silent.
IsContactSignUp = (1U << 28), IsContactSignUp = (1U << 29),
// In channels. // In channels.
IsSponsored = (1U << 29), IsSponsored = (1U << 30),
}; };
inline constexpr bool is_flag_type(MessageFlag) { return true; } inline constexpr bool is_flag_type(MessageFlag) { return true; }
using MessageFlags = base::flags<MessageFlag>; using MessageFlags = base::flags<MessageFlag>;

View file

@ -417,7 +417,7 @@ void paintRow(
: st::dialogsSendingIcon)); : st::dialogsSendingIcon));
} }
} else if (item && !item->isEmpty() && item->needCheck()) { } else if (item && !item->isEmpty() && item->needCheck()) {
if (item->id > 0) { if (!item->isSending() && !item->hasFailed()) {
if (item->unread()) { if (item->unread()) {
return &(active return &(active
? st::dialogsSentIconActive ? st::dialogsSentIconActive

View file

@ -91,7 +91,7 @@ void activateBotCommand(
// Copy string before passing it to the sending method // Copy string before passing it to the sending method
// because the original button can be destroyed inside. // because the original button can be destroyed inside.
if (sessionController) { if (sessionController) {
MsgId replyTo = (msg->id > 0) ? msg->id : 0; MsgId replyTo = msg->isRegular() ? msg->id : 0;
sessionController->content()->sendBotCommand({ sessionController->content()->sendBotCommand({
.peer = msg->history()->peer, .peer = msg->history()->peer,
.command = QString(button->text), .command = QString(button->text),

View file

@ -147,8 +147,9 @@ void InnerWidget::enumerateUserpics(Method method) {
auto userpicCallback = [&](not_null<Element*> view, int itemtop, int itembottom) { auto userpicCallback = [&](not_null<Element*> view, int itemtop, int itembottom) {
// Skip all service messages. // Skip all service messages.
const auto message = view->data()->toHistoryMessage(); if (view->data()->isService()) {
if (!message) return true; return true;
}
if (lowestAttachedItemTop < 0 && view->isAttachedToNext()) { if (lowestAttachedItemTop < 0 && view->isAttachedToNext()) {
lowestAttachedItemTop = itemtop + view->marginTop(); lowestAttachedItemTop = itemtop + view->marginTop();
@ -963,10 +964,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
// paint the userpic if it intersects the painted rect // paint the userpic if it intersects the painted rect
if (userpicTop + st::msgPhotoSize > clip.top()) { if (userpicTop + st::msgPhotoSize > clip.top()) {
const auto message = view->data()->toHistoryMessage(); const auto from = view->data()->from();
Assert(message != nullptr);
const auto from = message->from();
from->paintUserpicLeft( from->paintUserpicLeft(
p, p,
_userpics[from], _userpics[from],
@ -1677,26 +1675,21 @@ void InnerWidget::updateSelected() {
dragState = view->textState(itemPoint, request); dragState = view->textState(itemPoint, request);
lnkhost = view; lnkhost = view;
if (!dragState.link && itemPoint.x() >= st::historyPhotoLeft && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) { if (!dragState.link && itemPoint.x() >= st::historyPhotoLeft && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) {
if (item->toHistoryMessage()) { if (!item->isService() && view->hasFromPhoto()) {
if (view->hasFromPhoto()) { enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
enumerateUserpics([&](not_null<Element*> view, int userpicTop) { // stop enumeration if the userpic is below our point
// stop enumeration if the userpic is below our point if (userpicTop > point.y()) {
if (userpicTop > point.y()) { return false;
return false; }
}
// stop enumeration if we've found a userpic under the cursor // stop enumeration if we've found a userpic under the cursor
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) { if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
const auto message = view->data()->toHistoryMessage(); dragState.link = view->data()->from()->openLink();
Assert(message != nullptr); lnkhost = view;
return false;
dragState.link = message->from()->openLink(); }
lnkhost = view; return true;
return false; });
}
return true;
});
}
} }
} }
} }

View file

@ -146,7 +146,7 @@ void History::itemRemoved(not_null<HistoryItem*> item) {
checkChatListMessageRemoved(item); checkChatListMessageRemoved(item);
itemVanished(item); itemVanished(item);
if (IsClientMsgId(item->id)) { if (IsClientMsgId(item->id)) {
unregisterLocalMessage(item); unregisterClientSideMessage(item);
} }
if (const auto chat = peer->asChat()) { if (const auto chat = peer->asChat()) {
if (const auto to = chat->getMigrateToChannel()) { if (const auto to = chat->getMigrateToChannel()) {
@ -428,7 +428,7 @@ void History::destroyMessage(not_null<HistoryItem*> item) {
if (item->isHistoryEntry()) { if (item->isHistoryEntry()) {
// All this must be done for all items manually in History::clear()! // All this must be done for all items manually in History::clear()!
item->destroyHistoryEntry(); item->destroyHistoryEntry();
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
if (const auto types = item->sharedMediaTypes()) { if (const auto types = item->sharedMediaTypes()) {
session().storage().remove(Storage::SharedMediaRemoveOne( session().storage().remove(Storage::SharedMediaRemoveOne(
peerId, peerId,
@ -550,7 +550,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
return addNewItem( return addNewItem(
makeMessage( makeMessage(
id, id,
flags, flags | MessageFlag::Local,
replyTo, replyTo,
viaBotId, viaBotId,
date, date,
@ -569,11 +569,11 @@ not_null<HistoryItem*> History::addNewLocalMessage(
TimeId date, TimeId date,
PeerId from, PeerId from,
const QString &postAuthor, const QString &postAuthor,
not_null<HistoryMessage*> forwardOriginal) { not_null<HistoryItem*> forwardOriginal) {
return addNewItem( return addNewItem(
makeMessage( makeMessage(
id, id,
flags, flags | MessageFlag::Local,
date, date,
from, from,
postAuthor, postAuthor,
@ -595,7 +595,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
return addNewItem( return addNewItem(
makeMessage( makeMessage(
id, id,
flags, flags | MessageFlag::Local,
replyTo, replyTo,
viaBotId, viaBotId,
date, date,
@ -621,7 +621,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
return addNewItem( return addNewItem(
makeMessage( makeMessage(
id, id,
flags, flags | MessageFlag::Local,
replyTo, replyTo,
viaBotId, viaBotId,
date, date,
@ -646,7 +646,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
return addNewItem( return addNewItem(
makeMessage( makeMessage(
id, id,
flags, flags | MessageFlag::Local,
replyTo, replyTo,
viaBotId, viaBotId,
date, date,
@ -766,7 +766,7 @@ not_null<HistoryItem*> History::addNewToBack(
addItemToBlock(item); addItemToBlock(item);
if (!unread && IsServerMsgId(item->id)) { if (!unread && item->isRegular()) {
if (const auto sharedMediaTypes = item->sharedMediaTypes()) { if (const auto sharedMediaTypes = item->sharedMediaTypes()) {
auto from = loadedAtTop() ? 0 : minMsgId(); auto from = loadedAtTop() ? 0 : minMsgId();
auto till = loadedAtBottom() ? ServerMaxMsgId : maxMsgId(); auto till = loadedAtBottom() ? ServerMaxMsgId : maxMsgId();
@ -1144,28 +1144,28 @@ void History::newItemAdded(not_null<HistoryItem*> item) {
} }
} }
void History::registerLocalMessage(not_null<HistoryItem*> item) { void History::registerClientSideMessage(not_null<HistoryItem*> item) {
Expects(item->isHistoryEntry()); Expects(item->isHistoryEntry());
Expects(IsClientMsgId(item->id)); Expects(IsClientMsgId(item->id));
_localMessages.emplace(item); _clientSideMessages.emplace(item);
session().changes().historyUpdated(this, UpdateFlag::LocalMessages); session().changes().historyUpdated(this, UpdateFlag::ClientSideMessages);
} }
void History::unregisterLocalMessage(not_null<HistoryItem*> item) { void History::unregisterClientSideMessage(not_null<HistoryItem*> item) {
const auto removed = _localMessages.remove(item); const auto removed = _clientSideMessages.remove(item);
Assert(removed); Assert(removed);
session().changes().historyUpdated(this, UpdateFlag::LocalMessages); session().changes().historyUpdated(this, UpdateFlag::ClientSideMessages);
} }
const base::flat_set<not_null<HistoryItem*>> &History::localMessages() { const base::flat_set<not_null<HistoryItem*>> &History::clientSideMessages() {
return _localMessages; return _clientSideMessages;
} }
HistoryItem *History::latestSendingMessage() const { HistoryItem *History::latestSendingMessage() const {
auto sending = ranges::views::all( auto sending = ranges::views::all(
_localMessages _clientSideMessages
) | ranges::views::filter([](not_null<HistoryItem*> item) { ) | ranges::views::filter([](not_null<HistoryItem*> item) {
return item->isSending(); return item->isSending();
}); });
@ -1446,7 +1446,7 @@ void History::calculateFirstUnreadMessage() {
for (const auto &block : ranges::views::reverse(blocks)) { for (const auto &block : ranges::views::reverse(blocks)) {
for (const auto &message : ranges::views::reverse(block->messages)) { for (const auto &message : ranges::views::reverse(block->messages)) {
const auto item = message->data(); const auto item = message->data();
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
continue; continue;
} else if (!item->out()) { } else if (!item->out()) {
if (item->id >= *_inboxReadBefore) { if (item->id >= *_inboxReadBefore) {
@ -1474,7 +1474,7 @@ bool History::readInboxTillNeedsRequest(MsgId tillId) {
void History::readClientSideMessages() { void History::readClientSideMessages() {
auto &histories = owner().histories(); auto &histories = owner().histories();
for (const auto &item : _localMessages) { for (const auto &item : _clientSideMessages) {
histories.readClientSideMessage(item); histories.readClientSideMessage(item);
} }
} }
@ -1502,7 +1502,7 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
for (const auto &block : blocks) { for (const auto &block : blocks) {
for (const auto &message : block->messages) { for (const auto &message : block->messages) {
const auto item = message->data(); const auto item = message->data();
if (!IsServerMsgId(item->id) if (!item->isRegular()
|| (item->out() && !item->isFromScheduled())) { || (item->out() && !item->isFromScheduled())) {
continue; continue;
} else if (item->id > readTillId) { } else if (item->id > readTillId) {
@ -1534,7 +1534,7 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
for (const auto &block : ranges::views::reverse(blocks)) { for (const auto &block : ranges::views::reverse(blocks)) {
for (const auto &message : ranges::views::reverse(block->messages)) { for (const auto &message : ranges::views::reverse(block->messages)) {
const auto item = message->data(); const auto item = message->data();
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
if (item->id <= readTillId) { if (item->id <= readTillId) {
return result; return result;
} else if (!item->out()) { } else if (!item->out()) {
@ -1588,7 +1588,7 @@ void History::inboxRead(MsgId upTo, std::optional<int> stillUnread) {
} }
void History::inboxRead(not_null<const HistoryItem*> wasRead) { void History::inboxRead(not_null<const HistoryItem*> wasRead) {
if (IsServerMsgId(wasRead->id)) { if (wasRead->isRegular()) {
inboxRead(wasRead->id); inboxRead(wasRead->id);
} }
} }
@ -1596,7 +1596,7 @@ void History::inboxRead(not_null<const HistoryItem*> wasRead) {
void History::outboxRead(MsgId upTo) { void History::outboxRead(MsgId upTo) {
setOutboxReadTill(upTo); setOutboxReadTill(upTo);
if (const auto last = chatListMessage()) { if (const auto last = chatListMessage()) {
if (last->out() && IsServerMsgId(last->id) && last->id <= upTo) { if (last->out() && last->isRegular() && last->id <= upTo) {
session().changes().messageUpdated( session().changes().messageUpdated(
last, last,
Data::MessageUpdate::Flag::DialogRowRepaint); Data::MessageUpdate::Flag::DialogRowRepaint);
@ -1607,7 +1607,7 @@ void History::outboxRead(MsgId upTo) {
} }
void History::outboxRead(not_null<const HistoryItem*> wasRead) { void History::outboxRead(not_null<const HistoryItem*> wasRead) {
if (IsServerMsgId(wasRead->id)) { if (wasRead->isRegular()) {
outboxRead(wasRead->id); outboxRead(wasRead->id);
} }
} }
@ -1663,7 +1663,7 @@ void History::setUnreadCount(int newUnreadCount) {
const auto lastOutgoing = [&] { const auto lastOutgoing = [&] {
const auto last = lastMessage(); const auto last = lastMessage();
return last return last
&& IsServerMsgId(last->id) && last->isRegular()
&& loadedAtBottom() && loadedAtBottom()
&& !isEmpty() && !isEmpty()
&& blocks.back()->messages.back()->data() == last && blocks.back()->messages.back()->data() == last
@ -1757,7 +1757,7 @@ void History::getNextFirstUnreadMessage() {
const auto block = _firstUnreadView->block(); const auto block = _firstUnreadView->block();
const auto index = _firstUnreadView->indexInBlock(); const auto index = _firstUnreadView->indexInBlock();
const auto setFromMessage = [&](const auto &view) { const auto setFromMessage = [&](const auto &view) {
if (IsServerMsgId(view->data()->id)) { if (view->data()->isRegular()) {
_firstUnreadView = view.get(); _firstUnreadView = view.get();
return true; return true;
} }
@ -2213,7 +2213,7 @@ void History::setLastServerMessage(HistoryItem *item) {
_lastServerMessage = item; _lastServerMessage = item;
if (_lastMessage if (_lastMessage
&& *_lastMessage && *_lastMessage
&& !IsServerMsgId((*_lastMessage)->id) && !(*_lastMessage)->isRegular()
&& (!item || (*_lastMessage)->date() > item->date())) { && (!item || (*_lastMessage)->date() > item->date())) {
return; return;
} }
@ -2225,7 +2225,7 @@ void History::setLastMessage(HistoryItem *item) {
return; return;
} }
_lastMessage = item; _lastMessage = item;
if (!item || IsServerMsgId(item->id)) { if (!item || item->isRegular()) {
_lastServerMessage = item; _lastServerMessage = item;
} }
if (peer->migrateTo()) { if (peer->migrateTo()) {
@ -2260,7 +2260,7 @@ void History::setChatListMessage(HistoryItem *item) {
} }
if (_chatListMessage if (_chatListMessage
&& *_chatListMessage && *_chatListMessage
&& !IsServerMsgId((*_chatListMessage)->id) && !(*_chatListMessage)->isRegular()
&& (*_chatListMessage)->date() > item->date()) { && (*_chatListMessage)->date() > item->date()) {
return; return;
} }
@ -2539,7 +2539,7 @@ void History::unknownMessageDeleted(MsgId messageId) {
} }
bool History::isServerSideUnread(not_null<const HistoryItem*> item) const { bool History::isServerSideUnread(not_null<const HistoryItem*> item) const {
Expects(IsServerMsgId(item->id)); Expects(item->isRegular());
return item->out() return item->out()
? (!_outboxReadBefore || (item->id >= *_outboxReadBefore)) ? (!_outboxReadBefore || (item->id >= *_outboxReadBefore))
@ -2743,7 +2743,7 @@ MsgId History::minMsgId() const {
for (const auto &block : blocks) { for (const auto &block : blocks) {
for (const auto &message : block->messages) { for (const auto &message : block->messages) {
const auto item = message->data(); const auto item = message->data();
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
return item->id; return item->id;
} }
} }
@ -2755,7 +2755,7 @@ MsgId History::maxMsgId() const {
for (const auto &block : ranges::views::reverse(blocks)) { for (const auto &block : ranges::views::reverse(blocks)) {
for (const auto &message : ranges::views::reverse(block->messages)) { for (const auto &message : ranges::views::reverse(block->messages)) {
const auto item = message->data(); const auto item = message->data();
if (IsServerMsgId(item->id)) { if (item->isRegular()) {
return item->id; return item->id;
} }
} }
@ -2765,7 +2765,7 @@ MsgId History::maxMsgId() const {
MsgId History::msgIdForRead() const { MsgId History::msgIdForRead() const {
const auto last = lastMessage(); const auto last = lastMessage();
const auto result = (last && IsServerMsgId(last->id)) const auto result = (last && last->isRegular())
? last->id ? last->id
: MsgId(0); : MsgId(0);
return loadedAtBottom() return loadedAtBottom()
@ -2944,7 +2944,7 @@ void History::checkLocalMessages() {
const auto goodDate = [&](TimeId date) { const auto goodDate = [&](TimeId date) {
return (date >= firstDate && date < lastDate); return (date >= firstDate && date < lastDate);
}; };
for (const auto &item : _localMessages) { for (const auto &item : _clientSideMessages) {
if (!item->mainView() && goodDate(item->date())) { if (!item->mainView() && goodDate(item->date())) {
insertLocalMessage(item); insertLocalMessage(item);
} }
@ -2989,7 +2989,7 @@ bool History::isDisplayedEmpty() const {
} }
const auto isChangePhoto = [](not_null<HistoryItem*> item) { const auto isChangePhoto = [](not_null<HistoryItem*> item) {
if (const auto media = item->media()) { if (const auto media = item->media()) {
return (media->photo() != nullptr) && !item->toHistoryMessage(); return (media->photo() != nullptr) && item->isService();
} }
return false; return false;
}; };
@ -3108,7 +3108,7 @@ void History::clear(ClearType type) {
} else { } else {
// Leave the 'sending' messages in local messages. // Leave the 'sending' messages in local messages.
auto local = base::flat_set<not_null<HistoryItem*>>(); auto local = base::flat_set<not_null<HistoryItem*>>();
for (const auto &item : _localMessages) { for (const auto &item : _clientSideMessages) {
if (!item->isSending()) { if (!item->isSending()) {
local.emplace(item); local.emplace(item);
} }
@ -3124,7 +3124,7 @@ void History::clear(ClearType type) {
if (type == ClearType::DeleteChat) { if (type == ClearType::DeleteChat) {
setLastServerMessage(nullptr); setLastServerMessage(nullptr);
} else if (_lastMessage && *_lastMessage) { } else if (_lastMessage && *_lastMessage) {
if (IsServerMsgId((*_lastMessage)->id)) { if ((*_lastMessage)->isRegular()) {
(*_lastMessage)->applyEditionToHistoryCleared(); (*_lastMessage)->applyEditionToHistoryCleared();
} else { } else {
_lastMessage = std::nullopt; _lastMessage = std::nullopt;
@ -3158,7 +3158,7 @@ void History::clearUpTill(MsgId availableMinId) {
remove.reserve(_messages.size()); remove.reserve(_messages.size());
for (const auto &item : _messages) { for (const auto &item : _messages) {
const auto itemId = item->id; const auto itemId = item->id;
if (!IsServerMsgId(itemId)) { if (!item->isRegular()) {
continue; continue;
} else if (itemId == availableMinId) { } else if (itemId == availableMinId) {
item->applyEditionToHistoryCleared(); item->applyEditionToHistoryCleared();

View file

@ -158,7 +158,7 @@ public:
TimeId date, TimeId date,
PeerId from, PeerId from,
const QString &postAuthor, const QString &postAuthor,
not_null<HistoryMessage*> forwardOriginal); not_null<HistoryItem*> forwardOriginal);
not_null<HistoryItem*> addNewLocalMessage( not_null<HistoryItem*> addNewLocalMessage(
MsgId id, MsgId id,
MessageFlags flags, MessageFlags flags,
@ -206,9 +206,9 @@ public:
void newItemAdded(not_null<HistoryItem*> item); void newItemAdded(not_null<HistoryItem*> item);
void registerLocalMessage(not_null<HistoryItem*> item); void registerClientSideMessage(not_null<HistoryItem*> item);
void unregisterLocalMessage(not_null<HistoryItem*> item); void unregisterClientSideMessage(not_null<HistoryItem*> item);
[[nodiscard]] auto localMessages() [[nodiscard]] auto clientSideMessages()
-> const base::flat_set<not_null<HistoryItem*>> &; -> const base::flat_set<not_null<HistoryItem*>> &;
[[nodiscard]] HistoryItem *latestSendingMessage() const; [[nodiscard]] HistoryItem *latestSendingMessage() const;
@ -600,7 +600,7 @@ private:
base::flat_set<MsgId> _unreadMentions; base::flat_set<MsgId> _unreadMentions;
std::optional<HistoryItem*> _lastMessage; std::optional<HistoryItem*> _lastMessage;
std::optional<HistoryItem*> _lastServerMessage; std::optional<HistoryItem*> _lastServerMessage;
base::flat_set<not_null<HistoryItem*>> _localMessages; base::flat_set<not_null<HistoryItem*>> _clientSideMessages;
std::unordered_set<std::unique_ptr<HistoryItem>> _messages; std::unordered_set<std::unique_ptr<HistoryItem>> _messages;
// This almost always is equal to _lastMessage. The only difference is // This almost always is equal to _lastMessage. The only difference is

View file

@ -428,7 +428,9 @@ void HistoryInner::enumerateUserpics(Method method) {
auto userpicCallback = [&](not_null<Element*> view, int itemtop, int itembottom) { auto userpicCallback = [&](not_null<Element*> view, int itemtop, int itembottom) {
// Skip all service messages. // Skip all service messages.
const auto item = view->data(); const auto item = view->data();
if (view->isHidden() || !item->toHistoryMessage()) return true; if (view->isHidden() || item->isService()) {
return true;
}
if (lowestAttachedItemTop < 0 && view->isAttachedToNext()) { if (lowestAttachedItemTop < 0 && view->isAttachedToNext()) {
lowestAttachedItemTop = itemtop + view->marginTop(); lowestAttachedItemTop = itemtop + view->marginTop();
@ -565,7 +567,7 @@ TextSelection HistoryInner::itemRenderSelection(
const auto item = view->data(); const auto item = view->data();
const auto y = view->block()->y() + view->y(); const auto y = view->block()->y() + view->y();
if (y >= selfromy && y < seltoy) { if (y >= selfromy && y < seltoy) {
if (_dragSelecting && !item->serviceMsg() && item->id > 0) { if (_dragSelecting && !item->isService() && item->isRegular()) {
return FullSelection; return FullSelection;
} }
} else if (!_selected.empty()) { } else if (!_selected.empty()) {
@ -792,8 +794,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
// paint the userpic if it intersects the painted rect // paint the userpic if it intersects the painted rect
if (userpicTop + st::msgPhotoSize > clip.top()) { if (userpicTop + st::msgPhotoSize > clip.top()) {
const auto message = view->data()->toHistoryMessage(); if (const auto from = view->data()->displayFrom()) {
if (const auto from = message->displayFrom()) {
from->paintUserpicLeft( from->paintUserpicLeft(
p, p,
_userpics[from], _userpics[from],
@ -801,7 +802,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
userpicTop, userpicTop,
width(), width(),
st::msgPhotoSize); st::msgPhotoSize);
} else if (const auto info = message->hiddenForwardedInfo()) { } else if (const auto info = view->data()->hiddenForwardedInfo()) {
info->userpic.paint( info->userpic.paint(
p, p,
st::historyPhotoLeft, st::historyPhotoLeft,
@ -1462,8 +1463,8 @@ void HistoryInner::mouseActionFinish(
_selected.erase(i); _selected.erase(i);
repaintItem(_mouseActionItem); repaintItem(_mouseActionItem);
} else if ((i == _selected.cend()) } else if ((i == _selected.cend())
&& !_dragStateItem->serviceMsg() && !_dragStateItem->isService()
&& (_dragStateItem->id > 0) && _dragStateItem->isRegular()
&& inSelectionMode()) { && inSelectionMode()) {
if (_selected.size() < MaxSelectedItems) { if (_selected.size() < MaxSelectedItems) {
_selected.emplace(_dragStateItem, FullSelection); _selected.emplace(_dragStateItem, FullSelection);
@ -1621,7 +1622,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
HistoryItem *item, HistoryItem *item,
HistoryItem *albumPartItem) { HistoryItem *albumPartItem) {
if (!item if (!item
|| !IsServerMsgId(item->id) || !item->isRegular()
|| isUponSelected == 2 || isUponSelected == 2
|| isUponSelected == -2) { || isUponSelected == -2) {
return; return;
@ -1633,8 +1634,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}); });
} }
const auto repliesCount = item->repliesCount(); const auto repliesCount = item->repliesCount();
const auto withReplies = IsServerMsgId(item->id) const auto withReplies = (repliesCount > 0);
&& (repliesCount > 0);
if (withReplies && item->history()->peer->isMegagroup()) { if (withReplies && item->history()->peer->isMegagroup()) {
const auto rootId = repliesCount ? item->id : item->replyToTop(); const auto rootId = repliesCount ? item->id : item->replyToTop();
const auto phrase = (repliesCount > 0) const auto phrase = (repliesCount > 0)
@ -1807,7 +1807,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}); });
} }
} }
if (IsServerMsgId(item->id) && !item->serviceMsg()) { if (item->isRegular() && !item->isService()) {
_menu->addAction(tr::lng_context_select_msg(tr::now), [=] { _menu->addAction(tr::lng_context_select_msg(tr::now), [=] {
if (const auto item = session->data().message(itemId)) { if (const auto item = session->data().message(itemId)) {
if (const auto view = item->mainView()) { if (const auto view = item->mainView()) {
@ -1837,13 +1837,12 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
const auto itemId = item ? item->fullId() : FullMsgId(); const auto itemId = item ? item->fullId() : FullMsgId();
const auto canDelete = item const auto canDelete = item
&& item->canDelete() && item->canDelete()
&& (item->id > 0 || !item->serviceMsg()); && (item->isRegular() || !item->isService());
const auto canForward = item && item->allowsForward(); const auto canForward = item && item->allowsForward();
const auto canReport = item && item->suggestReport(); const auto canReport = item && item->suggestReport();
const auto canBlockSender = item && item->history()->peer->isRepliesChat(); const auto canBlockSender = item && item->history()->peer->isRepliesChat();
const auto view = item ? item->mainView() : nullptr; const auto view = item ? item->mainView() : nullptr;
const auto msg = dynamic_cast<HistoryMessage*>(item);
if (isUponSelected > 0) { if (isUponSelected > 0) {
_menu->addAction( _menu->addAction(
((isUponSelected > 1) ((isUponSelected > 1)
@ -1885,12 +1884,15 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}); });
} }
} }
if (msg && view && !link && (view->hasVisibleText() || mediaHasTextForCopy)) { if (item->isSponsored()) {
if (item->isSponsored()) { _menu->addAction(tr::lng_sponsored_title({}), [=] {
_menu->addAction(tr::lng_sponsored_title({}), [=] { _controller->show(Box(Ui::AboutSponsoredBox));
_controller->show(Box(Ui::AboutSponsoredBox)); });
}); }
} if (!item->isService()
&& view
&& !link
&& (view->hasVisibleText() || mediaHasTextForCopy)) {
_menu->addAction(tr::lng_context_copy_text(tr::now), [=] { _menu->addAction(tr::lng_context_copy_text(tr::now), [=] {
copyContextText(itemId); copyContextText(itemId);
}); });
@ -1926,7 +1928,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(tr::lng_context_clear_selection(tr::now), [=] { _menu->addAction(tr::lng_context_clear_selection(tr::now), [=] {
_widget->clearSelected(); _widget->clearSelected();
}); });
} else if (item && ((isUponSelected != -2 && (canForward || canDelete)) || item->id > 0)) { } else if (item && ((isUponSelected != -2 && (canForward || canDelete)) || item->isRegular())) {
if (isUponSelected != -2) { if (isUponSelected != -2) {
if (canForward) { if (canForward) {
_menu->addAction(tr::lng_context_forward_msg(tr::now), [=] { _menu->addAction(tr::lng_context_forward_msg(tr::now), [=] {
@ -1937,7 +1939,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
const auto callback = [=] { const auto callback = [=] {
deleteAsGroup(itemId); deleteAsGroup(itemId);
}; };
if (msg && msg->uploading()) { if (item->isUploading()) {
_menu->addAction(tr::lng_context_cancel_upload(tr::now), callback); _menu->addAction(tr::lng_context_cancel_upload(tr::now), callback);
} else { } else {
_menu->addAction(Ui::DeleteMessageContextAction( _menu->addAction(Ui::DeleteMessageContextAction(
@ -1953,7 +1955,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}); });
} }
} }
if (item->id > 0 && !item->serviceMsg()) { if (item->isRegular() && !item->isService()) {
_menu->addAction(tr::lng_context_select_msg(tr::now), [=] { _menu->addAction(tr::lng_context_select_msg(tr::now), [=] {
if (const auto item = session->data().message(itemId)) { if (const auto item = session->data().message(itemId)) {
if (const auto view = item->mainView()) { if (const auto view = item->mainView()) {
@ -1971,8 +1973,8 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
} }
} else { } else {
if (App::mousedItem() if (App::mousedItem()
&& IsServerMsgId(App::mousedItem()->data()->id) && App::mousedItem()->data()->isRegular()
&& !App::mousedItem()->data()->serviceMsg()) { && !App::mousedItem()->data()->isService()) {
const auto itemId = App::mousedItem()->data()->fullId(); const auto itemId = App::mousedItem()->data()->fullId();
_menu->addAction(tr::lng_context_select_msg(tr::now), [=] { _menu->addAction(tr::lng_context_select_msg(tr::now), [=] {
if (const auto item = session->data().message(itemId)) { if (const auto item = session->data().message(itemId)) {
@ -2783,7 +2785,7 @@ MessageIdsList HistoryInner::getSelectedItems() const {
_selected.end() _selected.end()
) | views::filter([](const auto &selected) { ) | views::filter([](const auto &selected) {
const auto item = selected.first; const auto item = selected.first;
return item && item->toHistoryMessage() && (item->id > 0); return item && !item->isService() && item->isRegular();
}) | views::transform([](const auto &selected) { }) | views::transform([](const auto &selected) {
return selected.first->fullId(); return selected.first->fullId();
}) | to_vector; }) | to_vector;
@ -2935,27 +2937,22 @@ void HistoryInner::mouseActionUpdate() {
_dragStateItem = session().data().message(dragState.itemId); _dragStateItem = session().data().message(dragState.itemId);
lnkhost = view; lnkhost = view;
if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) { if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) {
if (item->toHistoryMessage()) { if (!item->isService() && view->hasFromPhoto()) {
if (view->hasFromPhoto()) { enumerateUserpics([&](not_null<Element*> view, int userpicTop) -> bool {
enumerateUserpics([&](not_null<Element*> view, int userpicTop) -> bool { // stop enumeration if the userpic is below our point
// stop enumeration if the userpic is below our point if (userpicTop > point.y()) {
if (userpicTop > point.y()) { return false;
return false; }
}
// stop enumeration if we've found a userpic under the cursor // stop enumeration if we've found a userpic under the cursor
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) { if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
const auto message = view->data()->toHistoryMessage(); dragState = TextState(nullptr, view->fromPhotoLink());
Assert(message != nullptr); _dragStateItem = nullptr;
lnkhost = view;
dragState = TextState(nullptr, view->fromPhotoLink()); return false;
_dragStateItem = session().data().message(dragState.itemId); }
lnkhost = view; return true;
return false; });
}
return true;
});
}
} }
} }
} }
@ -3040,7 +3037,9 @@ void HistoryInner::mouseActionUpdate() {
} }
auto dragSelecting = false; auto dragSelecting = false;
auto dragFirstAffected = dragSelFrom; auto dragFirstAffected = dragSelFrom;
while (dragFirstAffected && (dragFirstAffected->data()->id < 0 || dragFirstAffected->data()->serviceMsg())) { while (dragFirstAffected
&& (!dragFirstAffected->data()->isRegular()
|| dragFirstAffected->data()->isService())) {
dragFirstAffected = (dragFirstAffected != dragSelTo) dragFirstAffected = (dragFirstAffected != dragSelTo)
? (selectingDown ? (selectingDown
? nextItem(dragFirstAffected) ? nextItem(dragFirstAffected)
@ -3186,7 +3185,7 @@ auto HistoryInner::findViewForPinnedTracking(int top) const
const auto fromHistory = [&](not_null<History*> history, int historyTop) const auto fromHistory = [&](not_null<History*> history, int historyTop)
-> std::pair<Element*, int> { -> std::pair<Element*, int> {
auto [view, offset] = history->findItemAndOffset(top - historyTop); auto [view, offset] = history->findItemAndOffset(top - historyTop);
while (view && !IsServerMsgId(view->data()->id)) { while (view && !view->data()->isRegular()) {
offset -= view->height(); offset -= view->height();
view = view->nextInBlocks(); view = view->nextInBlocks();
} }
@ -3262,10 +3261,9 @@ bool HistoryInner::goodForSelection(
not_null<SelectedItems*> toItems, not_null<SelectedItems*> toItems,
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
int &totalCount) const { int &totalCount) const {
if (item->id <= 0 || item->serviceMsg()) { if (!item->isRegular() || item->isService()) {
return false; return false;
} } else if (toItems->find(item) == toItems->end()) {
if (toItems->find(item) == toItems->end()) {
++totalCount; ++totalCount;
} }
return true; return true;
@ -3367,11 +3365,9 @@ void HistoryInner::deleteItem(FullMsgId itemId) {
} }
void HistoryInner::deleteItem(not_null<HistoryItem*> item) { void HistoryInner::deleteItem(not_null<HistoryItem*> item) {
if (auto message = item->toHistoryMessage()) { if (item->isUploading()) {
if (message->uploading()) { _controller->cancelUploadLayer(item);
_controller->cancelUploadLayer(item); return;
return;
}
} }
const auto suggestModerateActions = true; const auto suggestModerateActions = true;
_controller->show(Box<DeleteMessagesBox>(item, suggestModerateActions)); _controller->show(Box<DeleteMessagesBox>(item, suggestModerateActions));

View file

@ -164,6 +164,15 @@ MediaCheckResult CheckMessageMedia(const MTPMessageMedia &media) {
}); });
} }
[[nodiscard]] MessageFlags FinalizeMessageFlags(MessageFlags flags) {
if (!(flags & MessageFlag::FakeHistoryItem)
&& !(flags & MessageFlag::IsOrWasScheduled)
&& !(flags & MessageFlag::AdminLogEntry)) {
flags |= MessageFlag::HistoryEntry;
}
return flags;
}
} // namespace } // namespace
void HistoryItem::HistoryItem::Destroyer::operator()(HistoryItem *value) { void HistoryItem::HistoryItem::Destroyer::operator()(HistoryItem *value) {
@ -181,10 +190,10 @@ HistoryItem::HistoryItem(
: id(id) : id(id)
, _history(history) , _history(history)
, _from(from ? history->owner().peer(from) : history->peer) , _from(from ? history->owner().peer(from) : history->peer)
, _flags(flags) , _flags(FinalizeMessageFlags(flags))
, _date(date) { , _date(date) {
if (isHistoryEntry() && IsClientMsgId(id)) { if (isHistoryEntry() && IsClientMsgId(id)) {
_history->registerLocalMessage(this); _history->registerClientSideMessage(this);
} }
} }
@ -433,8 +442,7 @@ UserData *HistoryItem::getMessageBot() const {
} }
bool HistoryItem::isHistoryEntry() const { bool HistoryItem::isHistoryEntry() const {
return IsServerMsgId(id) return (_flags & MessageFlag::HistoryEntry);
|| (_flags & MessageFlag::LocalHistoryEntry);
} }
bool HistoryItem::isAdminLogEntry() const { bool HistoryItem::isAdminLogEntry() const {
@ -553,7 +561,7 @@ void HistoryItem::applySentMessage(
} }
void HistoryItem::indexAsNewItem() { void HistoryItem::indexAsNewItem() {
if (IsServerMsgId(id)) { if (isRegular()) {
addToUnreadMentions(UnreadMentionType::New); addToUnreadMentions(UnreadMentionType::New);
if (const auto types = sharedMediaTypes()) { if (const auto types = sharedMediaTypes()) {
_history->session().storage().add(Storage::SharedMediaAddNew( _history->session().storage().add(Storage::SharedMediaAddNew(
@ -572,9 +580,9 @@ void HistoryItem::setRealId(MsgId newId) {
Expects(IsClientMsgId(id)); Expects(IsClientMsgId(id));
const auto oldId = std::exchange(id, newId); const auto oldId = std::exchange(id, newId);
_flags &= ~MessageFlag::BeingSent; _flags &= ~(MessageFlag::BeingSent | MessageFlag::Local);
if (IsServerMsgId(id)) { if (isRegular()) {
_history->unregisterLocalMessage(this); _history->unregisterClientSideMessage(this);
} }
_history->owner().notifyItemIdChange({ this, oldId }); _history->owner().notifyItemIdChange({ this, oldId });
@ -591,7 +599,7 @@ void HistoryItem::setRealId(MsgId newId) {
} }
bool HistoryItem::canPin() const { bool HistoryItem::canPin() const {
if (id < 0 || !toHistoryMessage()) { if (!isRegular() || isService()) {
return false; return false;
} else if (const auto m = media(); m && m->call()) { } else if (const auto m = media(); m && m->call()) {
return false; return false;
@ -612,7 +620,7 @@ bool HistoryItem::allowsEdit(TimeId now) const {
} }
bool HistoryItem::canStopPoll() const { bool HistoryItem::canStopPoll() const {
if (id < 0 if (!isRegular()
|| Has<HistoryMessageVia>() || Has<HistoryMessageVia>()
|| Has<HistoryMessageForwarded>()) { || Has<HistoryMessageForwarded>()) {
return false; return false;
@ -636,7 +644,7 @@ bool HistoryItem::canStopPoll() const {
bool HistoryItem::canDelete() const { bool HistoryItem::canDelete() const {
if (isSponsored()) { if (isSponsored()) {
return false; return false;
} else if (!IsServerMsgId(id) && serviceMsg()) { } else if (isService() && !isRegular()) {
return false; return false;
} else if (!isHistoryEntry() && !isScheduled()) { } else if (!isHistoryEntry() && !isScheduled()) {
return false; return false;
@ -652,7 +660,7 @@ bool HistoryItem::canDelete() const {
if (channel->canDeleteMessages()) { if (channel->canDeleteMessages()) {
return true; return true;
} }
if (out() && toHistoryMessage()) { if (out() && !isService()) {
return isPost() ? channel->canPublish() : true; return isPost() ? channel->canPublish() : true;
} }
return false; return false;
@ -667,7 +675,7 @@ bool HistoryItem::canDeleteForEveryone(TimeId now) const {
: peer->isUser() : peer->isUser()
? (now - date() >= config.revokePrivateTimeLimit) ? (now - date() >= config.revokePrivateTimeLimit)
: (now - date() >= config.revokeTimeLimit); : (now - date() >= config.revokeTimeLimit);
if (id < 0 || messageToMyself || messageTooOld || isPost()) { if (!isRegular() || messageToMyself || messageTooOld || isPost()) {
return false; return false;
} }
if (peer->isChannel()) { if (peer->isChannel()) {
@ -699,7 +707,7 @@ bool HistoryItem::canDeleteForEveryone(TimeId now) const {
} }
bool HistoryItem::suggestReport() const { bool HistoryItem::suggestReport() const {
if (out() || serviceMsg() || !IsServerMsgId(id)) { if (out() || isService() || !isRegular()) {
return false; return false;
} else if (const auto channel = history()->peer->asChannel()) { } else if (const auto channel = history()->peer->asChannel()) {
return true; return true;
@ -729,7 +737,7 @@ bool HistoryItem::suggestDeleteAllReport() const {
} }
bool HistoryItem::hasDirectLink() const { bool HistoryItem::hasDirectLink() const {
return IsServerMsgId(id) && _history->peer->isChannel(); return isRegular() && _history->peer->isChannel();
} }
ChannelId HistoryItem::channelId() const { ChannelId HistoryItem::channelId() const {
@ -855,6 +863,14 @@ void HistoryItem::applyTTL(TimeId destroyAt) {
} }
} }
bool HistoryItem::isUploading() const {
return _media && _media->uploading();
}
bool HistoryItem::isRegular() const {
return isHistoryEntry() && !isLocal();
}
void HistoryItem::sendFailed() { void HistoryItem::sendFailed() {
Expects(_flags & MessageFlag::BeingSent); Expects(_flags & MessageFlag::BeingSent);
Expects(!(_flags & MessageFlag::SendingFailed)); Expects(!(_flags & MessageFlag::SendingFailed));
@ -862,11 +878,11 @@ void HistoryItem::sendFailed() {
_flags = (_flags | MessageFlag::SendingFailed) & ~MessageFlag::BeingSent; _flags = (_flags | MessageFlag::SendingFailed) & ~MessageFlag::BeingSent;
history()->session().changes().historyUpdated( history()->session().changes().historyUpdated(
history(), history(),
Data::HistoryUpdate::Flag::LocalMessages); Data::HistoryUpdate::Flag::ClientSideMessages);
} }
bool HistoryItem::needCheck() const { bool HistoryItem::needCheck() const {
return (out() && !isEmpty()) || (id < 0 && history()->peer->isSelf()); return (out() && !isEmpty()) || (!isRegular() && history()->peer->isSelf());
} }
bool HistoryItem::unread() const { bool HistoryItem::unread() const {
@ -881,7 +897,7 @@ bool HistoryItem::unread() const {
return false; return false;
} }
if (IsServerMsgId(id)) { if (isRegular()) {
if (!history()->isServerSideUnread(this)) { if (!history()->isServerSideUnread(this)) {
return false; return false;
} }
@ -898,7 +914,7 @@ bool HistoryItem::unread() const {
return true; return true;
} }
if (IsServerMsgId(id)) { if (isRegular()) {
if (!history()->isServerSideUnread(this)) { if (!history()->isServerSideUnread(this)) {
return false; return false;
} }
@ -933,7 +949,7 @@ bool HistoryItem::isEmpty() const {
QString HistoryItem::notificationText() const { QString HistoryItem::notificationText() const {
const auto result = [&] { const auto result = [&] {
if (_media && !serviceMsg()) { if (_media && !isService()) {
return _media->notificationText(); return _media->notificationText();
} else if (!emptyText()) { } else if (!emptyText()) {
return _text.toString(); return _text.toString();
@ -1040,10 +1056,14 @@ ClickHandlerPtr goToMessageClickHandler(
}); });
} }
MessageFlags FlagsFromMTP(MTPDmessage::Flags flags) { MessageFlags FlagsFromMTP(
MsgId id,
MTPDmessage::Flags flags,
MessageFlags localFlags) {
using Flag = MessageFlag; using Flag = MessageFlag;
using MTP = MTPDmessage::Flag; using MTP = MTPDmessage::Flag;
return Flag() return localFlags
| (IsServerMsgId(id) ? Flag::HistoryEntry : Flag())
| ((flags & MTP::f_out) ? Flag::Outgoing : Flag()) | ((flags & MTP::f_out) ? Flag::Outgoing : Flag())
| ((flags & MTP::f_mentioned) ? Flag::MentionsMe : Flag()) | ((flags & MTP::f_mentioned) ? Flag::MentionsMe : Flag())
| ((flags & MTP::f_media_unread) ? Flag::MediaIsUnread : Flag()) | ((flags & MTP::f_media_unread) ? Flag::MediaIsUnread : Flag())
@ -1060,10 +1080,14 @@ MessageFlags FlagsFromMTP(MTPDmessage::Flags flags) {
| ((flags & MTP::f_views) ? Flag::HasViews : Flag()); | ((flags & MTP::f_views) ? Flag::HasViews : Flag());
} }
MessageFlags FlagsFromMTP(MTPDmessageService::Flags flags) { MessageFlags FlagsFromMTP(
MsgId id,
MTPDmessageService::Flags flags,
MessageFlags localFlags) {
using Flag = MessageFlag; using Flag = MessageFlag;
using MTP = MTPDmessageService::Flag; using MTP = MTPDmessageService::Flag;
return Flag() return localFlags
| (IsServerMsgId(id) ? Flag::HistoryEntry : Flag())
| ((flags & MTP::f_out) ? Flag::Outgoing : Flag()) | ((flags & MTP::f_out) ? Flag::Outgoing : Flag())
| ((flags & MTP::f_mentioned) ? Flag::MentionsMe : Flag()) | ((flags & MTP::f_mentioned) ? Flag::MentionsMe : Flag())
| ((flags & MTP::f_media_unread) ? Flag::MediaIsUnread : Flag()) | ((flags & MTP::f_media_unread) ? Flag::MediaIsUnread : Flag())
@ -1088,7 +1112,7 @@ not_null<HistoryItem*> HistoryItem::Create(
return CreateUnsupportedMessage( return CreateUnsupportedMessage(
history, history,
id, id,
FlagsFromMTP(data.vflags().v) | localFlags, FlagsFromMTP(id, data.vflags().v, localFlags),
MsgId(0), // No need to pass reply_to data here. MsgId(0), // No need to pass reply_to data here.
data.vvia_bot_id().value_or_empty(), data.vvia_bot_id().value_or_empty(),
data.vdate().v, data.vdate().v,
@ -1099,7 +1123,7 @@ not_null<HistoryItem*> HistoryItem::Create(
}; };
return history->makeServiceMessage( return history->makeServiceMessage(
id, id,
FlagsFromMTP(data.vflags().v) | localFlags, FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v, data.vdate().v,
text, text,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)); data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0));

View file

@ -87,8 +87,14 @@ struct ToPreviewOptions {
struct HiddenSenderInfo; struct HiddenSenderInfo;
class History; class History;
[[nodiscard]] MessageFlags FlagsFromMTP(MTPDmessage::Flags flags); [[nodiscard]] MessageFlags FlagsFromMTP(
[[nodiscard]] MessageFlags FlagsFromMTP(MTPDmessageService::Flags flags); MsgId id,
MTPDmessage::Flags flags,
MessageFlags localFlags);
[[nodiscard]] MessageFlags FlagsFromMTP(
MsgId id,
MTPDmessageService::Flags flags,
MessageFlags localFlags);
class HistoryItem : public RuntimeComposer<HistoryItem> { class HistoryItem : public RuntimeComposer<HistoryItem> {
public: public:
@ -230,6 +236,11 @@ public:
[[nodiscard]] bool hideEditedBadge() const { [[nodiscard]] bool hideEditedBadge() const {
return (_flags & MessageFlag::HideEdited); return (_flags & MessageFlag::HideEdited);
} }
[[nodiscard]] bool isLocal() const {
return _flags & MessageFlag::Local;
}
[[nodiscard]] bool isRegular() const;
[[nodiscard]] bool isUploading() const;
void sendFailed(); void sendFailed();
[[nodiscard]] virtual int viewsCount() const { [[nodiscard]] virtual int viewsCount() const {
return hasViews() ? 1 : -1; return hasViews() ? 1 : -1;
@ -278,7 +289,7 @@ public:
[[nodiscard]] virtual bool needCheck() const; [[nodiscard]] virtual bool needCheck() const;
[[nodiscard]] virtual bool serviceMsg() const { [[nodiscard]] virtual bool isService() const {
return false; return false;
} }
virtual void applyEdition(HistoryMessageEdition &&edition) { virtual void applyEdition(HistoryMessageEdition &&edition) {
@ -392,12 +403,6 @@ public:
return false; return false;
} }
[[nodiscard]] virtual HistoryMessage *toHistoryMessage() { // dynamic_cast optimize
return nullptr;
}
[[nodiscard]] virtual const HistoryMessage *toHistoryMessage() const { // dynamic_cast optimize
return nullptr;
}
[[nodiscard]] MsgId replyToId() const; [[nodiscard]] MsgId replyToId() const;
[[nodiscard]] MsgId replyToTop() const; [[nodiscard]] MsgId replyToTop() const;

View file

@ -58,7 +58,7 @@ namespace {
[[nodiscard]] MessageFlags NewForwardedFlags( [[nodiscard]] MessageFlags NewForwardedFlags(
not_null<PeerData*> peer, not_null<PeerData*> peer,
PeerId from, PeerId from,
not_null<HistoryMessage*> fwd) { not_null<HistoryItem*> fwd) {
auto result = NewMessageFlags(peer); auto result = NewMessageFlags(peer);
if (from) { if (from) {
result |= MessageFlag::HasFromId; result |= MessageFlag::HasFromId;
@ -458,7 +458,7 @@ HistoryMessage::HistoryMessage(
: HistoryItem( : HistoryItem(
history, history,
id, id,
FlagsFromMTP(data.vflags().v) | localFlags, FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v, data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) { data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
auto config = CreateConfig(); auto config = CreateConfig();
@ -516,7 +516,7 @@ HistoryMessage::HistoryMessage(
: HistoryItem( : HistoryItem(
history, history,
id, id,
FlagsFromMTP(data.vflags().v) | localFlags, FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v, data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) { data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
auto config = CreateConfig(); auto config = CreateConfig();
@ -553,11 +553,11 @@ HistoryMessage::HistoryMessage(
TimeId date, TimeId date,
PeerId from, PeerId from,
const QString &postAuthor, const QString &postAuthor,
not_null<HistoryMessage*> original) not_null<HistoryItem*> original)
: HistoryItem( : HistoryItem(
history, history,
id, id,
NewForwardedFlags(history->peer, from, original) | flags, (NewForwardedFlags(history->peer, from, original) | flags),
date, date,
from) { from) {
const auto peer = history->peer; const auto peer = history->peer;
@ -1026,10 +1026,7 @@ void HistoryMessage::applySentMessage(
} }
bool HistoryMessage::allowsForward() const { bool HistoryMessage::allowsForward() const {
if (id < 0 || !isHistoryEntry()) { return isRegular() && (!_media || _media->allowsForward());
return false;
}
return !_media || _media->allowsForward();
} }
bool HistoryMessage::allowsSendNow() const { bool HistoryMessage::allowsSendNow() const {
@ -1050,10 +1047,6 @@ bool HistoryMessage::allowsEdit(TimeId now) const {
&& !isEditingMedia(); && !isEditingMedia();
} }
bool HistoryMessage::uploading() const {
return _media && _media->uploading();
}
void HistoryMessage::createComponents(CreateConfig &&config) { void HistoryMessage::createComponents(CreateConfig &&config) {
uint64 mask = 0; uint64 mask = 0;
if (config.replyTo) { if (config.replyTo) {
@ -1486,14 +1479,14 @@ void HistoryMessage::updateReplyMarkup(HistoryMessageMarkupData &&markup) {
void HistoryMessage::contributeToSlowmode(TimeId realDate) { void HistoryMessage::contributeToSlowmode(TimeId realDate) {
if (const auto channel = history()->peer->asChannel()) { if (const auto channel = history()->peer->asChannel()) {
if (out() && IsServerMsgId(id)) { if (out() && isRegular()) {
channel->growSlowmodeLastMessage(realDate ? realDate : date()); channel->growSlowmodeLastMessage(realDate ? realDate : date());
} }
} }
} }
void HistoryMessage::addToUnreadMentions(UnreadMentionType type) { void HistoryMessage::addToUnreadMentions(UnreadMentionType type) {
if (IsServerMsgId(id) && isUnreadMention()) { if (isRegular() && isUnreadMention()) {
if (history()->addToUnreadMentions(id, type)) { if (history()->addToUnreadMentions(id, type)) {
history()->session().changes().historyUpdated( history()->session().changes().historyUpdated(
history(), history(),
@ -1921,7 +1914,7 @@ void HistoryMessage::incrementReplyToTopCounter() {
void HistoryMessage::changeReplyToTopCounter( void HistoryMessage::changeReplyToTopCounter(
not_null<HistoryMessageReply*> reply, not_null<HistoryMessageReply*> reply,
int delta) { int delta) {
if (!IsServerMsgId(id) || !reply->replyToTop()) { if (!isRegular() || !reply->replyToTop()) {
return; return;
} }
const auto channelId = history()->channelId(); const auto channelId = history()->channelId();

View file

@ -64,7 +64,7 @@ public:
TimeId date, TimeId date,
PeerId from, PeerId from,
const QString &postAuthor, const QString &postAuthor,
not_null<HistoryMessage*> original); // local forwarded not_null<HistoryItem*> original); // local forwarded
HistoryMessage( HistoryMessage(
not_null<History*> history, not_null<History*> history,
MsgId id, MsgId id,
@ -126,7 +126,6 @@ public:
[[nodiscard]] bool allowsForward() const override; [[nodiscard]] bool allowsForward() const override;
[[nodiscard]] bool allowsSendNow() const override; [[nodiscard]] bool allowsSendNow() const override;
[[nodiscard]] bool allowsEdit(TimeId now) const override; [[nodiscard]] bool allowsEdit(TimeId now) const override;
[[nodiscard]] bool uploading() const;
void setViewsCount(int count) override; void setViewsCount(int count) override;
void setForwardsCount(int count) override; void setForwardsCount(int count) override;
@ -205,14 +204,6 @@ public:
const MTPDupdateShortSentMessage &data, const MTPDupdateShortSentMessage &data,
bool wasAlready) override; bool wasAlready) override;
// dynamic_cast optimization.
[[nodiscard]] HistoryMessage *toHistoryMessage() override {
return this;
}
[[nodiscard]] const HistoryMessage *toHistoryMessage() const override {
return this;
}
[[nodiscard]] std::unique_ptr<HistoryView::Element> createView( [[nodiscard]] std::unique_ptr<HistoryView::Element> createView(
not_null<HistoryView::ElementDelegate*> delegate, not_null<HistoryView::ElementDelegate*> delegate,
HistoryView::Element *replacing = nullptr) override; HistoryView::Element *replacing = nullptr) override;

View file

@ -889,7 +889,7 @@ HistoryService::HistoryService(
: HistoryItem( : HistoryItem(
history, history,
id, id,
FlagsFromMTP(data.vflags().v) | localFlags, FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v, data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) { data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
createFromMtp(data); createFromMtp(data);
@ -904,7 +904,7 @@ HistoryService::HistoryService(
: HistoryItem( : HistoryItem(
history, history,
id, id,
FlagsFromMTP(data.vflags().v) | localFlags, FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v, data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) { data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
createFromMtp(data); createFromMtp(data);
@ -1280,7 +1280,7 @@ not_null<HistoryService*> GenerateJoinedMessage(
bool viaRequest) { bool viaRequest) {
return history->makeServiceMessage( return history->makeServiceMessage(
history->owner().nextLocalMessageId(), history->owner().nextLocalMessageId(),
MessageFlag::LocalHistoryEntry, MessageFlag::Local,
inviteDate, inviteDate,
GenerateJoinedText(history, inviter, viaRequest)); GenerateJoinedText(history, inviter, viaRequest));
} }

View file

@ -108,7 +108,7 @@ public:
void dependencyItemRemoved(HistoryItem *dependency) override; void dependencyItemRemoved(HistoryItem *dependency) override;
bool needCheck() const override; bool needCheck() const override;
bool serviceMsg() const override { bool isService() const override {
return true; return true;
} }
ItemPreview toPreview(ToPreviewOptions options) const override; ItemPreview toPreview(ToPreviewOptions options) const override;

View file

@ -562,7 +562,7 @@ HistoryWidget::HistoryWidget(
| HistoryUpdateFlag::UnreadMentions | HistoryUpdateFlag::UnreadMentions
| HistoryUpdateFlag::UnreadView | HistoryUpdateFlag::UnreadView
| HistoryUpdateFlag::TopPromoted | HistoryUpdateFlag::TopPromoted
| HistoryUpdateFlag::LocalMessages | HistoryUpdateFlag::ClientSideMessages
| HistoryUpdateFlag::PinnedMessages | HistoryUpdateFlag::PinnedMessages
) | rpl::filter([=](const Data::HistoryUpdate &update) { ) | rpl::filter([=](const Data::HistoryUpdate &update) {
if (_migrated && update.history.get() == _migrated) { if (_migrated && update.history.get() == _migrated) {
@ -586,7 +586,7 @@ HistoryWidget::HistoryWidget(
if (flags & HistoryUpdateFlag::CloudDraft) { if (flags & HistoryUpdateFlag::CloudDraft) {
applyCloudDraft(update.history); applyCloudDraft(update.history);
} }
if (flags & HistoryUpdateFlag::LocalMessages) { if (flags & HistoryUpdateFlag::ClientSideMessages) {
updateSendButtonType(); updateSendButtonType();
} }
if (flags & HistoryUpdateFlag::UnreadMentions) { if (flags & HistoryUpdateFlag::UnreadMentions) {
@ -5337,7 +5337,7 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) {
} }
void HistoryWidget::botCallbackSent(not_null<HistoryItem*> item) { void HistoryWidget::botCallbackSent(not_null<HistoryItem*> item) {
if (item->id < 0 || _peer != item->history()->peer) { if (!item->isRegular() || _peer != item->history()->peer) {
return; return;
} }
@ -6239,11 +6239,10 @@ void HistoryWidget::replyToMessage(FullMsgId itemId) {
} }
void HistoryWidget::replyToMessage(not_null<HistoryItem*> item) { void HistoryWidget::replyToMessage(not_null<HistoryItem*> item) {
if (!IsServerMsgId(item->id) || !_canSendMessages) { if (!item->isRegular() || !_canSendMessages) {
return; return;
} } else if (item->history() == _migrated) {
if (item->history() == _migrated) { if (item->isService()) {
if (item->serviceMsg()) {
controller()->show(Box<Ui::InformBox>( controller()->show(Box<Ui::InformBox>(
tr::lng_reply_cant(tr::now))); tr::lng_reply_cant(tr::now)));
} else { } else {

View file

@ -62,14 +62,6 @@ namespace {
constexpr auto kRescheduleLimit = 20; constexpr auto kRescheduleLimit = 20;
MsgId ItemIdAcrossData(not_null<HistoryItem*> item) {
if (!item->isScheduled() || item->isSending() || item->hasFailed()) {
return item->id;
}
const auto session = &item->history()->session();
return session->data().scheduledMessages().lookupId(item);
}
bool HasEditMessageAction( bool HasEditMessageAction(
const ContextMenuRequest &request, const ContextMenuRequest &request,
not_null<ListWidget*> list) { not_null<ListWidget*> list) {
@ -548,7 +540,7 @@ bool AddReplyToMessageAction(
const auto context = list->elementContext(); const auto context = list->elementContext();
const auto item = request.item; const auto item = request.item;
if (!item if (!item
|| !IsServerMsgId(item->id) || !item->isRegular()
|| !item->history()->peer->canWrite() || !item->history()->peer->canWrite()
|| (context != Context::History && context != Context::Replies)) { || (context != Context::History && context != Context::Replies)) {
return false; return false;
@ -572,7 +564,7 @@ bool AddViewRepliesAction(
const auto context = list->elementContext(); const auto context = list->elementContext();
const auto item = request.item; const auto item = request.item;
if (!item if (!item
|| !IsServerMsgId(item->id) || !item->isRegular()
|| (context != Context::History && context != Context::Pinned)) { || (context != Context::History && context != Context::Pinned)) {
return false; return false;
} }
@ -626,7 +618,7 @@ bool AddPinMessageAction(
const auto context = list->elementContext(); const auto context = list->elementContext();
const auto item = request.item; const auto item = request.item;
if (!item if (!item
|| !IsServerMsgId(item->id) || !item->isRegular()
|| (context != Context::History && context != Context::Pinned)) { || (context != Context::History && context != Context::Pinned)) {
return false; return false;
} }
@ -653,7 +645,7 @@ bool AddGoToMessageAction(
const auto context = list->elementContext(); const auto context = list->elementContext();
const auto view = request.view; const auto view = request.view;
if (!view if (!view
|| !IsServerMsgId(view->data()->id) || !view->data()->isRegular()
|| context != Context::Pinned || context != Context::Pinned
|| !view->hasOutLayout()) { || !view->hasOutLayout()) {
return false; return false;
@ -719,8 +711,7 @@ bool AddDeleteMessageAction(
if (asGroup) { if (asGroup) {
if (const auto group = owner->groups().find(item)) { if (const auto group = owner->groups().find(item)) {
if (ranges::any_of(group->items, [](auto item) { if (ranges::any_of(group->items, [](auto item) {
const auto id = ItemIdAcrossData(item); return item->isLocal() || !item->canDelete();
return !IsServerMsgId(id) || !item->canDelete();
})) { })) {
return false; return false;
} }
@ -738,24 +729,20 @@ bool AddDeleteMessageAction(
return; return;
} }
} }
if (const auto message = item->toHistoryMessage()) { if (item->isUploading()) {
if (message->uploading()) { controller->cancelUploadLayer(item);
controller->cancelUploadLayer(item); return;
return;
}
} }
const auto suggestModerateActions = true; const auto suggestModerateActions = true;
controller->show( controller->show(
Box<DeleteMessagesBox>(item, suggestModerateActions)); Box<DeleteMessagesBox>(item, suggestModerateActions));
} }
}); });
if (const auto message = item->toHistoryMessage()) { if (item->isUploading()) {
if (message->uploading()) { menu->addAction(
menu->addAction( tr::lng_context_cancel_upload(tr::now),
tr::lng_context_cancel_upload(tr::now), callback);
callback); return true;
return true;
}
} }
menu->addAction(Ui::DeleteMessageContextAction( menu->addAction(Ui::DeleteMessageContextAction(
menu->menu(), menu->menu(),
@ -820,11 +807,7 @@ bool AddSelectMessageAction(
const auto item = request.item; const auto item = request.item;
if (request.overSelection && !request.selectedItems.empty()) { if (request.overSelection && !request.selectedItems.empty()) {
return false; return false;
} else if (!item } else if (!item || item->isLocal() || item->isService()) {
|| item->isSending()
|| item->hasFailed()
|| !IsServerMsgId(ItemIdAcrossData(item))
|| item->serviceMsg()) {
return false; return false;
} }
const auto owner = &item->history()->owner(); const auto owner = &item->history()->owner();

View file

@ -536,7 +536,7 @@ void Element::refreshDataId() {
bool Element::computeIsAttachToPrevious(not_null<Element*> previous) { bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
const auto mayBeAttached = [](not_null<HistoryItem*> item) { const auto mayBeAttached = [](not_null<HistoryItem*> item) {
return !item->serviceMsg() return !item->isService()
&& !item->isEmpty() && !item->isEmpty()
&& !item->isPost() && !item->isPost()
&& (item->from() != item->history()->peer && (item->from() != item->history()->peer

View file

@ -166,8 +166,9 @@ void ListWidget::enumerateUserpics(Method method) {
auto userpicCallback = [&](not_null<Element*> view, int itemtop, int itembottom) { auto userpicCallback = [&](not_null<Element*> view, int itemtop, int itembottom) {
// Skip all service messages. // Skip all service messages.
auto message = view->data()->toHistoryMessage(); if (view->data()->isService()) {
if (!message) return true; return true;
}
if (lowestAttachedItemTop < 0 && view->isAttachedToNext()) { if (lowestAttachedItemTop < 0 && view->isAttachedToNext()) {
lowestAttachedItemTop = itemtop + view->marginTop(); lowestAttachedItemTop = itemtop + view->marginTop();
@ -1659,10 +1660,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
// paint the userpic if it intersects the painted rect // paint the userpic if it intersects the painted rect
if (userpicTop + st::msgPhotoSize > clip.top()) { if (userpicTop + st::msgPhotoSize > clip.top()) {
const auto message = view->data()->toHistoryMessage(); if (const auto from = view->data()->displayFrom()) {
Assert(message != nullptr);
if (const auto from = message->displayFrom()) {
from->paintUserpicLeft( from->paintUserpicLeft(
p, p,
_userpics[from], _userpics[from],
@ -1670,7 +1668,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
userpicTop, userpicTop,
view->width(), view->width(),
st::msgPhotoSize); st::msgPhotoSize);
} else if (const auto info = message->hiddenForwardedInfo()) { } else if (const auto info = view->data()->hiddenForwardedInfo()) {
info->userpic.paint( info->userpic.paint(
p, p,
st::historyPhotoLeft, st::historyPhotoLeft,
@ -1917,7 +1915,7 @@ void ListWidget::mouseDoubleClickEvent(QMouseEvent *e) {
|| _mouseCursorState == CursorState::Date) || _mouseCursorState == CursorState::Date)
&& _selected.empty() && _selected.empty()
&& _overElement && _overElement
&& IsServerMsgId(_overElement->data()->id)) { && _overElement->data()->isRegular()) {
mouseActionCancel(); mouseActionCancel();
replyToMessageRequestNotify(_overElement->data()->fullId()); replyToMessageRequestNotify(_overElement->data()->fullId());
} }
@ -2543,11 +2541,8 @@ void ListWidget::mouseActionUpdate() {
// stop enumeration if we've found a userpic under the cursor // stop enumeration if we've found a userpic under the cursor
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) { if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
const auto message = view->data()->toHistoryMessage();
Assert(message != nullptr);
dragState = TextState(nullptr, view->fromPhotoLink()); dragState = TextState(nullptr, view->fromPhotoLink());
_overItemExact = session().data().message(dragState.itemId); _overItemExact = nullptr;
lnkhost = view; lnkhost = view;
return false; return false;
} }

View file

@ -1783,14 +1783,14 @@ void Message::drawInfo(
if (views->replies.count > 0 if (views->replies.count > 0
&& !views->commentsMegagroupId && !views->commentsMegagroupId
&& this->context() != Context::Replies) { && this->context() != Context::Replies) {
const auto &icon = (item->id > 0) const auto &icon = (!item->isSending() && !item->hasFailed())
? (invertedsprites ? (invertedsprites
? st->historyRepliesInvertedIcon() ? st->historyRepliesInvertedIcon()
: stm->historyRepliesIcon) : stm->historyRepliesIcon)
: (invertedsprites : (invertedsprites
? st->historyViewsSendingInvertedIcon() ? st->historyViewsSendingInvertedIcon()
: st->historyViewsSendingIcon()); : st->historyViewsSendingIcon());
if (item->id > 0) { if (!item->isSending() && !item->hasFailed()) {
icon.paint(p, left, viewIconTop, width); icon.paint(p, left, viewIconTop, width);
p.drawText(left + st::historyViewsWidth, textTop, views->replies.text); p.drawText(left + st::historyViewsWidth, textTop, views->replies.text);
} else if (!context.outbg && views->views.count < 0) { // sending outbg icon will be painted below } else if (!context.outbg && views->views.count < 0) { // sending outbg icon will be painted below
@ -1802,14 +1802,14 @@ void Message::drawInfo(
+ st::historyViewsWidth; + st::historyViewsWidth;
} }
if (views->views.count >= 0) { if (views->views.count >= 0) {
const auto &icon = (item->id > 0) const auto &icon = (!item->isSending() && !item->hasFailed())
? (invertedsprites ? (invertedsprites
? st->historyViewsInvertedIcon() ? st->historyViewsInvertedIcon()
: stm->historyViewsIcon) : stm->historyViewsIcon)
: (invertedsprites : (invertedsprites
? st->historyViewsSendingInvertedIcon() ? st->historyViewsSendingInvertedIcon()
: st->historyViewsSendingIcon()); : st->historyViewsSendingIcon());
if (item->id > 0) { if (!item->isSending() && !item->hasFailed()) {
icon.paint(p, left, viewIconTop, width); icon.paint(p, left, viewIconTop, width);
p.drawText(left + st::historyViewsWidth, textTop, views->views.text); p.drawText(left + st::historyViewsWidth, textTop, views->views.text);
} else if (!context.outbg) { // sending outbg icon will be painted below } else if (!context.outbg) { // sending outbg icon will be painted below
@ -1820,7 +1820,9 @@ void Message::drawInfo(
+ views->views.textWidth + views->views.textWidth
+ st::historyViewsWidth; + st::historyViewsWidth;
} }
} else if (item->id < 0 && item->history()->peer->isSelf() && !context.outbg) { } else if ((item->isSending() || item->hasFailed())
&& item->history()->peer->isSelf()
&& !context.outbg) {
const auto &icon = invertedsprites const auto &icon = invertedsprites
? st->historyViewsSendingInvertedIcon() ? st->historyViewsSendingInvertedIcon()
: st->historyViewsSendingIcon(); : st->historyViewsSendingIcon();
@ -1834,7 +1836,7 @@ void Message::drawInfo(
left += st::historyPinWidth; left += st::historyPinWidth;
} }
if (context.outbg) { if (context.outbg) {
const auto &icon = (item->id <= 0) const auto &icon = (item->isSending() || item->hasFailed())
? (invertedsprites ? (invertedsprites
? st->historySendingInvertedIcon() ? st->historySendingInvertedIcon()
: st->historySendingIcon()) : st->historySendingIcon())
@ -1896,7 +1898,8 @@ int Message::infoWidth() const {
+ views->replies.textWidth + views->replies.textWidth
+ st::historyViewsWidth; + st::historyViewsWidth;
} }
} else if (item->id < 0 && item->history()->peer->isSelf()) { } else if ((item->isSending() || item->hasFailed())
&& item->history()->peer->isSelf()) {
if (!hasOutLayout()) { if (!hasOutLayout()) {
result += st::historySendStateSpace; result += st::historySendStateSpace;
} }
@ -1948,7 +1951,8 @@ int Message::timeLeft() const {
&& context() != Context::Replies) { && context() != Context::Replies) {
result += st::historyViewsSpace + views->replies.textWidth + st::historyViewsWidth; result += st::historyViewsSpace + views->replies.textWidth + st::historyViewsWidth;
} }
} else if (item->id < 0 && item->history()->peer->isSelf()) { } else if ((item->isSending() || item->hasFailed())
&& item->history()->peer->isSelf()) {
if (!hasOutLayout()) { if (!hasOutLayout()) {
result += st::historySendStateSpace; result += st::historySendStateSpace;
} }
@ -2180,7 +2184,7 @@ bool Message::hasFastReply() const {
bool Message::displayFastReply() const { bool Message::displayFastReply() const {
return hasFastReply() return hasFastReply()
&& IsServerMsgId(data()->id) && data()->isRegular()
&& data()->history()->peer->canWrite() && data()->history()->peer->canWrite()
&& !delegate()->elementInSelectionMode(); && !delegate()->elementInSelectionMode();
} }
@ -2213,7 +2217,7 @@ std::optional<QSize> Message::rightActionSize() const {
bool Message::displayFastShare() const { bool Message::displayFastShare() const {
const auto item = message(); const auto item = message();
const auto peer = item->history()->peer; const auto peer = item->history()->peer;
if (!IsServerMsgId(item->id)) { if (!item->isRegular()) {
return false; return false;
} else if (peer->isChannel()) { } else if (peer->isChannel()) {
return !peer->isMegagroup(); return !peer->isMegagroup();

View file

@ -613,7 +613,7 @@ bool PinnedWidget::listAllowsMultiSelect() {
bool PinnedWidget::listIsItemGoodForSelection( bool PinnedWidget::listIsItemGoodForSelection(
not_null<HistoryItem*> item) { not_null<HistoryItem*> item) {
return IsServerMsgId(item->id); return item->isRegular();
} }
bool PinnedWidget::listIsLessInOrder( bool PinnedWidget::listIsLessInOrder(
@ -661,7 +661,7 @@ bool PinnedWidget::listElementShownUnread(not_null<const Element*> view) {
bool PinnedWidget::listIsGoodForAroundPosition( bool PinnedWidget::listIsGoodForAroundPosition(
not_null<const Element*> view) { not_null<const Element*> view) {
return IsServerMsgId(view->data()->id); return view->data()->isRegular();
} }
void PinnedWidget::listSendBotCommand( void PinnedWidget::listSendBotCommand(

View file

@ -460,7 +460,7 @@ void RepliesWidget::setupComposeControls() {
auto hasSendingMessage = session().changes().historyFlagsValue( auto hasSendingMessage = session().changes().historyFlagsValue(
_history, _history,
Data::HistoryUpdate::Flag::LocalMessages Data::HistoryUpdate::Flag::ClientSideMessages
) | rpl::map([=] { ) | rpl::map([=] {
return _history->latestSendingMessage() != nullptr; return _history->latestSendingMessage() != nullptr;
}) | rpl::distinct_until_changed(); }) | rpl::distinct_until_changed();
@ -1782,7 +1782,7 @@ bool RepliesWidget::listAllowsMultiSelect() {
bool RepliesWidget::listIsItemGoodForSelection( bool RepliesWidget::listIsItemGoodForSelection(
not_null<HistoryItem*> item) { not_null<HistoryItem*> item) {
return IsServerMsgId(item->id); return item->isRegular();
} }
bool RepliesWidget::listIsLessInOrder( bool RepliesWidget::listIsLessInOrder(
@ -1845,9 +1845,7 @@ void RepliesWidget::readTill(not_null<HistoryItem*> item) {
void RepliesWidget::listVisibleItemsChanged(HistoryItemsList &&items) { void RepliesWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
const auto reversed = ranges::views::reverse(items); const auto reversed = ranges::views::reverse(items);
const auto good = ranges::find_if(reversed, [](auto item) { const auto good = ranges::find_if(reversed, &HistoryItem::isRegular);
return IsServerMsgId(item->id);
});
if (good != end(reversed)) { if (good != end(reversed)) {
readTill(*good); readTill(*good);
} }
@ -1862,7 +1860,7 @@ MessagesBarData RepliesWidget::listMessagesBar(
const auto hidden = (till < 2); const auto hidden = (till < 2);
for (auto i = 0, count = int(elements.size()); i != count; ++i) { for (auto i = 0, count = int(elements.size()); i != count; ++i) {
const auto item = elements[i]->data(); const auto item = elements[i]->data();
if (IsServerMsgId(item->id) && item->id > till) { if (item->isRegular() && item->id > till) {
if (item->out() || !item->replyToId()) { if (item->out() || !item->replyToId()) {
readTill(item); readTill(item);
} else { } else {
@ -1904,7 +1902,7 @@ bool RepliesWidget::listElementShownUnread(not_null<const Element*> view) {
bool RepliesWidget::listIsGoodForAroundPosition( bool RepliesWidget::listIsGoodForAroundPosition(
not_null<const Element*> view) { not_null<const Element*> view) {
return IsServerMsgId(view->data()->id); return view->data()->isRegular();
} }
void RepliesWidget::listSendBotCommand( void RepliesWidget::listSendBotCommand(

View file

@ -595,7 +595,7 @@ bool Document::downloadInCorner() const {
return _data->isAudioFile() return _data->isAudioFile()
&& _data->canBeStreamed() && _data->canBeStreamed()
&& !_data->inappPlaybackFailed() && !_data->inappPlaybackFailed()
&& IsServerMsgId(_realParent->id); && _realParent->isRegular();
} }
void Document::drawCornerDownload( void Document::drawCornerDownload(

View file

@ -49,7 +49,7 @@ QSize Game::countOptimalSize() {
auto lineHeight = unitedLineHeight(); auto lineHeight = unitedLineHeight();
const auto item = _parent->data(); const auto item = _parent->data();
if (!_openl && IsServerMsgId(item->id)) { if (!_openl && item->isRegular()) {
const auto row = 0; const auto row = 0;
const auto column = 0; const auto column = 0;
_openl = std::make_shared<ReplyMarkupClickHandler>( _openl = std::make_shared<ReplyMarkupClickHandler>(

View file

@ -909,7 +909,9 @@ void Gif::drawGrouped(
ensureDataMediaCreated(); ensureDataMediaCreated();
const auto item = _parent->data(); const auto item = _parent->data();
const auto loaded = dataLoaded(); const auto loaded = dataLoaded();
const auto displayLoading = (item->id < 0) || _data->displayLoading(); const auto displayLoading = item->isSending()
|| item->hasFailed()
|| _data->displayLoading();
const auto st = context.st; const auto st = context.st;
const auto sti = context.imageStyle(); const auto sti = context.imageStyle();
const auto autoPaused = _parent->delegate()->elementIsGifPaused(); const auto autoPaused = _parent->delegate()->elementIsGifPaused();
@ -1508,20 +1510,23 @@ void Gif::checkAnimation() {
float64 Gif::dataProgress() const { float64 Gif::dataProgress() const {
ensureDataMediaCreated(); ensureDataMediaCreated();
return (_data->uploading() || _parent->data()->id > 0) return (_data->uploading()
|| (!_parent->data()->isSending() && !_parent->data()->hasFailed()))
? _dataMedia->progress() ? _dataMedia->progress()
: 0; : 0;
} }
bool Gif::dataFinished() const { bool Gif::dataFinished() const {
return (_parent->data()->id > 0) return (!_parent->data()->isSending() && !_parent->data()->hasFailed())
? (!_data->loading() && !_data->uploading()) ? (!_data->loading() && !_data->uploading())
: false; : false;
} }
bool Gif::dataLoaded() const { bool Gif::dataLoaded() const {
ensureDataMediaCreated(); ensureDataMediaCreated();
return (_parent->data()->id > 0) ? _dataMedia->loaded() : false; return !_parent->data()->isSending()
&& !_parent->data()->hasFailed()
&& _dataMedia->loaded();
} }
bool Gif::needInfoDisplay() const { bool Gif::needInfoDisplay() const {

View file

@ -760,7 +760,8 @@ bool GroupedMedia::computeNeedBubble() const {
bool GroupedMedia::needInfoDisplay() const { bool GroupedMedia::needInfoDisplay() const {
return (_mode != Mode::Column) return (_mode != Mode::Column)
&& (_parent->data()->id < 0 && (_parent->data()->isSending()
|| _parent->data()->hasFailed()
|| _parent->isUnderCursor() || _parent->isUnderCursor()
|| _parent->isLastAndSelfMessage()); || _parent->isLastAndSelfMessage());
} }

View file

@ -437,10 +437,11 @@ QPoint UnwrappedMedia::calculateFastActionPosition(
} }
bool UnwrappedMedia::needInfoDisplay() const { bool UnwrappedMedia::needInfoDisplay() const {
return (_parent->data()->id < 0) return _parent->data()->isSending()
|| (_parent->isUnderCursor()) || _parent->data()->hasFailed()
|| (_parent->rightActionSize()) || _parent->isUnderCursor()
|| (_parent->isLastAndSelfMessage()) || _parent->rightActionSize()
|| _parent->isLastAndSelfMessage()
|| (_parent->hasOutLayout() || (_parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide() && !_parent->delegate()->elementIsChatWide()
&& _content->alwaysShowOutTimestamp()); && _content->alwaysShowOutTimestamp());

View file

@ -619,9 +619,10 @@ bool Photo::dataLoaded() const {
} }
bool Photo::needInfoDisplay() const { bool Photo::needInfoDisplay() const {
return (_parent->data()->id < 0 return _parent->data()->isSending()
|| _parent->data()->hasFailed()
|| _parent->isUnderCursor() || _parent->isUnderCursor()
|| _parent->isLastAndSelfMessage()); || _parent->isLastAndSelfMessage();
} }
void Photo::validateGroupedCache( void Photo::validateGroupedCache(
@ -813,15 +814,13 @@ bool Photo::needsBubble() const {
return true; return true;
} }
const auto item = _parent->data(); const auto item = _parent->data();
if (item->toHistoryMessage()) { return !item->isService()
return item->repliesAreComments() && (item->repliesAreComments()
|| item->externalReply() || item->externalReply()
|| item->viaBot() || item->viaBot()
|| _parent->displayedReply() || _parent->displayedReply()
|| _parent->displayForwardedFrom() || _parent->displayForwardedFrom()
|| _parent->displayFromName(); || _parent->displayFromName());
}
return false;
} }
bool Photo::isReadyForOpen() const { bool Photo::isReadyForOpen() const {

View file

@ -282,7 +282,7 @@ bool Poll::showVotes() const {
} }
bool Poll::canVote() const { bool Poll::canVote() const {
return !showVotes() && IsServerMsgId(_parent->data()->id); return !showVotes() && _parent->data()->isRegular();
} }
bool Poll::canSendVotes() const { bool Poll::canSendVotes() const {

View file

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

View file

@ -249,7 +249,7 @@ void ListController::loadMoreRows() {
return; return;
} }
const auto item = session().data().message(_context); const auto item = session().data().message(_context);
if (!item || !IsServerMsgId(item->id)) { if (!item || !item->isRegular()) {
_leftToLoad = 0; _leftToLoad = 0;
return; return;
} }

View file

@ -332,7 +332,7 @@ auto Instance::playlistKey(not_null<Data*> data) const
return {}; return {};
} }
const auto item = data->history->owner().message(contextId); const auto item = data->history->owner().message(contextId);
if (!item || (!IsServerMsgId(contextId.msg) && !item->isScheduled())) { if (!item || (!item->isRegular() && !item->isScheduled())) {
return {}; return {};
} }

View file

@ -244,7 +244,7 @@ void Panel::refreshList() {
const auto document = media ? media->document() : nullptr; const auto document = media ? media->document() : nullptr;
if (!document if (!document
|| !document->isSharedMediaMusic() || !document->isSharedMediaMusic()
|| (!IsServerMsgId(item->id) && !item->isScheduled())) { || (!item->isRegular() && !item->isScheduled())) {
return nullptr; return nullptr;
} }
const auto result = item->history()->peer; const auto result = item->history()->peer;

View file

@ -110,7 +110,7 @@ Context ComputeContext(
return v::null; return v::null;
} else if (const auto msgId = std::get_if<FullMsgId>(&value)) { } else if (const auto msgId = std::get_if<FullMsgId>(&value)) {
if (const auto item = session->data().message(*msgId)) { if (const auto item = session->data().message(*msgId)) {
if (!item->toHistoryMessage()) { if (item->isService()) {
return item->history()->peer->id; return item->history()->peer->id;
} else if (const auto groupId = item->groupId()) { } else if (const auto groupId = item->groupId()) {
return groupId; return groupId;

View file

@ -670,8 +670,7 @@ void OverlayWidget::documentUpdated(DocumentData *doc) {
} }
void OverlayWidget::changingMsgId(not_null<HistoryItem*> row, MsgId oldId) { void OverlayWidget::changingMsgId(not_null<HistoryItem*> row, MsgId oldId) {
if (FullMsgId(row->channelId(), oldId) == _msgid) { if (row == _message) {
_msgid = row->fullId();
refreshMediaViewer(); refreshMediaViewer();
} }
} }
@ -800,10 +799,8 @@ void OverlayWidget::updateControls() {
const auto dNow = QDateTime::currentDateTime(); const auto dNow = QDateTime::currentDateTime();
const auto d = [&] { const auto d = [&] {
if (!_session) { if (_message) {
return dNow; return ItemDateTime(_message);
} else if (const auto item = _session->data().message(_msgid)) {
return ItemDateTime(item);
} else if (_photo) { } else if (_photo) {
return base::unixtime::parse(_photo->date); return base::unixtime::parse(_photo->date);
} else if (_document) { } else if (_document) {
@ -885,7 +882,7 @@ void OverlayWidget::fillContextMenuActions(const MenuCallback &addAction) {
if (_document && _document->loading()) { if (_document && _document->loading()) {
addAction(tr::lng_cancel(tr::now), [=] { saveCancel(); }); addAction(tr::lng_cancel(tr::now), [=] { saveCancel(); });
} }
if (IsServerMsgId(_msgid.msg)) { if (_message && _message->isRegular()) {
addAction(tr::lng_context_to_msg(tr::now), [=] { toMessage(); }); addAction(tr::lng_context_to_msg(tr::now), [=] { toMessage(); });
} }
if (_document && !_document->filepath(true).isEmpty()) { if (_document && !_document->filepath(true).isEmpty()) {
@ -903,13 +900,13 @@ void OverlayWidget::fillContextMenuActions(const MenuCallback &addAction) {
tr::lng_context_attached_stickers(tr::now), tr::lng_context_attached_stickers(tr::now),
[=] { showAttachedStickers(); }); [=] { showAttachedStickers(); });
} }
if (_canForwardItem) { if (_message && _message->allowsForward()) {
addAction(tr::lng_mediaview_forward(tr::now), [=] { forwardMedia(); }); addAction(tr::lng_mediaview_forward(tr::now), [=] { forwardMedia(); });
} }
const auto canDelete = [&] { const auto canDelete = [&] {
if (_canDeleteItem) { if (_message && _message->canDelete()) {
return true; return true;
} else if (!_msgid } else if (!_message
&& _photo && _photo
&& _user && _user
&& _user == _user->session().user()) { && _user == _user->session().user()) {
@ -1447,11 +1444,7 @@ void OverlayWidget::subscribeToScreenGeometry() {
} }
void OverlayWidget::toMessage() { void OverlayWidget::toMessage() {
if (!_session) { if (const auto item = _message) {
return;
}
if (const auto item = _session->data().message(_msgid)) {
close(); close();
if (const auto window = findWindow()) { if (const auto window = findWindow()) {
window->showPeerHistoryAtItem(item); window->showPeerHistoryAtItem(item);
@ -1579,10 +1572,7 @@ void OverlayWidget::handleDocumentClick() {
if (_document->loading()) { if (_document->loading()) {
saveCancel(); saveCancel();
} else { } else {
Data::ResolveDocument( Data::ResolveDocument(findWindow(), _document, _message);
findWindow(),
_document,
_document->owner().message(_msgid));
if (_document->loading() && !_radial.animating()) { if (_document->loading() && !_radial.animating()) {
_radial.start(_documentMedia->progress()); _radial.start(_documentMedia->progress());
} }
@ -1703,15 +1693,13 @@ void OverlayWidget::forwardMedia() {
if (active.empty()) { if (active.empty()) {
return; return;
} }
const auto item = _session->data().message(_msgid); const auto id = (_message && _message->allowsForward())
if (!item || !IsServerMsgId(item->id) || item->serviceMsg()) { ? _message->fullId()
return; : FullMsgId();
if (id) {
close();
Window::ShowForwardMessagesBox(active.front(), { 1, id });
} }
close();
Window::ShowForwardMessagesBox(
active.front(),
{ 1, item->fullId() });
} }
void OverlayWidget::deleteMedia() { void OverlayWidget::deleteMedia() {
@ -1721,9 +1709,9 @@ void OverlayWidget::deleteMedia() {
const auto session = _session; const auto session = _session;
const auto photo = _photo; const auto photo = _photo;
const auto msgid = _msgid; const auto message = _message;
const auto deletingPeerPhoto = [&] { const auto deletingPeerPhoto = [&] {
if (!_msgid) { if (!_message) {
return true; return true;
} else if (_photo && _history) { } else if (_photo && _history) {
if (_history->peer->userpicPhotoId() == _photo->id) { if (_history->peer->userpicPhotoId() == _photo->id) {
@ -1747,10 +1735,10 @@ void OverlayWidget::deleteMedia() {
})), })),
Ui::LayerOption::CloseOther); Ui::LayerOption::CloseOther);
} }
} else if (const auto item = session->data().message(msgid)) { } else if (message) {
const auto suggestModerateActions = true; const auto suggestModerateActions = true;
window->show( window->show(
Box<DeleteMessagesBox>(item, suggestModerateActions), Box<DeleteMessagesBox>(message, suggestModerateActions),
Ui::LayerOption::CloseOther); Ui::LayerOption::CloseOther);
} }
} }
@ -1801,19 +1789,17 @@ void OverlayWidget::showAttachedStickers() {
auto OverlayWidget::sharedMediaType() const auto OverlayWidget::sharedMediaType() const
-> std::optional<SharedMediaType> { -> std::optional<SharedMediaType> {
using Type = SharedMediaType; using Type = SharedMediaType;
if (!_session) { if (_message) {
return std::nullopt; if (const auto media = _message->media()) {
} else if (const auto item = _session->data().message(_msgid)) {
if (const auto media = item->media()) {
if (media->webpage()) { if (media->webpage()) {
return std::nullopt; return std::nullopt;
} }
} }
if (_photo) { if (_photo) {
if (item->toHistoryMessage()) { if (_message->isService()) {
return Type::PhotoVideo; return Type::ChatPhoto;
} }
return Type::ChatPhoto; return Type::PhotoVideo;
} else if (_document) { } else if (_document) {
if (_document->isGifv()) { if (_document->isGifv()) {
return Type::GIF; return Type::GIF;
@ -1827,7 +1813,7 @@ auto OverlayWidget::sharedMediaType() const
} }
auto OverlayWidget::sharedMediaKey() const -> std::optional<SharedMediaKey> { auto OverlayWidget::sharedMediaKey() const -> std::optional<SharedMediaKey> {
if (!_msgid if (!_message
&& _peer && _peer
&& !_user && !_user
&& _photo && _photo
@ -1839,36 +1825,30 @@ auto OverlayWidget::sharedMediaKey() const -> std::optional<SharedMediaKey> {
_photo _photo
}; };
} }
const auto isServerMsgId = IsServerMsgId(_msgid.msg); if (!_message) {
const auto isScheduled = [&] { return std::nullopt;
if (isServerMsgId) { }
return false; const auto isScheduled = _message->isScheduled();
}
if (const auto item = _session->data().message(_msgid)) {
return item->isScheduled();
}
return false;
}();
const auto keyForType = [&](SharedMediaType type) -> SharedMediaKey { const auto keyForType = [&](SharedMediaType type) -> SharedMediaKey {
return { return {
_history->peer->id, _history->peer->id,
_migrated ? _migrated->peer->id : 0, _migrated ? _migrated->peer->id : 0,
type, type,
(_msgid.channel == _history->channelId()) (_message->history() == _history
? _msgid.msg ? _message->id
: (_msgid.msg - ServerMaxMsgId), : (_message->id - ServerMaxMsgId)),
isScheduled isScheduled
}; };
}; };
if (!isServerMsgId && !isScheduled) { if (!_message->isRegular() && !isScheduled) {
return std::nullopt; return std::nullopt;
} }
return sharedMediaType() | keyForType; return sharedMediaType() | keyForType;
} }
Data::FileOrigin OverlayWidget::fileOrigin() const { Data::FileOrigin OverlayWidget::fileOrigin() const {
if (_msgid) { if (_message) {
return _msgid; return _message->fullId();
} else if (_photo && _user) { } else if (_photo && _user) {
return Data::FileOriginUserPhoto(peerToUser(_user->id), _photo->id); return Data::FileOriginUserPhoto(peerToUser(_user->id), _photo->id);
} else if (_photo && _peer && _peer->userpicPhotoId() == _photo->id) { } else if (_photo && _peer && _peer->userpicPhotoId() == _photo->id) {
@ -1966,7 +1946,7 @@ void OverlayWidget::handleSharedMediaUpdate(SharedMediaWithLastSlice &&update) {
} }
std::optional<OverlayWidget::UserPhotosKey> OverlayWidget::userPhotosKey() const { std::optional<OverlayWidget::UserPhotosKey> OverlayWidget::userPhotosKey() const {
if (!_msgid && _user && _photo) { if (!_message && _user && _photo) {
return UserPhotosKey{ peerToUser(_user->id), _photo->id }; return UserPhotosKey{ peerToUser(_user->id), _photo->id };
} }
return std::nullopt; return std::nullopt;
@ -2026,10 +2006,8 @@ void OverlayWidget::handleUserPhotosUpdate(UserPhotosSlice &&update) {
} }
std::optional<OverlayWidget::CollageKey> OverlayWidget::collageKey() const { std::optional<OverlayWidget::CollageKey> OverlayWidget::collageKey() const {
if (!_session) { if (_message) {
return std::nullopt; if (const auto media = _message->media()) {
} else if (const auto item = _session->data().message(_msgid)) {
if (const auto media = item->media()) {
if (const auto page = media->webpage()) { if (const auto page = media->webpage()) {
for (const auto &item : page->collage.items) { for (const auto &item : page->collage.items) {
if (item == _photo || item == _document) { if (item == _photo || item == _document) {
@ -2065,8 +2043,8 @@ void OverlayWidget::validateCollage() {
if (const auto key = collageKey()) { if (const auto key = collageKey()) {
_collage = std::make_unique<Collage>(*key); _collage = std::make_unique<Collage>(*key);
_collageData = WebPageCollage(); _collageData = WebPageCollage();
if (const auto item = _session->data().message(_msgid)) { if (_message) {
if (const auto media = item->media()) { if (const auto media = _message->media()) {
if (const auto page = media->webpage()) { if (const auto page = media->webpage()) {
_collageData = page->collage; _collageData = page->collage;
} }
@ -2092,10 +2070,10 @@ void OverlayWidget::refreshMediaViewer() {
updateControls(); updateControls();
} }
void OverlayWidget::refreshFromLabel(HistoryItem *item) { void OverlayWidget::refreshFromLabel() {
if (_msgid && item) { if (_message) {
_from = item->senderOriginal(); _from = _message->senderOriginal();
if (const auto info = item->hiddenForwardedInfo()) { if (const auto info = _message->hiddenForwardedInfo()) {
_fromName = info->name; _fromName = info->name;
} else { } else {
Assert(_from != nullptr); Assert(_from != nullptr);
@ -2108,16 +2086,16 @@ void OverlayWidget::refreshFromLabel(HistoryItem *item) {
} }
} }
void OverlayWidget::refreshCaption(HistoryItem *item) { void OverlayWidget::refreshCaption() {
_caption = Ui::Text::String(); _caption = Ui::Text::String();
if (!item) { if (!_message) {
return; return;
} else if (const auto media = item->media()) { } else if (const auto media = _message->media()) {
if (media->webpage()) { if (media->webpage()) {
return; return;
} }
} }
const auto caption = item->originalText(); const auto caption = _message->originalText();
if (caption.text.isEmpty()) { if (caption.text.isEmpty()) {
return; return;
} }
@ -2128,15 +2106,15 @@ void OverlayWidget::refreshCaption(HistoryItem *item) {
? _document->getDuration() ? _document->getDuration()
: 0; : 0;
const auto base = duration const auto base = duration
? DocumentTimestampLinkBase(_document, item->fullId()) ? DocumentTimestampLinkBase(_document, _message->fullId())
: QString(); : QString();
const auto context = Core::MarkedTextContext{ const auto context = Core::MarkedTextContext{
.session = &item->history()->session() .session = &_message->history()->session()
}; };
_caption.setMarkedText( _caption.setMarkedText(
st::mediaviewCaptionStyle, st::mediaviewCaptionStyle,
AddTimestampLinks(caption, duration, base), AddTimestampLinks(caption, duration, base),
Ui::ItemTextOptions(item), Ui::ItemTextOptions(_message),
context); context);
} }
@ -2157,10 +2135,11 @@ void OverlayWidget::refreshGroupThumbs() {
*_index, *_index,
_groupThumbsAvailableWidth); _groupThumbsAvailableWidth);
} else if (_index && _collageData) { } else if (_index && _collageData) {
const auto messageId = _message ? _message->fullId() : FullMsgId();
View::GroupThumbs::Refresh( View::GroupThumbs::Refresh(
_session, _session,
_groupThumbs, _groupThumbs,
{ _msgid, &*_collageData }, { messageId, &*_collageData },
*_index, *_index,
_groupThumbsAvailableWidth); _groupThumbsAvailableWidth);
} else if (_groupThumbs) { } else if (_groupThumbs) {
@ -2296,7 +2275,7 @@ void OverlayWidget::show(OpenRequest request) {
_firstOpenedPeerPhoto = (contextPeer != nullptr); _firstOpenedPeerPhoto = (contextPeer != nullptr);
assignMediaPointer(photo); assignMediaPointer(photo);
displayPhoto(photo, contextPeer ? nullptr : contextItem); displayPhoto(photo);
preloadData(0); preloadData(0);
activateControls(); activateControls();
} else if (document) { } else if (document) {
@ -2313,7 +2292,6 @@ void OverlayWidget::show(OpenRequest request) {
_streamingStartPaused = false; _streamingStartPaused = false;
displayDocument( displayDocument(
document, document,
contextItem,
request.cloudTheme() request.cloudTheme()
? *request.cloudTheme() ? *request.cloudTheme()
: Data::CloudTheme(), : Data::CloudTheme(),
@ -2328,9 +2306,9 @@ void OverlayWidget::show(OpenRequest request) {
} }
} }
void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item) { void OverlayWidget::displayPhoto(not_null<PhotoData*> photo) {
if (photo->isNull()) { if (photo->isNull()) {
displayDocument(nullptr, item); displayDocument(nullptr);
return; return;
} }
_touchbarDisplay.fire(TouchBarItemType::Photo); _touchbarDisplay.fire(TouchBarItemType::Photo);
@ -2350,7 +2328,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
initStreaming(); initStreaming();
} }
refreshCaption(item); refreshCaption();
_blurred = true; _blurred = true;
_down = OverNone; _down = OverNone;
@ -2368,7 +2346,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
_h = size.height(); _h = size.height();
} }
contentSizeChanged(); contentSizeChanged();
refreshFromLabel(item); refreshFromLabel();
displayFinished(); displayFinished();
} }
@ -2384,19 +2362,16 @@ void OverlayWidget::destroyThemePreview() {
void OverlayWidget::redisplayContent() { void OverlayWidget::redisplayContent() {
if (isHidden() || !_session) { if (isHidden() || !_session) {
return; return;
} } else if (_photo) {
const auto item = _session->data().message(_msgid); displayPhoto(_photo);
if (_photo) {
displayPhoto(_photo, item);
} else { } else {
displayDocument(_document, item); displayDocument(_document);
} }
} }
// Empty messages shown as docs: doc can be nullptr. // Empty messages shown as docs: doc can be nullptr.
void OverlayWidget::displayDocument( void OverlayWidget::displayDocument(
DocumentData *doc, DocumentData *doc,
HistoryItem *item,
const Data::CloudTheme &cloud, const Data::CloudTheme &cloud,
bool continueStreaming) { bool continueStreaming) {
_fullScreenVideo = false; _fullScreenVideo = false;
@ -2405,7 +2380,9 @@ void OverlayWidget::displayDocument(
destroyThemePreview(); destroyThemePreview();
assignMediaPointer(doc); assignMediaPointer(doc);
_rotation = _document ? _document->owner().mediaRotation().get(_document) : 0; _rotation = _document
? _document->owner().mediaRotation().get(_document)
: 0;
_themeCloudData = cloud; _themeCloudData = cloud;
_radial.stop(); _radial.stop();
@ -2426,13 +2403,13 @@ void OverlayWidget::displayDocument(
if (_documentMedia->canBePlayed() if (_documentMedia->canBePlayed()
&& initStreaming(continueStreaming)) { && initStreaming(continueStreaming)) {
} else if (_document->isVideoFile()) { } else if (_document->isVideoFile()) {
_documentMedia->automaticLoad(fileOrigin(), item); _documentMedia->automaticLoad(fileOrigin(), _message);
initStreamingThumbnail(); initStreamingThumbnail();
} else if (_document->isTheme()) { } else if (_document->isTheme()) {
_documentMedia->automaticLoad(fileOrigin(), item); _documentMedia->automaticLoad(fileOrigin(), _message);
initThemePreview(); initThemePreview();
} else { } else {
_documentMedia->automaticLoad(fileOrigin(), item); _documentMedia->automaticLoad(fileOrigin(), _message);
_document->saveFromDataSilent(); _document->saveFromDataSilent();
auto &location = _document->location(true); auto &location = _document->location(true);
if (location.accessEnable()) { if (location.accessEnable()) {
@ -2454,7 +2431,7 @@ void OverlayWidget::displayDocument(
} }
} }
} }
refreshCaption(item); refreshCaption();
const auto docGeneric = Layout::DocumentGenericPreview::Create(_document); const auto docGeneric = Layout::DocumentGenericPreview::Create(_document);
_docExt = docGeneric.ext; _docExt = docGeneric.ext;
@ -2519,7 +2496,7 @@ void OverlayWidget::displayDocument(
if (videoShown()) { if (videoShown()) {
applyVideoSize(); applyVideoSize();
} }
refreshFromLabel(item); refreshFromLabel();
_blurred = false; _blurred = false;
if (_showAsPip && _streamed && !videoIsGifOrUserpic()) { if (_showAsPip && _streamed && !videoIsGifOrUserpic()) {
switchToPip(); switchToPip();
@ -3026,7 +3003,7 @@ void OverlayWidget::seekRelativeTime(crl::time time) {
void OverlayWidget::restartAtProgress(float64 progress) { void OverlayWidget::restartAtProgress(float64 progress) {
Expects(_streamed != nullptr); Expects(_streamed != nullptr);
restartAtSeekPosition(_streamed->instance.info().video.state.duration restartAtSeekPosition(_streamed->instance.info().video.state.duration
* std::clamp(progress, 0., 1.)); * std::clamp(progress, 0., 1.));
} }
@ -3047,7 +3024,8 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
options.loop = true; options.loop = true;
} else { } else {
Assert(_document != nullptr); Assert(_document != nullptr);
options.audioId = AudioMsgId(_document, _msgid); const auto messageId = _message ? _message->fullId() : FullMsgId();
options.audioId = AudioMsgId(_document, messageId);
options.speed = Core::App().settings().videoPlaybackSpeed(); options.speed = Core::App().settings().videoPlaybackSpeed();
if (_pip) { if (_pip) {
_pip = nullptr; _pip = nullptr;
@ -3130,20 +3108,20 @@ void OverlayWidget::switchToPip() {
Expects(_document != nullptr); Expects(_document != nullptr);
const auto document = _document; const auto document = _document;
const auto msgId = _msgid; const auto message = _message;
const auto closeAndContinue = [=] { const auto closeAndContinue = [=] {
_showAsPip = false; _showAsPip = false;
show(OpenRequest( show(OpenRequest(
findWindow(false), findWindow(false),
document, document,
document->owner().message(msgId), message,
true)); true));
}; };
_showAsPip = true; _showAsPip = true;
_pip = std::make_unique<PipWrap>( _pip = std::make_unique<PipWrap>(
_widget, _widget,
document, document,
msgId, message ? message->fullId() : FullMsgId(),
_streamed->instance.shared(), _streamed->instance.shared(),
closeAndContinue, closeAndContinue,
[=] { _pip = nullptr; }); [=] { _pip = nullptr; });
@ -3251,7 +3229,7 @@ void OverlayWidget::validatePhotoCurrentImage() {
validatePhotoImage(_photoMedia->image(Data::PhotoSize::Small), true); validatePhotoImage(_photoMedia->image(Data::PhotoSize::Small), true);
validatePhotoImage(_photoMedia->thumbnailInline(), true); validatePhotoImage(_photoMedia->thumbnailInline(), true);
if (_staticContent.isNull() if (_staticContent.isNull()
&& !_msgid && !_message
&& _peer && _peer
&& _peer->hasUserpic()) { && _peer->hasUserpic()) {
if (const auto view = _peer->activeUserpicView()) { if (const auto view = _peer->activeUserpicView()) {
@ -3933,15 +3911,14 @@ OverlayWidget::Entity OverlayWidget::entityForCollage(int index) const {
Expects(_collageData.has_value()); Expects(_collageData.has_value());
Expects(_session != nullptr); Expects(_session != nullptr);
const auto item = _session->data().message(_msgid);
const auto &items = _collageData->items; const auto &items = _collageData->items;
if (!item || index < 0 || index >= items.size()) { if (!_message || index < 0 || index >= items.size()) {
return { v::null, nullptr }; return { v::null, nullptr };
} }
if (const auto document = std::get_if<DocumentData*>(&items[index])) { if (const auto document = std::get_if<DocumentData*>(&items[index])) {
return { *document, item }; return { *document, _message };
} else if (const auto photo = std::get_if<PhotoData*>(&items[index])) { } else if (const auto photo = std::get_if<PhotoData*>(&items[index])) {
return { *photo, item }; return { *photo, _message };
} }
return { v::null, nullptr }; return { v::null, nullptr };
} }
@ -3979,19 +3956,15 @@ void OverlayWidget::setContext(
not_null<HistoryItem*>, not_null<HistoryItem*>,
not_null<PeerData*>> context) { not_null<PeerData*>> context) {
if (const auto item = std::get_if<not_null<HistoryItem*>>(&context)) { if (const auto item = std::get_if<not_null<HistoryItem*>>(&context)) {
_msgid = (*item)->fullId(); _message = (*item);
_canForwardItem = (*item)->allowsForward(); _history = _message->history();
_canDeleteItem = (*item)->canDelete();
_history = (*item)->history();
_peer = _history->peer; _peer = _history->peer;
} else if (const auto peer = std::get_if<not_null<PeerData*>>(&context)) { } else if (const auto peer = std::get_if<not_null<PeerData*>>(&context)) {
_msgid = FullMsgId();
_canForwardItem = _canDeleteItem = false;
_history = (*peer)->owner().history(*peer);
_peer = *peer; _peer = *peer;
_history = _peer->owner().history(_peer);
_message = nullptr;
} else { } else {
_msgid = FullMsgId(); _message = nullptr;
_canForwardItem = _canDeleteItem = false;
_history = nullptr; _history = nullptr;
_peer = nullptr; _peer = nullptr;
} }
@ -4039,10 +4012,10 @@ void OverlayWidget::setSession(not_null<Main::Session*> session) {
session->data().itemRemoved( session->data().itemRemoved(
) | rpl::filter([=](not_null<const HistoryItem*> item) { ) | rpl::filter([=](not_null<const HistoryItem*> item) {
return (_document != nullptr || _photo != nullptr) return (_message == item);
&& (item->fullId() == _msgid);
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
close(); close();
clearSession();
}, _sessionLifetime); }, _sessionLifetime);
session->account().sessionChanges( session->account().sessionChanges(
@ -4073,11 +4046,11 @@ bool OverlayWidget::moveToEntity(const Entity &entity, int preloadDelta) {
clearStreaming(); clearStreaming();
_streamingStartPaused = false; _streamingStartPaused = false;
if (auto photo = std::get_if<not_null<PhotoData*>>(&entity.data)) { if (auto photo = std::get_if<not_null<PhotoData*>>(&entity.data)) {
displayPhoto(*photo, entity.item); displayPhoto(*photo);
} else if (auto document = std::get_if<not_null<DocumentData*>>(&entity.data)) { } else if (auto document = std::get_if<not_null<DocumentData*>>(&entity.data)) {
displayDocument(*document, entity.item); displayDocument(*document);
} else { } else {
displayDocument(nullptr, entity.item); displayDocument(nullptr);
} }
preloadData(preloadDelta); preloadData(preloadDelta);
return true; return true;
@ -4305,7 +4278,7 @@ void OverlayWidget::updateOver(QPoint pos) {
updateOverState(OverRightNav); updateOverState(OverRightNav);
} else if (_from && _nameNav.contains(pos)) { } else if (_from && _nameNav.contains(pos)) {
updateOverState(OverName); updateOverState(OverName);
} else if (IsServerMsgId(_msgid.msg) && _dateNav.contains(pos)) { } else if (_message && _message->isRegular() && _dateNav.contains(pos)) {
updateOverState(OverDate); updateOverState(OverDate);
} else if (_headerHasLink && _headerNav.contains(pos)) { } else if (_headerHasLink && _headerNav.contains(pos)) {
updateOverState(OverHeader); updateOverState(OverHeader);
@ -4348,7 +4321,7 @@ void OverlayWidget::handleMouseRelease(
ActivateClickHandler(_widget, activated, { ActivateClickHandler(_widget, activated, {
button, button,
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.itemId = _msgid, .itemId = _message ? _message->fullId() : FullMsgId(),
.sessionWindow = base::make_weak(findWindow()), .sessionWindow = base::make_weak(findWindow()),
}) })
}); });
@ -4682,8 +4655,8 @@ void OverlayWidget::updateImage() {
void OverlayWidget::findCurrent() { void OverlayWidget::findCurrent() {
using namespace rpl::mappers; using namespace rpl::mappers;
if (_sharedMediaData) { if (_sharedMediaData) {
_index = _msgid _index = _message
? _sharedMediaData->indexOf(_msgid) ? _sharedMediaData->indexOf(_message->fullId())
: _photo ? _sharedMediaData->indexOf(_photo) : std::nullopt; : _photo ? _sharedMediaData->indexOf(_photo) : std::nullopt;
_fullIndex = _sharedMediaData->skippedBefore() _fullIndex = _sharedMediaData->skippedBefore()
? (_index | func::add(*_sharedMediaData->skippedBefore())) ? (_index | func::add(*_sharedMediaData->skippedBefore()))
@ -4735,7 +4708,7 @@ void OverlayWidget::updateHeader() {
} else { } else {
if (_document) { if (_document) {
_headerText = _document->filename().isEmpty() ? tr::lng_mediaview_doc_image(tr::now) : _document->filename(); _headerText = _document->filename().isEmpty() ? tr::lng_mediaview_doc_image(tr::now) : _document->filename();
} else if (_msgid) { } else if (_message) {
_headerText = tr::lng_mediaview_single_photo(tr::now); _headerText = tr::lng_mediaview_single_photo(tr::now);
} else if (_user) { } else if (_user) {
_headerText = tr::lng_mediaview_profile_photo(tr::now); _headerText = tr::lng_mediaview_profile_photo(tr::now);

View file

@ -263,8 +263,8 @@ private:
[[nodiscard]] Data::FileOrigin fileOrigin() const; [[nodiscard]] Data::FileOrigin fileOrigin() const;
[[nodiscard]] Data::FileOrigin fileOrigin(const Entity& entity) const; [[nodiscard]] Data::FileOrigin fileOrigin(const Entity& entity) const;
void refreshFromLabel(HistoryItem *item); void refreshFromLabel();
void refreshCaption(HistoryItem *item); void refreshCaption();
void refreshMediaViewer(); void refreshMediaViewer();
void refreshNavVisibility(); void refreshNavVisibility();
void refreshGroupThumbs(); void refreshGroupThumbs();
@ -280,10 +280,9 @@ private:
void resizeCenteredControls(); void resizeCenteredControls();
void resizeContentByScreenSize(); void resizeContentByScreenSize();
void displayPhoto(not_null<PhotoData*> photo, HistoryItem *item); void displayPhoto(not_null<PhotoData*> photo);
void displayDocument( void displayDocument(
DocumentData *document, DocumentData *document,
HistoryItem *item,
const Data::CloudTheme &cloud = Data::CloudTheme(), const Data::CloudTheme &cloud = Data::CloudTheme(),
bool continueStreaming = false); bool continueStreaming = false);
void displayFinished(); void displayFinished();
@ -516,9 +515,7 @@ private:
std::optional<int> _index; // Index in current _sharedMedia data. std::optional<int> _index; // Index in current _sharedMedia data.
std::optional<int> _fullIndex; // Index in full shared media. std::optional<int> _fullIndex; // Index in full shared media.
std::optional<int> _fullCount; std::optional<int> _fullCount;
FullMsgId _msgid; HistoryItem *_message = nullptr;
bool _canForwardItem = false;
bool _canDeleteItem = false;
mtpRequestId _loadRequest = 0; mtpRequestId _loadRequest = 0;

View file

@ -971,7 +971,7 @@ bool Document::downloadInCorner() const {
return _data->isAudioFile() return _data->isAudioFile()
&& _data->canBeStreamed() && _data->canBeStreamed()
&& !_data->inappPlaybackFailed() && !_data->inappPlaybackFailed()
&& IsServerMsgId(parent()->id); && parent()->isRegular();
} }
void Document::initDimensions() { void Document::initDimensions() {

View file

@ -491,7 +491,8 @@ FileLoadTask::FileLoadTask(
, _type(type) , _type(type)
, _caption(caption) { , _caption(caption) {
Expects(to.options.scheduled Expects(to.options.scheduled
|| (to.replaceMediaOf == 0 || IsServerMsgId(to.replaceMediaOf))); || !to.replaceMediaOf
|| IsServerMsgId(to.replaceMediaOf));
} }
FileLoadTask::FileLoadTask( FileLoadTask::FileLoadTask(

View file

@ -674,13 +674,13 @@ void Manager::openNotificationMessage(
not_null<History*> history, not_null<History*> history,
MsgId messageId) { MsgId messageId) {
const auto openExactlyMessage = [&] { const auto openExactlyMessage = [&] {
if (history->peer->isUser() if (history->peer->isUser() || history->peer->isChannel()) {
|| history->peer->isChannel()
|| !IsServerMsgId(messageId)) {
return false; return false;
} }
const auto item = history->owner().message(history->channelId(), messageId); const auto item = history->owner().message(
if (!item || !item->mentionsMe()) { history->channelId(),
messageId);
if (!item || !item->isRegular() || !item->mentionsMe()) {
return false; return false;
} }
return true; return true;