Implement sending of shortcutted messages.

This commit is contained in:
John Preston 2024-02-26 22:24:00 +04:00
parent 5c11fa4f63
commit 7f3ebde252
35 changed files with 709 additions and 934 deletions

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_media.h"
#include "api/api_text_entities.h"
#include "ui/boxes/confirm_box.h"
#include "data/business/data_shortcut_messages.h"
#include "data/data_histories.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h"
@ -92,6 +93,8 @@ mtpRequestId EditMessage(
const auto id = item->isScheduled()
? session->data().scheduledMessages().lookupId(item)
: item->isBusinessShortcut()
? session->data().shortcutMessages().lookupId(item)
: item->id;
return api->request(MTPmessages_EditMessage(
MTP_flags(flags),

View file

@ -85,20 +85,21 @@ void SendExistingMedia(
? (*localMessageId)
: session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();
const auto &action = message.action;
auto flags = NewMessageFlags(peer);
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (message.action.replyTo) {
if (action.replyTo) {
flags |= MessageFlag::HasReplyInfo;
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
}
const auto anonymousPost = peer->amAnonymous();
const auto silentPost = ShouldSendSilent(peer, message.action.options);
InnerFillMessagePostFlags(message.action.options, peer, flags);
const auto silentPost = ShouldSendSilent(peer, action.options);
InnerFillMessagePostFlags(action.options, peer, flags);
if (silentPost) {
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
const auto sendAs = message.action.options.sendAs;
const auto sendAs = action.options.sendAs;
const auto messageFromId = sendAs
? sendAs->id
: anonymousPost
@ -125,33 +126,30 @@ void SendExistingMedia(
}
const auto captionText = caption.text;
if (message.action.options.scheduled) {
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
}
if (message.action.options.shortcutId) {
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
session->data().registerMessageRandomId(randomId, newId);
const auto viaBotId = UserId();
history->addNewLocalMessage(
newId.msg,
flags,
viaBotId,
message.action.replyTo,
HistoryItem::NewMessageDate(message.action.options.scheduled),
messageFromId,
messagePostAuthor,
media,
caption,
HistoryMessageMarkupData());
history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = action.replyTo,
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
}, media, caption);
const auto performRequest = [=](const auto &repeatRequest) -> void {
auto &histories = history->owner().histories();
const auto session = &history->session();
const auto &action = message.action;
const auto usedFileReference = media->fileReference();
histories.sendPreparedMessage(
history,
@ -187,7 +185,7 @@ void SendExistingMedia(
};
performRequest(performRequest);
api->finishForwarding(message.action);
api->finishForwarding(action);
}
} // namespace
@ -307,23 +305,23 @@ bool SendDice(MessageToSend &message) {
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
session->data().registerMessageRandomId(randomId, newId);
const auto viaBotId = UserId();
history->addNewLocalMessage(
newId.msg,
flags,
viaBotId,
action.replyTo,
HistoryItem::NewMessageDate(action.options.scheduled),
messageFromId,
messagePostAuthor,
TextWithEntities(),
MTP_messageMediaDice(MTP_int(0), MTP_string(emoji)),
HistoryMessageMarkupData());
history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = action.replyTo,
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
}, TextWithEntities(), MTP_messageMediaDice(
MTP_int(0),
MTP_string(emoji)));
histories.sendPreparedMessage(
history,
action.replyTo,
@ -420,7 +418,13 @@ void SendConfirmedFile(
if (file->to.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
// Scheduled messages have no the 'edited' badge.
// Scheduled messages have no 'edited' badge.
flags |= MessageFlag::HideEdited;
}
if (file->to.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
// Shortcut messages have no 'edited' badge.
flags |= MessageFlag::HideEdited;
}
if (file->type == SendMediaType::Audio) {
@ -429,8 +433,7 @@ void SendConfirmedFile(
}
}
const auto messageFromId =
file->to.options.sendAs
const auto messageFromId = file->to.options.sendAs
? file->to.options.sendAs->id
: anonymousPost
? PeerId()
@ -500,19 +503,15 @@ void SendConfirmedFile(
edition.savePreviousMedia = true;
itemToEdit->applyEdition(std::move(edition));
} else {
const auto viaBotId = UserId();
history->addNewLocalMessage(
newId.msg,
flags,
viaBotId,
file->to.replyTo,
HistoryItem::NewMessageDate(file->to.options.scheduled),
messageFromId,
messagePostAuthor,
caption,
media,
HistoryMessageMarkupData(),
groupId);
history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = file->to.replyTo,
.date = HistoryItem::NewMessageDate(file->to.options),
.shortcutId = file->to.options.shortcutId,
.postAuthor = messagePostAuthor,
}, caption, media);
}
if (isEditing) {

View file

@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtp_instance.h"
#include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "data/business/data_shortcut_messages.h"
#include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h"
#include "data/data_saved_messages.h"
@ -1774,6 +1775,31 @@ void Updates::feedUpdate(const MTPUpdate &update) {
session().data().scheduledMessages().apply(d);
} break;
case mtpc_updateQuickReplies: {
const auto &d = update.c_updateQuickReplies();
session().data().shortcutMessages().apply(d);
} break;
case mtpc_updateNewQuickReply: {
const auto &d = update.c_updateNewQuickReply();
session().data().shortcutMessages().apply(d);
} break;
case mtpc_updateDeleteQuickReply: {
const auto &d = update.c_updateDeleteQuickReply();
session().data().shortcutMessages().apply(d);
} break;
case mtpc_updateQuickReplyMessage: {
const auto &d = update.c_updateQuickReplyMessage();
session().data().shortcutMessages().apply(d);
} break;
case mtpc_updateDeleteQuickReplyMessages: {
const auto &d = update.c_updateDeleteQuickReplyMessages();
session().data().shortcutMessages().apply(d);
} break;
case mtpc_updateWebPage: {
auto &d = update.c_updateWebPage();

View file

@ -2449,6 +2449,14 @@ void ApiWrap::refreshFileReference(
request(MTPmessages_GetScheduledMessages(
item->history()->peer->input,
MTP_vector<MTPint>(1, MTP_int(realId))));
} else if (item->isBusinessShortcut()) {
const auto &shortcuts = _session->data().shortcutMessages();
const auto realId = shortcuts.lookupId(item);
request(MTPmessages_GetQuickReplyMessages(
MTP_flags(MTPmessages_GetQuickReplyMessages::Flag::f_id),
MTP_int(item->shortcutId()),
MTP_vector<MTPint>(1, MTP_int(realId)),
MTP_long(0)));
} else if (const auto channel = item->history()->peer->asChannel()) {
request(MTPchannels_GetMessages(
channel->inputChannel,
@ -3232,6 +3240,7 @@ void ApiWrap::forwardMessages(
sendFlags |= SendFlag::f_schedule_date;
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= SendFlag::f_quick_reply_shortcut;
}
if (draft.options != Data::ForwardOptions::PreserveInfo) {
@ -3317,14 +3326,15 @@ void ApiWrap::forwardMessages(
const auto messagePostAuthor = peer->isBroadcast()
? self->name()
: QString();
history->addNewLocalMessage(
newId.msg,
flags,
HistoryItem::NewMessageDate(action.options.scheduled),
messageFromId,
messagePostAuthor,
item,
topMsgId);
history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = { .topicRootId = topMsgId },
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
}, item);
_session->data().registerMessageRandomId(randomId, newId);
if (!localIds) {
localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();
@ -3405,6 +3415,9 @@ void ApiWrap::sendSharedContact(
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
}
const auto messageFromId = action.options.sendAs
? action.options.sendAs->id
: anonymousPost
@ -3413,23 +3426,20 @@ void ApiWrap::sendSharedContact(
const auto messagePostAuthor = peer->isBroadcast()
? _session->user()->name()
: QString();
const auto viaBotId = UserId();
const auto item = history->addNewLocalMessage(
newId.msg,
flags,
viaBotId,
action.replyTo,
HistoryItem::NewMessageDate(action.options.scheduled),
messageFromId,
messagePostAuthor,
TextWithEntities(),
MTP_messageMediaContact(
MTP_string(phone),
MTP_string(firstName),
MTP_string(lastName),
MTP_string(), // vcard
MTP_long(userId.bare)),
HistoryMessageMarkupData());
const auto item = history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = action.replyTo,
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
}, TextWithEntities(), MTP_messageMediaContact(
MTP_string(phone),
MTP_string(firstName),
MTP_string(lastName),
MTP_string(), // vcard
MTP_long(userId.bare)));
const auto media = MTP_inputMediaContact(
MTP_string(phone),
@ -3737,21 +3747,19 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut;
mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
}
const auto viaBotId = UserId();
lastMessage = history->addNewLocalMessage(
newId.msg,
flags,
viaBotId,
action.replyTo,
HistoryItem::NewMessageDate(action.options.scheduled),
messageFromId,
messagePostAuthor,
sending,
media,
HistoryMessageMarkupData());
lastMessage = history->addNewLocalMessage({
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = action.replyTo,
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.postAuthor = messagePostAuthor,
}, sending, media);
const auto done = [=](
const MTPUpdates &result,
const MTP::Response &response) {
@ -3903,6 +3911,7 @@ void ApiWrap::sendInlineResult(
sendFlags |= SendFlag::f_schedule_date;
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= SendFlag::f_quick_reply_shortcut;
}
if (action.options.hideViaBot) {
@ -3923,15 +3932,18 @@ void ApiWrap::sendInlineResult(
_session->data().registerMessageRandomId(randomId, newId);
data->addToHistory(
history,
flags,
newId.msg,
messageFromId,
HistoryItem::NewMessageDate(action.options.scheduled),
(bot && !action.options.hideViaBot) ? peerToUser(bot->id) : 0,
action.replyTo,
messagePostAuthor);
data->addToHistory(history, {
.id = newId.msg,
.flags = flags,
.from = messageFromId,
.replyTo = action.replyTo,
.date = HistoryItem::NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.viaBotId = ((bot && !action.options.hideViaBot)
? peerToUser(bot->id)
: UserId()),
.postAuthor = messagePostAuthor,
});
history->clearCloudDraft(topicRootId);
history->startSavingCloudDraft(topicRootId);

View file

@ -81,11 +81,11 @@ constexpr auto kMaxWallPaperSlugLength = 255;
const auto flags = MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId
| (out ? MessageFlag::Outgoing : MessageFlag(0));
const auto item = history->makeMessage(
history->owner().nextLocalMessageId(),
flags,
base::unixtime::now(),
PreparedServiceText{ { text } });
const auto item = history->makeMessage({
.id = history->owner().nextLocalMessageId(),
.flags = flags,
.date = base::unixtime::now(),
}, PreparedServiceText{ { text } });
return AdminLog::OwnedItem(delegate, item);
}
@ -96,24 +96,16 @@ constexpr auto kMaxWallPaperSlugLength = 255;
bool out) {
Expects(history->peer->isUser());
const auto flags = MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId
| (out ? MessageFlag::Outgoing : MessageFlag(0));
const auto replyTo = FullReplyTo();
const auto viaBotId = UserId();
const auto groupedId = uint64();
const auto item = history->makeMessage(
history->nextNonHistoryEntryId(),
flags,
replyTo,
viaBotId,
base::unixtime::now(),
out ? history->session().userId() : peerToUser(history->peer->id),
QString(),
TextWithEntities{ text },
MTP_messageMediaEmpty(),
HistoryMessageMarkupData(),
groupedId);
const auto item = history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId
| (out ? MessageFlag::Outgoing : MessageFlag(0))),
.from = (out
? history->session().userId()
: peerToUser(history->peer->id)),
.date = base::unixtime::now(),
}, TextWithEntities{ text }, MTP_messageMediaEmpty());
return AdminLog::OwnedItem(delegate, item);
}

View file

@ -319,47 +319,36 @@ PreviewWrap::PreviewWrap(
, _delegate(std::make_unique<PreviewDelegate>(box, _style.get(), [=] {
update();
}))
, _replyToItem(_history->addNewLocalMessage(
_history->nextNonHistoryEntryId(),
(MessageFlag::FakeHistoryItem
, _replyToItem(_history->addNewLocalMessage({
.id = _history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId
| MessageFlag::Post),
UserId(), // via
FullReplyTo(),
base::unixtime::now(), // date
_fake->id,
QString(), // postAuthor
TextWithEntities{ _peer->isSelf()
? tr::lng_settings_color_reply(tr::now)
: tr::lng_settings_color_reply_channel(tr::now),
},
MTP_messageMediaEmpty(),
HistoryMessageMarkupData(),
uint64(0)))
, _replyItem(_history->addNewLocalMessage(
_history->nextNonHistoryEntryId(),
(MessageFlag::FakeHistoryItem
.from = _fake->id,
.date = base::unixtime::now(),
}, TextWithEntities{ _peer->isSelf()
? tr::lng_settings_color_reply(tr::now)
: tr::lng_settings_color_reply_channel(tr::now),
}, MTP_messageMediaEmpty()))
, _replyItem(_history->addNewLocalMessage({
.id = _history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId
| MessageFlag::HasReplyInfo
| MessageFlag::Post),
UserId(), // via
FullReplyTo{ .messageId = _replyToItem->fullId() },
base::unixtime::now(), // date
_fake->id,
QString(), // postAuthor
TextWithEntities{ _peer->isSelf()
? tr::lng_settings_color_text(tr::now)
: tr::lng_settings_color_text_channel(tr::now),
},
MTP_messageMediaWebPage(
.from = _fake->id,
.replyTo = FullReplyTo{.messageId = _replyToItem->fullId() },
.date = base::unixtime::now(),
}, TextWithEntities{ _peer->isSelf()
? tr::lng_settings_color_text(tr::now)
: tr::lng_settings_color_text_channel(tr::now),
}, MTP_messageMediaWebPage(
MTP_flags(0),
MTP_webPagePending(
MTP_flags(0),
MTP_webPagePending(
MTP_flags(0),
MTP_long(_webpage->id),
MTPstring(),
MTP_int(0))),
HistoryMessageMarkupData(),
uint64(0)))
MTP_long(_webpage->id),
MTPstring(),
MTP_int(0)))))
, _element(_replyItem->createView(_delegate.get()))
, _position(0, st::msgMargin.bottom()) {
_style->apply(_theme.get());

View file

@ -77,20 +77,15 @@ AdminLog::OwnedItem GenerateItem(
const QString &text) {
Expects(history->peer->isUser());
const auto item = history->addNewLocalMessage(
history->nextNonHistoryEntryId(),
(MessageFlag::FakeHistoryItem
const auto item = history->addNewLocalMessage({
.id = history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId
| MessageFlag::HasReplyInfo),
UserId(), // via
FullReplyTo{ .messageId = replyTo },
base::unixtime::now(), // date
from,
QString(), // postAuthor
TextWithEntities{ .text = text },
MTP_messageMediaEmpty(),
HistoryMessageMarkupData(),
uint64(0)); // groupedId
.from = from,
.replyTo = FullReplyTo{ .messageId = replyTo },
.date = base::unixtime::now(),
}, TextWithEntities{ .text = text }, MTP_messageMediaEmpty());
return AdminLog::OwnedItem(delegate, item);
}

View file

@ -27,13 +27,13 @@ constexpr auto kRequestTimeLimit = 60 * crl::time(1000);
[[nodiscard]] MsgId RemoteToLocalMsgId(MsgId id) {
Expects(IsServerMsgId(id));
return ServerMaxMsgId + id + 1;
return ScheduledMaxMsgId + id + 1;
}
[[nodiscard]] MsgId LocalToRemoteMsgId(MsgId id) {
Expects(IsShortcutMsgId(id));
return (id - ServerMaxMsgId - 1);
return (id - ScheduledMaxMsgId - 1);
}
[[nodiscard]] bool TooEarlyForRequest(crl::time received) {
@ -145,6 +145,14 @@ int ShortcutMessages::count(BusinessShortcutId shortcutId) const {
return (i != end(_data)) ? i->second.items.size() : 0;
}
void ShortcutMessages::apply(const MTPDupdateQuickReplies &update) {
}
void ShortcutMessages::apply(const MTPDupdateNewQuickReply &update) {
}
void ShortcutMessages::apply(const MTPDupdateQuickReplyMessage &update) {
const auto &message = update.vmessage();
const auto shortcutId = BusinessShortcutIdFromMessage(message);

View file

@ -50,6 +50,8 @@ public:
[[nodiscard]] int count(BusinessShortcutId shortcutId) const;
[[nodiscard]] MsgId localMessageId(MsgId remoteId) const;
void apply(const MTPDupdateQuickReplies &update);
void apply(const MTPDupdateNewQuickReply &update);
void apply(const MTPDupdateQuickReplyMessage &update);
void apply(const MTPDupdateDeleteQuickReplyMessages &update);
void apply(const MTPDupdateDeleteQuickReply &update);

View file

@ -879,29 +879,20 @@ not_null<HistoryItem*> DownloadManager::generateItem(
const auto session = document
? &document->session()
: &photo->session();
const auto fromId = previousItem
? previousItem->from()->id
: session->userPeerId();
const auto history = previousItem
? previousItem->history()
: session->data().history(session->user());
const auto flags = MessageFlag::FakeHistoryItem;
const auto replyTo = FullReplyTo();
const auto viaBotId = UserId();
const auto date = base::unixtime::now();
;
const auto caption = TextWithEntities();
const auto make = [&](const auto media) {
return history->makeMessage(
history->nextNonHistoryEntryId(),
flags,
replyTo,
viaBotId,
date,
fromId,
QString(),
media,
caption,
HistoryMessageMarkupData());
return history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::FakeHistoryItem,
.from = (previousItem
? previousItem->from()->id
: session->userPeerId()),
.date = base::unixtime::now(),
}, media, caption);
};
const auto result = document ? make(document) : make(photo);
_generated.emplace(result);

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_histories.h"
#include "api/api_text_entities.h"
#include "data/business/data_shortcut_messages.h"
#include "data/data_session.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
@ -821,6 +822,7 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) {
remove.reserve(ids.size());
base::flat_map<not_null<History*>, QVector<MTPint>> idsByPeer;
base::flat_map<not_null<PeerData*>, QVector<MTPint>> scheduledIdsByPeer;
base::flat_map<BusinessShortcutId, QVector<MTPint>> quickIdsByShortcut;
for (const auto &itemId : ids) {
if (const auto item = _owner->message(itemId)) {
const auto history = item->history();
@ -834,6 +836,16 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) {
_owner->scheduledMessages().removeSending(item);
}
continue;
} else if (item->isBusinessShortcut()) {
const auto wasOnServer = !item->isSending()
&& !item->hasFailed();
if (wasOnServer) {
quickIdsByShortcut[item->shortcutId()].push_back(MTP_int(
_owner->shortcutMessages().lookupId(item)));
} else {
_owner->shortcutMessages().removeSending(item);
}
continue;
}
remove.push_back(item);
if (item->isRegular()) {
@ -853,6 +865,15 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) {
peer->session().api().applyUpdates(result);
}).send();
}
for (const auto &[shortcutId, ids] : quickIdsByShortcut) {
const auto api = &_owner->session().api();
api->request(MTPmessages_DeleteQuickReplyMessages(
MTP_int(shortcutId),
MTP_vector<MTPint>(ids)
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result);
}).send();
}
for (const auto item : remove) {
const auto history = item->history();

View file

@ -34,11 +34,11 @@ constexpr auto kMaxMessagesToDeleteMyTopic = 10;
not_null<History*> history,
TimeId date,
const QString &text) {
return history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::FakeHistoryItem,
date,
PreparedServiceText{ { .text = text } });
return history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::FakeHistoryItem,
.date = date,
}, PreparedServiceText{ { .text = text } });
}
[[nodiscard]] bool IsCreating(not_null<History*> history, MsgId rootId) {

View file

@ -80,7 +80,7 @@ bool SponsoredMessages::append(not_null<History*> history) {
entryIt->itemFullId = FullMsgId(
history->peer->id,
_session->data().nextLocalMessageId());
entryIt->item.reset(history->addNewLocalMessage(
entryIt->item.reset(history->addSponsoredMessage(
entryIt->itemFullId.msg,
entryIt->sponsored.from,
entryIt->sponsored.textWithEntities));

View file

@ -970,7 +970,7 @@ std::shared_ptr<HistoryItem> Stories::resolveItem(not_null<Story*> story) {
}
const auto history = _owner->history(story->peer());
auto result = std::shared_ptr<HistoryItem>(
history->makeMessage(story).get(),
history->makeMessage(StoryIdToMsgId(story->id()), story).get(),
HistoryItem::Destroyer());
i->second = result;
return result;

View file

@ -318,6 +318,8 @@ enum class MessageFlag : uint64 {
Sponsored = (1ULL << 42),
ReactionsAreTags = (1ULL << 43),
ShortcutMessage = (1ULL << 44),
};
inline constexpr bool is_flag_type(MessageFlag) { return true; }
using MessageFlags = base::flags<MessageFlag>;

View file

@ -801,13 +801,12 @@ void GenerateItems(
auto message = PreparedServiceText{ text };
message.links.push_back(fromLink);
addPart(
history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::AdminLogEntry,
date,
std::move(message),
peerToUser(from->id),
photo),
history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::AdminLogEntry,
.from = from->id,
.date = date,
}, std::move(message), photo),
0,
realId);
};
@ -826,23 +825,11 @@ void GenerateItems(
};
const auto makeSimpleTextMessage = [&](TextWithEntities &&text) {
const auto bodyFlags = MessageFlag::HasFromId
| MessageFlag::AdminLogEntry;
const auto bodyReplyTo = FullReplyTo();
const auto bodyViaBotId = UserId();
const auto bodyGroupedId = uint64();
return history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyReplyTo,
bodyViaBotId,
date,
peerToUser(from->id),
QString(),
std::move(text),
MTP_messageMediaEmpty(),
HistoryMessageMarkupData(),
bodyGroupedId);
return history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::HasFromId | MessageFlag::AdminLogEntry,
.from = from->id,
}, std::move(text), MTP_messageMediaEmpty());
};
const auto addSimpleTextMessage = [&](TextWithEntities &&text) {
@ -1145,12 +1132,12 @@ void GenerateItems(
auto message = PreparedServiceText{ text };
message.links.push_back(fromLink);
message.links.push_back(setLink);
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::AdminLogEntry,
date,
std::move(message),
peerToUser(from->id)));
addPart(history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::AdminLogEntry,
.from = from->id,
.date = date,
}, std::move(message)));
}
};
@ -1189,12 +1176,12 @@ void GenerateItems(
auto message = PreparedServiceText{ text };
message.links.push_back(fromLink);
message.links.push_back(setLink);
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::AdminLogEntry,
date,
std::move(message),
peerToUser(from->id)));
addPart(history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::AdminLogEntry,
.from = from->id,
.date = date,
}, std::move(message)));
}
};
@ -1270,12 +1257,12 @@ void GenerateItems(
auto message = PreparedServiceText{ text };
message.links.push_back(fromLink);
message.links.push_back(chatLink);
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::AdminLogEntry,
date,
std::move(message),
peerToUser(from->id)));
addPart(history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::AdminLogEntry,
.from = from->id,
.date = date,
}, std::move(message)));
}
};
@ -1366,12 +1353,12 @@ void GenerateItems(
auto message = PreparedServiceText{ text };
message.links.push_back(fromLink);
message.links.push_back(link);
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::AdminLogEntry,
date,
std::move(message),
peerToUser(from->id)));
addPart(history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::AdminLogEntry,
.from = from->id,
.date = date,
}, std::move(message)));
};
const auto createParticipantMute = [&](const LogMute &data) {
@ -1441,13 +1428,12 @@ void GenerateItems(
if (additional) {
message.links.push_back(std::move(additional));
}
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
MessageFlag::AdminLogEntry,
date,
std::move(message),
peerToUser(from->id),
nullptr));
addPart(history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::AdminLogEntry,
.from = from->id,
.date = date,
}, std::move(message)));
};
const auto createParticipantJoinByInvite = [&](

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_translation.h"
#include "history/history_unread_things.h"
#include "dialogs/ui/dialogs_layout.h"
#include "data/business/data_shortcut_messages.h"
#include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h"
@ -71,6 +72,12 @@ constexpr auto kSkipCloudDraftsFor = TimeId(2);
using UpdateFlag = Data::HistoryUpdate::Flag;
[[nodiscard]] HistoryItemCommonFields WithLocalFlag(
HistoryItemCommonFields fields) {
fields.flags |= MessageFlag::Local;
return fields;
}
} // namespace
History::History(not_null<Data::Session*> owner, PeerId peerId)
@ -446,17 +453,17 @@ std::vector<not_null<HistoryItem*>> History::createItems(
not_null<HistoryItem*> History::addNewMessage(
MsgId id,
const MTPMessage &msg,
const MTPMessage &message,
MessageFlags localFlags,
NewMessageType type) {
const auto detachExistingItem = (type == NewMessageType::Unread);
const auto item = createItem(id, msg, localFlags, detachExistingItem);
const auto detachExisting = (type == NewMessageType::Unread);
const auto item = createItem(id, message, localFlags, detachExisting);
if (type == NewMessageType::Existing || item->mainView()) {
return item;
}
const auto unread = (type == NewMessageType::Unread);
if (unread && item->isHistoryEntry()) {
applyMessageChanges(item, msg);
applyMessageChanges(item, message);
}
return addNewItem(item, unread);
}
@ -585,6 +592,9 @@ not_null<HistoryItem*> History::addNewItem(
if (item->isScheduled()) {
owner().scheduledMessages().appendSending(item);
return item;
} else if (item->isBusinessShortcut()) {
owner().shortcutMessages().appendSending(item);
return item;
} else if (!item->isHistoryEntry()) {
return item;
}
@ -635,139 +645,54 @@ void History::checkForLoadedAtTop(not_null<HistoryItem*> added) {
}
not_null<HistoryItem*> History::addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
const TextWithEntities &text,
const MTPMessageMedia &media,
HistoryMessageMarkupData &&markup,
uint64 groupedId) {
const MTPMessageMedia &media) {
return addNewItem(
makeMessage(
id,
flags | MessageFlag::Local,
replyTo,
viaBotId,
date,
from,
postAuthor,
text,
media,
std::move(markup),
groupedId),
makeMessage(WithLocalFlag(std::move(fields)), text, media),
true);
}
not_null<HistoryItem*> History::addNewLocalMessage(
MsgId id,
MessageFlags flags,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<HistoryItem*> forwardOriginal,
MsgId topicRootId) {
HistoryItemCommonFields &&fields,
not_null<HistoryItem*> forwardOriginal) {
return addNewItem(
makeMessage(
id,
flags | MessageFlag::Local,
date,
from,
postAuthor,
forwardOriginal,
topicRootId),
makeMessage(WithLocalFlag(std::move(fields)), forwardOriginal),
true);
}
not_null<HistoryItem*> History::addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<DocumentData*> document,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup) {
const TextWithEntities &caption) {
return addNewItem(
makeMessage(
id,
flags | MessageFlag::Local,
replyTo,
viaBotId,
date,
from,
postAuthor,
document,
caption,
std::move(markup)),
makeMessage(WithLocalFlag(std::move(fields)), document, caption),
true);
}
not_null<HistoryItem*> History::addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<PhotoData*> photo,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup) {
const TextWithEntities &caption) {
return addNewItem(
makeMessage(
id,
flags | MessageFlag::Local,
replyTo,
viaBotId,
date,
from,
postAuthor,
photo,
caption,
std::move(markup)),
makeMessage(WithLocalFlag(std::move(fields)), photo, caption),
true);
}
not_null<HistoryItem*> History::addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<GameData*> game,
HistoryMessageMarkupData &&markup) {
HistoryItemCommonFields &&fields,
not_null<GameData*> game) {
return addNewItem(
makeMessage(
id,
flags | MessageFlag::Local,
replyTo,
viaBotId,
date,
from,
postAuthor,
game,
std::move(markup)),
makeMessage(WithLocalFlag(std::move(fields)), game),
true);
}
not_null<HistoryItem*> History::addNewLocalMessage(
not_null<HistoryItem*> History::addSponsoredMessage(
MsgId id,
Data::SponsoredFrom from,
const TextWithEntities &textWithEntities) {
return addNewItem(
makeMessage(
id,
from,
textWithEntities,
nullptr),
makeMessage(id, from, textWithEntities, nullptr),
true);
}

View file

@ -20,6 +20,7 @@ class History;
class HistoryBlock;
class HistoryTranslation;
class HistoryItem;
struct HistoryItemCommonFields;
struct HistoryMessageMarkupData;
class HistoryMainElementDelegateMixin;
struct LanguageId;
@ -127,11 +128,23 @@ public:
void applyGroupAdminChanges(const base::flat_set<UserId> &changes);
template <typename ...Args>
not_null<HistoryItem*> makeMessage(Args &&...args) {
not_null<HistoryItem*> makeMessage(MsgId id, Args &&...args) {
return static_cast<HistoryItem*>(
insertItem(
std::make_unique<HistoryItem>(
this,
id,
std::forward<Args>(args)...)).get());
}
template <typename ...Args>
not_null<HistoryItem*> makeMessage(
HistoryItemCommonFields &&fields,
Args &&...args) {
return static_cast<HistoryItem*>(
insertItem(
std::make_unique<HistoryItem>(
this,
std::move(fields),
std::forward<Args>(args)...)).get());
}
@ -143,62 +156,30 @@ public:
not_null<HistoryItem*> addNewMessage(
MsgId id,
const MTPMessage &msg,
const MTPMessage &message,
MessageFlags localFlags,
NewMessageType type);
not_null<HistoryItem*> addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
const TextWithEntities &text,
const MTPMessageMedia &media,
HistoryMessageMarkupData &&markup,
uint64 groupedId = 0);
const MTPMessageMedia &media);
not_null<HistoryItem*> addNewLocalMessage(
MsgId id,
MessageFlags flags,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<HistoryItem*> forwardOriginal,
MsgId topicRootId);
HistoryItemCommonFields &&fields,
not_null<HistoryItem*> forwardOriginal);
not_null<HistoryItem*> addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<DocumentData*> document,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup);
const TextWithEntities &caption);
not_null<HistoryItem*> addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<PhotoData*> photo,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup);
not_null<HistoryItem*> addNewLocalMessage(
MsgId id,
MessageFlags flags,
UserId viaBotId,
FullReplyTo replyTo,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<GameData*> game,
HistoryMessageMarkupData &&markup);
const TextWithEntities &caption);
not_null<HistoryItem*> addNewLocalMessage(
HistoryItemCommonFields &&fields,
not_null<GameData*> game);
not_null<HistoryItem*> addSponsoredMessage(
MsgId id,
Data::SponsoredFrom from,
const TextWithEntities &textWithEntities); // sponsored

View file

@ -125,6 +125,14 @@ template <typename T>
return false;
}
[[nodiscard]] HistoryItemCommonFields ForwardedFields(
HistoryItemCommonFields fields,
not_null<History*> history,
not_null<HistoryItem*> original) {
fields.flags |= NewForwardedFlags(history->peer, fields.from, original);
return fields;
}
} // namespace
void HistoryItem::HistoryItem::Destroyer::operator()(HistoryItem *value) {
@ -347,12 +355,13 @@ HistoryItem::HistoryItem(
MsgId id,
const MTPDmessage &data,
MessageFlags localFlags)
: HistoryItem(
history,
id,
FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
: HistoryItem(history, {
.id = id,
.flags = FlagsFromMTP(id, data.vflags().v, localFlags),
.from = data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0),
.date = data.vdate().v,
.shortcutId = data.vquick_reply_shortcut_id().value_or_empty(),
}) {
_boostsApplied = data.vfrom_boosts_applied().value_or_empty();
const auto media = data.vmedia();
@ -406,12 +415,12 @@ HistoryItem::HistoryItem(
MsgId id,
const MTPDmessageService &data,
MessageFlags localFlags)
: HistoryItem(
history,
id,
FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
: HistoryItem(history, {
.id = id,
.flags = FlagsFromMTP(id, data.vflags().v, localFlags),
.from = data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0),
.date = data.vdate().v,
}) {
if (data.vaction().type() != mtpc_messageActionPhoneCall) {
createServiceFromMtp(data);
} else {
@ -431,9 +440,7 @@ HistoryItem::HistoryItem(
MessageFlags localFlags)
: HistoryItem(
history,
id,
localFlags,
TimeId(0),
{ .id = id, .flags = localFlags },
PreparedServiceText{ tr::lng_message_empty(
tr::now,
Ui::Text::WithEntities) }) {
@ -441,13 +448,10 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
TimeId date,
HistoryItemCommonFields &&fields,
PreparedServiceText &&message,
PeerId from,
PhotoData *photo)
: HistoryItem(history, id, flags, date, from) {
: HistoryItem(history, fields) {
setServiceText(std::move(message));
if (photo) {
_media = std::make_unique<Data::MediaPhoto>(
@ -459,25 +463,16 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<HistoryItem*> original,
MsgId topicRootId)
: HistoryItem(
history,
id,
(NewForwardedFlags(history->peer, from, original) | flags),
date,
from) {
HistoryItemCommonFields &&fields,
not_null<HistoryItem*> original)
: HistoryItem(history, ForwardedFields(fields, history, original)) {
const auto peer = history->peer;
auto config = CreateConfig();
const auto originalMedia = original->media();
const auto dropForwardInfo = original->computeDropForwardedInfo();
const auto topicRootId = fields.replyTo.topicRootId;
config.reply.messageId = config.reply.topMessageId = topicRootId;
config.reply.topicPost = (topicRootId != 0) ? 1 : 0;
if (const auto originalReply = original->Get<HistoryMessageReply>()) {
@ -520,8 +515,8 @@ HistoryItem::HistoryItem(
? original->author()->id
: PeerId();
}
if (flags & MessageFlag::HasPostAuthor) {
config.postAuthor = postAuthor;
if (_flags & MessageFlag::HasPostAuthor) {
config.postAuthor = fields.postAuthor;
}
if (const auto fwdViaBot = original->viaBot()) {
config.viaBotId = peerToUser(fwdViaBot->id);
@ -571,63 +566,28 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
const TextWithEntities &textWithEntities,
const MTPMessageMedia &media,
HistoryMessageMarkupData &&markup,
uint64 groupedId)
: HistoryItem(
history,
id,
flags,
date,
(flags & MessageFlag::HasFromId) ? from : 0) {
createComponentsHelper(
flags,
replyTo,
viaBotId,
postAuthor,
std::move(markup));
const MTPMessageMedia &media)
: HistoryItem(history, fields) {
createComponentsHelper(std::move(fields));
setMedia(media);
setText(textWithEntities);
if (groupedId) {
if (fields.groupedId) {
setGroupId(MessageGroupId::FromRaw(
history->peer->id,
groupedId,
flags & MessageFlag::IsOrWasScheduled));
fields.groupedId,
_flags & MessageFlag::IsOrWasScheduled));
}
}
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<DocumentData*> document,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup)
: HistoryItem(
history,
id,
flags,
date,
(flags & MessageFlag::HasFromId) ? from : 0) {
createComponentsHelper(
flags,
replyTo,
viaBotId,
postAuthor,
std::move(markup));
const TextWithEntities &caption)
: HistoryItem(history, fields) {
createComponentsHelper(std::move(fields));
const auto skipPremiumEffect = !history->session().premium();
const auto spoiler = false;
@ -642,28 +602,11 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<PhotoData*> photo,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup)
: HistoryItem(
history,
id,
flags,
date,
(flags & MessageFlag::HasFromId) ? from : 0) {
createComponentsHelper(
flags,
replyTo,
viaBotId,
postAuthor,
std::move(markup));
const TextWithEntities &caption)
: HistoryItem(history, fields) {
createComponentsHelper(std::move(fields));
const auto spoiler = false;
_media = std::make_unique<Data::MediaPhoto>(this, photo, spoiler);
@ -672,27 +615,10 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<GameData*> game,
HistoryMessageMarkupData &&markup)
: HistoryItem(
history,
id,
flags,
date,
(flags & MessageFlag::HasFromId) ? from : 0) {
createComponentsHelper(
flags,
replyTo,
viaBotId,
postAuthor,
std::move(markup));
HistoryItemCommonFields &&fields,
not_null<GameData*> game)
: HistoryItem(history, fields) {
createComponentsHelper(std::move(fields));
_media = std::make_unique<Data::MediaGame>(this, game);
setTextValue({});
@ -704,18 +630,15 @@ HistoryItem::HistoryItem(
Data::SponsoredFrom from,
const TextWithEntities &textWithEntities,
HistoryItem *injectedAfter)
: HistoryItem(
history,
id,
((history->peer->isChannel() ? MessageFlag::Post : MessageFlag(0))
//| (from.peer ? MessageFlag::HasFromId : MessageFlag(0))
| MessageFlag::Local),
HistoryItem::NewMessageDate(injectedAfter
? injectedAfter->date()
: 0),
/*from.peer ? from.peer->id : */PeerId(0)) {
_flags |= MessageFlag::Sponsored;
: HistoryItem(history, {
.id = id,
.flags = (MessageFlag::Local
| MessageFlag::Sponsored
| (history->peer->isChannel() ? MessageFlag::Post : MessageFlag(0))),
.date = HistoryItem::NewMessageDate(injectedAfter
? injectedAfter->date()
: 0),
}) {
const auto webPageType = !from.externalLink.isEmpty()
? WebPageType::None
: from.isExactPost
@ -758,15 +681,15 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
TimeId date,
PeerId from)
: id(id)
const HistoryItemCommonFields &fields)
: id(fields.id)
, _history(history)
, _from(from ? history->owner().peer(from) : history->peer)
, _flags(FinalizeMessageFlags(history, flags))
, _date(date) {
, _from((fields.flags & MessageFlag::HasFromId && fields.from)
? history->owner().peer(fields.from)
: history->peer)
, _flags(FinalizeMessageFlags(history, fields.flags))
, _date(fields.date)
, _shortcutId(fields.shortcutId) {
if (isHistoryEntry() && IsClientMsgId(id)) {
_history->registerClientSideMessage(this);
}
@ -774,15 +697,18 @@ HistoryItem::HistoryItem(
HistoryItem::HistoryItem(
not_null<History*> history,
MsgId id,
not_null<Data::Story*> story)
: id(StoryIdToMsgId(story->id()))
, _history(history)
, _from(history->peer)
, _flags(MessageFlag::Local
| MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem
| MessageFlag::StoryItem)
, _date(story->date()) {
: HistoryItem(history, {
.id = id,
.flags = (MessageFlag::Local
| MessageFlag::Outgoing
| MessageFlag::HasFromId
| MessageFlag::FakeHistoryItem
| MessageFlag::StoryItem),
.from = history->peer->id,
.date = story->date(),
}) {
setStoryFields(story);
}
@ -807,6 +733,11 @@ TimeId HistoryItem::NewMessageDate(TimeId scheduled) {
return scheduled ? scheduled : base::unixtime::now();
}
TimeId HistoryItem::NewMessageDate(
const Api::SendOptions &options) {
return options.shortcutId ? TimeId() : NewMessageDate(options.scheduled);
}
HistoryServiceDependentData *HistoryItem::GetServiceDependentData() {
if (const auto pinned = Get<HistoryServicePinned>()) {
return pinned;
@ -1603,6 +1534,14 @@ bool HistoryItem::isUserpicSuggestion() const {
return (_flags & MessageFlag::IsUserpicSuggestion);
}
BusinessShortcutId HistoryItem::shortcutId() const {
return _shortcutId;
}
bool HistoryItem::isBusinessShortcut() const {
return _shortcutId != 0;
}
void HistoryItem::destroy() {
_history->destroyMessage(this);
}
@ -3520,15 +3459,11 @@ TextWithEntities HistoryItem::withLocalEntities(
return textWithEntities;
}
void HistoryItem::createComponentsHelper(
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) {
void HistoryItem::createComponentsHelper(HistoryItemCommonFields &&fields) {
const auto &replyTo = fields.replyTo;
auto config = CreateConfig();
config.viaBotId = viaBotId;
if (flags & MessageFlag::HasReplyInfo) {
config.viaBotId = fields.viaBotId;
if (fields.flags & MessageFlag::HasReplyInfo) {
config.reply.messageId = replyTo.messageId.msg;
config.reply.storyId = replyTo.storyId.story;
config.reply.externalPeerId = replyTo.storyId
@ -3567,9 +3502,13 @@ void HistoryItem::createComponentsHelper(
config.reply.quoteOffset = replyTo.quoteOffset;
config.reply.quote = std::move(replyTo.quote);
}
config.markup = std::move(markup);
if (flags & MessageFlag::HasPostAuthor) config.postAuthor = postAuthor;
if (flags & MessageFlag::HasViews) config.viewsCount = 1;
config.markup = std::move(fields.markup);
if (fields.flags & MessageFlag::HasPostAuthor) {
config.postAuthor = fields.postAuthor;
}
if (fields.flags & MessageFlag::HasViews) {
config.viewsCount = 1;
}
createComponents(std::move(config));
}

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class HiddenSenderInfo;
class History;
struct HistoryMessageReply;
struct HistoryMessageViews;
struct HistoryMessageMarkupData;
@ -28,6 +29,10 @@ struct PreparedServiceText;
class ReplyKeyboard;
struct LanguageId;
namespace Api {
struct SendOptions;
} // namespace Api
namespace base {
template <typename Enum>
class enum_mask;
@ -86,6 +91,19 @@ class Service;
class ServiceMessagePainter;
} // namespace HistoryView
struct HistoryItemCommonFields {
MsgId id = 0;
MessageFlags flags = 0;
PeerId from = 0;
FullReplyTo replyTo;
TimeId date = 0;
BusinessShortcutId shortcutId = 0;
UserId viaBotId = 0;
QString postAuthor;
uint64 groupedId = 0;
HistoryMessageMarkupData markup;
};
class HistoryItem final : public RuntimeComposer<HistoryItem> {
public:
[[nodiscard]] static std::unique_ptr<Data::Media> CreateMedia(
@ -114,73 +132,39 @@ public:
Data::SponsoredFrom from,
const TextWithEntities &textWithEntities,
HistoryItem *injectedAfter);
HistoryItem( // Story wrap.
not_null<History*> history,
MsgId id,
not_null<Data::Story*> story);
HistoryItem( // Local message.
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
const TextWithEntities &textWithEntities,
const MTPMessageMedia &media,
HistoryMessageMarkupData &&markup,
uint64 groupedId);
const MTPMessageMedia &media);
HistoryItem( // Local service message.
not_null<History*> history,
MsgId id,
MessageFlags flags,
TimeId date,
HistoryItemCommonFields &&fields,
PreparedServiceText &&message,
PeerId from = 0,
PhotoData *photo = nullptr);
HistoryItem( // Local forwarded.
not_null<History*> history,
MsgId id,
MessageFlags flags,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<HistoryItem*> original,
MsgId topicRootId);
HistoryItemCommonFields &&fields,
not_null<HistoryItem*> original);
HistoryItem( // Local photo.
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<PhotoData*> photo,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup);
const TextWithEntities &caption);
HistoryItem( // Local document.
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
HistoryItemCommonFields &&fields,
not_null<DocumentData*> document,
const TextWithEntities &caption,
HistoryMessageMarkupData &&markup);
const TextWithEntities &caption);
HistoryItem( // Local game.
not_null<History*> history,
MsgId id,
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
TimeId date,
PeerId from,
const QString &postAuthor,
not_null<GameData*> game,
HistoryMessageMarkupData &&markup);
HistoryItem(not_null<History*> history, not_null<Data::Story*> story);
HistoryItemCommonFields &&fields,
not_null<GameData*> game);
~HistoryItem();
struct Destroyer {
@ -210,12 +194,8 @@ public:
[[nodiscard]] bool isSponsored() const;
[[nodiscard]] bool skipNotification() const;
[[nodiscard]] bool isUserpicSuggestion() const;
[[nodiscard]] BusinessShortcutId shortcutId() const {
return _shortcutId;
}
[[nodiscard]] bool isBusinessShortcut() const {
return _shortcutId != 0;
}
[[nodiscard]] BusinessShortcutId shortcutId() const;
[[nodiscard]] bool isBusinessShortcut() const;
void addLogEntryOriginal(
WebPageId localId,
@ -473,6 +453,8 @@ public:
[[nodiscard]] TimeId date() const;
[[nodiscard]] static TimeId NewMessageDate(TimeId scheduled);
[[nodiscard]] static TimeId NewMessageDate(
const Api::SendOptions &options);
[[nodiscard]] Data::Media *media() const {
return _media.get();
@ -554,17 +536,9 @@ private:
HistoryItem(
not_null<History*> history,
MsgId id,
MessageFlags flags,
TimeId date,
PeerId from);
const HistoryItemCommonFields &fields);
void createComponentsHelper(
MessageFlags flags,
FullReplyTo replyTo,
UserId viaBotId,
const QString &postAuthor,
HistoryMessageMarkupData &&markup);
void createComponentsHelper(HistoryItemCommonFields &&fields);
void createComponents(CreateConfig &&config);
void setupForwardedComponent(const CreateConfig &config);

View file

@ -301,6 +301,7 @@ ReplyFields ReplyFieldsFromMTP(
if (const auto id = data.vreply_to_msg_id().value_or_empty()) {
result.messageId = data.is_reply_to_scheduled()
? owner->scheduledMessages().localMessageId(id)
AssertIsDebug()
: id;
result.topMessageId
= data.vreply_to_top_id().value_or(id);

View file

@ -386,6 +386,9 @@ MessageFlags FlagsFromMTP(
| ((flags & MTP::f_from_id) ? Flag::HasFromId : Flag())
| ((flags & MTP::f_reply_to) ? Flag::HasReplyInfo : Flag())
| ((flags & MTP::f_reply_markup) ? Flag::HasReplyMarkup : Flag())
| ((flags & MTP::f_quick_reply_shortcut_id)
? Flag::ShortcutMessage
: Flag())
| ((flags & MTP::f_from_scheduled)
? Flag::IsOrWasScheduled
: Flag())
@ -598,11 +601,11 @@ not_null<HistoryItem*> GenerateJoinedMessage(
TimeId inviteDate,
not_null<UserData*> inviter,
bool viaRequest) {
return history->makeMessage(
history->owner().nextLocalMessageId(),
MessageFlag::Local | MessageFlag::ShowSimilarChannels,
inviteDate,
GenerateJoinedText(history, inviter, viaRequest));
return history->makeMessage({
.id = history->owner().nextLocalMessageId(),
.flags = MessageFlag::Local | MessageFlag::ShowSimilarChannels,
.date = inviteDate,
}, GenerateJoinedText(history, inviter, viaRequest));
}
std::optional<bool> PeerHasThisCall(
@ -657,6 +660,7 @@ std::optional<bool> PeerHasThisCall(
MessageFlags flags) {
if (!(flags & MessageFlag::FakeHistoryItem)
&& !(flags & MessageFlag::IsOrWasScheduled)
&& !(flags & MessageFlag::ShortcutMessage)
&& !(flags & MessageFlag::AdminLogEntry)) {
flags |= MessageFlag::HistoryEntry;
if (history->peer->isSelf()) {

View file

@ -257,38 +257,32 @@ rpl::producer<QString> PreviewWrap::showLinkSelector(
was->destroy();
}
using Flag = MTPDmessageMediaWebPage::Flag;
_draftItem = _history->addNewLocalMessage(
_history->nextNonHistoryEntryId(),
(MessageFlag::FakeHistoryItem
_draftItem = _history->addNewLocalMessage({
.id = _history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeHistoryItem
| MessageFlag::Outgoing
| MessageFlag::HasFromId
| (webpage.invert ? MessageFlag::InvertMedia : MessageFlag())),
UserId(), // via
FullReplyTo(),
base::unixtime::now(), // date
_history->session().userPeerId(),
QString(), // postAuthor
HighlightParsedLinks({
message.text,
TextUtilities::ConvertTextTagsToEntities(message.tags),
}, links),
MTP_messageMediaWebPage(
MTP_flags(Flag()
| (webpage.forceLargeMedia
? Flag::f_force_large_media
: Flag())
| (webpage.forceSmallMedia
? Flag::f_force_small_media
: Flag())),
MTP_webPagePending(
MTP_flags(webpage.url.isEmpty()
? MTPDwebPagePending::Flag()
: MTPDwebPagePending::Flag::f_url),
MTP_long(webpage.id),
MTP_string(webpage.url),
MTP_int(0))),
HistoryMessageMarkupData(),
uint64(0)); // groupedId
.from = _history->session().userPeerId(),
.date = base::unixtime::now(),
}, HighlightParsedLinks({
message.text,
TextUtilities::ConvertTextTagsToEntities(message.tags),
}, links), MTP_messageMediaWebPage(
MTP_flags(Flag()
| (webpage.forceLargeMedia
? Flag::f_force_large_media
: Flag())
| (webpage.forceSmallMedia
? Flag::f_force_small_media
: Flag())),
MTP_webPagePending(
MTP_flags(webpage.url.isEmpty()
? MTPDwebPagePending::Flag()
: MTPDwebPagePending::Flag::f_url),
MTP_long(webpage.id),
MTP_string(webpage.url),
MTP_int(0))));
_element = _draftItem->createView(_delegate.get());
_selectType = TextSelectType::Letters;
_symbol = _selectionStartSymbol = 0;

View file

@ -188,54 +188,39 @@ bool AboutView::refresh() {
}
AdminLog::OwnedItem AboutView::makeAboutBot(not_null<BotInfo*> info) {
const auto flags = MessageFlag::FakeAboutView
| MessageFlag::FakeHistoryItem
| MessageFlag::Local;
const auto postAuthor = QString();
const auto date = TimeId(0);
const auto replyTo = FullReplyTo();
const auto viaBotId = UserId(0);
const auto groupedId = uint64(0);
const auto textWithEntities = TextUtilities::ParseEntities(
info->description,
Ui::ItemTextBotNoMonoOptions().flags);
const auto make = [&](auto &&a, auto &&b, auto &&...other) {
return _history->makeMessage(
_history->nextNonHistoryEntryId(),
flags,
replyTo,
viaBotId,
date,
_history->peer->id,
postAuthor,
std::forward<decltype(a)>(a),
std::forward<decltype(b)>(b),
HistoryMessageMarkupData(),
std::forward<decltype(other)>(other)...);
const auto make = [&](auto &&...args) {
return _history->makeMessage({
.id = _history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeAboutView
| MessageFlag::FakeHistoryItem
| MessageFlag::Local),
.from = _history->peer->id,
}, std::forward<decltype(args)>(args)...);
};
const auto item = info->document
? make(info->document, textWithEntities)
: info->photo
? make(info->photo, textWithEntities)
: make(textWithEntities, MTP_messageMediaEmpty(), groupedId);
: make(textWithEntities, MTP_messageMediaEmpty());
return AdminLog::OwnedItem(_delegate, item);
}
AdminLog::OwnedItem AboutView::makePremiumRequired() {
const auto flags = MessageFlag::FakeAboutView
| MessageFlag::FakeHistoryItem
| MessageFlag::Local;
const auto date = TimeId(0);
const auto item = _history->makeMessage(
_history->nextNonHistoryEntryId(),
flags,
date,
PreparedServiceText{ tr::lng_send_non_premium_text(
tr::now,
lt_user,
Ui::Text::Bold(_history->peer->shortName()),
Ui::Text::RichLangValue) },
peerToUser(_history->peer->id));
const auto item = _history->makeMessage({
.id = _history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeAboutView
| MessageFlag::FakeHistoryItem
| MessageFlag::Local),
.from = _history->peer->id,
}, PreparedServiceText{ tr::lng_send_non_premium_text(
tr::now,
lt_user,
Ui::Text::Bold(_history->peer->shortName()),
Ui::Text::RichLangValue),
});
auto result = AdminLog::OwnedItem(_delegate, item);
result->overrideMedia(std::make_unique<ServiceBox>(
result.get(),

View file

@ -59,6 +59,7 @@ enum class Context : char {
ContactPreview,
SavedSublist,
TTLViewer,
ShortcutMessages,
};
enum class OnlyEmojiAndSpaces : char {

View file

@ -1792,7 +1792,7 @@ void ListWidget::updateItemsGeometry() {
if (view->isHidden()) {
view->setDisplayDate(false);
} else {
view->setDisplayDate(true);
view->setDisplayDate(_context != Context::ShortcutMessages);
view->setAttachToPrevious(false);
return i;
}
@ -2048,7 +2048,8 @@ void ListWidget::checkActivation() {
}
void ListWidget::paintEvent(QPaintEvent *e) {
if (_controller->contentOverlapped(this, e)) {
if ((_context != Context::ShortcutMessages)
&& _controller->contentOverlapped(this, e)) {
return;
}
@ -3737,7 +3738,8 @@ void ListWidget::refreshAttachmentsFromTill(int from, int till) {
} else {
const auto viewDate = view->dateTime();
const auto nextDate = next->dateTime();
next->setDisplayDate(nextDate.date() != viewDate.date());
next->setDisplayDate(_context != Context::ShortcutMessages
&& nextDate.date() != viewDate.date());
auto attached = next->computeIsAttachToPrevious(view);
next->setAttachToPrevious(attached, view);
view->setAttachToNext(attached, next);

View file

@ -631,11 +631,11 @@ private:
const not_null<ListDelegate*> _delegate;
const not_null<Window::SessionController*> _controller;
const std::unique_ptr<EmojiInteractions> _emojiInteractions;
const Context _context;
Data::MessagePosition _aroundPosition;
Data::MessagePosition _shownAtPosition;
Data::MessagePosition _initialAroundPosition;
Context _context;
int _aroundIndex = -1;
int _idsLimit = kMinimalIdsLimit;
Data::MessagesSlice _slice;

View file

@ -2061,6 +2061,7 @@ bool Message::hasFromPhoto() const {
return !item->out() && !item->history()->peer->isUser();
} break;
case Context::ContactPreview:
case Context::ShortcutMessages:
return false;
}
Unexpected("Context in Message::hasFromPhoto.");
@ -3268,6 +3269,7 @@ bool Message::hasFromName() const {
return false;
} break;
case Context::ContactPreview:
case Context::ShortcutMessages:
return false;
}
Unexpected("Context in Message::hasFromName.");
@ -3306,6 +3308,9 @@ bool Message::hasOutLayout() const {
const auto item = data();
if (item->history()->peer->isSelf()) {
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
if (context() == Context::ShortcutMessages) {
return true;
}
return (context() == Context::SavedSublist)
&& (!forwarded->forwardOfForward()
? (forwarded->originalSender

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_photo_media.h"
#include "data/data_document_media.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_reply_markup.h"
#include "inline_bots/inline_bot_layout_item.h"
#include "inline_bots/inline_bot_send_data.h"
@ -376,30 +377,15 @@ bool Result::hasThumbDisplay() const {
void Result::addToHistory(
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor) const {
flags |= MessageFlag::FromInlineBot;
auto markup = _replyMarkup ? *_replyMarkup : HistoryMessageMarkupData();
if (!markup.isNull()) {
flags |= MessageFlag::HasReplyMarkup;
HistoryItemCommonFields &&fields) const {
fields.flags |= MessageFlag::FromInlineBot;
if (_replyMarkup) {
fields.markup = *_replyMarkup;
if (!fields.markup.isNull()) {
fields.flags |= MessageFlag::HasReplyMarkup;
}
}
sendData->addToHistory(
this,
history,
flags,
msgId,
fromId,
date,
viaBotId,
replyTo,
postAuthor,
std::move(markup));
sendData->addToHistory(this, history, std::move(fields));
}
QString Result::getErrorOnSend(not_null<History*> history) const {

View file

@ -16,6 +16,7 @@ class FileLoader;
class History;
class UserData;
struct HistoryMessageMarkupData;
struct HistoryItemCommonFields;
namespace Data {
class LocationPoint;
@ -64,13 +65,7 @@ public:
void addToHistory(
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor) const;
HistoryItemCommonFields &&fields) const;
QString getErrorOnSend(not_null<History*> history) const;
// interface for Layout:: usage

View file

@ -31,29 +31,15 @@ QString SendData::getLayoutDescription(const Result *owner) const {
void SendDataCommon::addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const {
auto fields = getSentMessageFields();
if (replyTo) {
flags |= MessageFlag::HasReplyInfo;
HistoryItemCommonFields &&fields) const {
auto distinct = getSentMessageFields();
if (fields.replyTo) {
fields.flags |= MessageFlag::HasReplyInfo;
}
history->addNewLocalMessage(
msgId,
flags,
viaBotId,
replyTo,
date,
fromId,
postAuthor,
std::move(fields.text),
std::move(fields.media),
std::move(markup));
std::move(fields),
std::move(distinct.text),
std::move(distinct.media));
}
QString SendDataCommon::getErrorOnSend(
@ -113,25 +99,11 @@ QString SendContact::getLayoutDescription(const Result *owner) const {
void SendPhoto::addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const {
HistoryItemCommonFields &&fields) const {
history->addNewLocalMessage(
msgId,
flags,
viaBotId,
replyTo,
date,
fromId,
postAuthor,
std::move(fields),
_photo,
{ _message, _entities },
std::move(markup));
{ _message, _entities });
}
QString SendPhoto::getErrorOnSend(
@ -144,25 +116,11 @@ QString SendPhoto::getErrorOnSend(
void SendFile::addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const {
HistoryItemCommonFields &&fields) const {
history->addNewLocalMessage(
msgId,
flags,
viaBotId,
replyTo,
date,
fromId,
postAuthor,
std::move(fields),
_document,
{ _message, _entities },
std::move(markup));
{ _message, _entities });
}
QString SendFile::getErrorOnSend(
@ -175,24 +133,8 @@ QString SendFile::getErrorOnSend(
void SendGame::addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const {
history->addNewLocalMessage(
msgId,
flags,
viaBotId,
replyTo,
date,
fromId,
postAuthor,
_game,
std::move(markup));
HistoryItemCommonFields &&fields) const {
history->addNewLocalMessage(std::move(fields), _game);
}
QString SendGame::getErrorOnSend(

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_location_manager.h"
struct HistoryMessageMarkupData;
struct HistoryItemCommonFields;
namespace Main {
class Session;
@ -43,14 +43,7 @@ public:
virtual void addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const = 0;
HistoryItemCommonFields &&fields) const = 0;
virtual QString getErrorOnSend(
const Result *owner,
not_null<History*> history) const = 0;
@ -85,14 +78,7 @@ public:
void addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const override;
HistoryItemCommonFields &&fields) const override;
QString getErrorOnSend(
const Result *owner,
@ -253,14 +239,7 @@ public:
void addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const override;
HistoryItemCommonFields &&fields) const override;
QString getErrorOnSend(
const Result *owner,
@ -294,14 +273,7 @@ public:
void addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const override;
HistoryItemCommonFields &&fields) const override;
QString getErrorOnSend(
const Result *owner,
@ -329,14 +301,7 @@ public:
void addToHistory(
const Result *owner,
not_null<History*> history,
MessageFlags flags,
MsgId msgId,
PeerId fromId,
TimeId date,
UserId viaBotId,
FullReplyTo replyTo,
const QString &postAuthor,
HistoryMessageMarkupData &&markup) const override;
HistoryItemCommonFields &&fields) const override;
QString getErrorOnSend(
const Result *owner,

View file

@ -131,23 +131,12 @@ private:
not_null<History*> history) {
Expects(history->peer->isUser());
const auto flags = MessageFlag::FakeHistoryItem
| MessageFlag::HasFromId;
const auto replyTo = FullReplyTo();
const auto viaBotId = UserId();
const auto groupedId = uint64();
const auto item = history->makeMessage(
history->nextNonHistoryEntryId(),
flags,
replyTo,
viaBotId,
base::unixtime::now(),
peerToUser(history->peer->id),
QString(),
TextWithEntities(),
MTP_messageMediaEmpty(),
HistoryMessageMarkupData(),
groupedId);
const auto item = history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = MessageFlag::FakeHistoryItem | MessageFlag::HasFromId,
.from = history->peer->id,
.date = base::unixtime::now(),
}, TextWithEntities(), MTP_messageMediaEmpty());
return AdminLog::OwnedItem(delegate, item);
}

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/tabbed_selector.h"
#include "core/file_utilities.h"
#include "core/mime_type.h"
#include "data/business/data_shortcut_messages.h"
#include "data/data_message_reaction_id.h"
#include "data/data_premium_limits.h"
#include "data/data_session.h"
@ -75,6 +76,8 @@ public:
}
[[nodiscard]] rpl::producer<QString> title() override;
[[nodiscard]] rpl::producer<> sectionShowBack() override;
void setInnerFocus() override;
bool paintOuter(
not_null<QWidget*> outer,
@ -82,6 +85,8 @@ public:
QRect clip) override;
private:
void outerResized(QSize outer);
// ListDelegate interface.
Context listContext() override;
bool listScrollTo(int top, bool syntetic = true) override;
@ -154,7 +159,11 @@ private:
QPointer<Ui::RpWidget> createPinnedToBottom(
not_null<Ui::RpWidget*> parent) override;
void setupComposeControls();
void processScroll();
void updateInnerVisibleArea();
void pushReplyReturn(not_null<HistoryItem*> item);
void checkReplyReturns();
void uploadFile(const QByteArray &fileContent, SendMediaType type);
bool confirmSendingFiles(
@ -234,6 +243,7 @@ private:
QPointer<ListWidget> _inner;
std::unique_ptr<Ui::RpWidget> _controlsWrap;
std::unique_ptr<ComposeControls> _composeControls;
rpl::event_stream<> _showBackRequests;
bool _skipScrollEvent = false;
std::unique_ptr<StickerToast> _stickerToast;
@ -294,10 +304,17 @@ ShortcutMessages::ShortcutMessages(
this,
controller,
static_cast<ListDelegate*>(this));
//_scroll->scrolls(
//) | rpl::start_with_next([=] {
// onScroll();
//}, lifetime());
_scroll->sizeValue() | rpl::filter([](QSize size) {
return !size.isEmpty();
}) | rpl::start_with_next([=](QSize size) {
outerResized(size);
}, lifetime());
_scroll->scrolls(
) | rpl::start_with_next([=] {
processScroll();
}, lifetime());
_inner->editMessageRequested(
) | rpl::start_with_next([=](auto fullId) {
@ -312,10 +329,10 @@ ShortcutMessages::ShortcutMessages(
{
auto emptyInfo = base::make_unique_q<EmptyListBubbleWidget>(
_inner,
controller->chatStyle(),
_style.get(),
st::msgServicePadding);
const auto emptyText = Ui::Text::Semibold(
tr::lng_scheduled_messages_empty(tr::now));
u"give me your money.."_q);
emptyInfo->setText(emptyText);
_inner->setEmptyInfoWidget(std::move(emptyInfo));
}
@ -335,6 +352,31 @@ rpl::producer<QString> ShortcutMessages::title() {
return rpl::single(u"Editing messages list"_q);
}
void ShortcutMessages::processScroll() {
if (_skipScrollEvent) {
return;
}
updateInnerVisibleArea();
}
void ShortcutMessages::updateInnerVisibleArea() {
if (!_inner->animatedScrolling()) {
checkReplyReturns();
}
const auto scrollTop = _scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
_cornerButtons.updateJumpDownVisibility();
_cornerButtons.updateUnreadThingsVisibility();
}
rpl::producer<> ShortcutMessages::sectionShowBack() {
return _showBackRequests.events();
}
void ShortcutMessages::setInnerFocus() {
_composeControls->focus();
}
bool ShortcutMessages::paintOuter(
not_null<QWidget*> outer,
int maxVisibleHeight,
@ -349,6 +391,29 @@ bool ShortcutMessages::paintOuter(
return true;
}
void ShortcutMessages::outerResized(QSize outer) {
const auto contentWidth = outer.width();
const auto newScrollTop = _scroll->isHidden()
? std::nullopt
: _scroll->scrollTop()
? base::make_optional(_scroll->scrollTop())
: 0;
_skipScrollEvent = true;
_inner->resizeToWidth(contentWidth, _scroll->height());
resize(width(), _inner->height());
_skipScrollEvent = false;
if (!_scroll->isHidden()) {
if (newScrollTop) {
_scroll->scrollToY(*newScrollTop);
}
updateInnerVisibleArea();
}
_composeControls->setAutocompleteBoundingRect(_scroll->geometry());
_cornerButtons.updatePositions();
}
void ShortcutMessages::setupComposeControls() {
_composeControls->setHistory({
.history = _history.get(),
@ -446,10 +511,10 @@ void ShortcutMessages::setupComposeControls() {
if (action == Ui::InputField::MimeAction::Check) {
return Core::CanSendFiles(data);
} else if (action == Ui::InputField::MimeAction::Insert) {
//return confirmSendingFiles(
// data,
// std::nullopt,
// Core::ReadMimeText(data));#TODO
return confirmSendingFiles(
data,
std::nullopt,
Core::ReadMimeText(data));
}
Unexpected("action in MimeData hook.");
});
@ -480,22 +545,24 @@ QPointer<Ui::RpWidget> ShortcutMessages::createPinnedToBottom(
_controlsWrap.get(),
_controller,
[=](not_null<DocumentData*> emoji) { listShowPremiumToast(emoji); },
ComposeControls::Mode::Scheduled,
ComposeControls::Mode::Normal,
SendMenu::Type::Disabled);
setupComposeControls();
showAtEnd();
return _controlsWrap.get();
}
Context ShortcutMessages::listContext() {
return Context::History;
return Context::ShortcutMessages;
}
bool ShortcutMessages::listScrollTo(int top, bool syntetic) {
top = std::clamp(top, 0, _scroll->scrollTopMax());
if (_scroll->scrollTop() == top) {
//updateInnerVisibleArea();
updateInnerVisibleArea();
return false;
}
_scroll->scrollToY(top);
@ -509,7 +576,7 @@ void ShortcutMessages::listCancelRequest() {
} else if (_composeControls->handleCancelRequest()) {
return;
}
_controller->showBackFromStack();
_showBackRequests.fire({});
}
void ShortcutMessages::listDeleteRequest() {
@ -525,13 +592,11 @@ rpl::producer<Data::MessagesSlice> ShortcutMessages::listSource(
int limitBefore,
int limitAfter) {
const auto data = &_controller->session().data();
//return rpl::single(rpl::empty) | rpl::then(
// data->scheduledMessages().updates(_history)
//) | rpl::map([=] {
// return data->scheduledMessages().list(_history);
//}) | rpl::after_next([=](const Data::MessagesSlice &slice) {
// highlightSingleNewMessage(slice);
//});
return rpl::single(rpl::empty) | rpl::then(
data->shortcutMessages().updates(_shortcutId)
) | rpl::map([=] {
return data->shortcutMessages().list(_shortcutId);
});
return rpl::never<Data::MessagesSlice>();
}
@ -698,12 +763,12 @@ std::optional<bool> ShortcutMessages::cornerButtonsDownShown() {
|| _composeControls->isTTLButtonShown()) {
return false;
}
//const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
//if (top < _scroll->scrollTopMax() || _cornerButtons.replyReturn()) {
// return true;
//} else if (_inner->loadedAtBottomKnown()) {
// return !_inner->loadedAtBottom();
//}
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
if (top < _scroll->scrollTopMax() || _cornerButtons.replyReturn()) {
return true;
} else if (_inner->loadedAtBottomKnown()) {
return !_inner->loadedAtBottom();
}
return std::nullopt;
}
@ -717,10 +782,31 @@ bool ShortcutMessages::cornerButtonsHas(CornerButtonType type) {
return (type == CornerButtonType::Down);
}
void ShortcutMessages::pushReplyReturn(not_null<HistoryItem*> item) {
if (item->shortcutId() == _shortcutId) {
_cornerButtons.pushReplyReturn(item);
}
}
void ShortcutMessages::checkReplyReturns() {
const auto currentTop = _scroll->scrollTop();
while (const auto replyReturn = _cornerButtons.replyReturn()) {
const auto position = replyReturn->position();
const auto scrollTop = _inner->scrollTopForPosition(position);
const auto below = scrollTop
? (currentTop >= std::min(*scrollTop, _scroll->scrollTopMax()))
: _inner->isBelowPosition(position);
if (below) {
_cornerButtons.calculateNextReplyReturn();
} else {
break;
}
}
}
void ShortcutMessages::uploadFile(
const QByteArray &fileContent,
SendMediaType type) {
// #TODO replies schedule
_session->api().sendFile(fileContent, type, prepareSendAction({}));
}
@ -773,11 +859,6 @@ void ShortcutMessages::send() {
return;
}
send({});
// #TODO replies schedule
//const auto callback = [=](Api::SendOptions options) { send(options); };
//Ui::show(
// PrepareScheduleBox(this, sendMenuType(), callback),
// Ui::LayerOption::KeepOther);
}
void ShortcutMessages::sendVoice(ComposeControls::VoiceToSend &&data) {
@ -933,7 +1014,7 @@ bool ShortcutMessages::confirmSendingFiles(
_composeControls->getTextWithAppliedMarkdown(),
_history->peer,
Api::SendType::Normal,
SendMenu::Type::SilentOnly); // #TODO replies schedule
SendMenu::Type::Disabled);
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,

View file

@ -273,24 +273,14 @@ AdminLog::OwnedItem GenerateCommentItem(
if (data.comment.isEmpty()) {
return nullptr;
}
const auto flags = MessageFlag::HasFromId
| MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem;
const auto replyTo = FullReplyTo();
const auto viaBotId = UserId();
const auto groupedId = uint64();
const auto item = history->makeMessage(
history->nextNonHistoryEntryId(),
flags,
replyTo,
viaBotId,
base::unixtime::now(),
history->session().userId(),
QString(),
TextWithEntities{ data.comment },
MTP_messageMediaEmpty(),
HistoryMessageMarkupData(),
groupedId);
const auto item = history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = (MessageFlag::HasFromId
| MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem),
.from = history->session().userPeerId(),
.date = base::unixtime::now(),
}, TextWithEntities{ data.comment }, MTP_messageMediaEmpty());
return AdminLog::OwnedItem(delegate, item);
}
@ -298,29 +288,19 @@ AdminLog::OwnedItem GenerateContactItem(
not_null<HistoryView::ElementDelegate*> delegate,
not_null<History*> history,
const Contact &data) {
const auto replyTo = FullReplyTo();
const auto viaBotId = UserId();
const auto postAuthor = QString();
const auto groupedId = uint64();
const auto item = history->makeMessage(
history->nextNonHistoryEntryId(),
(MessageFlag::HasFromId
const auto item = history->makeMessage({
.id = history->nextNonHistoryEntryId(),
.flags = (MessageFlag::HasFromId
| MessageFlag::Outgoing
| MessageFlag::FakeHistoryItem),
replyTo,
viaBotId,
base::unixtime::now(),
history->session().userPeerId(),
postAuthor,
TextWithEntities(),
MTP_messageMediaContact(
MTP_string(data.phone),
MTP_string(data.firstName),
MTP_string(data.lastName),
MTP_string(), // vcard
MTP_long(0)), // user_id
HistoryMessageMarkupData(),
groupedId);
.from = history->session().userPeerId(),
.date = base::unixtime::now(),
}, TextWithEntities(), MTP_messageMediaContact(
MTP_string(data.phone),
MTP_string(data.firstName),
MTP_string(data.lastName),
MTP_string(), // vcard
MTP_long(0))); // user_id
return AdminLog::OwnedItem(delegate, item);
}