Bundle silent and scheduled to Api::SendOptions.

This commit is contained in:
John Preston 2019-08-12 13:11:34 +01:00
parent 0b08810d5a
commit caef7dde24
27 changed files with 413 additions and 349 deletions

View File

@ -1240,6 +1240,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_send_button" = "Send";
"lng_send_silent_message" = "Send without sound";
"lng_schedule_message" = "Schedule message";
"lng_message_ph" = "Write a message...";
"lng_broadcast_ph" = "Broadcast a message...";
"lng_broadcast_silent_ph" = "Silent broadcast...";

View File

@ -0,0 +1,39 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Api {
struct SendOptions {
TimeId scheduled = 0;
bool silent = false;
bool handleSupportSwitch = false;
bool removeWebPageId = false;
};
struct SendAction {
explicit SendAction(not_null<History*> history) : history(history) {
}
not_null<History*> history;
SendOptions options;
MsgId replyTo = 0;
bool clearDraft = false;
bool generateLocal = true;
};
struct MessageToSend {
explicit MessageToSend(not_null<History*> history) : action(history) {
}
SendAction action;
TextWithTags textWithTags;
WebPageId webPageId = 0;
};
} // namespace Api

View File

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h"
#include "history/history.h"
#include "history/history_message.h" // NewMessageFlags.
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
#include "ui/text/text_entity.h" // TextWithEntities.
#include "main/main_session.h"
#include "mainwidget.h"
@ -26,24 +27,18 @@ namespace {
template <typename MediaData>
void SendExistingMedia(
not_null<History*> history,
Api::MessageToSend &&message,
not_null<MediaData*> media,
const MTPInputMedia &inputMedia,
Data::FileOrigin origin,
TextWithEntities caption,
MsgId replyToId,
bool silent) {
Data::FileOrigin origin) {
const auto history = message.action.history;
const auto peer = history->peer;
const auto session = &history->session();
const auto api = &session->api();
auto options = ApiWrap::SendOptions(history);
options.clearDraft = false;
options.replyTo = replyToId;
options.generateLocal = true;
options.silent = silent;
api->sendAction(options);
message.action.clearDraft = false;
message.action.generateLocal = true;
api->sendAction(message.action);
const auto newId = FullMsgId(peerToChannel(peer->id), clientMsgId());
const auto randomId = rand_value<uint64>();
@ -51,12 +46,12 @@ void SendExistingMedia(
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media;
auto clientFlags = NewMessageClientFlags();
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (options.replyTo) {
if (message.action.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = options.silent
const auto silentPost = message.action.options.silent
|| (channelPost && session->data().notifySilentPosts(peer));
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
@ -75,6 +70,10 @@ void SendExistingMedia(
? App::peerName(session->user())
: QString();
auto caption = TextWithEntities{
message.textWithTags.text,
ConvertTextTagsToEntities(message.textWithTags.tags)
};
TextUtilities::Trim(caption);
auto sentEntities = TextUtilities::EntitiesToMTP(
caption.entities,
@ -82,7 +81,7 @@ void SendExistingMedia(
if (!sentEntities.v.isEmpty()) {
sendFlags |= MTPmessages_SendMedia::Flag::f_entities;
}
const auto replyTo = options.replyTo;
const auto replyTo = message.action.replyTo;
const auto captionText = caption.text;
session->data().registerMessageRandomId(randomId, newId);
@ -137,36 +136,23 @@ void SendExistingMedia(
performRequest();
if (const auto main = App::main()) {
main->finishForwarding(history, options.silent);
main->finishForwarding(message.action);
}
}
} // namespace
void SendExistingDocument(
not_null<History*> history,
not_null<DocumentData*> document,
bool silent) {
SendExistingDocument(history, document, {}, 0, silent);
}
void SendExistingDocument(
not_null<History*> history,
not_null<DocumentData*> document,
TextWithEntities caption,
MsgId replyToId,
bool silent) {
Api::MessageToSend &&message,
not_null<DocumentData*> document) {
SendExistingMedia(
history,
std::move(message),
document,
MTP_inputMediaDocument(
MTP_flags(0),
document->mtpInput(),
MTPint()),
document->stickerOrGifOrigin(),
caption,
replyToId,
silent);
document->stickerOrGifOrigin());
if (document->sticker()) {
if (const auto main = App::main()) {
@ -177,29 +163,16 @@ void SendExistingDocument(
}
void SendExistingPhoto(
not_null<History*> history,
not_null<PhotoData*> photo,
bool silent) {
SendExistingPhoto(history, photo, {}, 0, silent);
}
void SendExistingPhoto(
not_null<History*> history,
not_null<PhotoData*> photo,
TextWithEntities caption,
MsgId replyToId,
bool silent) {
Api::MessageToSend &&message,
not_null<PhotoData*> photo) {
SendExistingMedia(
history,
std::move(message),
photo,
MTP_inputMediaPhoto(
MTP_flags(0),
photo->mtpInput(),
MTPint()),
Data::FileOrigin(),
caption,
replyToId,
silent);
Data::FileOrigin());
}
} // namespace Api

View File

@ -9,32 +9,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class History;
class DocumentData;
struct TextWithEntities;
namespace Api {
void SendExistingDocument(
not_null<History*> history,
not_null<DocumentData*> document,
bool silent = false);
struct MessageToSend;
void SendExistingDocument(
not_null<History*> history,
not_null<DocumentData*> document,
TextWithEntities caption,
MsgId replyToId = 0,
bool silent = false);
Api::MessageToSend &&message,
not_null<DocumentData*> document);
void SendExistingPhoto(
not_null<History*> history,
not_null<PhotoData*> photo,
bool silent = false);
void SendExistingPhoto(
not_null<History*> history,
not_null<PhotoData*> photo,
TextWithEntities caption,
MsgId replyToId = 0,
bool silent = false);
Api::MessageToSend &&message,
not_null<PhotoData*> photo);
} // namespace Api

View File

@ -156,14 +156,6 @@ MTPVector<MTPDocumentAttribute> ComposeSendingDocumentAttributes(
} // namespace
ApiWrap::SendOptions::SendOptions(not_null<History*> history)
: history(history) {
}
ApiWrap::MessageToSend::MessageToSend(not_null<History*> history)
: history(history) {
}
MTPInputPrivacyKey ApiWrap::Privacy::Input(Key key) {
switch (key) {
case Privacy::Key::Calls: return MTP_inputPrivacyKeyPhoneCall();
@ -4386,15 +4378,15 @@ void ApiWrap::userPhotosDone(
// )).send();
//}
void ApiWrap::sendAction(const SendOptions &options) {
readServerHistory(options.history);
options.history->getReadyFor(ShowAtTheEndMsgId);
_sendActions.fire_copy(options);
void ApiWrap::sendAction(const SendAction &action) {
readServerHistory(action.history);
action.history->getReadyFor(ShowAtTheEndMsgId);
_sendActions.fire_copy(action);
}
void ApiWrap::forwardMessages(
HistoryItemsList &&items,
const SendOptions &options,
const SendAction &action,
FnMut<void()> &&successCallback) {
Expects(!items.empty());
@ -4410,14 +4402,14 @@ void ApiWrap::forwardMessages(
}
const auto count = int(items.size());
const auto genClientSideMessage = options.generateLocal && (count < 2);
const auto history = options.history;
const auto genClientSideMessage = action.generateLocal && (count < 2);
const auto history = action.history;
const auto peer = history->peer;
readServerHistory(history);
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = options.silent
const auto silentPost = action.options.silent
|| (channelPost && _session->data().notifySilentPosts(peer));
auto flags = MTPDmessage::Flags(0);
@ -4530,14 +4522,14 @@ void ApiWrap::shareContact(
const QString &phone,
const QString &firstName,
const QString &lastName,
const SendOptions &options) {
const SendAction &action) {
const auto userId = UserId(0);
sendSharedContact(phone, firstName, lastName, userId, options);
sendSharedContact(phone, firstName, lastName, userId, action);
}
void ApiWrap::shareContact(
not_null<UserData*> user,
const SendOptions &options) {
const SendAction &action) {
const auto userId = peerToUser(user->id);
const auto phone = _session->data().findContactPhone(user);
if (phone.isEmpty()) {
@ -4548,7 +4540,7 @@ void ApiWrap::shareContact(
user->firstName,
user->lastName,
userId,
options);
action);
}
void ApiWrap::sendSharedContact(
@ -4556,10 +4548,10 @@ void ApiWrap::sendSharedContact(
const QString &firstName,
const QString &lastName,
UserId userId,
const SendOptions &options) {
sendAction(options);
const SendAction &action) {
sendAction(action);
const auto history = options.history;
const auto history = action.history;
const auto peer = history->peer;
const auto newId = FullMsgId(history->channelId(), clientMsgId());
@ -4567,7 +4559,7 @@ void ApiWrap::sendSharedContact(
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media;
auto clientFlags = NewMessageClientFlags();
if (options.replyTo) {
if (action.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
}
if (channelPost) {
@ -4593,7 +4585,7 @@ void ApiWrap::sendSharedContact(
peerToMTP(peer->id),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(options.replyTo),
MTP_int(action.replyTo),
MTP_int(base::unixtime::now()),
MTP_string(),
MTP_messageMediaContact(
@ -4618,7 +4610,9 @@ void ApiWrap::sendSharedContact(
MTP_string(firstName),
MTP_string(lastName),
MTP_string(vcard));
sendMedia(item, media, _session->data().notifySilentPosts(peer));
auto options = action.options;
options.silent = _session->data().notifySilentPosts(peer);
sendMedia(item, media, options);
if (const auto main = App::main()) {
_session->data().sendHistoryChangeNotifications();
@ -4631,9 +4625,9 @@ void ApiWrap::sendVoiceMessage(
QByteArray result,
VoiceWaveform waveform,
int duration,
const SendOptions &options) {
const SendAction &action) {
const auto caption = TextWithTags();
const auto to = fileLoadTaskOptions(options);
const auto to = fileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>(
result,
duration,
@ -4646,12 +4640,12 @@ void ApiWrap::editMedia(
Storage::PreparedList &&list,
SendMediaType type,
TextWithTags &&caption,
const SendOptions &options,
const SendAction &action,
MsgId msgIdToEdit) {
if (list.files.empty()) return;
auto &file = list.files.front();
const auto to = fileLoadTaskOptions(options);
const auto to = fileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>(
file.path,
file.content,
@ -4668,22 +4662,22 @@ void ApiWrap::sendFiles(
SendMediaType type,
TextWithTags &&caption,
std::shared_ptr<SendingAlbum> album,
const SendOptions &options) {
const SendAction &action) {
const auto haveCaption = !caption.text.isEmpty();
const auto isAlbum = (album != nullptr);
const auto compressImages = (type == SendMediaType::Photo);
if (haveCaption && !list.canAddCaption(isAlbum, compressImages)) {
auto message = MessageToSend(options.history);
auto message = MessageToSend(action.history);
message.textWithTags = std::move(caption);
message.replyTo = options.replyTo;
message.clearDraft = false;
message.action = action;
message.action.clearDraft = false;
sendMessage(std::move(message));
caption = TextWithTags();
}
const auto to = fileLoadTaskOptions(options);
const auto to = fileLoadTaskOptions(action);
if (album) {
album->silent = to.silent;
album->options = to.options;
}
auto tasks = std::vector<std::unique_ptr<Task>>();
tasks.reserve(list.files.size());
@ -4722,8 +4716,8 @@ void ApiWrap::sendFiles(
void ApiWrap::sendFile(
const QByteArray &fileContent,
SendMediaType type,
const SendOptions &options) {
const auto to = fileLoadTaskOptions(options);
const SendAction &action) {
const auto to = fileLoadTaskOptions(action);
auto caption = TextWithTags();
_fileLoader->addTask(std::make_unique<FileLoadTask>(
QString(),
@ -4737,7 +4731,7 @@ void ApiWrap::sendFile(
void ApiWrap::sendUploadedPhoto(
FullMsgId localId,
const MTPInputFile &file,
bool silent) {
Api::SendOptions options) {
if (const auto item = _session->data().message(localId)) {
const auto media = MTP_inputMediaUploadedPhoto(
MTP_flags(0),
@ -4747,7 +4741,7 @@ void ApiWrap::sendUploadedPhoto(
if (const auto groupId = item->groupId()) {
uploadAlbumMedia(item, groupId, media);
} else {
sendMedia(item, media, silent);
sendMedia(item, media, options);
}
}
}
@ -4756,7 +4750,7 @@ void ApiWrap::sendUploadedDocument(
FullMsgId localId,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
bool silent) {
Api::SendOptions options) {
if (const auto item = _session->data().message(localId)) {
auto media = item->media();
if (auto document = media ? media->document() : nullptr) {
@ -4779,7 +4773,7 @@ void ApiWrap::sendUploadedDocument(
if (groupId) {
uploadAlbumMedia(item, groupId, media);
} else {
sendMedia(item, media, silent);
sendMedia(item, media, options);
}
}
}
@ -4789,7 +4783,7 @@ void ApiWrap::editUploadedFile(
FullMsgId localId,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
bool silent,
Api::SendOptions options,
bool isDocument) {
const auto item = _session->data().message(localId);
if (!item) {
@ -4887,18 +4881,13 @@ void ApiWrap::cancelLocalItem(not_null<HistoryItem*> item) {
}
void ApiWrap::sendMessage(MessageToSend &&message) {
const auto history = message.history;
const auto history = message.action.history;
const auto peer = history->peer;
auto &textWithTags = message.textWithTags;
auto options = ApiWrap::SendOptions(history);
options.clearDraft = message.clearDraft;
options.replyTo = message.replyTo;
options.silent = message.silent;
options.generateLocal = true;
options.webPageId = message.webPageId;
options.handleSupportSwitch = message.handleSupportSwitch;
sendAction(options);
auto action = message.action;
action.generateLocal = true;
sendAction(action);
if (!peer->canWrite()) {
return;
@ -4930,7 +4919,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_entities;
auto clientFlags = NewMessageClientFlags();
auto sendFlags = MTPmessages_SendMessage::Flags(0);
if (message.replyTo) {
if (action.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to_msg_id;
}
@ -4946,7 +4935,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
flags |= MTPDmessage::Flag::f_media;
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = message.silent
const auto silentPost = action.options.silent
|| (channelPost && _session->data().notifySilentPosts(peer));
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
@ -4965,7 +4954,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (!sentEntities.v.isEmpty()) {
sendFlags |= MTPmessages_SendMessage::Flag::f_entities;
}
if (message.clearDraft) {
if (action.clearDraft) {
sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft;
history->clearCloudDraft();
history->setSentDraftText(QString());
@ -4982,7 +4971,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
peerToMTP(peer->id),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(message.replyTo),
MTP_int(action.replyTo),
MTP_int(base::unixtime::now()),
msgText,
media,
@ -4999,7 +4988,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
history->sendRequestId = request(MTPmessages_SendMessage(
MTP_flags(sendFlags),
peer->input,
MTP_int(message.replyTo),
MTP_int(action.replyTo),
msgText,
MTP_long(randomId),
MTPReplyMarkup(),
@ -5020,7 +5009,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
}
if (const auto main = App::main()) {
main->finishForwarding(history, message.silent);
main->finishForwarding(action);
}
}
@ -5059,10 +5048,10 @@ void ApiWrap::sendBotStart(not_null<UserData*> bot, PeerData *chat) {
void ApiWrap::sendInlineResult(
not_null<UserData*> bot,
not_null<InlineBots::Result*> data,
const SendOptions &options) {
sendAction(options);
const SendAction &action) {
sendAction(action);
const auto history = options.history;
const auto history = action.history;
const auto peer = history->peer;
const auto newId = FullMsgId(peerToChannel(peer->id), clientMsgId());
const auto randomId = rand_value<uint64>();
@ -5070,12 +5059,12 @@ void ApiWrap::sendInlineResult(
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media;
auto clientFlags = NewMessageClientFlags();
auto sendFlags = MTPmessages_SendInlineBotResult::Flag::f_clear_draft | 0;
if (options.replyTo) {
if (action.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendInlineBotResult::Flag::f_reply_to_msg_id;
}
bool channelPost = peer->isChannel() && !peer->isMegagroup();
bool silentPost = options.silent
bool silentPost = action.options.silent
|| (channelPost && _session->data().notifySilentPosts(peer));
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
@ -5111,7 +5100,7 @@ void ApiWrap::sendInlineResult(
messageFromId,
messageDate,
messageViaBotId,
options.replyTo,
action.replyTo,
messagePostAuthor);
history->clearCloudDraft();
@ -5120,7 +5109,7 @@ void ApiWrap::sendInlineResult(
history->sendRequestId = request(MTPmessages_SendInlineBotResult(
MTP_flags(sendFlags),
peer->input,
MTP_int(options.replyTo),
MTP_int(action.replyTo),
MTP_long(randomId),
MTP_long(data->getQueryId()),
MTP_string(data->getId()),
@ -5135,7 +5124,7 @@ void ApiWrap::sendInlineResult(
).send();
if (const auto main = App::main()) {
main->finishForwarding(history, options.silent);
main->finishForwarding(action);
}
}
@ -5217,17 +5206,17 @@ void ApiWrap::uploadAlbumMedia(
void ApiWrap::sendMedia(
not_null<HistoryItem*> item,
const MTPInputMedia &media,
bool silent) {
Api::SendOptions options) {
const auto randomId = rand_value<uint64>();
_session->data().registerMessageRandomId(randomId, item->fullId());
sendMediaWithRandomId(item, media, silent, randomId);
sendMediaWithRandomId(item, media, options, randomId);
}
void ApiWrap::sendMediaWithRandomId(
not_null<HistoryItem*> item,
const MTPInputMedia &media,
bool silent,
Api::SendOptions options,
uint64 randomId) {
const auto history = item->history();
const auto replyTo = item->replyToId();
@ -5242,7 +5231,7 @@ void ApiWrap::sendMediaWithRandomId(
| (replyTo
? MTPmessages_SendMedia::Flag::f_reply_to_msg_id
: MTPmessages_SendMedia::Flag(0))
| (silent
| (options.silent
? MTPmessages_SendMedia::Flag::f_silent
: MTPmessages_SendMedia::Flag(0))
| (!sentEntities.v.isEmpty()
@ -5328,7 +5317,7 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
sendMediaWithRandomId(
sample,
single.vmedia(),
album->silent,
album->options,
single.vrandom_id().v);
_sendingAlbums.remove(groupId);
return;
@ -5339,7 +5328,7 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
| (replyTo
? MTPmessages_SendMultiMedia::Flag::f_reply_to_msg_id
: MTPmessages_SendMultiMedia::Flag(0))
| (album->silent
| (album->options.silent
? MTPmessages_SendMultiMedia::Flag::f_silent
: MTPmessages_SendMultiMedia::Flag(0));
const auto peer = history->peer;
@ -5365,12 +5354,16 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
).send();
}
FileLoadTo ApiWrap::fileLoadTaskOptions(const SendOptions &options) const {
const auto peer = options.history->peer;
FileLoadTo ApiWrap::fileLoadTaskOptions(const SendAction &action) const {
const auto peer = action.history->peer;
auto options = action.options;
if (_session->data().notifySilentPosts(peer)) {
options.silent = true;
}
return FileLoadTo(
peer->id,
options.silent || _session->data().notifySilentPosts(peer),
options.replyTo);
action.options,
action.replyTo);
}
void ApiWrap::requestSupportContact(FnMut<void(const MTPUser &)> callback) {
@ -5802,30 +5795,30 @@ void ApiWrap::setSelfDestructDays(int days) {
void ApiWrap::createPoll(
const PollData &data,
const SendOptions &options,
const SendAction &action,
FnMut<void()> done,
FnMut<void(const RPCError &error)> fail) {
sendAction(options);
sendAction(action);
const auto history = options.history;
const auto history = action.history;
const auto peer = history->peer;
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (options.replyTo) {
if (action.replyTo) {
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
if (options.clearDraft) {
if (action.clearDraft) {
sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
history->clearLocalDraft();
history->clearCloudDraft();
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = options.silent
const auto silentPost = action.options.silent
|| (channelPost && _session->data().notifySilentPosts(peer));
if (silentPost) {
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
const auto replyTo = options.replyTo;
const auto replyTo = action.replyTo;
history->sendRequestId = request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,

View File

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include <rpl/event_stream.h>
#include "api/api_common.h"
#include "base/timer.h"
#include "base/flat_map.h"
#include "base/flat_set.h"
@ -87,6 +87,9 @@ QString RequestKey(Types &&...values) {
class ApiWrap : public MTP::Sender, private base::Subscriber {
public:
using SendAction = Api::SendAction;
using MessageToSend = Api::MessageToSend;
struct Privacy {
enum class Key {
PhoneNumber,
@ -366,31 +369,21 @@ public:
not_null<PeerData*> peer,
const std::vector<not_null<UserData*>> &users);
struct SendOptions {
SendOptions(not_null<History*> history);
not_null<History*> history;
MsgId replyTo = 0;
WebPageId webPageId = 0;
bool silent = false;
bool clearDraft = false;
bool generateLocal = true;
bool handleSupportSwitch = false;
};
rpl::producer<SendOptions> sendActions() const {
rpl::producer<SendAction> sendActions() const {
return _sendActions.events();
}
void sendAction(const SendOptions &options);
void sendAction(const SendAction &action);
void forwardMessages(
HistoryItemsList &&items,
const SendOptions &options,
const SendAction &action,
FnMut<void()> &&successCallback = nullptr);
void shareContact(
const QString &phone,
const QString &firstName,
const QString &lastName,
const SendOptions &options);
void shareContact(not_null<UserData*> user, const SendOptions &options);
const SendAction &action);
void shareContact(not_null<UserData*> user, const SendAction &action);
void readServerHistory(not_null<History*> history);
void readServerHistoryForce(not_null<History*> history);
//void readFeed( // #feed
@ -401,60 +394,49 @@ public:
QByteArray result,
VoiceWaveform waveform,
int duration,
const SendOptions &options);
const SendAction &action);
void sendFiles(
Storage::PreparedList &&list,
SendMediaType type,
TextWithTags &&caption,
std::shared_ptr<SendingAlbum> album,
const SendOptions &options);
const SendAction &action);
void sendFile(
const QByteArray &fileContent,
SendMediaType type,
const SendOptions &options);
const SendAction &action);
void editMedia(
Storage::PreparedList &&list,
SendMediaType type,
TextWithTags &&caption,
const SendOptions &options,
const SendAction &action,
MsgId msgIdToEdit);
void sendUploadedPhoto(
FullMsgId localId,
const MTPInputFile &file,
bool silent);
Api::SendOptions options);
void sendUploadedDocument(
FullMsgId localId,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
bool silent);
Api::SendOptions options);
void editUploadedFile(
FullMsgId localId,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
bool silent,
Api::SendOptions options,
bool isDocument);
void cancelLocalItem(not_null<HistoryItem*> item);
struct MessageToSend {
MessageToSend(not_null<History*> history);
not_null<History*> history;
TextWithTags textWithTags;
MsgId replyTo = 0;
WebPageId webPageId = 0;
bool silent = false;
bool clearDraft = true;
bool handleSupportSwitch = false;
};
void sendMessage(MessageToSend &&message);
void sendBotStart(not_null<UserData*> bot, PeerData *chat = nullptr);
void sendInlineResult(
not_null<UserData*> bot,
not_null<InlineBots::Result*> data,
const SendOptions &options);
const SendAction &action);
void sendMessageFail(
const RPCError &error,
not_null<PeerData*> peer,
@ -489,7 +471,7 @@ public:
void createPoll(
const PollData &data,
const SendOptions &options,
const SendAction &action,
FnMut<void()> done,
FnMut<void(const RPCError &error)> fail);
void sendPollVotes(
@ -634,7 +616,7 @@ private:
const QString &firstName,
const QString &lastName,
UserId userId,
const SendOptions &options);
const SendAction &action);
void deleteHistory(
not_null<PeerData*> peer,
@ -668,13 +650,13 @@ private:
void sendMedia(
not_null<HistoryItem*> item,
const MTPInputMedia &media,
bool silent);
Api::SendOptions options);
void sendMediaWithRandomId(
not_null<HistoryItem*> item,
const MTPInputMedia &media,
bool silent,
Api::SendOptions options,
uint64 randomId);
FileLoadTo fileLoadTaskOptions(const SendOptions &options) const;
FileLoadTo fileLoadTaskOptions(const SendAction &action) const;
//void readFeeds(); // #feed
@ -817,7 +799,7 @@ private:
not_null<Data::Folder*>,
DialogsLoadState> _foldersLoadState;
rpl::event_stream<SendOptions> _sendActions;
rpl::event_stream<SendAction> _sendActions;
struct ReadRequest {
ReadRequest(mtpRequestId requestId, MsgId upTo)

View File

@ -920,7 +920,7 @@ void EditCaptionBox::save() {
std::move(_preparedList),
(!_asFile && _photo) ? SendMediaType::Photo : SendMediaType::File,
_field->getTextWithAppliedMarkdown(),
ApiWrap::SendOptions(item->history()),
Api::SendAction(item->history()),
item->fullId().msg);
closeBox();
return;

View File

@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lottie/lottie_single_player.h"
#include "data/data_document.h"
#include "media/clip/media_clip_reader.h"
#include "api/api_common.h"
#include "window/window_session_controller.h"
#include "layout.h"
#include "styles/style_history.h"
@ -1468,8 +1469,12 @@ void SendFilesBox::setupShadows(
}
void SendFilesBox::prepare() {
_send = addButton(tr::lng_send_button(), [=] { send(); });
SetupSendWithoutSound(_send, [=] { return true; }, [=] { send(true); });
_send = addButton(tr::lng_send_button(), [=] { send({}); });
SetupSendWithoutSound(
_send,
[=] { return true; },
[=] { sendSilent(); },
[=] { sendScheduled(); });
addButton(tr::lng_cancel(), [=] { closeBox(); });
initSendWay();
setupCaption();
@ -1638,7 +1643,7 @@ void SendFilesBox::setupCaption() {
const auto ctrlShiftEnter = modifiers.testFlag(Qt::ShiftModifier)
&& (modifiers.testFlag(Qt::ControlModifier)
|| modifiers.testFlag(Qt::MetaModifier));
send(false, ctrlShiftEnter);
send({}, ctrlShiftEnter);
});
connect(_caption, &Ui::InputField::cancelled, [=] { closeBox(); });
_caption->setMimeDataHook([=](
@ -1842,7 +1847,7 @@ void SendFilesBox::keyPressEvent(QKeyEvent *e) {
const auto ctrl = modifiers.testFlag(Qt::ControlModifier)
|| modifiers.testFlag(Qt::MetaModifier);
const auto shift = modifiers.testFlag(Qt::ShiftModifier);
send(false, ctrl && shift);
send({}, ctrl && shift);
} else {
BoxContent::keyPressEvent(e);
}
@ -1913,7 +1918,9 @@ void SendFilesBox::setInnerFocus() {
}
}
void SendFilesBox::send(bool silent, bool ctrlShiftEnter) {
void SendFilesBox::send(
Api::SendOptions options,
bool ctrlShiftEnter) {
using Way = SendFilesWay;
const auto way = _sendWay ? _sendWay->value() : Way::Files;
@ -1942,10 +1949,22 @@ void SendFilesBox::send(bool silent, bool ctrlShiftEnter) {
std::move(_list),
way,
std::move(caption),
silent,
options,
ctrlShiftEnter);
}
closeBox();
}
void SendFilesBox::sendSilent() {
auto options = Api::SendOptions();
options.silent = true;
send(options);
}
void SendFilesBox::sendScheduled() {
auto options = Api::SendOptions();
options.scheduled = INT_MAX;
send(options);
}
SendFilesBox::~SendFilesBox() = default;

View File

@ -16,6 +16,10 @@ namespace Window {
class SessionController;
} // namespace Window
namespace Api {
struct SendOptions;
} // namespace Api
namespace ChatHelpers {
class TabbedPanel;
} // namespace ChatHelpers
@ -60,7 +64,7 @@ public:
Storage::PreparedList &&list,
SendFilesWay way,
TextWithTags &&caption,
bool silent,
Api::SendOptions options,
bool ctrlShiftEnter)> callback) {
_confirmedCallback = std::move(callback);
}
@ -101,7 +105,9 @@ private:
void prepareAlbumPreview();
void applyAlbumOrder();
void send(bool silent = false, bool ctrlShiftEnter = false);
void send(Api::SendOptions options, bool ctrlShiftEnter = false);
void sendSilent();
void sendScheduled();
void captionResized();
void setupTitleText();
@ -128,7 +134,7 @@ private:
Storage::PreparedList &&list,
SendFilesWay way,
TextWithTags &&caption,
bool silent,
Api::SendOptions options,
bool ctrlShiftEnter)> _confirmedCallback;
Fn<void()> _cancelledCallback;
bool _confirmed = false;

View File

@ -195,7 +195,7 @@ void ShareBox::prepareCommentField() {
const auto field = _comment->entity();
connect(field, &Ui::InputField::submitted, [=] {
submit();
submit({});
});
field->setInstantReplaces(Ui::InstantReplaces::Default());
@ -242,7 +242,7 @@ void ShareBox::prepare() {
_select->setSubmittedCallback([=](Qt::KeyboardModifiers modifiers) {
if (modifiers.testFlag(Qt::ControlModifier)
|| modifiers.testFlag(Qt::MetaModifier)) {
submit();
submit({});
} else {
_inner->selectActive();
}
@ -412,12 +412,13 @@ void ShareBox::createButtons() {
clearButtons();
if (_hasSelected) {
const auto send = addButton(tr::lng_share_confirm(), [=] {
submit();
submit({});
});
SetupSendWithoutSound(
send,
[=] { return true; },
[=] { submit(true); });
[=] { submitSilent(); },
[=] { submitScheduled(); });
} else if (_copyCallback) {
addButton(tr::lng_share_copy_link(), [=] { copyLink(); });
}
@ -451,15 +452,27 @@ void ShareBox::innerSelectedChanged(PeerData *peer, bool checked) {
update();
}
void ShareBox::submit(bool silent) {
void ShareBox::submit(Api::SendOptions options) {
if (_submitCallback) {
_submitCallback(
_inner->selected(),
_comment->entity()->getTextWithAppliedMarkdown(),
silent);
options);
}
}
void ShareBox::submitSilent() {
auto options = Api::SendOptions();
options.silent = true;
submit(options);
}
void ShareBox::submitScheduled() {
auto options = Api::SendOptions();
options.scheduled = INT_MAX;
submit(options);
}
void ShareBox::copyLink() {
if (_copyCallback) {
_copyCallback();

View File

@ -17,6 +17,10 @@ namespace Window {
class SessionNavigation;
} // namespace Window
namespace Api {
struct SendOptions;
} // namespace Api
namespace Main {
class Session;
} // namespace Main
@ -52,7 +56,7 @@ public:
using SubmitCallback = Fn<void(
QVector<PeerData*>&&,
TextWithTags&&,
bool)>;
Api::SendOptions)>;
using FilterCallback = Fn<bool(PeerData*)>;
ShareBox(
@ -73,7 +77,9 @@ private:
void prepareCommentField();
void scrollAnimationCallback();
void submit(bool silent = false);
void submit(Api::SendOptions options);
void submitSilent();
void submitScheduled();
void copyLink();
bool searchByUsername(bool useCache = false);

View File

@ -787,13 +787,25 @@ void MessageLinksParser::apply(
void SetupSendWithoutSound(
not_null<Ui::RpWidget*> button,
Fn<bool()> enabled,
Fn<void()> send) {
Fn<void()> send,
Fn<void()> schedule) {
if (!send && !schedule) {
return;
}
const auto menu = std::make_shared<base::unique_qptr<Ui::PopupMenu>>();
const auto showMenu = [=] {
*menu = base::make_unique_q<Ui::PopupMenu>(button);
if (send) {
(*menu)->addAction(tr::lng_send_silent_message(tr::now), send);
}
if (schedule) {
(*menu)->addAction(tr::lng_schedule_message(tr::now), schedule);
}
(*menu)->popup(QCursor::pos());
};
Core::InstallEventFilter(button, [=](not_null<QEvent*> e) {
if (e->type() == QEvent::ContextMenu && enabled()) {
*menu = base::make_unique_q<Ui::PopupMenu>(button);
(*menu)->addAction(tr::lng_send_silent_message(tr::now), send);
(*menu)->popup(QCursor::pos());
showMenu();
return true;
}
return false;

View File

@ -109,4 +109,5 @@ private:
void SetupSendWithoutSound(
not_null<Ui::RpWidget*> button,
Fn<bool()> enabled,
Fn<void()> send);
Fn<void()> send,
Fn<void()> schedule);

View File

@ -113,11 +113,11 @@ void activateBotCommand(
const auto history = msg->history();
Ui::show(Box<ConfirmBox>(tr::lng_bot_share_phone(tr::now), tr::lng_bot_share_phone_confirm(tr::now), [=] {
Ui::showPeerHistory(history, ShowAtTheEndMsgId);
auto options = ApiWrap::SendOptions(history);
options.replyTo = msgId;
auto action = Api::SendAction(history);
action.replyTo = msgId;
history->session().api().shareContact(
history->session().user(),
options);
action);
}));
} break;

View File

@ -223,7 +223,7 @@ void FastShareMessage(not_null<HistoryItem*> item) {
auto submitCallback = [=](
QVector<PeerData*> &&result,
TextWithTags &&comment,
bool silent) {
Api::SendOptions options) {
if (!data->requests.empty()) {
return; // Share clicked already.
}
@ -272,7 +272,7 @@ void FastShareMessage(not_null<HistoryItem*> item) {
| (isGroup
? MTPmessages_ForwardMessages::Flag::f_grouped
: MTPmessages_ForwardMessages::Flag(0))
| (silent
| (options.silent
? MTPmessages_ForwardMessages::Flag::f_silent
: MTPmessages_ForwardMessages::Flag(0));
auto msgIds = QVector<MTPint>();
@ -292,7 +292,7 @@ void FastShareMessage(not_null<HistoryItem*> item) {
if (!comment.text.isEmpty()) {
auto message = ApiWrap::MessageToSend(history);
message.textWithTags = comment;
message.clearDraft = false;
message.action.clearDraft = false;
history->session().api().sendMessage(std::move(message));
}
history->sendRequestId = MTP::send(

View File

@ -309,7 +309,7 @@ HistoryWidget::HistoryWidget(
SetupSendWithoutSound(_send, [=] {
return (_send->type() == Ui::SendButton::Type::Send)
&& !_send->isDisabled();
}, [=] { send(true); });
}, [=] { sendSilent(); }, [=] { sendScheduled(); });
_unblock->addClickHandler([=] { unblockUser(); });
_botStart->addClickHandler([=] { sendBotStartCommand(); });
_joinChannel->addClickHandler([=] { joinChannel(); });
@ -318,7 +318,7 @@ HistoryWidget::HistoryWidget(
connect(
_field,
&Ui::InputField::submitted,
[=](Qt::KeyboardModifiers modifiers) { send(false, modifiers); });
[=](Qt::KeyboardModifiers modifiers) { sendWithModifiers(modifiers); });
connect(_field, &Ui::InputField::cancelled, [=] {
escape();
});
@ -631,18 +631,18 @@ HistoryWidget::HistoryWidget(
}, _topBar->lifetime());
session().api().sendActions(
) | rpl::filter([=](const ApiWrap::SendOptions &options) {
return (options.history == _history);
}) | rpl::start_with_next([=](const ApiWrap::SendOptions &options) {
fastShowAtEnd(options.history);
) | rpl::filter([=](const Api::SendAction &action) {
return (action.history == _history);
}) | rpl::start_with_next([=](const Api::SendAction &action) {
fastShowAtEnd(action.history);
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
options.history->channelId(),
options.replyTo));
if (cancelReply(lastKeyboardUsed) && !options.clearDraft) {
action.history->channelId(),
action.replyTo));
if (cancelReply(lastKeyboardUsed) && !action.clearDraft) {
onCloudDraftSave();
}
if (options.handleSupportSwitch) {
handleSupportSwitch(options.history);
if (action.options.handleSupportSwitch) {
handleSupportSwitch(action.history);
}
}, lifetime());
@ -705,14 +705,16 @@ void HistoryWidget::supportShareContact(Support::Contact contact) {
if (!history) {
return;
}
send(false, Support::SkipSwitchModifiers());
auto options = ApiWrap::SendOptions(history);
auto options = Api::SendOptions();
auto action = Api::SendAction(history);
send(options);
options.handleSupportSwitch = Support::HandleSwitch(modifiers);
action.options = options;
session().api().shareContact(
contact.phone,
contact.firstName,
contact.lastName,
options);
action);
};
const auto box = Ui::show(Box<Support::ConfirmContactBox>(
_history,
@ -978,7 +980,7 @@ void HistoryWidget::onHashtagOrBotCommandInsert(
// Send bot command at once, if it was not inserted by pressing Tab.
if (str.at(0) == '/' && method != FieldAutocomplete::ChooseMethod::ByTab) {
App::sendBotCommand(_peer, nullptr, str, replyToId());
App::main()->finishForwarding(_history, false);
App::main()->finishForwarding(Api::SendAction(_history));
setFieldText(_field->getTextWithTagsPart(_field->textCursor().position()));
} else {
_field->insertTag(str);
@ -1336,9 +1338,9 @@ void HistoryWidget::onRecordDone(
ActivateWindow(controller());
const auto duration = samples / Media::Player::kDefaultFrequency;
auto options = ApiWrap::SendOptions(_history);
options.replyTo = replyToId();
session().api().sendVoiceMessage(result, waveform, duration, options);
auto action = Api::SendAction(_history);
action.replyTo = replyToId();
session().api().sendVoiceMessage(result, waveform, duration, action);
}
void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
@ -2887,7 +2889,7 @@ void HistoryWidget::hideSelectorControlsAnimated() {
}
}
void HistoryWidget::send(bool silent, Qt::KeyboardModifiers modifiers) {
void HistoryWidget::send(Api::SendOptions options) {
if (!_history) {
return;
} else if (_editMsgId) {
@ -2905,10 +2907,9 @@ void HistoryWidget::send(bool silent, Qt::KeyboardModifiers modifiers) {
auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = _field->getTextWithAppliedMarkdown();
message.replyTo = replyToId();
message.action.options = options;
message.action.replyTo = replyToId();
message.webPageId = webPageId;
message.silent = silent;
message.handleSupportSwitch = Support::HandleSwitch(modifiers);
if (_canSendMessages) {
const auto error = GetErrorTextForForward(
@ -2938,6 +2939,24 @@ void HistoryWidget::send(bool silent, Qt::KeyboardModifiers modifiers) {
}
}
void HistoryWidget::sendWithModifiers(Qt::KeyboardModifiers modifiers) {
auto options = Api::SendOptions();
options.handleSupportSwitch = Support::HandleSwitch(modifiers);
send(options);
}
void HistoryWidget::sendSilent() {
auto options = Api::SendOptions();
options.silent = true;
send(options);
}
void HistoryWidget::sendScheduled() {
auto options = Api::SendOptions();
options.scheduled = INT_MAX;
send(options);
}
void HistoryWidget::unblockUser() {
if (const auto user = _peer ? _peer->asUser() : nullptr) {
Window::PeerMenuUnblockUserWithBotRestart(user);
@ -3169,7 +3188,7 @@ void HistoryWidget::sendButtonClicked() {
if (type == Ui::SendButton::Type::Cancel) {
onInlineBotCancel();
} else if (type != Ui::SendButton::Type::Record) {
send();
send({});
}
}
@ -3316,7 +3335,7 @@ void HistoryWidget::sendBotCommand(PeerData *peer, UserData *bot, const QString
auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = { toSend, TextWithTags::Tags() };
message.replyTo = replyTo
message.action.replyTo = replyTo
? ((!_peer->isUser()/* && (botStatus == 0 || botStatus == 2)*/)
? replyTo
: replyToId())
@ -4163,7 +4182,7 @@ bool HistoryWidget::confirmSendingFiles(
Storage::PreparedList &&list,
SendFilesWay way,
TextWithTags &&caption,
bool silent,
Api::SendOptions options,
bool ctrlShiftEnter) {
if (showSendingFilesError(list)) {
return;
@ -4179,7 +4198,7 @@ bool HistoryWidget::confirmSendingFiles(
type,
std::move(caption),
replyToId(),
silent,
options,
album);
}));
box->setCancelledCallback(crl::guard(this, [=] {
@ -4288,7 +4307,7 @@ void HistoryWidget::uploadFilesAfterConfirmation(
SendMediaType type,
TextWithTags &&caption,
MsgId replyTo,
bool silent,
Api::SendOptions options,
std::shared_ptr<SendingAlbum> album) {
Assert(canWriteMessage());
@ -4303,15 +4322,15 @@ void HistoryWidget::uploadFilesAfterConfirmation(
return;
}
auto options = ApiWrap::SendOptions(_history);
options.replyTo = replyTo;
options.silent = silent;
auto action = Api::SendAction(_history);
action.replyTo = replyTo;
action.options = options;
session().api().sendFiles(
std::move(list),
type,
std::move(caption),
album,
options);
action);
}
void HistoryWidget::uploadFile(
@ -4319,9 +4338,9 @@ void HistoryWidget::uploadFile(
SendMediaType type) {
if (!canWriteMessage()) return;
auto options = ApiWrap::SendOptions(_history);
options.replyTo = replyToId();
session().api().sendFile(fileContent, type, options);
auto action = Api::SendAction(_history);
action.replyTo = replyToId();
session().api().sendFile(fileContent, type, action);
}
void HistoryWidget::subscribeToUploader() {
@ -4331,9 +4350,11 @@ void HistoryWidget::subscribeToUploader() {
using namespace Storage;
session().uploader().photoReady(
) | rpl::start_with_next([=](const UploadedPhoto &data) {
data.edit
? photoEdited(data.fullId, data.silent, data.file)
: photoUploaded(data.fullId, data.silent, data.file);
if (data.edit) {
photoEdited(data.fullId, data.options, data.file);
} else {
photoUploaded(data.fullId, data.options, data.file);
}
}, _uploaderSubscriptions);
session().uploader().photoProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
@ -4345,15 +4366,17 @@ void HistoryWidget::subscribeToUploader() {
}, _uploaderSubscriptions);
session().uploader().documentReady(
) | rpl::start_with_next([=](const UploadedDocument &data) {
data.edit
? documentEdited(data.fullId, data.silent, data.file)
: documentUploaded(data.fullId, data.silent, data.file);
if (data.edit) {
documentEdited(data.fullId, data.options, data.file);
} else {
documentUploaded(data.fullId, data.options, data.file);
}
}, _uploaderSubscriptions);
session().uploader().thumbDocumentReady(
) | rpl::start_with_next([=](const UploadedThumbDocument &data) {
thumbDocumentUploaded(
data.fullId,
data.silent,
data.options,
data.file,
data.thumb,
data.edit);
@ -4399,11 +4422,11 @@ void HistoryWidget::sendFileConfirmed(
const auto history = session().data().history(file->to.peer);
const auto peer = history->peer;
auto options = ApiWrap::SendOptions(history);
options.clearDraft = false;
options.replyTo = file->to.replyTo;
options.generateLocal = true;
session().api().sendAction(options);
auto action = Api::SendAction(history);
action.clearDraft = false;
action.replyTo = file->to.replyTo;
action.generateLocal = true;
session().api().sendAction(action);
auto caption = TextWithEntities{
file->caption.text,
@ -4430,7 +4453,7 @@ void HistoryWidget::sendFileConfirmed(
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = file->to.silent;
const auto silentPost = file->to.options.silent;
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -4572,41 +4595,43 @@ void HistoryWidget::sendFileConfirmed(
void HistoryWidget::photoUploaded(
const FullMsgId &newId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().sendUploadedPhoto(newId, file, silent);
session().api().sendUploadedPhoto(newId, file, options);
}
void HistoryWidget::documentUploaded(
const FullMsgId &newId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().sendUploadedDocument(newId, file, std::nullopt, silent);
session().api().sendUploadedDocument(newId, file, std::nullopt, options);
}
void HistoryWidget::documentEdited(
const FullMsgId &newId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().editUploadedFile(newId, file, std::nullopt, silent, true);
session().api().editUploadedFile(newId, file, std::nullopt, options, true);
}
void HistoryWidget::photoEdited(
const FullMsgId &newId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().editUploadedFile(newId, file, std::nullopt, silent, false);
session().api().editUploadedFile(newId, file, std::nullopt, options, false);
}
void HistoryWidget::thumbDocumentUploaded(
const FullMsgId &newId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file,
const MTPInputFile &thumb,
bool edit) {
edit
? session().api().editUploadedFile(newId, file, thumb, silent, true)
: session().api().sendUploadedDocument(newId, file, thumb, silent);
if (edit) {
session().api().editUploadedFile(newId, file, thumb, options, true);
} else {
session().api().sendUploadedDocument(newId, file, thumb, options);
}
}
void HistoryWidget::photoProgress(const FullMsgId &newId) {
@ -5349,7 +5374,7 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
session().settings().sendSubmitWay(),
e->modifiers());
if (submitting) {
send(false, e->modifiers());
sendWithModifiers(e->modifiers());
}
}
} else if (e->key() == Qt::Key_O && e->modifiers() == Qt::ControlModifier) {
@ -5478,11 +5503,11 @@ void HistoryWidget::sendInlineResult(
return;
}
auto options = ApiWrap::SendOptions(_history);
options.clearDraft = true;
options.replyTo = replyToId();
options.generateLocal = true;
session().api().sendInlineResult(bot, result, options);
auto action = Api::SendAction(_history);
action.clearDraft = true;
action.replyTo = replyToId();
action.generateLocal = true;
session().api().sendInlineResult(bot, result, action);
clearFieldText();
_saveDraftText = true;
@ -5612,9 +5637,7 @@ void HistoryWidget::destroyPinnedBar() {
_inPinnedMsg = false;
}
bool HistoryWidget::sendExistingDocument(
not_null<DocumentData*> document,
TextWithEntities caption) {
bool HistoryWidget::sendExistingDocument(not_null<DocumentData*> document) {
const auto error = _peer
? Data::RestrictionError(_peer, ChatRestriction::f_send_stickers)
: std::nullopt;
@ -5627,7 +5650,9 @@ bool HistoryWidget::sendExistingDocument(
return false;
}
Api::SendExistingDocument(_history, document, caption, replyToId());
auto message = Api::MessageToSend(_history);
message.action.replyTo = replyToId();
Api::SendExistingDocument(std::move(message), document);
if (_fieldAutocomplete->stickersShown()) {
clearFieldText();
@ -5643,9 +5668,7 @@ bool HistoryWidget::sendExistingDocument(
return true;
}
bool HistoryWidget::sendExistingPhoto(
not_null<PhotoData*> photo,
TextWithEntities caption) {
bool HistoryWidget::sendExistingPhoto(not_null<PhotoData*> photo) {
const auto error = _peer
? Data::RestrictionError(_peer, ChatRestriction::f_send_media)
: std::nullopt;
@ -5658,7 +5681,9 @@ bool HistoryWidget::sendExistingPhoto(
return false;
}
Api::SendExistingPhoto(_history, photo, caption, replyToId());
auto message = Api::MessageToSend(_history);
message.action.replyTo = replyToId();
Api::SendExistingPhoto(std::move(message), photo);
hideSelectorControlsAnimated();

View File

@ -24,6 +24,10 @@ enum class SendMediaType;
enum class CompressConfirm;
class MessageLinksParser;
namespace Api {
struct SendOptions;
} // namespace Api
namespace InlineBots {
namespace Layout {
class ItemBase;
@ -237,12 +241,8 @@ public:
void confirmDeleteSelected();
void clearSelected();
bool sendExistingDocument(
not_null<DocumentData*> document,
TextWithEntities caption = TextWithEntities());
bool sendExistingPhoto(
not_null<PhotoData*> photo,
TextWithEntities caption = TextWithEntities());
bool sendExistingDocument(not_null<DocumentData*> document);
bool sendExistingPhoto(not_null<PhotoData*> photo);
// Float player interface.
bool wheelEventFromFloatPlayer(QEvent *e) override;
@ -324,9 +324,10 @@ private:
void initTabbedSelector();
void updateField();
void send(
bool silent = false,
Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers());
void send(Api::SendOptions options);
void sendWithModifiers(Qt::KeyboardModifiers modifiers);
void sendSilent();
void sendScheduled();
void handlePendingHistoryUpdate();
void fullPeerUpdated(PeerData *peer);
void toggleTabbedSelectorMode();
@ -410,24 +411,24 @@ private:
SendMediaType type,
TextWithTags &&caption,
MsgId replyTo,
bool silent,
Api::SendOptions options,
std::shared_ptr<SendingAlbum> album = nullptr);
void subscribeToUploader();
void photoUploaded(
const FullMsgId &msgId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file);
void photoProgress(const FullMsgId &msgId);
void photoFailed(const FullMsgId &msgId);
void documentUploaded(
const FullMsgId &msgId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file);
void thumbDocumentUploaded(
const FullMsgId &msgId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file,
const MTPInputFile &thumb,
bool edit = false);
@ -436,12 +437,12 @@ private:
void documentEdited(
const FullMsgId &msgId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file);
void photoEdited(
const FullMsgId &msgId,
bool silent,
Api::SendOptions options,
const MTPInputFile &file);
void itemRemoved(not_null<const HistoryItem*> item);

View File

@ -680,7 +680,8 @@ void MainWidget::cancelForwarding(not_null<History*> history) {
_history->updateForwarding();
}
void MainWidget::finishForwarding(not_null<History*> history, bool silent) {
void MainWidget::finishForwarding(Api::SendAction action) {
const auto history = action.history;
auto toForward = history->validateForwardDraft();
if (!toForward.empty()) {
const auto error = GetErrorTextForForward(history->peer, toForward);
@ -688,9 +689,7 @@ void MainWidget::finishForwarding(not_null<History*> history, bool silent) {
return;
}
auto options = ApiWrap::SendOptions(history);
options.silent = silent;
session().api().forwardMessages(std::move(toForward), options);
session().api().forwardMessages(std::move(toForward), action);
cancelForwarding(history);
}

View File

@ -21,6 +21,10 @@ class HistoryWidget;
class StackItem;
struct FileLoadResult;
namespace Api {
struct SendAction;
} // namespace Api
namespace Main {
class Session;
} // namespace Main
@ -231,7 +235,7 @@ public:
void pushReplyReturn(not_null<HistoryItem*> item);
void cancelForwarding(not_null<History*> history);
void finishForwarding(not_null<History*> history, bool silent);
void finishForwarding(Api::SendAction action);
// Does offerPeer or showPeerHistory.
void choosePeer(PeerId peerId, MsgId showAtMsgId);

View File

@ -1510,7 +1510,7 @@ void FormController::uploadEncryptedFile(
auto prepared = std::make_shared<FileLoadResult>(
TaskId(),
file.uploadData->fileId,
FileLoadTo(PeerId(0), false, MsgId(0)),
FileLoadTo(PeerId(0), Api::SendOptions(), MsgId(0)),
TextWithTags(),
std::shared_ptr<SendingAlbum>(nullptr));
prepared->type = SendMediaType::Secure;

View File

@ -312,8 +312,9 @@ void Uploader::sendNext() {
if (parts.isEmpty()) {
if (uploadingData.docSentParts >= uploadingData.docPartsCount) {
if (requestsSent.empty() && docRequestsSent.empty()) {
const auto silent = uploadingData.file
&& uploadingData.file->to.silent;
const auto options = uploadingData.file
? uploadingData.file->to.options
: Api::SendOptions();
const auto edit = uploadingData.file &&
uploadingData.file->edit;
if (uploadingData.type() == SendMediaType::Photo) {
@ -332,7 +333,7 @@ void Uploader::sendNext() {
MTP_int(uploadingData.partsCount),
MTP_string(photoFilename),
MTP_bytes(md5));
_photoReady.fire({ uploadingId, silent, file, edit });
_photoReady.fire({ uploadingId, options, file, edit });
} else if (uploadingData.type() == SendMediaType::File
|| uploadingData.type() == SendMediaType::WallPaper
|| uploadingData.type() == SendMediaType::Audio) {
@ -363,14 +364,14 @@ void Uploader::sendNext() {
MTP_bytes(thumbMd5));
_thumbDocumentReady.fire({
uploadingId,
silent,
options,
file,
thumb,
edit });
} else {
_documentReady.fire({
uploadingId,
silent,
options,
file,
edit });
}

View File

@ -7,9 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "api/api_common.h"
class ApiWrap;
struct FileLoadResult;
struct SendMediaReady;
class ApiWrap;
namespace Storage {
@ -18,21 +20,21 @@ constexpr auto kUseBigFilesFrom = 10 * 1024 * 1024;
struct UploadedPhoto {
FullMsgId fullId;
bool silent = false;
Api::SendOptions options;
MTPInputFile file;
bool edit = false;
};
struct UploadedDocument {
FullMsgId fullId;
bool silent = false;
Api::SendOptions options;
MTPInputFile file;
bool edit = false;
};
struct UploadedThumbDocument {
FullMsgId fullId;
bool silent = false;
Api::SendOptions options;
MTPInputFile file;
MTPInputFile thumb;
bool edit = false;

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/variant.h"
#include "api/api_common.h"
enum class CompressConfirm {
Auto,
@ -175,18 +176,18 @@ struct SendingAlbum {
uint64 groupId = 0;
std::vector<Item> items;
bool silent = false;
Api::SendOptions options;
};
struct FileLoadTo {
FileLoadTo(const PeerId &peer, bool silent, MsgId replyTo)
: peer(peer)
, silent(silent)
, replyTo(replyTo) {
FileLoadTo(const PeerId &peer, Api::SendOptions options, MsgId replyTo)
: peer(peer)
, options(options)
, replyTo(replyTo) {
}
PeerId peer;
bool silent;
Api::SendOptions options;
MsgId replyTo;
};

View File

@ -609,7 +609,7 @@ QString InterpretSendPath(const QString &path) {
SendMediaType::File,
{ caption },
nullptr,
ApiWrap::SendOptions(history));
Api::SendAction(history));
return QString();
}

View File

@ -512,10 +512,10 @@ void Manager::notificationReplied(
const auto history = system()->session().data().history(peerId);
auto message = ApiWrap::MessageToSend(history);
auto message = Api::MessageToSend(history);
message.textWithTags = reply;
message.replyTo = (msgId > 0 && !history->peer->isUser()) ? msgId : 0;
message.clearDraft = false;
message.action.replyTo = (msgId > 0 && !history->peer->isUser()) ? msgId : 0;
message.action.clearDraft = false;
history->session().api().sendMessage(std::move(message));
const auto item = history->owner().message(history->channelId(), msgId);

View File

@ -667,8 +667,8 @@ void PeerMenuShareContactBox(
LayerOption::KeepOther);
return;
} else if (peer->isSelf()) {
auto options = ApiWrap::SendOptions(peer->owner().history(peer));
user->session().api().shareContact(user, options);
auto action = Api::SendAction(peer->owner().history(peer));
user->session().api().shareContact(user, action);
Ui::Toast::Show(tr::lng_share_done(tr::now));
if (auto strong = *weak) {
strong->closeBox();
@ -684,8 +684,8 @@ void PeerMenuShareContactBox(
[peer, user] {
const auto history = peer->owner().history(peer);
Ui::showPeerHistory(history, ShowAtTheEndMsgId);
auto options = ApiWrap::SendOptions(history);
user->session().api().shareContact(user, options);
auto action = Api::SendAction(history);
user->session().api().shareContact(user, action);
}), LayerOption::KeepOther);
};
*weak = Ui::show(Box<PeerListBox>(
@ -707,15 +707,15 @@ void PeerMenuCreatePoll(not_null<PeerData*> peer) {
if (std::exchange(*lock, true)) {
return;
}
auto options = ApiWrap::SendOptions(peer->owner().history(peer));
if (const auto id = App::main()->currentReplyToIdFor(options.history)) {
options.replyTo = id;
auto action = Api::SendAction(peer->owner().history(peer));
if (const auto id = App::main()->currentReplyToIdFor(action.history)) {
action.replyTo = id;
}
if (const auto localDraft = options.history->localDraft()) {
options.clearDraft = localDraft->textWithTags.text.isEmpty();
if (const auto localDraft = action.history->localDraft()) {
action.clearDraft = localDraft->textWithTags.text.isEmpty();
}
const auto api = &peer->session().api();
api->createPoll(result, options, crl::guard(box, [=] {
api->createPoll(result, action, crl::guard(box, [=] {
box->closeBox();
}), crl::guard(box, [=](const RPCError &error) {
*lock = false;
@ -822,9 +822,9 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
auto items = peer->owner().idsToItems(ids);
if (!items.empty()) {
const auto api = &peer->session().api();
auto options = ApiWrap::SendOptions(peer->owner().history(peer));
options.generateLocal = false;
api->forwardMessages(std::move(items), options, [] {
auto action = Api::SendAction(peer->owner().history(peer));
action.generateLocal = false;
api->forwardMessages(std::move(items), action, [] {
Ui::Toast::Show(tr::lng_share_done(tr::now));
});
}

View File

@ -1,3 +1,4 @@
<(src_loc)/api/api_common.h
<(src_loc)/api/api_hash.h
<(src_loc)/api/api_sending.cpp
<(src_loc)/api/api_sending.h