Move shareContact and readServerHistory to ApiWrap.

Also allow non-confirming contact info sharing to Saved Messages.
This commit is contained in:
John Preston 2017-12-07 17:02:24 +04:00
parent f0a03223e8
commit 5bc47e5203
15 changed files with 551 additions and 431 deletions

View File

@ -31,7 +31,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "messenger.h"
#include "mainwidget.h"
#include "history/history_widget.h"
#include "boxes/add_contact_box.h"
#include "history/history_message.h"
#include "storage/localstorage.h"
#include "auth_session.h"
#include "boxes/confirm_box.h"
@ -171,7 +172,7 @@ void ApiWrap::resolveMessageDatas() {
gotMessageDatas(nullptr, result, requestId);
}).fail([this](const RPCError &error, mtpRequestId requestId) {
finalizeMessageDataRequest(nullptr, requestId);
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
for (auto &request : _messageDataRequests) {
if (request.requestId > 0) continue;
request.requestId = requestId;
@ -192,7 +193,7 @@ void ApiWrap::resolveMessageDatas() {
gotMessageDatas(channel, result, requestId);
}).fail([=](const RPCError &error, mtpRequestId requestId) {
finalizeMessageDataRequest(channel, requestId);
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
for (auto &request : *j) {
if (request.requestId > 0) continue;
@ -839,7 +840,7 @@ void ApiWrap::requestSelfParticipant(ChannelData *channel) {
if (error.type() == qstr("USER_NOT_PARTICIPANT")) {
channel->inviter = -1;
}
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
_selfParticipantRequests.insert(channel, requestId);
}
@ -933,7 +934,7 @@ void ApiWrap::requestStickerSets() {
gotStickerSet(setId, result);
}).fail([this, setId = i.key()](const RPCError &error) {
_stickerSetRequests.remove(setId);
}).after(waitMs).send();
}).afterDelay(waitMs).send();
}
}
@ -987,7 +988,7 @@ void ApiWrap::saveStickerSets(const Stickers::Order &localOrder, const Stickers:
stickerSetDisenabled(requestId);
}).fail([this](const RPCError &error, mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
_stickerSetDisenableRequests.insert(requestId);
@ -1024,7 +1025,7 @@ void ApiWrap::saveStickerSets(const Stickers::Order &localOrder, const Stickers:
stickerSetDisenabled(requestId);
}).fail([this](const RPCError &error, mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
_stickerSetDisenableRequests.insert(requestId);
@ -1336,13 +1337,30 @@ void ApiWrap::clearHistory(not_null<PeerData*> peer) {
int ApiWrap::applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result) {
auto &d = result.c_messages_affectedHistory();
if (peer && peer->isChannel()) {
peer->asChannel()->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
const auto &data = result.c_messages_affectedHistory();
if (const auto channel = peer->asChannel()) {
channel->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
} else {
App::main()->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
App::main()->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
}
return d.voffset.v;
return data.voffset.v;
}
void ApiWrap::applyAffectedMessages(
not_null<PeerData*> peer,
const MTPmessages_AffectedMessages &result) {
const auto &data = result.c_messages_affectedMessages();
if (const auto channel = peer->asChannel()) {
channel->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
} else {
applyAffectedMessages(result);
}
}
void ApiWrap::applyAffectedMessages(
const MTPmessages_AffectedMessages &result) {
const auto &data = result.c_messages_affectedMessages();
App::main()->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
}
void ApiWrap::saveDraftsToCloud() {
@ -1522,13 +1540,13 @@ void ApiWrap::resolveWebPages() {
if (!ids.isEmpty()) {
requestId = request(MTPmessages_GetMessages(MTP_vector<MTPint>(ids))).done([this](const MTPmessages_Messages &result, mtpRequestId requestId) {
gotWebPages(nullptr, result, requestId);
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
}
QVector<mtpRequestId> reqsByIndex(idsByChannel.size(), 0);
for (auto i = idsByChannel.cbegin(), e = idsByChannel.cend(); i != e; ++i) {
reqsByIndex[i.value().first] = request(MTPchannels_GetMessages(i.key()->inputChannel, MTP_vector<MTPint>(i.value().second))).done([this, channel = i.key()](const MTPmessages_Messages &result, mtpRequestId requestId) {
gotWebPages(channel, result, requestId);
}).after(kSmallDelayMs).send();
}).afterDelay(kSmallDelayMs).send();
}
if (requestId || !reqsByIndex.isEmpty()) {
for (auto &pendingRequestId : _webPagesPending) {
@ -2242,7 +2260,7 @@ void ApiWrap::sendSaveChatAdminsRequests(not_null<ChatData*> chat) {
if (error.type() == qstr("USER_RESTRICTED")) {
Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
}
}).canWait(5).send();
}).afterDelay(kSmallDelayMs).send();
_chatAdminsSaveRequests[chat].insert(requestId);
};
@ -2388,6 +2406,12 @@ void ApiWrap::userPhotosDone(
));
}
void ApiWrap::sendAction(const SendOptions &options) {
readServerHistory(options.history);
options.history->getReadyFor(ShowAtTheEndMsgId);
_sendActions.fire_copy(options);
}
void ApiWrap::forwardMessages(
HistoryItemsList &&items,
const SendOptions &options,
@ -2409,7 +2433,7 @@ void ApiWrap::forwardMessages(
const auto genClientSideMessage = options.generateLocal && (count < 2);
const auto history = options.history;
App::main()->readServerHistory(history);
readServerHistory(history);
const auto channelPost = history->peer->isChannel()
&& !history->peer->isMegagroup();
@ -2450,7 +2474,7 @@ void ApiWrap::forwardMessages(
if (shared && !--shared->requestsLeft) {
shared->callback();
}
}).after(
}).afterRequest(
history->sendRequestId
).send();
@ -2494,4 +2518,187 @@ void ApiWrap::forwardMessages(
sendAccumulated();
}
void ApiWrap::shareContact(
const QString &phone,
const QString &firstName,
const QString &lastName,
const SendOptions &options) {
const auto userId = UserId(0);
sendSharedContact(phone, firstName, lastName, userId, options);
}
void ApiWrap::shareContact(
not_null<UserData*> user,
const SendOptions &options) {
const auto userId = peerToUser(user->id);
const auto phone = user->phone().isEmpty()
? App::phoneFromSharedContact(userId)
: user->phone();
if (phone.isEmpty()) {
return;
}
sendSharedContact(
phone,
user->firstName,
user->lastName,
userId,
options);
}
void ApiWrap::sendSharedContact(
const QString &phone,
const QString &firstName,
const QString &lastName,
UserId userId,
const SendOptions &options) {
sendAction(options);
const auto history = options.history;
const auto peer = history->peer;
const auto randomId = rand_value<uint64>();
const auto newId = FullMsgId(history->channelId(), clientMsgId());
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = channelPost && options.silent;
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media;
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (options.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
if (peer->asChannel()->addsSignature()) {
flags |= MTPDmessage::Flag::f_post_author;
}
} else {
flags |= MTPDmessage::Flag::f_from_id;
}
if (silentPost) {
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
const auto messageFromId = channelPost ? 0 : Auth().userId();
const auto messagePostAuthor = channelPost
? (Auth().user()->firstName + ' ' + Auth().user()->lastName)
: QString();
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(peer->id),
MTPnullFwdHeader,
MTPint(),
MTP_int(options.replyTo),
MTP_int(unixtime()),
MTP_string(""),
MTP_messageMediaContact(
MTP_string(phone),
MTP_string(firstName),
MTP_string(lastName),
MTP_int(userId)),
MTPnullMarkup,
MTPnullEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTPlong()),
NewMessageUnread);
history->sendRequestId = request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,
MTP_int(options.replyTo),
MTP_inputMediaContact(
MTP_string(phone),
MTP_string(firstName),
MTP_string(lastName)),
MTP_long(randomId),
MTPnullMarkup
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
}).fail([](const RPCError &error) {
if (error.type() == qstr("PEER_FLOOD")) {
Ui::show(Box<InformBox>(
PeerFloodErrorText(PeerFloodType::Send)));
} else if (error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
const auto link = textcmdLink(
Messenger::Instance().createInternalLinkFull(qsl("spambot")),
lang(lng_cant_more_info));
Ui::show(Box<InformBox>(lng_error_public_groups_denied(
lt_more_info,
link)));
}
}).afterRequest(
history->sendRequestId
).send();
App::historyRegRandom(randomId, newId);
}
void ApiWrap::readServerHistory(not_null<History*> history) {
if (history->unreadCount()) {
readServerHistoryForce(history);
}
}
void ApiWrap::readServerHistoryForce(not_null<History*> history) {
const auto peer = history->peer;
const auto upTo = history->inboxRead(0);
if (const auto channel = peer->asChannel()) {
if (!channel->amIn()) {
return; // no read request for channels that I didn't join
} else if (const auto migrateFrom = channel->migrateFrom()) {
if (const auto migrated = App::historyLoaded(migrateFrom)) {
readServerHistory(migrated);
}
}
}
if (_readRequests.contains(peer)) {
const auto i = _readRequestsPending.find(peer);
if (i == _readRequestsPending.cend()) {
_readRequestsPending.emplace(peer, upTo);
} else if (i->second < upTo) {
i->second = upTo;
}
} else {
sendReadRequest(peer, upTo);
}
}
void ApiWrap::sendReadRequest(not_null<PeerData*> peer, MsgId upTo) {
const auto requestId = [&] {
const auto finished = [=] {
_readRequests.remove(peer);
if (const auto next = _readRequestsPending.take(peer)) {
sendReadRequest(peer, *next);
}
};
if (const auto channel = peer->asChannel()) {
return request(MTPchannels_ReadHistory(
channel->inputChannel,
MTP_int(upTo)
)).done([=](const MTPBool &result) {
finished();
}).fail([=](const RPCError &error) {
finished();
}).send();
}
return request(MTPmessages_ReadHistory(
peer->input,
MTP_int(upTo)
)).done([=](const MTPmessages_AffectedMessages &result) {
applyAffectedMessages(peer, result);
finished();
}).fail([=](const RPCError &error) {
finished();
}).send();
}();
_readRequests.emplace(peer, requestId, upTo);
}
ApiWrap::~ApiWrap() = default;

View File

@ -167,13 +167,25 @@ public:
MsgId replyTo = 0;
bool silent = false;
WebPageId webPageId = 0;
bool clearDraft = true;
bool clearDraft = false;
bool generateLocal = true;
};
rpl::producer<SendOptions> sendActions() const {
return _sendActions.events();
}
void sendAction(const SendOptions &options);
void forwardMessages(
HistoryItemsList &&items,
const SendOptions &options,
base::lambda_once<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);
void readServerHistory(not_null<History*> history);
void readServerHistoryForce(not_null<History*> history);
~ApiWrap();
@ -245,10 +257,6 @@ private:
const QDate &date,
Callback &&callback);
int applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result);
void sharedMediaDone(
not_null<PeerData*> peer,
SharedMediaType type,
@ -261,6 +269,22 @@ private:
PhotoId photoId,
const MTPphotos_Photos &result);
void sendSharedContact(
const QString &phone,
const QString &firstName,
const QString &lastName,
UserId userId,
const SendOptions &options);
void sendReadRequest(not_null<PeerData*> peer, MsgId upTo);
int applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result);
void applyAffectedMessages(const MTPmessages_AffectedMessages &result);
void applyAffectedMessages(
not_null<PeerData*> peer,
const MTPmessages_AffectedMessages &result);
not_null<AuthSession*> _session;
mtpRequestId _changelogSubscription = 0;
@ -339,6 +363,20 @@ private:
base::flat_map<not_null<UserData*>, mtpRequestId> _userPhotosRequests;
rpl::event_stream<SendOptions> _sendActions;
struct ReadRequest {
ReadRequest(mtpRequestId requestId, MsgId upTo)
: requestId(requestId)
, upTo(upTo) {
}
mtpRequestId requestId = 0;
MsgId upTo = 0;
};
base::flat_map<not_null<PeerData*>, ReadRequest> _readRequests;
base::flat_map<not_null<PeerData*>, MsgId> _readRequestsPending;
base::Observable<PeerData*> _fullPeerUpdated;
rpl::event_stream<uint64> _stickerSetInstalled;

View File

@ -103,24 +103,16 @@ public:
using value_type = pair_type;
using difference_type = typename iterator_impl::difference_type;
using pointer = pointer_impl;
using const_pointer = const pair_type*;
using reference = reference_impl;
using const_reference = const pair_type&;
flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl())
: _impl(impl) {
}
reference operator*() {
reference operator*() const {
return *_impl;
}
const_reference operator*() const {
return *_impl;
}
pointer operator->() {
return std::addressof(**this);
}
const_pointer operator->() const {
pointer operator->() const {
return std::addressof(**this);
}
Me &operator++() {
@ -166,10 +158,7 @@ public:
other_reference_impl> &right) const {
return _impl - right._impl;
}
reference operator[](difference_type offset) {
return _impl[offset];
}
const_reference operator[](difference_type offset) const {
reference operator[](difference_type offset) const {
return _impl[offset];
}

View File

@ -756,7 +756,7 @@ void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) {
e->setDropAction(Qt::CopyAction);
e->accept();
updateDragInScroll(_scroll->geometry().contains(e->pos()));
} else if (App::main() && App::main()->getDragState(e->mimeData()) != DragStateNone) {
} else if (App::main() && App::main()->getDragState(e->mimeData()) != DragState::None) {
e->setDropAction(Qt::CopyAction);
e->accept();
}

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "observer_peer.h"
#include "mainwindow.h"
#include "mainwidget.h"
#include "apiwrap.h"
#include "messenger.h"
#include "auth_session.h"
#include "boxes/confirm_box.h"
@ -121,10 +122,13 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
case ButtonType::RequestPhone: {
hideSingleUseKeyboard(msg);
Ui::show(Box<ConfirmBox>(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm), [peerId = msg->history()->peer->id] {
if (auto m = App::main()) {
m->onShareContact(peerId, App::self());
}
const auto msgId = msg->id;
const auto history = msg->history();
Ui::show(Box<ConfirmBox>(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm), [=] {
Ui::showPeerHistory(history, ShowAtTheEndMsgId);
auto options = ApiWrap::SendOptions(history);
options.replyTo = msgId;
Auth().api().shareContact(App::self(), options);
}));
} break;

View File

@ -1,33 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
enum DragState {
DragStateNone = 0x00,
DragStateFiles = 0x01,
DragStatePhotoFiles = 0x02,
DragStateImage = 0x03,
};
enum class ReadServerHistoryChecks {
OnlyIfUnread,
ForceRequest,
};

View File

@ -395,7 +395,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
HistoryLayout::paintEmpty(p, width(), height());
}
if (!noHistoryDisplayed) {
auto readMentions = HistoryItemsMap();
auto readMentions = base::flat_set<not_null<HistoryItem*>>();
adjustCurrent(clip.top());

View File

@ -185,13 +185,6 @@ HistoryHider::HistoryHider(
init();
}
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : RpWidget(parent)
, _sharedContact(sharedContact)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
init();
}
HistoryHider::HistoryHider(MainWidget *parent) : RpWidget(parent)
, _sendPath(true)
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
@ -231,7 +224,7 @@ void HistoryHider::refreshLang() {
}
bool HistoryHider::withConfirm() const {
return _sharedContact || _sendPath;
return _sendPath;
}
void HistoryHider::paintEvent(QPaintEvent *e) {
@ -317,9 +310,7 @@ void HistoryHider::animationCallback() {
void HistoryHider::forward() {
if (!_hiding && _offered) {
if (_sharedContact) {
parent()->onShareContact(_offered->id, _sharedContact);
} else if (_sendPath) {
if (_sendPath) {
parent()->onSendPaths(_offered->id);
} else if (!_shareUrl.isEmpty()) {
parent()->shareUrl(_offered, _shareUrl, _shareText);
@ -375,17 +366,7 @@ bool HistoryHider::offerPeer(PeerId peer) {
_offered = App::peer(peer);
auto phrase = QString();
auto recipient = _offered->isUser() ? _offered->name : '\xAB' + _offered->name + '\xBB';
if (_sharedContact) {
if (!_offered->canWrite()) {
Ui::show(Box<InformBox>(lang(lng_forward_share_cant)));
_offered = nullptr;
_toText.setText(st::boxLabelStyle, QString());
_toTextWidth = 0;
resizeEvent(nullptr);
return false;
}
phrase = lng_forward_share_contact(lt_recipient, recipient);
} else if (_sendPath) {
if (_sendPath) {
auto toId = _offered->id;
_offered = nullptr;
if (parent()->onSendPaths(toId)) {
@ -766,6 +747,17 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
setMembersShowAreaActive(active);
}, _topBar->lifetime());
Auth().api().sendActions(
) | rpl::start_with_next([this](const ApiWrap::SendOptions &options) {
fastShowAtEnd(options.history);
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
options.history->channelId(),
options.replyTo));
if (cancelReply(lastKeyboardUsed) && !options.clearDraft) {
onCloudDraftSave();
}
}, lifetime());
orderWidgets();
}
@ -1345,7 +1337,6 @@ void HistoryWidget::onRecordDone(QByteArray result, VoiceWaveform waveform, qint
auto to = FileLoadTo(_peer->id, _silent->checked(), replyToId());
auto caption = QString();
_fileLoader.addTask(MakeShared<FileLoadTask>(result, duration, waveform, to, caption));
cancelReplyAfterMediaSend(lastForceReplyReplied());
}
void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
@ -1555,23 +1546,21 @@ void HistoryWidget::calcNextReplyReturn() {
if (!_replyReturn) updateControlsVisibility();
}
void HistoryWidget::fastShowAtEnd(History *h) {
if (h == _history) {
h->getReadyFor(ShowAtTheEndMsgId);
void HistoryWidget::fastShowAtEnd(not_null<History*> history) {
if (_history != history) {
return;
}
clearAllLoadRequests();
clearAllLoadRequests();
setMsgId(ShowAtUnreadMsgId);
_historyInited = false;
setMsgId(ShowAtUnreadMsgId);
_historyInited = false;
if (h->isReadyFor(_showAtMsgId)) {
historyLoaded();
} else {
firstLoadMessages();
doneShow();
}
} else if (h) {
h->getReadyFor(ShowAtTheEndMsgId);
if (_history->isReadyFor(_showAtMsgId)) {
historyLoaded();
} else {
firstLoadMessages();
doneShow();
}
}
@ -2219,7 +2208,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
if (item->mentionsMe() && item->isMediaUnread()) {
App::main()->mediaMarkRead(item);
}
historyWasRead(ReadServerHistoryChecks::ForceRequest);
Auth().api().readServerHistoryForce(history);
return;
}
}
@ -2237,13 +2226,6 @@ void HistoryWidget::historyToDown(History *history) {
}
}
void HistoryWidget::historyWasRead(ReadServerHistoryChecks checks) {
App::main()->readServerHistory(_history, checks);
if (_migrated) {
App::main()->readServerHistory(_migrated, ReadServerHistoryChecks::OnlyIfUnread);
}
}
void HistoryWidget::unreadCountChanged(History *history) {
if (history == _history || history == _migrated) {
updateHistoryDownVisibility();
@ -2722,7 +2704,7 @@ void HistoryWidget::visibleAreaUpdated() {
auto showFromVisible = (showFrom && !showFrom->detached() && scrollBottom > _list->itemTop(showFrom));
auto atBottom = (scrollTop >= _scroll->scrollTopMax());
if ((showFromVisible || atBottom) && App::wnd()->doWeReadServerHistory()) {
historyWasRead(ReadServerHistoryChecks::OnlyIfUnread);
Auth().api().readServerHistory(_history);
}
}
controller()->floatPlayerAreaUpdated().notify(true);
@ -2911,7 +2893,7 @@ void HistoryWidget::hideSelectorControlsAnimated() {
}
}
void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
void HistoryWidget::onSend(bool ctrlShiftEnter) {
if (!_history) return;
if (_editMsgId) {
@ -2919,14 +2901,11 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
return;
}
bool lastKeyboardUsed = lastForceReplyReplied(FullMsgId(_channel, replyTo));
WebPageId webPageId = _previewCancelled ? CancelledWebPageId : ((_previewData && _previewData->pendingTill >= 0) ? _previewData->id : 0);
MainWidget::MessageToSend message;
message.history = _history;
auto message = MainWidget::MessageToSend(_history);
message.textWithTags = _field->getTextWithTags();
message.replyTo = replyTo;
message.replyTo = replyToId();
message.silent = _silent->checked();
message.webPageId = webPageId;
App::main()->sendMessage(message);
@ -2938,11 +2917,12 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
hideSelectorControlsAnimated();
if (replyTo < 0) cancelReply(lastKeyboardUsed);
if (_previewData && _previewData->pendingTill) previewCancel();
_field->setFocus();
if (!_keyboard->hasMarkup() && _keyboard->forceReply() && !_kbReplyTo) onKbToggle();
if (!_keyboard->hasMarkup() && _keyboard->forceReply() && !_kbReplyTo) {
onKbToggle();
}
}
void HistoryWidget::onUnblock() {
@ -3039,84 +3019,6 @@ void HistoryWidget::onBroadcastSilentChange() {
updateFieldPlaceholder();
}
void HistoryWidget::onShareContact(const PeerId &peer, UserData *contact) {
auto phone = contact->phone();
if (phone.isEmpty()) phone = App::phoneFromSharedContact(peerToUser(contact->id));
if (!contact || phone.isEmpty()) return;
Ui::showPeerHistory(peer, ShowAtTheEndMsgId);
if (!_history) return;
shareContact(peer, phone, contact->firstName, contact->lastName, replyToId(), peerToUser(contact->id));
}
void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, int32 userId) {
auto history = App::history(peer);
uint64 randomId = rand_value<uint64>();
FullMsgId newId(peerToChannel(peer), clientMsgId());
App::main()->readServerHistory(history);
fastShowAtEnd(history);
auto p = App::peer(peer);
auto flags = NewMessageFlags(p) | MTPDmessage::Flag::f_media; // unread, out
bool lastKeyboardUsed = lastForceReplyReplied(FullMsgId(peerToChannel(peer), replyTo));
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
bool channelPost = p->isChannel() && !p->isMegagroup();
bool silentPost = channelPost && _silent->checked();
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
}
if (!channelPost) {
flags |= MTPDmessage::Flag::f_from_id;
} else if (p->asChannel()->addsSignature()) {
flags |= MTPDmessage::Flag::f_post_author;
}
if (silentPost) {
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(peer),
MTPnullFwdHeader,
MTPint(),
MTP_int(replyToId()),
MTP_int(unixtime()),
MTP_string(""),
MTP_messageMediaContact(
MTP_string(phone),
MTP_string(fname),
MTP_string(lname),
MTP_int(userId)),
MTPnullMarkup,
MTPnullEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTPlong()),
NewMessageUnread);
history->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_flags(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, history->sendRequestId);
App::historyRegRandom(randomId, newId);
App::main()->finishForwarding(history, _silent->checked());
cancelReplyAfterMediaSend(lastKeyboardUsed);
}
History *HistoryWidget::history() const {
return _history;
}
@ -3278,22 +3180,22 @@ void HistoryWidget::dragEnterEvent(QDragEnterEvent *e) {
_attachDrag = getDragState(e->mimeData());
updateDragAreas();
if (_attachDrag) {
if (_attachDrag != DragState::None) {
e->setDropAction(Qt::IgnoreAction);
e->accept();
}
}
void HistoryWidget::dragLeaveEvent(QDragLeaveEvent *e) {
if (_attachDrag != DragStateNone || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragStateNone;
if (_attachDrag != DragState::None || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragState::None;
updateDragAreas();
}
}
void HistoryWidget::leaveEventHook(QEvent *e) {
if (_attachDrag != DragStateNone || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragStateNone;
if (_attachDrag != DragState::None || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragState::None;
updateDragAreas();
}
if (hasMouseTracking()) mouseMoveEvent(0);
@ -3362,8 +3264,8 @@ void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) {
_replyForwardPressed = false;
update(0, _field->y() - st::historySendPadding - st::historyReplyHeight, width(), st::historyReplyHeight);
}
if (_attachDrag != DragStateNone || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragStateNone;
if (_attachDrag != DragState::None || !_attachDragPhoto->isHidden() || !_attachDragDocument->isHidden()) {
_attachDrag = DragState::None;
updateDragAreas();
}
if (_recording) {
@ -3405,10 +3307,13 @@ void HistoryWidget::sendBotCommand(PeerData *peer, UserData *bot, const QString
toSend += '@' + username;
}
MainWidget::MessageToSend message;
message.history = _history;
auto message = MainWidget::MessageToSend(_history);
message.textWithTags = { toSend, TextWithTags::Tags() };
message.replyTo = replyTo ? ((!_peer->isUser()/* && (botStatus == 0 || botStatus == 2)*/) ? replyTo : -1) : 0;
message.replyTo = replyTo
? ((!_peer->isUser()/* && (botStatus == 0 || botStatus == 2)*/)
? replyTo
: replyToId())
: 0;
message.silent = false;
App::main()->sendMessage(message);
if (replyTo) {
@ -3585,30 +3490,30 @@ DragState HistoryWidget::getDragState(const QMimeData *d) {
if (!d
|| d->hasFormat(qsl("application/x-td-forward-selected"))
|| d->hasFormat(qsl("application/x-td-forward-pressed"))
|| d->hasFormat(qsl("application/x-td-forward-pressed-link"))) return DragStateNone;
|| d->hasFormat(qsl("application/x-td-forward-pressed-link"))) return DragState::None;
if (d->hasImage()) return DragStateImage;
if (d->hasImage()) return DragState::Image;
QString uriListFormat(qsl("text/uri-list"));
if (!d->hasFormat(uriListFormat)) return DragStateNone;
if (!d->hasFormat(uriListFormat)) return DragState::None;
QStringList imgExtensions(cImgExtensions()), files;
const QList<QUrl> &urls(d->urls());
if (urls.isEmpty()) return DragStateNone;
if (urls.isEmpty()) return DragState::None;
bool allAreSmallImages = true;
for (QList<QUrl>::const_iterator i = urls.cbegin(), en = urls.cend(); i != en; ++i) {
if (!i->isLocalFile()) return DragStateNone;
if (!i->isLocalFile()) return DragState::None;
auto file = Platform::File::UrlToLocal(*i);
QFileInfo info(file);
if (info.isDir()) return DragStateNone;
if (info.isDir()) return DragState::None;
quint64 s = info.size();
if (s > App::kFileSizeLimit) {
return DragStateNone;
return DragState::None;
}
if (allAreSmallImages) {
if (s > App::kImageSizeLimit) {
@ -3627,30 +3532,30 @@ DragState HistoryWidget::getDragState(const QMimeData *d) {
}
}
}
return allAreSmallImages ? DragStatePhotoFiles : DragStateFiles;
return allAreSmallImages ? DragState::PhotoFiles : DragState::Files;
}
void HistoryWidget::updateDragAreas() {
_field->setAcceptDrops(!_attachDrag);
_field->setAcceptDrops(_attachDrag == DragState::None);
updateControlsGeometry();
switch (_attachDrag) {
case DragStateNone:
case DragState::None:
_attachDragDocument->otherLeave();
_attachDragPhoto->otherLeave();
break;
case DragStateFiles:
case DragState::Files:
_attachDragDocument->setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files));
_attachDragDocument->otherEnter();
_attachDragPhoto->hideFast();
break;
case DragStatePhotoFiles:
case DragState::PhotoFiles:
_attachDragDocument->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression));
_attachDragPhoto->setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick));
_attachDragDocument->otherEnter();
_attachDragPhoto->otherEnter();
break;
case DragStateImage:
case DragState::Image:
_attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
_attachDragDocument->hideFast();
_attachDragPhoto->otherEnter();
@ -3774,7 +3679,7 @@ bool HistoryWidget::kbWasHidden() const {
}
void HistoryWidget::dropEvent(QDropEvent *e) {
_attachDrag = DragStateNone;
_attachDrag = DragState::None;
updateDragAreas();
e->acceptProposedAction();
}
@ -4123,11 +4028,18 @@ bool HistoryWidget::showSendFilesBox(object_ptr<SendFilesBox> box, const QString
box->setConfirmedCallback(base::lambda_guarded(this, [this, withComment, sendCallback = std::move(callback)](const QStringList &files, const QImage &image, std::unique_ptr<FileLoadTask::MediaInformation> information, bool compressed, const QString &caption, bool ctrlShiftEnter) {
if (!canWriteMessage()) return;
auto replyTo = replyToId();
const auto replyTo = replyToId();
if (withComment) {
onSend(ctrlShiftEnter, replyTo);
// This call will clear replyToId().
onSend(ctrlShiftEnter);
}
sendCallback(files, image, std::move(information), compressed, caption, replyTo);
sendCallback(
files,
image,
std::move(information),
compressed,
caption,
replyTo);
}));
if (withComment) {
@ -4244,7 +4156,9 @@ bool HistoryWidget::confirmShareContact(
bool compressed,
const QString &caption,
MsgId replyTo) {
shareContact(_peer->id, phone, fname, lname, replyTo);
auto options = ApiWrap::SendOptions(_history);
options.replyTo = replyTo;
Auth().api().shareContact(phone, fname, lname, options);
};
auto insertTextOnCancel = QString();
return showSendFilesBox(
@ -4311,13 +4225,18 @@ void HistoryWidget::uploadFiles(const QStringList &files, SendMediaType type) {
uploadFilesAfterConfirmation(files, QByteArray(), QImage(), nullptr, type, caption);
}
void HistoryWidget::uploadFilesAfterConfirmation(const QStringList &files, const QByteArray &content, const QImage &image, std::unique_ptr<FileLoadTask::MediaInformation> information, SendMediaType type, QString caption) {
void HistoryWidget::uploadFilesAfterConfirmation(
const QStringList &files,
const QByteArray &content,
const QImage &image,
std::unique_ptr<FileLoadTask::MediaInformation> information,
SendMediaType type,
QString caption) {
Assert(canWriteMessage());
auto to = FileLoadTo(_peer->id, _silent->checked(), replyToId());
if (files.size() > 1 && !caption.isEmpty()) {
MainWidget::MessageToSend message;
message.history = _history;
auto message = MainWidget::MessageToSend(_history);
message.textWithTags = { caption, TextWithTags::Tags() };
message.replyTo = to.replyTo;
message.silent = to.silent;
@ -4335,8 +4254,6 @@ void HistoryWidget::uploadFilesAfterConfirmation(const QStringList &files, const
}
}
_fileLoader.addTasks(tasks);
cancelReplyAfterMediaSend(lastForceReplyReplied());
}
void HistoryWidget::uploadFile(const QByteArray &fileContent, SendMediaType type) {
@ -4345,8 +4262,6 @@ void HistoryWidget::uploadFile(const QByteArray &fileContent, SendMediaType type
auto to = FileLoadTo(_peer->id, _silent->checked(), replyToId());
auto caption = QString();
_fileLoader.addTask(MakeShared<FileLoadTask>(fileContent, QImage(), type, to, caption));
cancelReplyAfterMediaSend(lastForceReplyReplied());
}
void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
@ -4364,13 +4279,19 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
Auth().uploader().upload(newId, file);
History *h = App::history(file->to.peer);
const auto history = App::history(file->to.peer);
const auto peer = history->peer;
fastShowAtEnd(h);
auto options = ApiWrap::SendOptions(history);
options.clearDraft = false;
options.replyTo = file->to.replyTo;
options.generateLocal = true;
options.silent = file->to.silent;
Auth().api().sendAction(options);
auto flags = NewMessageFlags(h->peer) | MTPDmessage::Flag::f_media; // unread, out
auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media;
if (file->to.replyTo) flags |= MTPDmessage::Flag::f_reply_to_msg_id;
bool channelPost = h->peer->isChannel() && !h->peer->isMegagroup();
bool channelPost = peer->isChannel() && !peer->isMegagroup();
bool silentPost = channelPost && file->to.silent;
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
@ -4378,7 +4299,7 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
}
if (!channelPost) {
flags |= MTPDmessage::Flag::f_from_id;
} else if (h->peer->asChannel()->addsSignature()) {
} else if (peer->asChannel()->addsSignature()) {
flags |= MTPDmessage::Flag::f_post_author;
}
if (silentPost) {
@ -4396,7 +4317,7 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
file->photo,
MTP_string(file->caption),
MTPint());
h->addNewMessage(
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
@ -4425,7 +4346,7 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
file->document,
MTP_string(file->caption),
MTPint());
h->addNewMessage(
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
@ -4445,7 +4366,7 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
MTPlong()),
NewMessageUnread);
} else if (file->type == SendMediaType::Audio) {
if (!h->peer->isChannel()) {
if (!peer->isChannel()) {
flags |= MTPDmessage::Flag::f_media_unread;
}
auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
@ -4457,7 +4378,7 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
file->document,
MTP_string(file->caption),
MTPint());
h->addNewMessage(
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
@ -4483,8 +4404,6 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
}
App::main()->dialogsToUp();
peerMessagesUpdated(file->to.peer);
cancelReplyAfterMediaSend(lastKeyboardUsed);
}
void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file) {
@ -4833,17 +4752,17 @@ void HistoryWidget::updateControlsGeometry() {
}
switch (_attachDrag) {
case DragStateFiles:
case DragState::Files:
_attachDragDocument->resize(width() - st::dragMargin.left() - st::dragMargin.right(), height() - st::dragMargin.top() - st::dragMargin.bottom());
_attachDragDocument->move(st::dragMargin.left(), st::dragMargin.top());
break;
case DragStatePhotoFiles:
case DragState::PhotoFiles:
_attachDragDocument->resize(width() - st::dragMargin.left() - st::dragMargin.right(), (height() - st::dragMargin.top() - st::dragMargin.bottom()) / 2);
_attachDragDocument->move(st::dragMargin.left(), st::dragMargin.top());
_attachDragPhoto->resize(_attachDragDocument->width(), _attachDragDocument->height());
_attachDragPhoto->move(st::dragMargin.left(), height() - _attachDragPhoto->height() - st::dragMargin.bottom());
break;
case DragStateImage:
case DragState::Image:
_attachDragPhoto->resize(width() - st::dragMargin.left() - st::dragMargin.right(), height() - st::dragMargin.top() - st::dragMargin.bottom());
_attachDragPhoto->move(st::dragMargin.left(), st::dragMargin.top());
break;
@ -5365,23 +5284,24 @@ void HistoryWidget::onInlineResultSend(InlineBots::Result *result, UserData *bot
return;
}
App::main()->readServerHistory(_history);
fastShowAtEnd(_history);
auto options = ApiWrap::SendOptions(_history);
options.clearDraft = true;
options.replyTo = replyToId();
options.generateLocal = true;
options.silent = _silent->checked();
Auth().api().sendAction(options);
uint64 randomId = rand_value<uint64>();
FullMsgId newId(_channel, clientMsgId());
bool lastKeyboardUsed = lastForceReplyReplied();
bool out = !_peer->isSelf(), unread = !_peer->isSelf();
auto flags = NewMessageFlags(_peer) | MTPDmessage::Flag::f_media; // unread, out
auto flags = NewMessageFlags(_peer) | MTPDmessage::Flag::f_media;
auto sendFlags = MTPmessages_SendInlineBotResult::Flag::f_clear_draft | 0;
if (replyToId()) {
if (options.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 = channelPost && _silent->checked();
bool silentPost = channelPost && options.silent;
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -5408,7 +5328,6 @@ void HistoryWidget::onInlineResultSend(InlineBots::Result *result, UserData *bot
_history->sendRequestId = MTP::send(MTPmessages_SendInlineBotResult(MTP_flags(sendFlags), _peer->input, MTP_int(replyToId()), MTP_long(randomId), MTP_long(result->getQueryId()), MTP_string(result->getId())), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, _history->sendRequestId);
App::main()->finishForwarding(_history, _silent->checked());
cancelReply(lastKeyboardUsed);
App::historyRegRandom(randomId, newId);
@ -5548,23 +5467,24 @@ bool HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &capti
return false;
}
App::main()->readServerHistory(_history);
fastShowAtEnd(_history);
auto options = ApiWrap::SendOptions(_history);
options.clearDraft = false;
options.replyTo = replyToId();
options.generateLocal = true;
options.silent = _silent->checked();
Auth().api().sendAction(options);
uint64 randomId = rand_value<uint64>();
FullMsgId newId(_channel, clientMsgId());
bool lastKeyboardUsed = lastForceReplyReplied();
bool out = !_peer->isSelf(), unread = !_peer->isSelf();
auto flags = NewMessageFlags(_peer) | MTPDmessage::Flag::f_media; // unread, out
auto flags = NewMessageFlags(_peer) | MTPDmessage::Flag::f_media;
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (replyToId()) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
bool channelPost = _peer->isChannel() && !_peer->isMegagroup();
bool silentPost = channelPost && _silent->checked();
bool silentPost = channelPost && options.silent;
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -5583,7 +5503,6 @@ bool HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &capti
_history->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_flags(sendFlags), _peer->input, MTP_int(replyToId()), MTP_inputMediaDocument(MTP_flags(0), mtpInput, MTP_string(caption), MTPint()), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, _history->sendRequestId);
App::main()->finishForwarding(_history, _silent->checked());
cancelReplyAfterMediaSend(lastKeyboardUsed);
if (doc->sticker()) App::main()->incrementSticker(doc);
@ -5608,16 +5527,17 @@ void HistoryWidget::sendExistingPhoto(PhotoData *photo, const QString &caption)
return;
}
App::main()->readServerHistory(_history);
fastShowAtEnd(_history);
auto options = ApiWrap::SendOptions(_history);
options.clearDraft = false;
options.replyTo = replyToId();
options.generateLocal = true;
options.silent = _silent->checked();
Auth().api().sendAction(options);
uint64 randomId = rand_value<uint64>();
FullMsgId newId(_channel, clientMsgId());
bool lastKeyboardUsed = lastForceReplyReplied();
bool out = !_peer->isSelf(), unread = !_peer->isSelf();
auto flags = NewMessageFlags(_peer) | MTPDmessage::Flag::f_media; // unread, out
auto flags = NewMessageFlags(_peer) | MTPDmessage::Flag::f_media;
auto sendFlags = MTPmessages_SendMedia::Flags(0);
if (replyToId()) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
@ -5643,7 +5563,6 @@ void HistoryWidget::sendExistingPhoto(PhotoData *photo, const QString &caption)
_history->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_flags(sendFlags), _peer->input, MTP_int(replyToId()), MTP_inputMediaPhoto(MTP_flags(0), MTP_inputPhoto(MTP_long(photo->id), MTP_long(photo->access)), MTP_string(caption), MTPint()), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, _history->sendRequestId);
App::main()->finishForwarding(_history, _silent->checked());
cancelReplyAfterMediaSend(lastKeyboardUsed);
App::historyRegRandom(randomId, newId);
@ -5843,10 +5762,18 @@ void HistoryWidget::onCopyPostLink() {
}
bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
if (replyTo.msg > 0 && replyTo.channel != _channel) return false;
if (replyTo.channel != _channel) {
return false;
}
return _keyboard->forceReply()
&& _keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)
&& _keyboard->forMsgId().msg == (replyTo.msg < 0 ? replyToId() : replyTo.msg);
&& _keyboard->forMsgId().msg == replyTo.msg;
}
bool HistoryWidget::lastForceReplyReplied() const {
return _keyboard->forceReply()
&& _keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)
&& _keyboard->forMsgId().msg == replyToId();
}
bool HistoryWidget::cancelReply(bool lastKeyboardUsed) {
@ -5880,7 +5807,10 @@ bool HistoryWidget::cancelReply(bool lastKeyboardUsed) {
_saveDraftStart = getms();
onDraftSave();
}
if (!_editMsgId && _keyboard->singleUse() && _keyboard->forceReply() && lastKeyboardUsed) {
if (!_editMsgId
&& _keyboard->singleUse()
&& _keyboard->forceReply()
&& lastKeyboardUsed) {
if (_kbReplyTo) {
onKbToggle(false);
}

View File

@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localimageloader.h"
#include "ui/widgets/tooltip.h"
#include "history/history_common.h"
#include "mainwidget.h"
#include "chat_helpers/field_autocomplete.h"
#include "window/section_widget.h"
#include "core/single_timer.h"
@ -103,7 +103,6 @@ class HistoryHider : public Ui::RpWidget, private base::Subscriber {
public:
HistoryHider(MainWidget *parent, MessageIdsList &&items); // forward messages
HistoryHider(MainWidget *parent, UserData *sharedContact); // share contact
HistoryHider(MainWidget *parent); // send path from command line argument
HistoryHider(MainWidget *parent, const QString &url, const QString &text); // share url
HistoryHider(MainWidget *parent, const QString &botAndQuery); // inline switch button handler
@ -142,7 +141,6 @@ private:
void init();
MainWidget *parent();
UserData *_sharedContact = nullptr;
MessageIdsList _forwardItems;
bool _sendPath = false;
@ -200,7 +198,6 @@ public:
void newUnreadMsg(History *history, HistoryItem *item);
void historyToDown(History *history);
void historyWasRead(ReadServerHistoryChecks checks);
void unreadCountChanged(History *history);
QRect historyRect() const;
@ -234,10 +231,6 @@ public:
void updateControlsVisibility();
void updateControlsGeometry();
void onShareContact(const PeerId &peer, UserData *contact);
void shareContact(const PeerId &peer, const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, int32 userId = 0);
History *history() const;
PeerData *peer() const;
void setMsgId(MsgId showAtMsgId);
@ -268,7 +261,8 @@ public:
MsgId replyToId() const;
void messageDataReceived(ChannelData *channel, MsgId msgId);
bool lastForceReplyReplied(const FullMsgId &replyTo = FullMsgId(NoChannel, -1)) const;
bool lastForceReplyReplied(const FullMsgId &replyTo) const;
bool lastForceReplyReplied() const;
bool cancelReply(bool lastKeyboardUsed = false);
void cancelEdit();
void updateForwarding();
@ -301,7 +295,7 @@ public:
DragState getDragState(const QMimeData *d);
void fastShowAtEnd(History *h);
void fastShowAtEnd(not_null<History*> history);
void applyDraft(bool parseLinks = true, Ui::FlatTextarea::UndoHistoryAction undoHistoryAction = Ui::FlatTextarea::ClearUndoHistory);
void showHistory(const PeerId &peer, MsgId showAtMsgId, bool reload = false);
void clearDelayedShowAt();
@ -405,7 +399,6 @@ public slots:
void onReportSpamClear();
void onScroll();
void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1);
void onUnblock();
void onBotStart();
@ -452,6 +445,8 @@ public slots:
void preloadHistoryIfNeeded();
private slots:
void onSend(bool ctrlShiftEnter = false);
void onHashtagOrBotCommandInsert(QString str, FieldAutocomplete::ChooseMethod method);
void onMentionInsert(UserData *user);
void onInlineBotCancel();
@ -825,7 +820,7 @@ private:
object_ptr<InlineBots::Layout::Widget> _inlineResults = { nullptr };
object_ptr<TabbedPanel> _tabbedPanel;
QPointer<TabbedSelector> _tabbedSelector;
DragState _attachDrag = DragStateNone;
DragState _attachDrag = DragState::None;
object_ptr<DragArea> _attachDragDocument, _attachDragPhoto;
object_ptr<Ui::Emoji::SuggestionsController> _emojiSuggestions = { nullptr };

View File

@ -790,10 +790,6 @@ void MainWidget::onUpdateMuted() {
App::updateMuted();
}
void MainWidget::onShareContact(const PeerId &peerId, UserData *contact) {
_history->onShareContact(peerId, contact);
}
bool MainWidget::onSendPaths(const PeerId &peerId) {
Expects(peerId != 0);
auto peer = App::peer(peerId);
@ -1016,10 +1012,6 @@ void MainWidget::deletePhotoLayer(PhotoData *photo) {
})));
}
void MainWidget::shareContactLayer(UserData *contact) {
hiderLayer(object_ptr<HistoryHider>(this, contact));
}
void MainWidget::shareUrlLayer(const QString &url, const QString &text) {
// Don't allow to insert an inline bot query by share url link.
if (url.trimmed().startsWith('@')) {
@ -1100,15 +1092,26 @@ void MainWidget::deleteHistoryPart(DeleteHistoryRequest request, const MTPmessag
MTP::send(MTPmessages_DeleteHistory(MTP_flags(flags), peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, request));
}
void MainWidget::deleteMessages(PeerData *peer, const QVector<MTPint> &ids, bool forEveryone) {
if (peer->isChannel()) {
MTP::send(MTPchannels_DeleteMessages(peer->asChannel()->inputChannel, MTP_vector<MTPint>(ids)), rpcDone(&MainWidget::messagesAffected, peer));
void MainWidget::deleteMessages(
not_null<PeerData*> peer,
const QVector<MTPint> &ids,
bool forEveryone) {
if (const auto channel = peer->asChannel()) {
MTP::send(
MTPchannels_DeleteMessages(
channel->inputChannel,
MTP_vector<MTPint>(ids)),
rpcDone(&MainWidget::messagesAffected, peer));
} else {
auto flags = MTPmessages_DeleteMessages::Flags(0);
if (forEveryone) {
flags |= MTPmessages_DeleteMessages::Flag::f_revoke;
}
MTP::send(MTPmessages_DeleteMessages(MTP_flags(flags), MTP_vector<MTPint>(ids)), rpcDone(&MainWidget::messagesAffected, peer));
MTP::send(
MTPmessages_DeleteMessages(
MTP_flags(flags),
MTP_vector<MTPint>(ids)),
rpcDone(&MainWidget::messagesAffected, peer));
}
}
@ -1458,13 +1461,18 @@ Dialogs::IndexedList *MainWidget::contactsNoDialogsList() {
}
void MainWidget::sendMessage(const MessageToSend &message) {
auto history = message.history;
const auto history = message.history;
auto &textWithTags = message.textWithTags;
readServerHistory(history);
_history->fastShowAtEnd(history);
auto options = ApiWrap::SendOptions(message.history);
options.clearDraft = message.clearDraft;
options.replyTo = message.replyTo;
options.generateLocal = true;
options.silent = message.silent;
options.webPageId = message.webPageId;
Auth().api().sendAction(options);
if (!history || !history->peer->canWrite()) {
if (!history->peer->canWrite()) {
return;
}
saveRecentHashtags(textWithTags.text);
@ -1476,7 +1484,6 @@ void MainWidget::sendMessage(const MessageToSend &message) {
HistoryItem *lastMessage = nullptr;
auto replyTo = (message.replyTo < 0) ? _history->replyToId() : message.replyTo;
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
auto newId = FullMsgId(peerToChannel(history->peer->id), clientMsgId());
auto randomId = rand_value<uint64>();
@ -1489,7 +1496,7 @@ void MainWidget::sendMessage(const MessageToSend &message) {
MTPstring msgText(MTP_string(sending.text));
auto flags = NewMessageFlags(history->peer) | MTPDmessage::Flag::f_entities; // unread, out
auto sendFlags = MTPmessages_SendMessage::Flags(0);
if (replyTo) {
if (message.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to_msg_id;
}
@ -1534,7 +1541,7 @@ void MainWidget::sendMessage(const MessageToSend &message) {
peerToMTP(history->peer->id),
MTPnullFwdHeader,
MTPint(),
MTP_int(replyTo),
MTP_int(message.replyTo),
MTP_int(unixtime()),
msgText,
media,
@ -1545,7 +1552,20 @@ void MainWidget::sendMessage(const MessageToSend &message) {
MTP_string(messagePostAuthor),
MTPlong()),
NewMessageUnread);
history->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_flags(sendFlags), history->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, sentEntities), rpcDone(&MainWidget::sentUpdatesReceived, randomId), rpcFail(&MainWidget::sendMessageFail), 0, 0, history->sendRequestId);
history->sendRequestId = MTP::send(
MTPmessages_SendMessage(
MTP_flags(sendFlags),
history->peer->input,
MTP_int(message.replyTo),
msgText,
MTP_long(randomId),
MTPnullMarkup,
sentEntities),
rpcDone(&MainWidget::sentUpdatesReceived, randomId),
rpcFail(&MainWidget::sendMessageFail),
0,
0,
history->sendRequestId);
}
history->lastSentMsg = lastMessage;
@ -1581,30 +1601,6 @@ void MainWidget::saveRecentHashtags(const QString &text) {
}
}
void MainWidget::readServerHistory(History *history, ReadServerHistoryChecks checks) {
if (!history) return;
if (checks == ReadServerHistoryChecks::OnlyIfUnread && !history->unreadCount()) return;
auto peer = history->peer;
MsgId upTo = history->inboxRead(0);
if (auto channel = peer->asChannel()) {
if (!channel->amIn()) {
return; // no read request for channels that I didn't koin
}
}
if (_readRequests.contains(peer)) {
auto i = _readRequestsPending.find(peer);
if (i == _readRequestsPending.cend()) {
_readRequestsPending.insert(peer, upTo);
} else if (i.value() < upTo) {
i.value() = upTo;
}
} else {
sendReadRequest(peer, upTo);
}
}
void MainWidget::unreadCountChanged(History *history) {
_history->unreadCountChanged(history);
}
@ -1761,45 +1757,14 @@ void MainWidget::overviewLoaded(
Notify::mediaOverviewUpdated(history->peer, type);
}
void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) {
if (peer->isChannel()) {
_readRequests.insert(peer, qMakePair(MTP::send(MTPchannels_ReadHistory(peer->asChannel()->inputChannel, MTP_int(upTo)), rpcDone(&MainWidget::channelReadDone, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo));
void MainWidget::messagesAffected(
not_null<PeerData*> peer,
const MTPmessages_AffectedMessages &result) {
const auto &data = result.c_messages_affectedMessages();
if (const auto channel = peer->asChannel()) {
channel->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
} else {
_readRequests.insert(peer, qMakePair(MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo)), rpcDone(&MainWidget::historyReadDone, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo));
}
}
void MainWidget::channelReadDone(PeerData *peer, const MTPBool &result) {
readRequestDone(peer);
}
void MainWidget::historyReadDone(PeerData *peer, const MTPmessages_AffectedMessages &result) {
messagesAffected(peer, result);
readRequestDone(peer);
}
bool MainWidget::readRequestFail(PeerData *peer, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
readRequestDone(peer);
return false;
}
void MainWidget::readRequestDone(PeerData *peer) {
_readRequests.remove(peer);
ReadRequestsPending::iterator i = _readRequestsPending.find(peer);
if (i != _readRequestsPending.cend()) {
sendReadRequest(peer, i.value());
_readRequestsPending.erase(i);
}
}
void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result) {
auto &d = result.c_messages_affectedMessages();
if (peer && peer->isChannel()) {
peer->asChannel()->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
} else {
ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
}
if (auto h = App::historyLoaded(peer ? peer->id : 0)) {
@ -1809,6 +1774,12 @@ void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMess
}
}
void MainWidget::messagesContentsRead(
const MTPmessages_AffectedMessages &result) {
const auto &data = result.c_messages_affectedMessages();
ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
}
void MainWidget::handleAudioUpdate(const AudioMsgId &audioId) {
using State = Media::Player::State;
auto state = Media::Player::mixer()->currentState(audioId.type());
@ -2063,31 +2034,37 @@ void MainWidget::mediaMarkRead(not_null<DocumentData*> data) {
auto &items = App::documentItems();
auto i = items.constFind(data);
if (i != items.cend()) {
mediaMarkRead(i.value());
mediaMarkRead({ i.value().begin(), i.value().end() });
}
}
void MainWidget::mediaMarkRead(const HistoryItemsMap &items) {
void MainWidget::mediaMarkRead(
const base::flat_set<not_null<HistoryItem*>> &items) {
QVector<MTPint> markedIds;
QMap<ChannelData*, QVector<MTPint>> channelMarkedIds;
base::flat_map<not_null<ChannelData*>, QVector<MTPint>> channelMarkedIds;
markedIds.reserve(items.size());
for_const (auto item, items) {
if ((!item->out() || item->mentionsMe()) && item->isMediaUnread()) {
item->markMediaRead();
if (item->id > 0) {
if (auto channel = item->history()->peer->asChannel()) {
channelMarkedIds[channel].push_back(MTP_int(item->id));
} else {
markedIds.push_back(MTP_int(item->id));
}
for (const auto item : items) {
if (!item->isMediaUnread() || (item->out() && !item->mentionsMe())) {
continue;
}
item->markMediaRead();
if (item->id > 0) {
if (const auto channel = item->history()->peer->asChannel()) {
channelMarkedIds[channel].push_back(MTP_int(item->id));
} else {
markedIds.push_back(MTP_int(item->id));
}
}
}
if (!markedIds.isEmpty()) {
MTP::send(MTPmessages_ReadMessageContents(MTP_vector<MTPint>(markedIds)), rpcDone(&MainWidget::messagesAffected, (PeerData*)0));
MTP::send(
MTPmessages_ReadMessageContents(MTP_vector<MTPint>(markedIds)),
rpcDone(&MainWidget::messagesContentsRead));
}
for (auto i = channelMarkedIds.cbegin(), e = channelMarkedIds.cend(); i != e; ++i) {
MTP::send(MTPchannels_ReadMessageContents(i.key()->inputChannel, MTP_vector<MTPint>(i.value())));
for (const auto &channelIds : channelMarkedIds) {
MTP::send(MTPchannels_ReadMessageContents(
channelIds.first->inputChannel,
MTP_vector<MTPint>(channelIds.second)));
}
}
@ -2095,10 +2072,16 @@ void MainWidget::mediaMarkRead(not_null<HistoryItem*> item) {
if ((!item->out() || item->mentionsMe()) && item->isMediaUnread()) {
item->markMediaRead();
if (item->id > 0) {
if (auto channel = item->history()->peer->asChannel()) {
MTP::send(MTPchannels_ReadMessageContents(channel->inputChannel, MTP_vector<MTPint>(1, MTP_int(item->id))));
const auto ids = MTP_vector<MTPint>(1, MTP_int(item->id));
if (const auto channel = item->history()->peer->asChannel()) {
MTP::send(
MTPchannels_ReadMessageContents(
channel->inputChannel,
ids));
} else {
MTP::send(MTPmessages_ReadMessageContents(MTP_vector<MTPint>(1, MTP_int(item->id))), rpcDone(&MainWidget::messagesAffected, (PeerData*)0));
MTP::send(
MTPmessages_ReadMessageContents(ids),
rpcDone(&MainWidget::messagesContentsRead));
}
}
}
@ -3115,7 +3098,9 @@ void MainWidget::newUnreadMsg(History *history, HistoryItem *item) {
}
void MainWidget::markActiveHistoryAsRead() {
_history->historyWasRead(ReadServerHistoryChecks::OnlyIfUnread);
if (const auto activeHistory = _history->history()) {
Auth().api().readServerHistory(activeHistory);
}
}
void MainWidget::showAnimated(const QPixmap &bgAnimCache, bool back) {

View File

@ -21,7 +21,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "storage/localimageloader.h"
#include "history/history_common.h"
#include "core/single_timer.h"
#include "base/weak_ptr.h"
#include "ui/rp_widget.h"
@ -81,6 +80,13 @@ class ItemBase;
} // namespace Layout
} // namespace InlineBots
enum class DragState {
None = 0x00,
Files = 0x01,
PhotoFiles = 0x02,
Image = 0x03,
};
class MainWidget : public Ui::RpWidget, public RPCSender, private base::Subscriber {
Q_OBJECT
@ -182,7 +188,6 @@ public:
void showSendPathsLayer();
void deleteLayer(int selectedCount = 0); // 0 - context item
void cancelUploadLayer();
void shareContactLayer(UserData *contact);
void shareUrlLayer(const QString &url, const QString &text);
void inlineSwitchLayer(const QString &botAndQuery);
void hiderLayer(object_ptr<HistoryHider> h);
@ -194,7 +199,6 @@ public:
const QString &url,
const QString &text);
bool onInlineSwitchChosen(const PeerId &peer, const QString &botAndQuery);
void onShareContact(const PeerId &peer, UserData *contact);
bool onSendPaths(const PeerId &peer);
void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data);
bool selectingPeer(bool withConfirm = false) const;
@ -208,7 +212,10 @@ public:
bool leaveChatFailed(PeerData *peer, const RPCError &e);
void deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates);
void deleteMessages(PeerData *peer, const QVector<MTPint> &ids, bool forEveryone);
void deleteMessages(
not_null<PeerData*> peer,
const QVector<MTPint> &ids,
bool forEveryone);
void deletedContact(UserData *user, const MTPcontacts_Link &result);
void deleteConversation(PeerData *peer, bool deleteHistory = true);
void deleteAndExit(ChatData *chat);
@ -243,7 +250,10 @@ public:
Dialogs::IndexedList *contactsNoDialogsList();
struct MessageToSend {
History *history = nullptr;
MessageToSend(not_null<History*> history) : history(history) {
}
not_null<History*> history;
TextWithTags textWithTags;
MsgId replyTo = 0;
bool silent = false;
@ -253,7 +263,6 @@ public:
void sendMessage(const MessageToSend &message);
void saveRecentHashtags(const QString &text);
void readServerHistory(History *history, ReadServerHistoryChecks checks = ReadServerHistoryChecks::OnlyIfUnread);
void unreadCountChanged(History *history);
TimeMs highlightStartTime(not_null<const HistoryItem*> item) const;
@ -295,7 +304,7 @@ public:
void finishForwarding(History *history, bool silent); // send them
void mediaMarkRead(not_null<DocumentData*> data);
void mediaMarkRead(const HistoryItemsMap &items);
void mediaMarkRead(const base::flat_set<not_null<HistoryItem*>> &items);
void mediaMarkRead(not_null<HistoryItem*> item);
void webPageUpdated(WebPageData *page);
@ -458,13 +467,10 @@ private:
void destroyCallTopBar();
void callTopBarHeightUpdated(int callTopBarHeight);
void sendReadRequest(PeerData *peer, MsgId upTo);
void channelReadDone(PeerData *peer, const MTPBool &result);
void historyReadDone(PeerData *peer, const MTPmessages_AffectedMessages &result);
bool readRequestFail(PeerData *peer, const RPCError &error);
void readRequestDone(PeerData *peer);
void messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result);
void messagesAffected(
not_null<PeerData*> peer,
const MTPmessages_AffectedMessages &result);
void messagesContentsRead(const MTPmessages_AffectedMessages &result);
void overviewLoaded(
std::pair<not_null<History*>, MsgId> historyAndStartMsgId,
const MTPmessages_Messages &result,
@ -640,11 +646,6 @@ private:
base::flat_set<not_null<PeerData*>> updateNotifySettingPeers;
SingleTimer updateNotifySettingTimer;
typedef QMap<PeerData*, QPair<mtpRequestId, MsgId> > ReadRequests;
ReadRequests _readRequests;
typedef QMap<PeerData*, MsgId> ReadRequestsPending;
ReadRequestsPending _readRequestsPending;
typedef QMap<PeerData*, mtpRequestId> OverviewsPreload;
OverviewsPreload _overviewPreload[OverviewCount], _overviewLoad[OverviewCount];

View File

@ -218,7 +218,7 @@ public:
setToDC(dcId);
return *this;
}
[[nodiscard]] SpecificRequestBuilder &canWait(TimeMs ms) noexcept {
[[nodiscard]] SpecificRequestBuilder &afterDelay(TimeMs ms) noexcept {
setCanWait(ms);
return *this;
}
@ -246,7 +246,7 @@ public:
setFailSkipPolicy(FailSkipPolicy::HandleAll);
return *this;
}
[[nodiscard]] SpecificRequestBuilder &after(mtpRequestId requestId) noexcept {
[[nodiscard]] SpecificRequestBuilder &afterRequest(mtpRequestId requestId) noexcept {
setAfter(requestId);
return *this;
}

View File

@ -417,13 +417,15 @@ void Manager::notificationActivated(PeerId peerId, MsgId msgId) {
onAfterNotificationActivated(peerId, msgId);
}
void Manager::notificationReplied(PeerId peerId, MsgId msgId, const QString &reply) {
void Manager::notificationReplied(
PeerId peerId,
MsgId msgId,
const QString &reply) {
if (!peerId) return;
auto history = App::history(peerId);
MainWidget::MessageToSend message;
message.history = history;
auto message = MainWidget::MessageToSend(history);
message.textWithTags = { reply, TextWithTags::Tags() };
message.replyTo = (msgId > 0 && !history->peer->isUser()) ? msgId : 0;
message.silent = false;

View File

@ -419,17 +419,20 @@ void PeerMenuAddContact(not_null<UserData*> user) {
}
void PeerMenuShareContactBox(not_null<UserData*> user) {
auto callback = [user](not_null<PeerData*> peer) {
const auto weak = std::make_shared<QPointer<PeerListBox>>();
auto callback = [=](not_null<PeerData*> peer) {
if (!peer->canWrite()) {
Ui::show(Box<InformBox>(
lang(lng_forward_share_cant)),
LayerOption::KeepOther);
return;
} else if (peer->isSelf()) {
App::main()->onShareContact(
peer->id,
user);
auto options = ApiWrap::SendOptions(App::history(peer));
Auth().api().shareContact(user, options);
Ui::Toast::Show(lang(lng_share_done));
if (auto strong = *weak) {
strong->closeBox();
}
return;
}
auto recipient = peer->isUser()
@ -439,13 +442,13 @@ void PeerMenuShareContactBox(not_null<UserData*> user) {
lng_forward_share_contact(lt_recipient, recipient),
lang(lng_forward_send),
[peer, user] {
App::main()->onShareContact(
peer->id,
user);
Ui::hideLayer();
const auto history = App::history(peer);
Ui::showPeerHistory(history, ShowAtTheEndMsgId);
auto options = ApiWrap::SendOptions(history);
Auth().api().shareContact(user, options);
}), LayerOption::KeepOther);
};
Ui::show(Box<PeerListBox>(
*weak = Ui::show(Box<PeerListBox>(
std::make_unique<ChooseRecipientBoxController>(std::move(callback)),
[](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_cancel), [box] {
@ -457,7 +460,7 @@ void PeerMenuShareContactBox(not_null<UserData*> user) {
void ShowForwardMessagesBox(
MessageIdsList &&items,
base::lambda_once<void()> &&successCallback) {
auto weak = std::make_shared<QPointer<PeerListBox>>();
const auto weak = std::make_shared<QPointer<PeerListBox>>();
auto callback = [
ids = std::move(items),
callback = std::move(successCallback),

View File

@ -203,7 +203,6 @@
<(src_loc)/history/history_admin_log_item.h
<(src_loc)/history/history_admin_log_section.cpp
<(src_loc)/history/history_admin_log_section.h
<(src_loc)/history/history_common.h
<(src_loc)/history/history_drag_area.cpp
<(src_loc)/history/history_drag_area.h
<(src_loc)/history/history_item.cpp