mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Implement sending of shortcutted messages.
This commit is contained in:
parent
5c11fa4f63
commit
7f3ebde252
35 changed files with 709 additions and 934 deletions
|
@ -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),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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 = [&](
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -59,6 +59,7 @@ enum class Context : char {
|
|||
ContactPreview,
|
||||
SavedSublist,
|
||||
TTLViewer,
|
||||
ShortcutMessages,
|
||||
};
|
||||
|
||||
enum class OnlyEmojiAndSpaces : char {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue