From e41e68b8b3413314d414b4ed866698aba5cb1fbb Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 12 Sep 2015 14:59:50 +0300 Subject: [PATCH] enabled forwarding from/to channel, replies and webpages loading in channels, scheme updated --- Telegram/SourceFiles/apiwrap.cpp | 193 +++++++++++++------ Telegram/SourceFiles/apiwrap.h | 11 +- Telegram/SourceFiles/dialogswidget.cpp | 6 +- Telegram/SourceFiles/history.cpp | 20 +- Telegram/SourceFiles/historywidget.cpp | 24 ++- Telegram/SourceFiles/mainwidget.cpp | 69 +++---- Telegram/SourceFiles/mtproto/mtpConnection.h | 4 + Telegram/SourceFiles/mtproto/mtpScheme.cpp | 55 ++++-- Telegram/SourceFiles/mtproto/mtpScheme.h | 116 ++++++++++- Telegram/SourceFiles/mtproto/scheme.tl | 6 +- Telegram/SourceFiles/overviewwidget.cpp | 10 +- 11 files changed, 372 insertions(+), 142 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index aeb5c22210..3a4f8c187e 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -38,17 +38,24 @@ void ApiWrap::init() { void ApiWrap::itemRemoved(HistoryItem *item) { if (HistoryReply *reply = item->toHistoryReply()) { - ReplyToRequests::iterator i = _replyToRequests.find(FullMsgId(reply->channelId(), reply->replyToId())); - if (i != _replyToRequests.cend()) { - for (QList::iterator j = i->replies.begin(); j != i->replies.end();) { - if ((*j) == reply) { - j = i->replies.erase(j); - } else { - ++j; + ChannelData *channel = reply->history()->peer->asChannel(); + ReplyToRequests *requests(replyToRequests(channel, true)); + if (requests) { + ReplyToRequests::iterator i = requests->find(reply->replyToId()); + if (i != requests->cend()) { + for (QList::iterator j = i->replies.begin(); j != i->replies.end();) { + if ((*j) == reply) { + j = i->replies.erase(j); + } else { + ++j; + } + } + if (i->replies.isEmpty()) { + requests->erase(i); } } - if (i->replies.isEmpty()) { - _replyToRequests.erase(i); + if (channel && requests->isEmpty()) { + _channelReplyToRequests.remove(channel); } } } @@ -56,52 +63,91 @@ void ApiWrap::itemRemoved(HistoryItem *item) { void ApiWrap::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) { if (HistoryReply *reply = oldItem->toHistoryReply()) { - ReplyToRequests::iterator i = _replyToRequests.find(FullMsgId(reply->channelId(), reply->replyToId())); - if (i != _replyToRequests.cend()) { - for (QList::iterator j = i->replies.begin(); j != i->replies.end();) { - if ((*j) == reply) { - if (HistoryReply *newReply = newItem->toHistoryReply()) { - *j = newReply; - ++j; + ChannelData *channel = reply->history()->peer->asChannel(); + ReplyToRequests *requests(replyToRequests(channel, true)); + if (requests) { + ReplyToRequests::iterator i = requests->find(reply->replyToId()); + if (i != requests->cend()) { + for (QList::iterator j = i->replies.begin(); j != i->replies.end();) { + if ((*j) == reply) { + if (HistoryReply *newReply = newItem->toHistoryReply()) { + *j = newReply; + ++j; + } else { + j = i->replies.erase(j); + } } else { - j = i->replies.erase(j); + ++j; } - } else { - ++j; + } + if (i->replies.isEmpty()) { + requests->erase(i); } } - if (i->replies.isEmpty()) { - _replyToRequests.erase(i); + if (channel && requests->isEmpty()) { + _channelReplyToRequests.remove(channel); } } } } -void ApiWrap::requestReplyTo(HistoryReply *reply, const FullMsgId &to) { - ReplyToRequest &req(_replyToRequests[to]); +void ApiWrap::requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id) { + ReplyToRequest &req(channel ? _channelReplyToRequests[channel][id] : _replyToRequests[id]); req.replies.append(reply); if (!req.req) _replyToTimer.start(1); } -void ApiWrap::resolveReplyTo() { - if (_replyToRequests.isEmpty()) return; - - QVector ids; - ids.reserve(_replyToRequests.size()); - for (ReplyToRequests::const_iterator i = _replyToRequests.cbegin(), e = _replyToRequests.cend(); i != e; ++i) { - if (!i.value().req) { - ids.push_back(MTP_int(i.key().msg)); // CHANNELS_TODO - } +ApiWrap::MessageIds ApiWrap::collectMessageIds(const ReplyToRequests &requests) { + MessageIds result; + result.reserve(requests.size()); + for (ReplyToRequests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) { + if (i.value().req > 0) continue; + result.push_back(MTP_int(i.key())); } + return result; +} + +ApiWrap::ReplyToRequests *ApiWrap::replyToRequests(ChannelData *channel, bool onlyExisting) { + if (channel) { + ChannelReplyToRequests::iterator i = _channelReplyToRequests.find(channel); + if (i == _channelReplyToRequests.cend()) { + if (onlyExisting) return 0; + i = _channelReplyToRequests.insert(channel, ReplyToRequests()); + } + return &i.value(); + } + return &_replyToRequests; +} + +void ApiWrap::resolveReplyTo() { + if (_replyToRequests.isEmpty() && _channelReplyToRequests.isEmpty()) return; + + MessageIds ids = collectMessageIds(_replyToRequests); if (!ids.isEmpty()) { - mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector(ids)), rpcDone(&ApiWrap::gotReplyTo)); - for (ReplyToRequests::iterator i = _replyToRequests.begin(), e = _replyToRequests.end(); i != e; ++i) { + mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector(ids)), rpcDone(&ApiWrap::gotReplyTo, (ChannelData*)0), RPCFailHandlerPtr(), 0, 5); + for (ReplyToRequests::iterator i = _replyToRequests.begin(); i != _replyToRequests.cend(); ++i) { + if (i.value().req > 0) continue; i.value().req = req; } } + for (ChannelReplyToRequests::iterator j = _channelReplyToRequests.begin(); j != _channelReplyToRequests.cend();) { + if (j->isEmpty()) { + j = _channelReplyToRequests.erase(j); + continue; + } + MessageIds ids = collectMessageIds(j.value()); + if (!ids.isEmpty()) { + mtpRequestId req = MTP::send(MTPmessages_GetChannelMessages(j.key()->input, MTP_vector(ids)), rpcDone(&ApiWrap::gotReplyTo, j.key()), RPCFailHandlerPtr(), 0, 5); + for (ReplyToRequests::iterator i = j->begin(); i != j->cend(); ++i) { + if (i.value().req > 0) continue; + i.value().req = req; + } + } + ++j; + } } -void ApiWrap::gotReplyTo(const MTPmessages_Messages &msgs, mtpRequestId req) { +void ApiWrap::gotReplyTo(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId req) { switch (msgs.type()) { case mtpc_messages_messages: { const MTPDmessages_messages &d(msgs.c_messages_messages()); @@ -124,18 +170,24 @@ void ApiWrap::gotReplyTo(const MTPmessages_Messages &msgs, mtpRequestId req) { App::feedMsgs(d.vmessages, -1); } break; } - for (ReplyToRequests::iterator i = _replyToRequests.begin(); i != _replyToRequests.cend();) { - if (i.value().req == req) { - for (QList::const_iterator j = i.value().replies.cbegin(), e = i.value().replies.cend(); j != e; ++j) { - if (*j) { - (*j)->updateReplyTo(true); - } else { - App::main()->updateReplyTo(); + ReplyToRequests *requests(replyToRequests(channel, true)); + if (requests) { + for (ReplyToRequests::iterator i = requests->begin(); i != requests->cend();) { + if (i.value().req == req) { + for (QList::const_iterator j = i.value().replies.cbegin(), e = i.value().replies.cend(); j != e; ++j) { + if (*j) { + (*j)->updateReplyTo(true); + } else { + App::main()->updateReplyTo(); + } } + i = requests->erase(i); + } else { + ++i; } - i = _replyToRequests.erase(i); - } else { - ++i; + } + if (channel && requests->isEmpty()) { + _channelReplyToRequests.remove(channel); } } } @@ -476,30 +528,63 @@ void ApiWrap::clearWebPageRequests() { } void ApiWrap::resolveWebPages() { - QVector ids; + MessageIds ids; // temp_req_id = -1 + typedef QPair IndexAndMessageIds; + typedef QMap MessageIdsByChannel; + MessageIdsByChannel idsByChannel; // temp_req_id = -index - 2 + const WebPageItems &items(App::webPageItems()); ids.reserve(_webPagesPending.size()); int32 t = unixtime(), m = INT_MAX; - for (WebPagesPending::const_iterator i = _webPagesPending.cbegin(), e = _webPagesPending.cend(); i != e; ++i) { - if (i.value()) continue; + for (WebPagesPending::iterator i = _webPagesPending.begin(); i != _webPagesPending.cend(); ++i) { + if (i.value() > 0) continue; if (i.key()->pendingTill <= t) { WebPageItems::const_iterator j = items.constFind(i.key()); if (j != items.cend() && !j.value().isEmpty()) { - ids.push_back(MTP_int(j.value().begin().key()->id)); + for (HistoryItemsMap::const_iterator it = j.value().cbegin(); it != j.value().cend(); ++it) { + HistoryItem *item = j.value().begin().key(); + if (item->id > 0) { + if (item->channelId() == NoChannel) { + ids.push_back(MTP_int(item->id)); + i.value() = -1; + } else { + ChannelData *channel = item->history()->peer->asChannel(); + MessageIdsByChannel::iterator channelMap = idsByChannel.find(channel); + if (channelMap == idsByChannel.cend()) { + channelMap = idsByChannel.insert(channel, IndexAndMessageIds(idsByChannel.size(), MessageIds(1, MTP_int(item->id)))); + } else { + channelMap.value().second.push_back(MTP_int(item->id)); + } + i.value() = -channelMap.value().first - 2; + } + break; + } + } } } else { m = qMin(m, i.key()->pendingTill - t); } } - if (!ids.isEmpty()) { - mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector(ids)), rpcDone(&ApiWrap::gotWebPages)); + + mtpRequestId req = ids.isEmpty() ? 0 : MTP::send(MTPmessages_GetMessages(MTP_vector(ids)), rpcDone(&ApiWrap::gotWebPages), RPCFailHandlerPtr(), 0, 5); + typedef QVector RequestIds; + RequestIds reqsByIndex(idsByChannel.size(), 0); + for (MessageIdsByChannel::const_iterator i = idsByChannel.cbegin(), e = idsByChannel.cend(); i != e; ++i) { + reqsByIndex[i.value().first] = MTP::send(MTPmessages_GetChannelMessages(i.key()->input, MTP_vector(i.value().second)), rpcDone(&ApiWrap::gotWebPages), RPCFailHandlerPtr(), 0, 5); + } + if (req || !reqsByIndex.isEmpty()) { for (WebPagesPending::iterator i = _webPagesPending.begin(); i != _webPagesPending.cend(); ++i) { - if (i.value()) continue; - if (i.key()->pendingTill <= t) { - i.value() = req; + if (i.value() > 0) continue; + if (i.value() < 0) { + if (i.value() == -1) { + i.value() = req; + } else { + i.value() = reqsByIndex[-i.value() - 2]; + } } } } + if (m < INT_MAX) _webPagesTimer.start(m * 1000); } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index ca40ea6aef..b51699ed74 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -28,7 +28,7 @@ public: void itemRemoved(HistoryItem *item); void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem); - void requestReplyTo(HistoryReply *reply, const FullMsgId &to); + void requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id); void requestFullPeer(PeerData *peer); void requestPeer(PeerData *peer); @@ -54,16 +54,21 @@ public slots: private: - void gotReplyTo(const MTPmessages_Messages &result, mtpRequestId req); + void gotReplyTo(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req); struct ReplyToRequest { ReplyToRequest() : req(0) { } mtpRequestId req; QList replies; }; - typedef QMap ReplyToRequests; + typedef QMap ReplyToRequests; ReplyToRequests _replyToRequests; + typedef QMap ChannelReplyToRequests; + ChannelReplyToRequests _channelReplyToRequests; SingleTimer _replyToTimer; + typedef QVector MessageIds; + MessageIds collectMessageIds(const ReplyToRequests &requests); + ReplyToRequests *replyToRequests(ChannelData *channel, bool onlyExisting = false); void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result); void gotUserFull(PeerData *peer, const MTPUserFull &result); diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 5607d9f059..8c3eabc681 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -1741,7 +1741,8 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { } else if (_searchQuery != q) { _searchQuery = q; _searchFull = false; - _searchRequest = MTP::send(MTPmessages_Search(_searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed)); + int32 flags = (_searchInPeer && _searchInPeer->isChannel()) ? MTPmessages_Search_flag_only_important : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed)); _searchQueries.insert(_searchRequest, _searchQuery); } if (!_searchInPeer && q.size() >= MinUsernameLength) { @@ -1787,7 +1788,8 @@ void DialogsWidget::searchMessages(const QString &query) { void DialogsWidget::onSearchMore(MsgId minMsgId) { if (!_searchRequest && !_searchFull) { - _searchRequest = MTP::send(MTPmessages_Search(_searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed)); + int32 flags = (_searchInPeer && _searchInPeer->isChannel()) ? MTPmessages_Search_flag_only_important : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed)); if (!minMsgId) { _searchQueries.insert(_searchRequest, _searchQuery); } diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 78515cc54a..02a2a72998 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -732,7 +732,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, boo if (badMedia) { result = new HistoryServiceMsg(this, block, m.vid.v, date(m.vdate), lang((badMedia == 2) ? lng_message_empty : lng_media_unsupported), m.vflags.v, 0, m.has_from_id() ? m.vfrom_id.v : 0); } else { - if ((m.has_fwd_date() && m.vfwd_date.v > 0) || (m.has_fwd_from_id() && m.vfwd_from_id.v != 0)) { + if ((m.has_fwd_date() && m.vfwd_date.v > 0) || (m.has_fwd_from_id() && peerFromMTP(m.vfwd_from_id) != 0)) { result = new HistoryForwarded(this, block, m); } else if (m.has_reply_to_msg_id() && m.vreply_to_msg_id.v > 0) { result = new HistoryReply(this, block, m); @@ -5850,7 +5850,7 @@ HistoryMessage::~HistoryMessage() { HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const MTPDmessage &msg) : HistoryMessage(history, block, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0, textClean(qs(msg.vmessage)), msg.has_entities() ? linksFromMTP(msg.ventities.c_vector().v) : LinksInText(), msg.has_media() ? (&msg.vmedia) : 0) , fwdDate(::date(msg.vfwd_date)) -, fwdFrom(App::user(msg.vfwd_from_id.v)) +, fwdFrom(App::peer(peerFromMTP(msg.vfwd_from_id))) , fwdFromVersion(fwdFrom->nameVersion) , fromWidth(st::msgServiceFont->m.width(lang(lng_forwarded_from)) + st::msgServiceFont->spacew) { @@ -5921,7 +5921,7 @@ void HistoryForwarded::drawMessageText(QPainter &p, const QRect &trect, uint32 s int32 HistoryForwarded::resize(int32 width) { HistoryMessage::resize(width); - _height += st::msgServiceNameFont->height; + if (!justMedia()) _height += st::msgServiceNameFont->height; return _height; } @@ -6050,7 +6050,7 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, const MTPDmess , _maxReplyWidth(0) { if (!updateReplyTo()) { - App::api()->requestReplyTo(this, FullMsgId(history->channelId(), replyToMsgId)); + App::api()->requestReplyTo(this, history->peer->asChannel(), replyToMsgId); } } @@ -6061,7 +6061,7 @@ HistoryReply::HistoryReply(History *history, HistoryBlock *block, MsgId msgId, i , _maxReplyWidth(0) { if (!updateReplyTo()) { - App::api()->requestReplyTo(this, FullMsgId(history->channelId(), replyToMsgId)); + App::api()->requestReplyTo(this, history->peer->asChannel(), replyToMsgId); } } @@ -6223,7 +6223,7 @@ void HistoryReply::drawMessageText(QPainter &p, const QRect &trect, uint32 selec int32 HistoryReply::resize(int32 width) { HistoryMessage::resize(width); - _height += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); + if (!justMedia()) _height += st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); return _height; } @@ -6366,8 +6366,8 @@ void HistoryServiceMsg::setMessageByAction(const MTPmessageAction &action) { second = TextLinkPtr(new PeerLink(u)); text = lng_action_add_user(lt_from, from, lt_user, textcmdLink(2, u->name)); if (d.vuser_id.v == MTP::authedId() && unread()) { - if (history()->peer->chat && !history()->peer->asChat()->inviterForSpamReport && !_from->chat) { - history()->peer->asChat()->inviterForSpamReport = App::userFromPeer(_from->id); + if (history()->peer->isChat() && !history()->peer->asChat()->inviterForSpamReport && _from->isUser()) { + history()->peer->asChat()->inviterForSpamReport = peerToUser(_from->id); } } } @@ -6388,8 +6388,8 @@ void HistoryServiceMsg::setMessageByAction(const MTPmessageAction &action) { const MTPDmessageActionChatCreate &d(action.c_messageActionChatCreate()); text = lng_action_created_chat(lt_from, from, lt_title, textClean(qs(d.vtitle))); if (unread()) { - if (history()->peer->chat && !history()->peer->asChat()->inviterForSpamReport && !_from->chat && App::userFromPeer(_from->id) != MTP::authedId()) { - history()->peer->asChat()->inviterForSpamReport = App::userFromPeer(_from->id); + if (history()->peer->isChat() && !history()->peer->asChat()->inviterForSpamReport && _from->isUser() && peerToUser(_from->id) != MTP::authedId()) { + history()->peer->asChat()->inviterForSpamReport = peerToUser(_from->id); } } } break; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 211cef0688..ee5715a252 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -539,7 +539,7 @@ void HistoryList::onDragExec() { mimeData->setText(sel); if (!urls.isEmpty()) mimeData->setUrls(urls); - if (uponSelected && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode() && !hist->peer->isChannel()) { + if (uponSelected && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode()) { mimeData->setData(qsl("application/x-td-forward-selected"), "1"); } drag->setMimeData(mimeData); @@ -553,18 +553,16 @@ void HistoryList::onDragExec() { lnkAudio = (lnkType == qstr("AudioOpenLink")), lnkDocument = (lnkType == qstr("DocumentOpenLink")), lnkContact = (lnkType == qstr("PeerLink") && dynamic_cast(pressedLnkItem->getMedia())), - dragSticker = dynamic_cast(pressedItem ? pressedItem->getMedia() : 0) && !hist->peer->isChannel(), - dragByDate = (_dragCursorState == HistoryInDateCursorState) && !hist->peer->isChannel(); + dragSticker = dynamic_cast(pressedItem ? pressedItem->getMedia() : 0), + dragByDate = (_dragCursorState == HistoryInDateCursorState); if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact || dragSticker || dragByDate) { QDrag *drag = new QDrag(App::wnd()); QMimeData *mimeData = new QMimeData; - if (!hist->peer->isChannel()) { - if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact) { - mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); - } else { - mimeData->setData(qsl("application/x-td-forward-pressed"), "1"); - } + if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact) { + mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1"); + } else { + mimeData->setData(qsl("application/x-td-forward-pressed"), "1"); } if (lnkDocument) { QString already = static_cast(textlnkDown().data())->document()->already(true); @@ -813,7 +811,7 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->addAction(lang(lng_context_clear_selection), historyWidget, SLOT(onClearSelected())); } else if (App::hoveredLinkItem()) { if (isUponSelected != -2 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) { - if (dynamic_cast(App::hoveredLinkItem()) && App::hoveredLinkItem()->id > 0 && !hist->peer->isChannel()) { + if (dynamic_cast(App::hoveredLinkItem()) && App::hoveredLinkItem()->id > 0) { _menu->addAction(lang(lng_context_forward_msg), historyWidget, SLOT(forwardMessage()))->setEnabled(true); } _menu->addAction(lang(lng_context_delete_msg), historyWidget, SLOT(deleteMessage()))->setEnabled(true); @@ -825,7 +823,7 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } } else { // maybe cursor on some text history item? bool canDelete = (item && item->itemType() == HistoryItem::MsgType) && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned); - bool canForward = canDelete && (item->id > 0) && !item->serviceMsg() && !hist->peer->isChannel(); + bool canForward = canDelete && (item->id > 0) && !item->serviceMsg(); HistoryMessage *msg = dynamic_cast(item); HistoryServiceMsg *srv = dynamic_cast(item); @@ -2950,7 +2948,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) { } if (_replyToId) { updateReplyTo(); - if (!_replyTo) App::api()->requestReplyTo(0, FullMsgId(_channel, _replyToId)); + if (!_replyTo) App::api()->requestReplyTo(0, _peer->asChannel(), _replyToId); resizeEvent(0); } if (!_previewCancelled) { @@ -4068,7 +4066,7 @@ bool HistoryWidget::canSendMessages(PeerData *peer) { } bool HistoryWidget::readyToForward() { - return _canSendMessages && !_channel && App::main()->hasForwardingItems(); + return _canSendMessages && App::main()->hasForwardingItems(); } bool HistoryWidget::isBotStart() const { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 60c7404b41..d6f3847af4 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -322,11 +322,7 @@ void TopBarWidget::showAll() { if (!p && _selCount) { _clearSelection.show(); _delete.show(); - if (!_selPeer || _selPeer->isChannel()) { - _forward.hide(); - } else { - _forward.show(); - } + _forward.show(); _mediaType.hide(); } else { _clearSelection.hide(); @@ -433,7 +429,7 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { PeerData *p = App::peer(peer); - if (!peer || p->isChannel() || (p->isChat() && p->asChat()->forbidden) || (p->isUser() && p->asUser()->access == UserNoAccess)) { + if (!peer || (p->isChannel() && !p->asChannel()->adminned) || (p->isChat() && p->asChat()->forbidden) || (p->isUser() && p->asUser()->access == UserNoAccess)) { App::wnd()->showLayer(new ConfirmBox(lang(lng_forward_cant), true)); return false; } @@ -529,33 +525,33 @@ void MainWidget::cancelForwarding() { void MainWidget::finishForwarding(History *hist) { if (!hist) return; if (!_toForward.isEmpty()) { + bool genClientSideMessage = (_toForward.size() < 2); + PeerData *forwardFrom = _toForward.cbegin().value()->history()->peer; App::main()->readServerHistory(hist, false); - if (_toForward.size() < 2) { + + QVector ids; + QVector randomIds; + ids.reserve(_toForward.size()); + randomIds.reserve(_toForward.size()); + for (SelectedItemSet::const_iterator i = _toForward.cbegin(), e = _toForward.cend(); i != e; ++i) { uint64 randomId = MTP::nonce(); - FullMsgId newId(peerToChannel(hist->peer->id), clientMsgId()); - HistoryMessage *msg = static_cast(_toForward.cbegin().value()); - hist->addToBackForwarded(newId.msg, msg); - App::historyRegRandom(randomId, newId); - hist->sendRequestId = MTP::send(MTPmessages_ForwardMessage(hist->peer->input, MTP_int(_toForward.cbegin().key()), MTP_long(randomId)), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); - if (HistorySticker *sticker = dynamic_cast(msg->getMedia())) { - App::main()->incrementSticker(sticker->document()); + if (genClientSideMessage) { + FullMsgId newId(peerToChannel(hist->peer->id), clientMsgId()); + HistoryMessage *msg = static_cast(_toForward.cbegin().value()); + hist->addToBackForwarded(newId.msg, msg); + if (HistorySticker *sticker = dynamic_cast(msg->getMedia())) { + App::main()->incrementSticker(sticker->document()); + } + App::historyRegRandom(randomId, newId); } - } else { - QVector ids; - QVector randomIds; - ids.reserve(_toForward.size()); - randomIds.reserve(_toForward.size()); - for (SelectedItemSet::const_iterator i = _toForward.cbegin(), e = _toForward.cend(); i != e; ++i) { - uint64 randomId = MTP::nonce(); - //MsgId newId = clientMsgId(); - //hist->addToBackForwarded(newId, static_cast(i.value())); - //App::historyRegRandom(randomId, newId); - ids.push_back(MTP_int(i.key())); - randomIds.push_back(MTP_long(randomId)); - } - hist->sendRequestId = MTP::send(MTPmessages_ForwardMessages(hist->peer->input, MTP_vector(ids), MTP_vector(randomIds)), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + ids.push_back(MTP_int(i.key())); + randomIds.push_back(MTP_long(randomId)); } + int32 flags = hist->peer->isChannel() ? MTPmessages_ForwardMessages_flag_broadcast : 0; + hist->sendRequestId = MTP::send(MTPmessages_ForwardMessages(MTP_int(flags), forwardFrom->input, MTP_vector(ids), MTP_vector(randomIds), hist->peer->input), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + if (history.peer() == hist->peer) history.peerMessagesUpdated(); + cancelForwarding(); } @@ -1220,7 +1216,8 @@ void MainWidget::preloadOverviews(PeerData *peer) { MTPMessagesFilter filter = typeToMediaFilter(type); if (type == OverviewCount) break; - _overviewPreload[i].insert(peer, MTP::send(MTPmessages_Search(peer->input, MTP_string(""), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::overviewPreloaded, peer), rpcFail(&MainWidget::overviewFailed, peer), 0, (i == last) ? 0 : 10)); + int32 flags = peer->isChannel() ? MTPmessages_Search_flag_only_important : 0; + _overviewPreload[i].insert(peer, MTP::send(MTPmessages_Search(MTP_int(flags), peer->input, MTP_string(""), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::overviewPreloaded, peer), rpcFail(&MainWidget::overviewFailed, peer), 0, (i == last) ? 0 : 10)); } } } @@ -1395,7 +1392,8 @@ void MainWidget::loadMediaBack(PeerData *peer, MediaOverviewType type, bool many MTPMessagesFilter filter = typeToMediaFilter(type); if (type == OverviewCount) return; - _overviewLoad[type].insert(hist->peer, MTP::send(MTPmessages_Search(hist->peer->input, MTPstring(), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MainWidget::photosLoaded, hist))); + int32 flags = peer->isChannel() ? MTPmessages_Search_flag_only_important : 0; + _overviewLoad[type].insert(peer, MTP::send(MTPmessages_Search(MTP_int(flags), peer->input, MTPstring(), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MainWidget::photosLoaded, hist))); } void MainWidget::peerUsernameChanged(PeerData *peer) { @@ -1903,7 +1901,7 @@ void MainWidget::dialogsCancelled() { } void MainWidget::serviceNotification(const QString &msg, const MTPMessageMedia &media, bool unread) { - int32 flags = (unread ? MTPDmessage_flag_unread : 0) | MTPDmessage::flag_entities; + int32 flags = (unread ? MTPDmessage_flag_unread : 0) | MTPDmessage::flag_entities | MTPDmessage::flag_from_id; QString sendingText, leftText = msg; HistoryItem *item = 0; while (textSplit(sendingText, leftText, MaxMessageSize)) { @@ -3510,8 +3508,9 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) { _byPtsUpdates.insert(ptsKey(SkippedUpdates), updates); return; } - bool out = (d.vflags.v & MTPDmessage_flag_out); - HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint())); + int32 flags = d.vflags.v | MTPDmessage::flag_from_id; + bool out = (flags & MTPDmessage_flag_out); + HistoryItem *item = App::histories().addToBack(MTP_message(MTP_int(flags), d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint())); if (item) { history.peerMessagesUpdated(item->history()->peer->id); } @@ -3531,7 +3530,9 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) { _byPtsUpdates.insert(ptsKey(SkippedUpdates), updates); return; } - HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint())); + int32 flags = d.vflags.v | MTPDmessage::flag_from_id; + bool out = (flags & MTPDmessage_flag_out); + HistoryItem *item = App::histories().addToBack(MTP_message(MTP_int(flags), d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, d.has_entities() ? d.ventities : MTPnullEntities, MTPint())); if (item) { history.peerMessagesUpdated(item->history()->peer->id); } diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.h b/Telegram/SourceFiles/mtproto/mtpConnection.h index a6edd8aa94..c3dc8c2df9 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.h +++ b/Telegram/SourceFiles/mtproto/mtpConnection.h @@ -30,6 +30,8 @@ enum { MTPmessages_SendMessage_flag_skipWebPage = (1 << 1), MTPmessages_SendMessage_flag_broadcast = (1 << 4), + MTPmessages_ForwardMessages_flag_broadcast = (1 << 4), + MTPDdcOption_flag_ipv6 = (1 << 0), MTPDdcOption_flag_files = (1 << 1), @@ -59,6 +61,8 @@ enum { MTPDchannelMessagesFilter_flag_only_important = (1 << 0), MTPmessages_CreateChannel_flag_broadcast = (1 << 0), + + MTPmessages_Search_flag_only_important = (1 << 0), }; static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector(0)); diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index a701517103..13b21fb51c 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -2843,6 +2843,21 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_updateChannelMessageViews: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ updateChannelMessageViews"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" views: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_updates_state: if (stage) { to.add(",\n").addSpaces(lev); @@ -5747,6 +5762,20 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ contacts_exportCard }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + case mtpc_messages_getMessagesViews: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_getMessagesViews"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_contacts_search: if (stage) { to.add(",\n").addSpaces(lev); @@ -5813,14 +5842,15 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" q: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" filter: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" min_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" max_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" q: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" filter: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" min_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" max_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 6: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 7: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 8: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -6012,10 +6042,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("\n").addSpaces(lev); } switch (stage) { - case 0: to.add(" from_peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" random_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" to_peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" from_peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" random_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" to_peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index a583fc7490..04328bb9e5 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -259,6 +259,7 @@ enum { mtpc_updateNewChannelMessage = 0x62ba04d9, mtpc_updateReadChannelInbox = 0x87b87b7d, mtpc_updateDeleteChannelMessages = 0x11da3046, + mtpc_updateChannelMessageViews = 0xf3349b09, mtpc_updates_state = 0xa56c2a3e, mtpc_updates_differenceEmpty = 0x5d75a138, mtpc_updates_difference = 0xf49ca0, @@ -473,7 +474,7 @@ enum { mtpc_messages_getMessages = 0x4222fa74, mtpc_messages_getDialogs = 0x859b3d3c, mtpc_messages_getHistory = 0x8a8ec2da, - mtpc_messages_search = 0x7e9f2ab, + mtpc_messages_search = 0xd4569248, mtpc_messages_readHistory = 0xb04f2510, mtpc_messages_deleteHistory = 0xf4f8fb61, mtpc_messages_deleteMessages = 0xa5f18925, @@ -481,7 +482,7 @@ enum { mtpc_messages_setTyping = 0xa3825e50, mtpc_messages_sendMessage = 0xfa88427a, mtpc_messages_sendMedia = 0xc8f16791, - mtpc_messages_forwardMessages = 0xf9adea76, + mtpc_messages_forwardMessages = 0x708e0195, mtpc_messages_reportSpam = 0xcf1592db, mtpc_messages_getChats = 0x27ae65b, mtpc_messages_getFullChat = 0x36a4dfe, @@ -520,6 +521,7 @@ enum { mtpc_messages_deleteChannelMessages = 0x9995a84f, mtpc_messages_getChannelMessages = 0x5f46b265, mtpc_messages_incrementMessagesViews = 0x91ffd479, + mtpc_messages_getMessagesViews = 0x9abfbbe1, mtpc_messages_editChatAbout = 0x8a969b93, mtpc_messages_getChannelParticipants = 0x4a771976, mtpc_messages_checkChannelUsername = 0xe6d2d8f4, @@ -880,6 +882,7 @@ class MTPDupdateChannelGroup; class MTPDupdateNewChannelMessage; class MTPDupdateReadChannelInbox; class MTPDupdateDeleteChannelMessages; +class MTPDupdateChannelMessageViews; class MTPupdates_state; class MTPDupdates_state; @@ -5351,6 +5354,18 @@ public: return *(const MTPDupdateDeleteChannelMessages*)data; } + MTPDupdateChannelMessageViews &_updateChannelMessageViews() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateChannelMessageViews) throw mtpErrorWrongTypeId(_type, mtpc_updateChannelMessageViews); + split(); + return *(MTPDupdateChannelMessageViews*)data; + } + const MTPDupdateChannelMessageViews &c_updateChannelMessageViews() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateChannelMessageViews) throw mtpErrorWrongTypeId(_type, mtpc_updateChannelMessageViews); + return *(const MTPDupdateChannelMessageViews*)data; + } + uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -5393,6 +5408,7 @@ private: explicit MTPupdate(MTPDupdateNewChannelMessage *_data); explicit MTPupdate(MTPDupdateReadChannelInbox *_data); explicit MTPupdate(MTPDupdateDeleteChannelMessages *_data); + explicit MTPupdate(MTPDupdateChannelMessageViews *_data); friend MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count); friend MTPupdate MTP_updateMessageID(MTPint _id, const MTPlong &_random_id); @@ -5427,6 +5443,7 @@ private: friend MTPupdate MTP_updateNewChannelMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count); friend MTPupdate MTP_updateReadChannelInbox(const MTPPeer &_peer, MTPint _max_id); friend MTPupdate MTP_updateDeleteChannelMessages(const MTPPeer &_peer, const MTPVector &_messages, MTPint _pts, MTPint _pts_count); + friend MTPupdate MTP_updateChannelMessageViews(const MTPPeer &_peer, MTPint _id, MTPint _views); mtpTypeId _type; }; @@ -10555,6 +10572,18 @@ public: MTPint vpts_count; }; +class MTPDupdateChannelMessageViews : public mtpDataImpl { +public: + MTPDupdateChannelMessageViews() { + } + MTPDupdateChannelMessageViews(const MTPPeer &_peer, MTPint _id, MTPint _views) : vpeer(_peer), vid(_id), vviews(_views) { + } + + MTPPeer vpeer; + MTPint vid; + MTPint vviews; +}; + class MTPDupdates_state : public mtpDataImpl { public: MTPDupdates_state() { @@ -14901,6 +14930,7 @@ public: class MTPmessages_search { // RPC method 'messages.search' public: + MTPint vflags; MTPInputPeer vpeer; MTPstring vq; MTPMessagesFilter vfilter; @@ -14915,16 +14945,17 @@ public: MTPmessages_search(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_search) { read(from, end, cons); } - MTPmessages_search(const MTPInputPeer &_peer, const MTPstring &_q, const MTPMessagesFilter &_filter, MTPint _min_date, MTPint _max_date, MTPint _offset, MTPint _max_id, MTPint _limit) : vpeer(_peer), vq(_q), vfilter(_filter), vmin_date(_min_date), vmax_date(_max_date), voffset(_offset), vmax_id(_max_id), vlimit(_limit) { + MTPmessages_search(MTPint _flags, const MTPInputPeer &_peer, const MTPstring &_q, const MTPMessagesFilter &_filter, MTPint _min_date, MTPint _max_date, MTPint _offset, MTPint _max_id, MTPint _limit) : vflags(_flags), vpeer(_peer), vq(_q), vfilter(_filter), vmin_date(_min_date), vmax_date(_max_date), voffset(_offset), vmax_id(_max_id), vlimit(_limit) { } uint32 innerLength() const { - return vpeer.innerLength() + vq.innerLength() + vfilter.innerLength() + vmin_date.innerLength() + vmax_date.innerLength() + voffset.innerLength() + vmax_id.innerLength() + vlimit.innerLength(); + return vflags.innerLength() + vpeer.innerLength() + vq.innerLength() + vfilter.innerLength() + vmin_date.innerLength() + vmax_date.innerLength() + voffset.innerLength() + vmax_id.innerLength() + vlimit.innerLength(); } mtpTypeId type() const { return mtpc_messages_search; } void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_search) { + vflags.read(from, end); vpeer.read(from, end); vq.read(from, end); vfilter.read(from, end); @@ -14935,6 +14966,7 @@ public: vlimit.read(from, end); } void write(mtpBuffer &to) const { + vflags.write(to); vpeer.write(to); vq.write(to); vfilter.write(to); @@ -14955,7 +14987,7 @@ public: } MTPmessages_Search(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_Search(const MTPInputPeer &_peer, const MTPstring &_q, const MTPMessagesFilter &_filter, MTPint _min_date, MTPint _max_date, MTPint _offset, MTPint _max_id, MTPint _limit) : MTPBoxed(MTPmessages_search(_peer, _q, _filter, _min_date, _max_date, _offset, _max_id, _limit)) { + MTPmessages_Search(MTPint _flags, const MTPInputPeer &_peer, const MTPstring &_q, const MTPMessagesFilter &_filter, MTPint _min_date, MTPint _max_date, MTPint _offset, MTPint _max_id, MTPint _limit) : MTPBoxed(MTPmessages_search(_flags, _peer, _q, _filter, _min_date, _max_date, _offset, _max_id, _limit)) { } }; @@ -15297,6 +15329,7 @@ public: class MTPmessages_forwardMessages { // RPC method 'messages.forwardMessages' public: + MTPint vflags; MTPInputPeer vfrom_peer; MTPVector vid; MTPVector vrandom_id; @@ -15307,22 +15340,24 @@ public: MTPmessages_forwardMessages(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_forwardMessages) { read(from, end, cons); } - MTPmessages_forwardMessages(const MTPInputPeer &_from_peer, const MTPVector &_id, const MTPVector &_random_id, const MTPInputPeer &_to_peer) : vfrom_peer(_from_peer), vid(_id), vrandom_id(_random_id), vto_peer(_to_peer) { + MTPmessages_forwardMessages(MTPint _flags, const MTPInputPeer &_from_peer, const MTPVector &_id, const MTPVector &_random_id, const MTPInputPeer &_to_peer) : vflags(_flags), vfrom_peer(_from_peer), vid(_id), vrandom_id(_random_id), vto_peer(_to_peer) { } uint32 innerLength() const { - return vfrom_peer.innerLength() + vid.innerLength() + vrandom_id.innerLength() + vto_peer.innerLength(); + return vflags.innerLength() + vfrom_peer.innerLength() + vid.innerLength() + vrandom_id.innerLength() + vto_peer.innerLength(); } mtpTypeId type() const { return mtpc_messages_forwardMessages; } void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_forwardMessages) { + vflags.read(from, end); vfrom_peer.read(from, end); vid.read(from, end); vrandom_id.read(from, end); vto_peer.read(from, end); } void write(mtpBuffer &to) const { + vflags.write(to); vfrom_peer.write(to); vid.write(to); vrandom_id.write(to); @@ -15339,7 +15374,7 @@ public: } MTPmessages_ForwardMessages(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_ForwardMessages(const MTPInputPeer &_from_peer, const MTPVector &_id, const MTPVector &_random_id, const MTPInputPeer &_to_peer) : MTPBoxed(MTPmessages_forwardMessages(_from_peer, _id, _random_id, _to_peer)) { + MTPmessages_ForwardMessages(MTPint _flags, const MTPInputPeer &_from_peer, const MTPVector &_id, const MTPVector &_random_id, const MTPInputPeer &_to_peer) : MTPBoxed(MTPmessages_forwardMessages(_flags, _from_peer, _id, _random_id, _to_peer)) { } }; @@ -16951,6 +16986,48 @@ public: } }; +class MTPmessages_getMessagesViews { // RPC method 'messages.getMessagesViews' +public: + MTPInputPeer vpeer; + MTPVector vid; + + MTPmessages_getMessagesViews() { + } + MTPmessages_getMessagesViews(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getMessagesViews) { + read(from, end, cons); + } + MTPmessages_getMessagesViews(const MTPInputPeer &_peer, const MTPVector &_id) : vpeer(_peer), vid(_id) { + } + + uint32 innerLength() const { + return vpeer.innerLength() + vid.innerLength(); + } + mtpTypeId type() const { + return mtpc_messages_getMessagesViews; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getMessagesViews) { + vpeer.read(from, end); + vid.read(from, end); + } + void write(mtpBuffer &to) const { + vpeer.write(to); + vid.write(to); + } + + typedef MTPVector ResponseType; +}; +class MTPmessages_GetMessagesViews : public MTPBoxed { +public: + MTPmessages_GetMessagesViews() { + } + MTPmessages_GetMessagesViews(const MTPmessages_getMessagesViews &v) : MTPBoxed(v) { + } + MTPmessages_GetMessagesViews(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPmessages_GetMessagesViews(const MTPInputPeer &_peer, const MTPVector &_id) : MTPBoxed(MTPmessages_getMessagesViews(_peer, _id)) { + } +}; + class MTPmessages_editChatAbout { // RPC method 'messages.editChatAbout' public: MTPInputChat vchat_id; @@ -22844,6 +22921,10 @@ inline uint32 MTPupdate::innerLength() const { const MTPDupdateDeleteChannelMessages &v(c_updateDeleteChannelMessages()); return v.vpeer.innerLength() + v.vmessages.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); } + case mtpc_updateChannelMessageViews: { + const MTPDupdateChannelMessageViews &v(c_updateChannelMessageViews()); + return v.vpeer.innerLength() + v.vid.innerLength() + v.vviews.innerLength(); + } } return 0; } @@ -23074,6 +23155,13 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vpts.read(from, end); v.vpts_count.read(from, end); } break; + case mtpc_updateChannelMessageViews: _type = cons; { + if (!data) setData(new MTPDupdateChannelMessageViews()); + MTPDupdateChannelMessageViews &v(_updateChannelMessageViews()); + v.vpeer.read(from, end); + v.vid.read(from, end); + v.vviews.read(from, end); + } break; default: throw mtpErrorUnexpected(cons, "MTPupdate"); } } @@ -23266,6 +23354,12 @@ inline void MTPupdate::write(mtpBuffer &to) const { v.vpts.write(to); v.vpts_count.write(to); } break; + case mtpc_updateChannelMessageViews: { + const MTPDupdateChannelMessageViews &v(c_updateChannelMessageViews()); + v.vpeer.write(to); + v.vid.write(to); + v.vviews.write(to); + } break; } } inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -23303,6 +23397,7 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_updateNewChannelMessage: setData(new MTPDupdateNewChannelMessage()); break; case mtpc_updateReadChannelInbox: setData(new MTPDupdateReadChannelInbox()); break; case mtpc_updateDeleteChannelMessages: setData(new MTPDupdateDeleteChannelMessages()); break; + case mtpc_updateChannelMessageViews: setData(new MTPDupdateChannelMessageViews()); break; default: throw mtpErrorBadTypeId(type, "MTPupdate"); } } @@ -23372,6 +23467,8 @@ inline MTPupdate::MTPupdate(MTPDupdateReadChannelInbox *_data) : mtpDataOwner(_d } inline MTPupdate::MTPupdate(MTPDupdateDeleteChannelMessages *_data) : mtpDataOwner(_data), _type(mtpc_updateDeleteChannelMessages) { } +inline MTPupdate::MTPupdate(MTPDupdateChannelMessageViews *_data) : mtpDataOwner(_data), _type(mtpc_updateChannelMessageViews) { +} inline MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count) { return MTPupdate(new MTPDupdateNewMessage(_message, _pts, _pts_count)); } @@ -23471,6 +23568,9 @@ inline MTPupdate MTP_updateReadChannelInbox(const MTPPeer &_peer, MTPint _max_id inline MTPupdate MTP_updateDeleteChannelMessages(const MTPPeer &_peer, const MTPVector &_messages, MTPint _pts, MTPint _pts_count) { return MTPupdate(new MTPDupdateDeleteChannelMessages(_peer, _messages, _pts, _pts_count)); } +inline MTPupdate MTP_updateChannelMessageViews(const MTPPeer &_peer, MTPint _id, MTPint _views) { + return MTPupdate(new MTPDupdateChannelMessageViews(_peer, _id, _views)); +} inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) { } diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index ad63214622..40d76656fd 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -382,6 +382,7 @@ updateChannelGroup#c36c1e3c channel_id:int group:MessageGroup = Update; updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update; updateReadChannelInbox#87b87b7d peer:Peer max_id:int = Update; updateDeleteChannelMessages#11da3046 peer:Peer messages:Vector pts:int pts_count:int = Update; +updateChannelMessageViews#f3349b09 peer:Peer id:int views:int = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -672,7 +673,7 @@ contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer; messages.getMessages#4222fa74 id:Vector = messages.Messages; messages.getDialogs#859b3d3c offset:int limit:int = messages.Dialogs; messages.getHistory#8a8ec2da peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; -messages.search#7e9f2ab peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages; +messages.search#d4569248 flags:# peer:InputPeer q:string filter:MessagesFilter min_date:int max_date:int offset:int max_id:int limit:int = messages.Messages; messages.readHistory#b04f2510 peer:InputPeer max_id:int offset:int = messages.AffectedHistory; messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHistory; messages.deleteMessages#a5f18925 id:Vector = messages.AffectedMessages; @@ -680,7 +681,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool; messages.sendMessage#fa88427a flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector = Updates; messages.sendMedia#c8f16791 flags:# peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates; -messages.forwardMessages#f9adea76 from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer = Updates; +messages.forwardMessages#708e0195 flags:# from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer = Updates; messages.reportSpam#cf1592db peer:InputPeer = Bool; messages.getChats#27ae65b id:Vector = messages.Chats; messages.getFullChat#36a4dfe chat_id:InputChat = messages.ChatFull; @@ -719,6 +720,7 @@ messages.createChannel#e830f8cb flags:# title:string users:Vector = U messages.deleteChannelMessages#9995a84f peer:InputPeer id:Vector = messages.AffectedMessages; messages.getChannelMessages#5f46b265 peer:InputPeer id:Vector = messages.Messages; messages.incrementMessagesViews#91ffd479 peer:InputPeer id:Vector = Bool; +messages.getMessagesViews#9abfbbe1 peer:InputPeer id:Vector = Vector; messages.editChatAbout#8a969b93 chat_id:InputChat about:string = Bool; messages.getChannelParticipants#4a771976 chat_id:InputChat offset:int limit:int = messages.ChannelParticipants; messages.checkChannelUsername#e6d2d8f4 chat_id:InputChat username:string = Bool; diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 4606082b98..5c9f3f91a9 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -942,7 +942,8 @@ int32 OverviewInner::itemTop(const FullMsgId &msgId) const { void OverviewInner::preloadMore() { if (_inSearch) { if (!_searchRequest && !_searchFull) { - _searchRequest = MTP::send(MTPmessages_Search(_hist->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_lastSearchId), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, !_lastSearchId), rpcFail(&OverviewInner::searchFailed)); + int32 flags = _hist->peer->isChannel() ? MTPmessages_Search_flag_only_important : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _hist->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(_lastSearchId), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, !_lastSearchId), rpcFail(&OverviewInner::searchFailed)); if (!_lastSearchId) { _searchQueries.insert(_searchRequest, _searchQuery); } @@ -1785,7 +1786,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected())); } else if (App::hoveredLinkItem()) { if (isUponSelected != -2) { - if (App::hoveredLinkItem()->toHistoryMessage() && !_peer->isChannel()) { + if (App::hoveredLinkItem()->toHistoryMessage()) { _menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true); } if (!_peer->isChannel() || _peer->asChannel()->adminned) { @@ -1823,7 +1824,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected())); } else { if (isUponSelected != -2) { - if (App::mousedItem()->toHistoryMessage() && !_peer->isChannel()) { + if (App::mousedItem()->toHistoryMessage()) { _menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true); } if (!_peer->isChannel() || _peer->asChannel()->adminned) { @@ -2015,7 +2016,8 @@ bool OverviewInner::onSearchMessages(bool searchCache) { } else if (_searchQuery != q) { _searchQuery = q; _searchFull = false; - _searchRequest = MTP::send(MTPmessages_Search(_hist->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, true), rpcFail(&OverviewInner::searchFailed)); + int32 flags = _hist->peer->isChannel() ? MTPmessages_Search_flag_only_important : 0; + _searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _hist->peer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterUrl(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&OverviewInner::searchReceived, true), rpcFail(&OverviewInner::searchFailed)); _searchQueries.insert(_searchRequest, _searchQuery); } return false;