enabled forwarding from/to channel, replies and webpages loading in channels, scheme updated

This commit is contained in:
John Preston 2015-09-12 14:59:50 +03:00
parent 659c52347c
commit e41e68b8b3
11 changed files with 372 additions and 142 deletions

View File

@ -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<HistoryReply*>::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<HistoryReply*>::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<HistoryReply*>::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<HistoryReply*>::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<MTPint> 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<MTPint>(ids)), rpcDone(&ApiWrap::gotReplyTo));
for (ReplyToRequests::iterator i = _replyToRequests.begin(), e = _replyToRequests.end(); i != e; ++i) {
mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector<MTPint>(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<MTPint>(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<HistoryReply*>::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<HistoryReply*>::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<MTPint> ids;
MessageIds ids; // temp_req_id = -1
typedef QPair<int32, MessageIds> IndexAndMessageIds;
typedef QMap<ChannelData*, IndexAndMessageIds> 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<MTPint>(ids)), rpcDone(&ApiWrap::gotWebPages));
mtpRequestId req = ids.isEmpty() ? 0 : MTP::send(MTPmessages_GetMessages(MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotWebPages), RPCFailHandlerPtr(), 0, 5);
typedef QVector<mtpRequestId> 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<MTPint>(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);
}

View File

@ -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<HistoryReply*> replies;
};
typedef QMap<FullMsgId, ReplyToRequest> ReplyToRequests;
typedef QMap<MsgId, ReplyToRequest> ReplyToRequests;
ReplyToRequests _replyToRequests;
typedef QMap<ChannelData*, ReplyToRequests> ChannelReplyToRequests;
ChannelReplyToRequests _channelReplyToRequests;
SingleTimer _replyToTimer;
typedef QVector<MTPint> 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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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<HistoryContact*>(pressedLnkItem->getMedia())),
dragSticker = dynamic_cast<HistorySticker*>(pressedItem ? pressedItem->getMedia() : 0) && !hist->peer->isChannel(),
dragByDate = (_dragCursorState == HistoryInDateCursorState) && !hist->peer->isChannel();
dragSticker = dynamic_cast<HistorySticker*>(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<DocumentOpenLink*>(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<HistoryMessage*>(App::hoveredLinkItem()) && App::hoveredLinkItem()->id > 0 && !hist->peer->isChannel()) {
if (dynamic_cast<HistoryMessage*>(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<HistoryMessage*>(item);
HistoryServiceMsg *srv = dynamic_cast<HistoryServiceMsg*>(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 {

View File

@ -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<MTPint> ids;
QVector<MTPlong> 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<uint64>();
FullMsgId newId(peerToChannel(hist->peer->id), clientMsgId());
HistoryMessage *msg = static_cast<HistoryMessage*>(_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<HistorySticker*>(msg->getMedia())) {
App::main()->incrementSticker(sticker->document());
if (genClientSideMessage) {
FullMsgId newId(peerToChannel(hist->peer->id), clientMsgId());
HistoryMessage *msg = static_cast<HistoryMessage*>(_toForward.cbegin().value());
hist->addToBackForwarded(newId.msg, msg);
if (HistorySticker *sticker = dynamic_cast<HistorySticker*>(msg->getMedia())) {
App::main()->incrementSticker(sticker->document());
}
App::historyRegRandom(randomId, newId);
}
} else {
QVector<MTPint> ids;
QVector<MTPlong> 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<uint64>();
//MsgId newId = clientMsgId();
//hist->addToBackForwarded(newId, static_cast<HistoryMessage*>(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<MTPint>(ids), MTP_vector<MTPlong>(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<MTPint>(ids), MTP_vector<MTPlong>(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);
}

View File

@ -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<MTPKeyboardButtonRow>(0));

View File

@ -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;

View File

@ -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<MTPint> &_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<MTPDupdateChannelMessageViews> {
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<MTPDupdates_state> {
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<MTPmessages_search>(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>(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>(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<MTPint> vid;
MTPVector<MTPlong> 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<MTPint> &_id, const MTPVector<MTPlong> &_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<MTPint> &_id, const MTPVector<MTPlong> &_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<MTPmessages_forwardMessages>(from, end, cons) {
}
MTPmessages_ForwardMessages(const MTPInputPeer &_from_peer, const MTPVector<MTPint> &_id, const MTPVector<MTPlong> &_random_id, const MTPInputPeer &_to_peer) : MTPBoxed<MTPmessages_forwardMessages>(MTPmessages_forwardMessages(_from_peer, _id, _random_id, _to_peer)) {
MTPmessages_ForwardMessages(MTPint _flags, const MTPInputPeer &_from_peer, const MTPVector<MTPint> &_id, const MTPVector<MTPlong> &_random_id, const MTPInputPeer &_to_peer) : MTPBoxed<MTPmessages_forwardMessages>(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<MTPint> 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<MTPint> &_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<MTPint> ResponseType;
};
class MTPmessages_GetMessagesViews : public MTPBoxed<MTPmessages_getMessagesViews> {
public:
MTPmessages_GetMessagesViews() {
}
MTPmessages_GetMessagesViews(const MTPmessages_getMessagesViews &v) : MTPBoxed<MTPmessages_getMessagesViews>(v) {
}
MTPmessages_GetMessagesViews(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_getMessagesViews>(from, end, cons) {
}
MTPmessages_GetMessagesViews(const MTPInputPeer &_peer, const MTPVector<MTPint> &_id) : MTPBoxed<MTPmessages_getMessagesViews>(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<MTPint> &_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()) {
}

View File

@ -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<int> 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<int> = 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<int> = messages.AffectedMessages;
@ -680,7 +681,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
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<MessageEntity> = 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<int> random_id:Vector<long> to_peer:InputPeer = Updates;
messages.forwardMessages#708e0195 flags:# from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer = Updates;
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.getChats#27ae65b id:Vector<InputChat> = messages.Chats;
messages.getFullChat#36a4dfe chat_id:InputChat = messages.ChatFull;
@ -719,6 +720,7 @@ messages.createChannel#e830f8cb flags:# title:string users:Vector<InputUser> = U
messages.deleteChannelMessages#9995a84f peer:InputPeer id:Vector<int> = messages.AffectedMessages;
messages.getChannelMessages#5f46b265 peer:InputPeer id:Vector<int> = messages.Messages;
messages.incrementMessagesViews#91ffd479 peer:InputPeer id:Vector<int> = Bool;
messages.getMessagesViews#9abfbbe1 peer:InputPeer id:Vector<int> = Vector<int>;
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;

View File

@ -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;