diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 022c51499..49e8e596a 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -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 peer) { int ApiWrap::applyAffectedHistory( not_null 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 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(ids))).done([this](const MTPmessages_Messages &result, mtpRequestId requestId) { gotWebPages(nullptr, result, requestId); - }).after(kSmallDelayMs).send(); + }).afterDelay(kSmallDelayMs).send(); } QVector 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(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 chat) { if (error.type() == qstr("USER_RESTRICTED")) { Ui::show(Box(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 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(); + 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( + 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(lng_error_public_groups_denied( + lt_more_info, + link))); + } + }).afterRequest( + history->sendRequestId + ).send(); + + App::historyRegRandom(randomId, newId); +} + +void ApiWrap::readServerHistory(not_null history) { + if (history->unreadCount()) { + readServerHistoryForce(history); + } +} + +void ApiWrap::readServerHistoryForce(not_null 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 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; diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index afdb77350..d758e54b6 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -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 sendActions() const { + return _sendActions.events(); + } + void sendAction(const SendOptions &options); void forwardMessages( HistoryItemsList &&items, const SendOptions &options, base::lambda_once &&successCallback = nullptr); + void shareContact( + const QString &phone, + const QString &firstName, + const QString &lastName, + const SendOptions &options); + void shareContact(not_null user, const SendOptions &options); + void readServerHistory(not_null history); + void readServerHistoryForce(not_null history); ~ApiWrap(); @@ -245,10 +257,6 @@ private: const QDate &date, Callback &&callback); - int applyAffectedHistory( - not_null peer, - const MTPmessages_AffectedHistory &result); - void sharedMediaDone( not_null 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 peer, MsgId upTo); + int applyAffectedHistory( + not_null peer, + const MTPmessages_AffectedHistory &result); + void applyAffectedMessages(const MTPmessages_AffectedMessages &result); + void applyAffectedMessages( + not_null peer, + const MTPmessages_AffectedMessages &result); + not_null _session; mtpRequestId _changelogSubscription = 0; @@ -339,6 +363,20 @@ private: base::flat_map, mtpRequestId> _userPhotosRequests; + rpl::event_stream _sendActions; + + struct ReadRequest { + ReadRequest(mtpRequestId requestId, MsgId upTo) + : requestId(requestId) + , upTo(upTo) { + } + + mtpRequestId requestId = 0; + MsgId upTo = 0; + }; + base::flat_map, ReadRequest> _readRequests; + base::flat_map, MsgId> _readRequestsPending; + base::Observable _fullPeerUpdated; rpl::event_stream _stickerSetInstalled; diff --git a/Telegram/SourceFiles/base/flat_map.h b/Telegram/SourceFiles/base/flat_map.h index bde096b92..5b1749767 100644 --- a/Telegram/SourceFiles/base/flat_map.h +++ b/Telegram/SourceFiles/base/flat_map.h @@ -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]; } diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index bfebcbca6..3fefbea0a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -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(); } diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 81dc39fa6..f92e6a6ef 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -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(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(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; diff --git a/Telegram/SourceFiles/history/history_common.h b/Telegram/SourceFiles/history/history_common.h deleted file mode 100644 index e82fe895d..000000000 --- a/Telegram/SourceFiles/history/history_common.h +++ /dev/null @@ -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, -}; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 02d51b1ac..1307a8c4f 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -395,7 +395,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { HistoryLayout::paintEmpty(p, width(), height()); } if (!noHistoryDisplayed) { - auto readMentions = HistoryItemsMap(); + auto readMentions = base::flat_set>(); adjustCurrent(clip.top()); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index dde26c33f..5b5f0834c 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -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(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 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(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) { + 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(); - 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 &urls(d->urls()); - if (urls.isEmpty()) return DragStateNone; + if (urls.isEmpty()) return DragState::None; bool allAreSmallImages = true; for (QList::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 box, const QString box->setConfirmedCallback(base::lambda_guarded(this, [this, withComment, sendCallback = std::move(callback)](const QStringList &files, const QImage &image, std::unique_ptr 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 information, SendMediaType type, QString caption) { +void HistoryWidget::uploadFilesAfterConfirmation( + const QStringList &files, + const QByteArray &content, + const QImage &image, + std::unique_ptr 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(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(); 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(); 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(); 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); } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 0b8d2b57a..eae74c963 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -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); 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 _inlineResults = { nullptr }; object_ptr _tabbedPanel; QPointer _tabbedSelector; - DragState _attachDrag = DragStateNone; + DragState _attachDrag = DragState::None; object_ptr _attachDragDocument, _attachDragPhoto; object_ptr _emojiSuggestions = { nullptr }; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 1825583d9..939de269f 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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(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 &ids, bool forEveryone) { - if (peer->isChannel()) { - MTP::send(MTPchannels_DeleteMessages(peer->asChannel()->inputChannel, MTP_vector(ids)), rpcDone(&MainWidget::messagesAffected, peer)); +void MainWidget::deleteMessages( + not_null peer, + const QVector &ids, + bool forEveryone) { + if (const auto channel = peer->asChannel()) { + MTP::send( + MTPchannels_DeleteMessages( + channel->inputChannel, + MTP_vector(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(ids)), rpcDone(&MainWidget::messagesAffected, peer)); + MTP::send( + MTPmessages_DeleteMessages( + MTP_flags(flags), + MTP_vector(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(); @@ -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 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 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> &items) { QVector markedIds; - QMap> channelMarkedIds; + base::flat_map, QVector> 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(markedIds)), rpcDone(&MainWidget::messagesAffected, (PeerData*)0)); + MTP::send( + MTPmessages_ReadMessageContents(MTP_vector(markedIds)), + rpcDone(&MainWidget::messagesContentsRead)); } - for (auto i = channelMarkedIds.cbegin(), e = channelMarkedIds.cend(); i != e; ++i) { - MTP::send(MTPchannels_ReadMessageContents(i.key()->inputChannel, MTP_vector(i.value()))); + for (const auto &channelIds : channelMarkedIds) { + MTP::send(MTPchannels_ReadMessageContents( + channelIds.first->inputChannel, + MTP_vector(channelIds.second))); } } @@ -2095,10 +2072,16 @@ void MainWidget::mediaMarkRead(not_null 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(1, MTP_int(item->id)))); + const auto ids = MTP_vector(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(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) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index c3e2296c5..645581160 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -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 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 &ids, bool forEveryone); + void deleteMessages( + not_null peer, + const QVector &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) { + } + + not_null 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 item) const; @@ -295,7 +304,7 @@ public: void finishForwarding(History *history, bool silent); // send them void mediaMarkRead(not_null data); - void mediaMarkRead(const HistoryItemsMap &items); + void mediaMarkRead(const base::flat_set> &items); void mediaMarkRead(not_null 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 peer, + const MTPmessages_AffectedMessages &result); + void messagesContentsRead(const MTPmessages_AffectedMessages &result); void overviewLoaded( std::pair, MsgId> historyAndStartMsgId, const MTPmessages_Messages &result, @@ -640,11 +646,6 @@ private: base::flat_set> updateNotifySettingPeers; SingleTimer updateNotifySettingTimer; - typedef QMap > ReadRequests; - ReadRequests _readRequests; - typedef QMap ReadRequestsPending; - ReadRequestsPending _readRequestsPending; - typedef QMap OverviewsPreload; OverviewsPreload _overviewPreload[OverviewCount], _overviewLoad[OverviewCount]; diff --git a/Telegram/SourceFiles/mtproto/sender.h b/Telegram/SourceFiles/mtproto/sender.h index daa298dcf..7e0fda4c3 100644 --- a/Telegram/SourceFiles/mtproto/sender.h +++ b/Telegram/SourceFiles/mtproto/sender.h @@ -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; } diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index 5bea6694a..cdfb686c6 100644 --- a/Telegram/SourceFiles/window/notifications_manager.cpp +++ b/Telegram/SourceFiles/window/notifications_manager.cpp @@ -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; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 6c25c7d1e..6a583c639 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -419,17 +419,20 @@ void PeerMenuAddContact(not_null user) { } void PeerMenuShareContactBox(not_null user) { - auto callback = [user](not_null peer) { + const auto weak = std::make_shared>(); + auto callback = [=](not_null peer) { if (!peer->canWrite()) { Ui::show(Box( 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 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( + *weak = Ui::show(Box( std::make_unique(std::move(callback)), [](not_null box) { box->addButton(langFactory(lng_cancel), [box] { @@ -457,7 +460,7 @@ void PeerMenuShareContactBox(not_null user) { void ShowForwardMessagesBox( MessageIdsList &&items, base::lambda_once &&successCallback) { - auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto callback = [ ids = std::move(items), callback = std::move(successCallback), diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index faeb62ff0..528826e47 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -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