broadcast channels support started

This commit is contained in:
John Preston 2015-09-06 13:17:09 +03:00
parent 95ff7821a3
commit b53e35e046
31 changed files with 1006 additions and 525 deletions

View file

@ -82,6 +82,7 @@ In Terminal go to **/home/user/TBuild/Libraries** and run
sudo apt-get install xutils-dev bison python-xcbgen
git clone https://github.com/xkbcommon/libxkbcommon.git
cd libxkbcommon
./autogen.sh --disable-x11
make
sudo make install

View file

@ -160,6 +160,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_filter" = "Search";
"lng_dlg_new_group_name" = "Group name";
"lng_dlg_new_channel_name" = "Channel name";
"lng_dlg_create_group" = "Create";
"lng_no_contacts" = "You have no contacts";
"lng_no_chats" = "Your chats will be here";
@ -395,14 +396,15 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links} »";
"lng_profile_shared_links_header" = "Shared links overview";
"lng_profile_audio_files_header" = "Playlist";
"lng_profile_show_all_types" = "Show all types";
"lng_profile_copy_phone" = "Copy phone number";
"lng_participant_filter" = "Search";
"lng_participant_invite" = "Invite";
"lng_create_new_group" = "New Group";
"lng_create_new_channel" = "New Channel";
"lng_create_group_next" = "Next";
"lng_create_group_title" = "New Group";
"lng_create_channel_title" = "New Channel";
"lng_failed_add_participant" = "Could not add user. Try again later.";
"lng_failed_add_not_mutual" = "Sorry, if a person left a group, only a\nmutual contact can bring them back\n(they need to have your phone\nnumber, and you need theirs).";
@ -435,6 +437,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_group_invite_link" = "Invite link";
"lng_group_invite_create" = "Create an invite link";
"lng_group_invite_about" = "Telegram users will be able to join\nyour group by following this link.";
"lng_channel_invite_about" = "Telegram users will be able to join\nyour channel by following this link.";
"lng_group_invite_create_new" = "Revoke invite link";
"lng_group_invite_about_new" = "Your previous link will be deactivated\nand we'll generate a new invite link for you.";
"lng_group_invite_copied" = "Invite link copied to clipboard.";
@ -599,6 +602,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_confirm_contact_data" = "New Contact";
"lng_add_contact" = "Create";
"lng_add_contact_button" = "Add Contact";
"lng_create_channel_button" = "Create Channel";
"lng_create_group_button" = "Create Group";
"lng_contacts_header" = "Contacts";
"lng_contact_not_joined" = "Unfortunately {name} did not join Telegram yet, but you can send your friend an invitation.\n\nWe will notify you about any of your contacts who is joining Telegram.";
"lng_try_other_contact" = "Try other";

View file

@ -1491,7 +1491,7 @@ dropdownMediaAudios: iconedButton(dropdownMediaDocuments) {
}
dropdownMediaLinks: iconedButton(dropdownMediaDocuments) {
icon: sprite(372px, 414px, 24px, 24px);
downIcon: sprite(62px, 348px, 24px, 24px);
downIcon: sprite(372px, 414px, 24px, 24px);
}
dragFont: font(28px semibold);

View file

@ -305,7 +305,7 @@ void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
if (peer->isChat()) {
peer->asChat()->version = v.at(0).c_chat().vversion.v;
} else if (peer->isChannel()) {
peer->asChannel()->version = v.at(0).c_chat().vversion.v;
peer->asChannel()->version = v.at(0).c_channel().vversion.v;
}
requestPeer(peer);
}

View file

@ -473,15 +473,15 @@ namespace App {
for (QVector<MTPChat>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
const MTPchat &chat(*i);
data = 0;
QString title;
switch (chat.type()) {
case mtpc_chat: {
const MTPDchat &d(chat.c_chat());
title = qs(d.vtitle);
data = App::chat(peerFromChat(d.vid.v));
data->input = MTP_inputPeerChat(d.vid);
data->updateName(qs(d.vtitle), QString(), QString());
ChatData *cdata = data->asChat();
cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v;
@ -496,11 +496,12 @@ namespace App {
} break;
case mtpc_chatForbidden: {
const MTPDchatForbidden &d(chat.c_chatForbidden());
title = qs(d.vtitle);
data = App::chat(peerFromChat(d.vid.v));
data->input = MTP_inputPeerChat(d.vid);
data->updateName(qs(d.vtitle), QString(), QString());
ChatData *cdata = data->asChat();
cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0;
@ -510,7 +511,6 @@ namespace App {
} break;
case mtpc_channel: {
const MTPDchannel &d(chat.c_channel());
title = qs(d.vtitle);
PeerId peer(peerFromChannel(d.vid.v));
data = App::channel(peer);
@ -518,6 +518,10 @@ namespace App {
ChannelData *cdata = data->asChannel();
cdata->inputChat = MTP_inputChannel(d.vid, d.vaccess_hash);
QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString();
cdata->setName(qs(d.vtitle), uname);
cdata->access = d.vaccess_hash.v;
cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v;
@ -532,9 +536,6 @@ namespace App {
}
if (!data) continue;
data->loaded = true;
data->updateName(title.trimmed(), QString(), QString());
if (App::main()) {
if (emitPeerUpdated) {
App::main()->peerUpdated(data);
@ -1178,9 +1179,9 @@ namespace App {
return ::self;
}
UserData *userByName(const QString &username) {
PeerData *peerByName(const QString &username) {
for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
if (i.value()->isUser() && !i.value()->asUser()->username.compare(username.trimmed(), Qt::CaseInsensitive)) {
if (!i.value()->userName().compare(username.trimmed(), Qt::CaseInsensitive)) {
return i.value()->asUser();
}
}
@ -1587,6 +1588,8 @@ namespace App {
if (maxInboxRead) {
i.value()->inboxReadTill = maxInboxRead;
}
} else if (maxInboxRead) {
i.value()->inboxReadTill = qMax(i.value()->inboxReadTill, maxInboxRead);
}
return i.value();
}
@ -2318,9 +2321,9 @@ namespace App {
}
}
void openUserByName(const QString &username, bool toProfile, const QString &startToken) {
void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
if (App::main()) {
App::main()->openUserByName(username, toProfile, startToken);
App::main()->openPeerByName(username, toProfile, startToken);
}
}

View file

@ -147,7 +147,7 @@ namespace App {
ChatData *chat(int32 chat_id);
ChannelData *channel(int32 channel_id);
UserData *self();
UserData *userByName(const QString &username);
PeerData *peerByName(const QString &username);
QString peerName(const PeerData *peer, bool forDialogs = false);
PhotoData *photo(const PhotoId &photo);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
@ -253,7 +253,7 @@ namespace App {
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
void insertBotCommand(const QString &cmd);
void searchByHashtag(const QString &tag);
void openUserByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);
void stickersBox(const QString &name);
void openLocalUrl(const QString &url);

View file

@ -233,11 +233,11 @@ void ContactsInner::paintDialog(QPainter &p, PeerData *peer, ContactData *data,
p.drawPixmap(QPoint(width() - st::contactsImg.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::contactsImg.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), st::contactsImg);
}
bool uname = user && (data->online.at(0) == '@');
bool uname = (user || peer->isChannel()) && (data->online.at(0) == '@');
p.setFont(st::profileSubFont->f);
if (uname && !data->inchat && !data->check && !_lastQuery.isEmpty() && user->username.startsWith(_lastQuery, Qt::CaseInsensitive)) {
if (uname && !data->inchat && !data->check && !_lastQuery.isEmpty() && peer->userName().startsWith(_lastQuery, Qt::CaseInsensitive)) {
int32 availw = width() - (left + st::profileListPhotoSize + st::profileListPadding.width() * 2);
QString first = '@' + user->username.mid(0, _lastQuery.size()), second = user->username.mid(_lastQuery.size());
QString first = '@' + peer->userName().mid(0, _lastQuery.size()), second = peer->userName().mid(_lastQuery.size());
int32 w = st::profileSubFont->m.width(first);
if (w >= availw || second.isEmpty()) {
p.setPen(st::profileOnlineColor->p);
@ -251,7 +251,7 @@ void ContactsInner::paintDialog(QPainter &p, PeerData *peer, ContactData *data,
} else {
if (data->inchat || data->check) {
p.setPen(st::white->p);
} else if (user && (uname || App::onlineColorUse(user, _time))) {
} else if ((user && (uname || App::onlineColorUse(user, _time))) || (peer->isChannel() && uname)) {
p.setPen(st::profileOnlineColor->p);
} else {
p.setPen(st::profileOfflineColor->p);
@ -679,29 +679,32 @@ void ContactsInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) {
resize(width(), newh);
}
void ContactsInner::peopleReceived(const QString &query, const QVector<MTPContactFound> &people) {
void ContactsInner::peopleReceived(const QString &query, const QVector<MTPPeer> &people) {
_lastQuery = query.toLower().trimmed();
if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1);
int32 already = _byUsernameFiltered.size();
_byUsernameFiltered.reserve(already + people.size());
d_byUsernameFiltered.reserve(already + people.size());
for (QVector<MTPContactFound>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
int32 uid = i->c_contactFound().vuser_id.v, j = 0;
for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
PeerId peerId = peerFromMTP(*i);
int32 j = 0;
for (; j < already; ++j) {
if (_byUsernameFiltered[j]->id == peerFromUser(uid)) break;
if (_byUsernameFiltered[j]->id == peerId) break;
}
if (j == already) {
UserData *u = App::user(uid);
if (u->botInfo && u->botInfo->cantJoinGroups && (_chat || _creatingChat)) continue; // skip bot's that can't be invited to groups
PeerData *p = App::peer(peerId);
if (!p) continue;
if ((!p->isUser() || p->asUser()->botInfo && p->asUser()->botInfo->cantJoinGroups) && (_chat || _creatingChat)) continue; // skip bot's that can't be invited to groups
ContactData *d = new ContactData();
_byUsernameDatas.push_back(d);
d->inchat = _chat ? _chat->participants.contains(u) : false;
d->check = _checkedContacts.contains(u);
d->name.setText(st::profileListNameFont, u->name, _textNameOptions);
d->online = '@' + u->username;
d->inchat = _chat ? _chat->participants.contains(p->asUser()) : false;
d->check = _checkedContacts.contains(p);
d->name.setText(st::profileListNameFont, p->name, _textNameOptions);
d->online = '@' + p->userName();
_byUsernameFiltered.push_back(u);
_byUsernameFiltered.push_back(p);
d_byUsernameFiltered.push_back(d);
}
}
@ -896,8 +899,8 @@ QVector<UserData*> ContactsInner::selected() {
}
}
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
if (d_byUsername[i]->check) {
result.push_back(_byUsername[i]);
if (d_byUsername[i]->check && _byUsername[i]->isUser()) {
result.push_back(_byUsername[i]->asUser());
}
}
return result;
@ -917,8 +920,8 @@ QVector<MTPInputUser> ContactsInner::selectedInputs() {
}
}
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
if (d_byUsername[i]->check) {
result.push_back(_byUsername[i]->inputUser);
if (d_byUsername[i]->check && _byUsername[i]->isUser()) {
result.push_back(_byUsername[i]->asUser()->inputUser);
}
}
return result;
@ -945,35 +948,44 @@ PeerData *ContactsInner::selectedUser() {
ContactsBox::ContactsBox(bool creatingChat) : ItemListBox(st::boxNoTopScroll), _inner(creatingChat),
_addContact(this, lang(lng_add_contact_button), st::contactsAdd),
_createChannel(this, lang(lng_create_channel_button), st::contactsAdd),
_filter(this, st::contactsFilter, lang(lng_participant_filter)),
_next(this, lang(lng_create_group_next), st::btnSelectDone),
_cancel(this, lang(lng_contacts_done), creatingChat ? st::btnSelectCancel : st::contactsClose) {
_cancel(this, lang(lng_contacts_done), creatingChat ? st::btnSelectCancel : st::contactsClose), _creatingChannel(false) {
init();
}
ContactsBox::ContactsBox(ChatData *chat) : ItemListBox(st::boxNoTopScroll), _inner(chat),
_addContact(this, lang(lng_add_contact_button), st::contactsAdd),
_createChannel(this, lang(lng_create_channel_button), st::contactsAdd),
_filter(this, st::contactsFilter, lang(lng_participant_filter)),
_next(this, lang(lng_participant_invite), st::btnSelectDone),
_cancel(this, lang(lng_cancel), st::btnSelectCancel) {
_cancel(this, lang(lng_cancel), st::btnSelectCancel), _creatingChannel(false) {
init();
}
ContactsBox::ContactsBox(UserData *bot) : ItemListBox(st::boxNoTopScroll), _inner(bot),
_addContact(this, lang(lng_add_contact_button), st::contactsAdd),
_createChannel(this, lang(lng_create_channel_button), st::contactsAdd),
_filter(this, st::contactsFilter, lang(lng_participant_filter)),
_next(this, lang(lng_create_group_next), st::btnSelectDone),
_cancel(this, lang(lng_cancel), st::contactsClose) {
_cancel(this, lang(lng_cancel), st::contactsClose), _creatingChannel(false) {
init();
}
void ContactsBox::init() {
ItemListBox::init(&_inner, _cancel.height(), st::contactsAdd.height + st::newGroupNamePadding.top() + _filter.height() + st::newGroupNamePadding.bottom());
if (_inner.chat() || _inner.creatingChat()) {
if (_inner.chat()) {
_addContact.hide();
_createChannel.hide();
} else if (_inner.creatingChat()) {
_addContact.hide();
_createChannel.show();
connect(&_createChannel, SIGNAL(clicked()), this, SLOT(onCreateChannel()));
} else {
connect(&_addContact, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
_createChannel.hide();
}
if (_inner.chat()) {
connect(&_next, SIGNAL(clicked()), this, SLOT(onInvite()));
@ -1067,6 +1079,7 @@ bool ContactsBox::peopleFailed(const RPCError &error, mtpRequestId req) {
void ContactsBox::hideAll() {
ItemListBox::hideAll();
_addContact.hide();
_createChannel.hide();
_filter.hide();
_next.hide();
_cancel.hide();
@ -1075,9 +1088,14 @@ void ContactsBox::hideAll() {
void ContactsBox::showAll() {
ItemListBox::showAll();
_filter.show();
if (_inner.chat() || _inner.creatingChat()) {
if (_inner.chat()) {
_next.show();
_addContact.hide();
_createChannel.hide();
} else if (_inner.creatingChat()) {
_next.show();
_addContact.hide();
_createChannel.show();
} else {
_next.hide();
if (_inner.bot()) {
@ -1085,6 +1103,7 @@ void ContactsBox::showAll() {
} else {
_addContact.show();
}
_createChannel.hide();
}
_cancel.show();
}
@ -1122,7 +1141,7 @@ void ContactsBox::paintEvent(QPaintEvent *e) {
if (paint(p)) return;
if (_inner.chat() || _inner.creatingChat()) {
paintTitle(p, lang(_inner.chat() ? lng_profile_add_participant : lng_create_new_group), true);
paintTitle(p, lang(_inner.chat() ? lng_profile_add_participant : (_creatingChannel ? lng_create_new_channel : lng_create_new_group)), true);
// paint button sep
p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b);
@ -1136,6 +1155,7 @@ void ContactsBox::paintEvent(QPaintEvent *e) {
void ContactsBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e);
_addContact.move(width() - _addContact.width(), 0);
_createChannel.move(width() - _createChannel.width(), 0);
_filter.move(st::newGroupNamePadding.left(), _addContact.height() + st::newGroupNamePadding.top());
_inner.resize(width(), _inner.height());
_next.move(width() - _next.width(), height() - _next.height());
@ -1151,6 +1171,13 @@ void ContactsBox::onAdd() {
App::wnd()->replaceLayer(new AddContactBox());
}
void ContactsBox::onCreateChannel() {
_creatingChannel = !_creatingChannel;
_createChannel.setText(lang(_creatingChannel ? lng_create_group_button : lng_create_channel_button));
_createChannel.move(width() - _createChannel.width(), 0);
update();
}
void ContactsBox::onInvite() {
QVector<UserData*> users(_inner.selected());
if (users.isEmpty()) {
@ -1170,7 +1197,7 @@ void ContactsBox::onNext() {
} else if (v.size() == 1) {
App::main()->showPeerHistory(_inner.selectedUser()->id, ShowAtUnreadMsgId);
} else {
App::wnd()->replaceLayer(new CreateGroupBox(users));
App::wnd()->replaceLayer(new CreateGroupBox(users, _creatingChannel));
}
}
@ -1178,9 +1205,10 @@ void ContactsBox::onScroll() {
_inner.loadProfilePhotos(_scroll.scrollTop());
}
CreateGroupBox::CreateGroupBox(const MTPVector<MTPInputUser> &users) : AbstractBox(), _users(users),
CreateGroupBox::CreateGroupBox(const MTPVector<MTPInputUser> &users, bool creatingChannel) : AbstractBox(), _users(users),
_creatingChannel(creatingChannel),
_createRequestId(0),
_name(this, st::newGroupName, lang(lng_dlg_new_group_name)),
_name(this, st::newGroupName, lang(_creatingChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)),
_create(this, lang(lng_dlg_create_group), st::btnSelectDone),
_cancel(this, lang(lng_cancel), st::btnSelectCancel) {
@ -1227,7 +1255,7 @@ void CreateGroupBox::paintEvent(QPaintEvent *e) {
Painter p(this);
if (paint(p)) return;
paintTitle(p, lang(lng_create_group_title), true);
paintTitle(p, lang(_creatingChannel ? lng_create_channel_title : lng_create_group_title), true);
// paint shadow
p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b);
@ -1256,7 +1284,11 @@ void CreateGroupBox::onCreate() {
_create.setDisabled(true);
_name.setDisabled(true);
_createRequestId = MTP::send(MTPmessages_CreateChat(_users, MTP_string(_name.text())), rpcDone(&CreateGroupBox::created), rpcFail(&CreateGroupBox::failed));
if (_creatingChannel) {
_createRequestId = MTP::send(MTPmessages_CreateChannel(MTP_int(MTPmessages_CreateChannel_flag_broadcast), MTP_string(_name.text()), _users), rpcDone(&CreateGroupBox::created), rpcFail(&CreateGroupBox::failed));
} else {
_createRequestId = MTP::send(MTPmessages_CreateChat(_users, MTP_string(_name.text())), rpcDone(&CreateGroupBox::created), rpcFail(&CreateGroupBox::failed));
}
}
void CreateGroupBox::created(const MTPUpdates &updates) {
@ -1279,7 +1311,9 @@ void CreateGroupBox::created(const MTPUpdates &updates) {
} break;
}
if (v && !v->isEmpty() && v->front().type() == mtpc_chat) {
App::main()->choosePeer(peerFromChat(v->front().c_chat().vid.v), ShowAtUnreadMsgId);
App::main()->showPeerHistory(peerFromChat(v->front().c_chat().vid.v), ShowAtUnreadMsgId);
} else if (v && !v->isEmpty() && v->front().type() == mtpc_channel) {
App::main()->showPeerHistory(peerFromChannel(v->front().c_channel().vid.v), ShowAtUnreadMsgId);
}
}

View file

@ -55,7 +55,7 @@ public:
void changeCheckState(DialogRow *row);
void changeCheckState(ContactData *data, PeerData *peer);
void peopleReceived(const QString &query, const QVector<MTPContactFound> &people);
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
void refresh();
@ -116,7 +116,7 @@ private:
bool _searching;
QString _lastQuery;
typedef QVector<UserData*> ByUsernameRows;
typedef QVector<PeerData*> ByUsernameRows;
typedef QVector<ContactData*> ByUsernameDatas;
ByUsernameRows _byUsername, _byUsernameFiltered;
ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas
@ -146,6 +146,7 @@ public slots:
void onScroll();
void onAdd();
void onCreateChannel();
void onInvite();
void onNext();
@ -163,7 +164,7 @@ private:
void init();
ContactsInner _inner;
FlatButton _addContact;
FlatButton _addContact, _createChannel;
FlatInput _filter;
FlatButton _next, _cancel;
@ -171,6 +172,8 @@ private:
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
bool peopleFailed(const RPCError &error, mtpRequestId req);
bool _creatingChannel;
QTimer _searchTimer;
QString _peopleQuery;
bool _peopleFull;
@ -188,7 +191,7 @@ class CreateGroupBox : public AbstractBox, public RPCSender {
public:
CreateGroupBox(const MTPVector<MTPInputUser> &users);
CreateGroupBox(const MTPVector<MTPInputUser> &users, bool creatingChannel);
void keyPressEvent(QKeyEvent *e);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
@ -209,6 +212,7 @@ private:
bool failed(const RPCError &e);
MTPVector<MTPInputUser> _users;
bool _creatingChannel;
int32 _createRequestId;

View file

@ -296,7 +296,7 @@ enum {
DefaultChatBackground = 21,
DialogsFirstLoad = 20, // first dialogs part size requested
DialogsPerPage = 200, // next dialogs part size
DialogsPerPage = 500, // next dialogs part size
MessagesFirstLoad = 30, // first history part size requested
MessagesPerPage = 50, // next history part size

View file

@ -45,7 +45,6 @@ _addContactLnk(this, lang(lng_add_contact_button)),
_cancelSearchInPeer(this, st::btnCancelSearch),
_overDelete(false),
_searchInPeer(0) {
connect(main, SIGNAL(dialogToTop(const History::DialogLinks&)), this, SLOT(onDialogToTop(const History::DialogLinks&)));
connect(main, SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)));
connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*)));
connect(main, SIGNAL(dialogRowReplaced(DialogRow*,DialogRow*)), this, SLOT(onDialogRowReplaced(DialogRow*,DialogRow*)));
@ -229,11 +228,11 @@ void DialogsListWidget::paintEvent(QPaintEvent *e) {
}
}
void DialogsListWidget::peopleResultPaint(UserData *user, QPainter &p, int32 w, bool act, bool sel) const {
void DialogsListWidget::peopleResultPaint(PeerData *peer, QPainter &p, int32 w, bool act, bool sel) const {
QRect fullRect(0, 0, w, st::dlgHeight);
p.fillRect(fullRect, (act ? st::dlgActiveBG : (sel ? st::dlgHoverBG : st::dlgBG))->b);
History *history = App::history(user->id);
History *history = App::history(peer->id);
p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, history->peer->photo->pix(st::dlgPhotoSize));
@ -249,8 +248,9 @@ void DialogsListWidget::peopleResultPaint(UserData *user, QPainter &p, int32 w,
QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height);
p.setFont(st::dlgHistFont->f);
if (!act && user->username.toLower().startsWith(peopleQuery)) {
QString first = '@' + user->username.mid(0, peopleQuery.size()), second = user->username.mid(peopleQuery.size());
QString username = peer->userName();
if (!act && username.toLower().startsWith(peopleQuery)) {
QString first = '@' + username.mid(0, peopleQuery.size()), second = username.mid(peopleQuery.size());
int32 w = st::dlgHistFont->m.width(first);
if (w >= tr.width()) {
p.setPen(st::dlgSystemColor->p);
@ -263,11 +263,11 @@ void DialogsListWidget::peopleResultPaint(UserData *user, QPainter &p, int32 w,
}
} else {
p.setPen((act ? st::dlgActiveColor : st::dlgSystemColor)->p);
p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->m.elidedText('@' + user->username, Qt::ElideRight, tr.width()));
p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->m.elidedText('@' + username, Qt::ElideRight, tr.width()));
}
p.setPen((act ? st::dlgActiveColor : st::dlgNameColor)->p);
user->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
void DialogsListWidget::searchInPeerPaint(QPainter &p, int32 w) const {
@ -414,17 +414,27 @@ void DialogsListWidget::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow
}
void DialogsListWidget::createDialogAtTop(History *history, int32 unreadCount) {
History::DialogLinks links = dialogs.addToEnd(history);
int32 movedFrom = links[0]->pos * st::dlgHeight;
dialogs.bringToTop(links);
history->dialogs = links;
if (history->dialogs.isEmpty()) {
History::DialogLinks links = dialogs.addToEnd(history);
int32 movedFrom = links[0]->pos * st::dlgHeight;
dialogs.adjustByPos(links);
history->dialogs = links;
contactsNoDialogs.del(history->peer, links[0]);
contactsNoDialogs.del(history->peer, links[0]);
emit dialogToTopFrom(movedFrom);
emit App::main()->dialogsUpdated();
emit dialogToTopFrom(movedFrom);
emit App::main()->dialogsUpdated();
refresh();
refresh();
} else {
int32 movedFrom = history->dialogs[0]->pos * st::dlgHeight;
dialogs.adjustByPos(history->dialogs);
emit dialogToTopFrom(movedFrom);
emit App::main()->dialogsUpdated();
parentWidget()->update();
}
}
void DialogsListWidget::removePeer(PeerData *peer) {
@ -543,14 +553,6 @@ void DialogsListWidget::onParentGeometryChanged() {
}
}
void DialogsListWidget::onDialogToTop(const History::DialogLinks &links) {
int32 movedFrom = links[0]->pos * st::dlgHeight;
dialogs.bringToTop(links);
emit dialogToTopFrom(movedFrom);
emit App::main()->dialogsUpdated();
parentWidget()->update();
}
void DialogsListWidget::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
dialogs.peerNameChanged(peer, oldNames, oldChars);
contactsNoDialogs.peerNameChanged(peer, oldNames, oldChars);
@ -772,16 +774,21 @@ void DialogsListWidget::dialogsReceived(const QVector<MTPDialog> &added) {
refresh();
}
void DialogsListWidget::addAllSavedPeers() {
void DialogsListWidget::addSavedPeersAfter(const QDateTime &date) {
SavedPeersByTime &saved(cRefSavedPeersByTime());
while (!saved.isEmpty()) {
while (!saved.isEmpty() && (date.isNull() || date < saved.lastKey())) {
History *history = App::history(saved.last()->id);
history->setPosInDialogsDate(saved.lastKey());
history->dialogs = dialogs.addToEnd(history);
contactsNoDialogs.del(history->peer);
saved.remove(saved.lastKey(), saved.last());
}
}
void DialogsListWidget::addAllSavedPeers() {
addSavedPeersAfter(QDateTime());
}
void DialogsListWidget::searchReceived(const QVector<MTPMessage> &messages, bool fromStart, int32 fullCount) {
if (fromStart) {
clearSearchResults(false);
@ -798,16 +805,16 @@ void DialogsListWidget::searchReceived(const QVector<MTPMessage> &messages, bool
refresh();
}
void DialogsListWidget::peopleReceived(const QString &query, const QVector<MTPContactFound> &people) {
void DialogsListWidget::peopleReceived(const QString &query, const QVector<MTPPeer> &people) {
peopleQuery = query.toLower().trimmed();
peopleResults.clear();
peopleResults.reserve(people.size());
for (QVector<MTPContactFound>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
int32 uid = i->c_contactFound().vuser_id.v;
History *h = App::historyLoaded(uid);
for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
PeerId peerId = peerFromMTP(*i);
History *h = App::historyLoaded(peerId);
if (h && !h->isEmpty()) continue; // skip dialogs
peopleResults.push_back(App::user(uid));
peopleResults.push_back(App::peer(peerId));
}
refresh();
}
@ -942,15 +949,8 @@ void DialogsListWidget::clearFilter() {
void DialogsListWidget::addDialog(const MTPDdialog &dialog) {
History *history = App::history(peerFromMTP(dialog.vpeer), dialog.vunread_count.v, dialog.vread_inbox_max_id.v);
if (history->lastMsg) {
SavedPeersByTime &saved(cRefSavedPeersByTime());
while (!saved.isEmpty() && history->lastMsg->date < saved.lastKey()) {
History *history = App::history(saved.last()->id);
history->dialogs = dialogs.addToEnd(history);
contactsNoDialogs.del(history->peer);
saved.remove(saved.lastKey(), saved.last());
}
}
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
history->dialogs = links;
contactsNoDialogs.del(history->peer);
@ -960,15 +960,8 @@ void DialogsListWidget::addDialog(const MTPDdialog &dialog) {
void DialogsListWidget::addDialogChannel(const MTPDdialogChannel &dialogChannel) {
History *history = App::history(peerFromMTP(dialogChannel.vpeer), dialogChannel.vunread_important_count.v, dialogChannel.vread_inbox_max_id.v);
if (history->lastMsg) {
SavedPeersByTime &saved(cRefSavedPeersByTime());
while (!saved.isEmpty() && history->lastMsg->date < saved.lastKey()) {
History *history = App::history(saved.last()->id);
history->dialogs = dialogs.addToEnd(history);
contactsNoDialogs.del(history->peer);
saved.remove(saved.lastKey(), saved.last());
}
}
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
history->dialogs = links;
contactsNoDialogs.del(history->peer);

View file

@ -27,9 +27,10 @@ public:
DialogsListWidget(QWidget *parent, MainWidget *main);
void dialogsReceived(const QVector<MTPDialog> &dialogs);
void addSavedPeersAfter(const QDateTime &date);
void addAllSavedPeers();
void searchReceived(const QVector<MTPMessage> &messages, bool fromStart, int32 fullCount);
void peopleReceived(const QString &query, const QVector<MTPContactFound> &people);
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
void showMore(int32 pixels);
void activate();
@ -48,13 +49,14 @@ public:
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void peopleResultPaint(UserData *user, QPainter &p, int32 w, bool act, bool sel) const;
void peopleResultPaint(PeerData *peer, QPainter &p, int32 w, bool act, bool sel) const;
void searchInPeerPaint(QPainter &p, int32 w) const;
void selectSkip(int32 direction);
void selectSkipPage(int32 pixels, int32 direction);
void createDialogAtTop(History *history, int32 unreadCount);
void moveDialogToTop(const History::DialogLinks &links);
void dlgUpdated(DialogRow *row);
void dlgUpdated(History *row);
void removePeer(PeerData *peer);
@ -74,7 +76,7 @@ public:
void scrollToPeer(const PeerId &peer, MsgId msgId);
typedef QVector<DialogRow*> FilteredDialogs;
typedef QVector<UserData*> PeopleResults;
typedef QVector<PeerData*> PeopleResults;
typedef QVector<FakeDialogRow*> SearchResults;
DialogsIndexed &contactsList();
@ -110,7 +112,6 @@ public slots:
void onUpdateSelected(bool force = false);
void onParentGeometryChanged();
void onDialogToTop(const History::DialogLinks &links);
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void onPeerPhotoChanged(PeerData *peer);
void onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow);

View file

@ -2707,7 +2707,7 @@ void MentionsInner::onParentGeometryChanged() {
}
MentionsDropdown::MentionsDropdown(QWidget *parent) : QWidget(parent),
_scroll(this, st::mentionScroll), _inner(this, &_rows, &_hrows, &_crows), _chat(0), _hiding(false), a_opacity(0), _shadow(st::dropdownDef.shadow) {
_scroll(this, st::mentionScroll), _inner(this, &_rows, &_hrows, &_crows), _chat(0), _user(0), _channel(0), _hiding(false), a_opacity(0), _shadow(st::dropdownDef.shadow) {
_hideTimer.setSingleShot(true);
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
connect(&_inner, SIGNAL(chosen(QString)), this, SIGNAL(chosen(QString)));
@ -2748,6 +2748,7 @@ void MentionsDropdown::paintEvent(QPaintEvent *e) {
void MentionsDropdown::showFiltered(PeerData *peer, QString start) {
_chat = peer->asChat();
_user = peer->asUser();
_channel = peer->asChannel();
start = start.toLower();
bool toDown = (_filter != start);
if (toDown) {
@ -2768,7 +2769,7 @@ void MentionsDropdown::updateFiltered(bool toDown) {
MentionRows rows;
HashtagRows hrows;
BotCommandRows crows;
if (_filter.at(0) == '@') {
if (_filter.at(0) == '@' && _chat) {
QMultiMap<int32, UserData*> ordered;
rows.reserve(_chat->participants.isEmpty() ? _chat->lastAuthors.size() : _chat->participants.size());
if (_chat->participants.isEmpty()) {

View file

@ -584,6 +584,7 @@ private:
ChatData *_chat;
UserData *_user;
ChannelData *_channel;
QString _filter;
QRect _boundings;

View file

@ -798,7 +798,7 @@ void TextLink::onClick(Qt::MouseButton button) const {
startToken = startParams.captured(3);
}
}
App::openUserByName(telegramMeUser.captured(1), start == qsl("startgroup"), startToken);
App::openPeerByName(telegramMeUser.captured(1), start == qsl("startgroup"), startToken);
} else if (telegramMeGroup.hasMatch()) {
App::joinGroupByHash(telegramMeGroup.captured(1));
} else if (telegramMeStickers.hasMatch()) {
@ -822,7 +822,7 @@ void EmailLink::onClick(Qt::MouseButton button) const {
void MentionLink::onClick(Qt::MouseButton button) const {
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
App::openUserByName(_tag.mid(1), true);
App::openPeerByName(_tag.mid(1), true);
}
}

View file

@ -500,7 +500,7 @@ void DialogsIndexed::peerNameChanged(PeerData *peer, const PeerData::Names &oldN
j = index.insert(*i, new DialogsList(sortMode));
}
if (sortMode == DialogsSortByDate) {
history->dialogs.insert(*i, j.value()->addByPos(history));
history->dialogs.insert(*i, j.value()->addToEnd(history));
} else {
j.value()->addToEnd(history);
}
@ -1033,11 +1033,6 @@ void History::newItemAdded(HistoryItem *item) {
notifies.push_back(item);
App::main()->newUnreadMsg(this, item);
}
if (dialogs.isEmpty()) {
App::main()->createDialogAtTop(this, unreadCount);
} else {
emit App::main()->dialogToTop(dialogs);
}
}
void History::addToFront(const QVector<MTPMessage> &slice) {
@ -1303,35 +1298,53 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
}
}
void History::inboxRead(int32 upTo) {
int32 History::countUnread(MsgId upTo) {
int32 result = 0;
for (const_iterator i = cend(), e = cbegin(); i != e;) {
--i;
for (HistoryBlock::const_iterator j = (*i)->cend(), en = (*i)->cbegin(); j != en;) {
--j;
if ((*j)->id > 0 && (*j)->id <= upTo) {
break;
} else if (!(*j)->out() && (*j)->unread() && (*j)->id > upTo) {
++result;
}
}
}
return result;
}
MsgId History::inboxRead(MsgId upTo) {
if (unreadCount) {
if (upTo && loadedAtBottom()) App::main()->historyToDown(this);
setUnreadCount(0);
}
if (!isEmpty()) {
int32 till = upTo ? upTo : back()->back()->id;
if (inboxReadTill < till) inboxReadTill = till;
setUnreadCount(upTo ? countUnread(upTo) : 0);
}
if (!upTo) upTo = msgIdForRead();
if (inboxReadTill < upTo) inboxReadTill = upTo;
if (!dialogs.isEmpty()) {
if (App::main()) App::main()->dlgUpdated(dialogs[0]);
}
showFrom = 0;
App::wnd()->notifyClear(this);
clearNotifications();
return upTo;
}
void History::inboxRead(HistoryItem *wasRead) {
MsgId History::inboxRead(HistoryItem *wasRead) {
return inboxRead(wasRead ? wasRead->id : 0);
}
void History::outboxRead(int32 upTo) {
if (!isEmpty()) {
int32 till = upTo ? upTo : back()->back()->id;
if (outboxReadTill < till) outboxReadTill = till;
}
MsgId History::outboxRead(int32 upTo) {
if (!upTo) upTo = msgIdForRead();
if (outboxReadTill < upTo) outboxReadTill = upTo;
return upTo;
}
void History::outboxRead(HistoryItem *wasRead) {
MsgId History::outboxRead(HistoryItem *wasRead) {
return outboxRead(wasRead ? wasRead->id : 0);
}
@ -1450,22 +1463,38 @@ void History::getReadyFor(MsgId msgId) {
}
}
void History::setLastMessage(HistoryItem *msg) {
namespace {
uint32 _dialogsPosToTopShift = 0x80000000UL;
}
inline uint64 dialogPosFromDate(const QDateTime &date) {
return (uint64(date.toTime_t()) << 32) | (++_dialogsPosToTopShift);
}
void History::setLastMessage(HistoryItem *msg, bool updatePosInDialogs) {
if (msg) {
if (!lastMsg) Local::removeSavedPeer(peer);
lastMsg = msg;
lastMsgDate = msg->date;
if (updatePosInDialogs) setPosInDialogsDate(msg->date);
} else {
lastMsg = 0;
}
}
void History::setPosInDialogsDate(const QDateTime &date) {
lastMsgDate = date;
posInDialogs = dialogPosFromDate(lastMsgDate);
if (App::main()) {
App::main()->createDialogAtTop(this, unreadCount);
}
}
void History::fixLastMessage(bool wasAtBottom) {
if (wasAtBottom && isEmpty()) {
wasAtBottom = false;
}
if (wasAtBottom) {
setLastMessage(back()->back());
setLastMessage(back()->back(), false);
} else {
setLastMessage(0);
if (App::main()) {
@ -1498,6 +1527,12 @@ MsgId History::maxMsgId() const {
return 0;
}
MsgId History::msgIdForRead() const {
MsgId result = (lastMsg && lastMsg->id > 0) ? lastMsg->id : 0;
if (loadedAtBottom()) result = qMax(result, maxMsgId());
return result;
}
int32 History::geomResize(int32 newWidth, int32 *ytransform, bool dontRecountText) {
if (width != newWidth || dontRecountText) {
int32 y = 0;
@ -5811,7 +5846,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const
fwdNameUpdated();
}
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, ((history->peer->input.type() != mtpc_inputPeerSelf) ? (MTPDmessage_flag_out | MTPDmessage_flag_unread) : 0) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->HistoryMessage::textLinks(), msg->getMedia())
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, HistoryMessage *msg) : HistoryMessage(history, block, id, newMessageFlags(history->peer) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), ::date(unixtime()), MTP::authedId(), msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->HistoryMessage::textLinks(), msg->getMedia())
, fwdDate(msg->dateForwarded())
, fwdFrom(msg->fromForwarded())
, fwdFromVersion(fwdFrom->nameVersion)

View file

@ -194,10 +194,11 @@ struct History : public QList<HistoryBlock*> {
void newItemAdded(HistoryItem *item);
void unregTyping(UserData *from);
void inboxRead(int32 upTo);
void inboxRead(HistoryItem *wasRead);
void outboxRead(int32 upTo);
void outboxRead(HistoryItem *wasRead);
int32 countUnread(MsgId upTo);
MsgId inboxRead(MsgId upTo);
MsgId inboxRead(HistoryItem *wasRead);
MsgId outboxRead(MsgId upTo);
MsgId outboxRead(HistoryItem *wasRead);
void setUnreadCount(int32 newUnreadCount, bool psUpdate = true);
void setMsgCount(int32 newMsgCount);
@ -211,11 +212,13 @@ struct History : public QList<HistoryBlock*> {
bool isReadyFor(MsgId msgId, bool check = false) const; // has messages for showing history at msgId
void getReadyFor(MsgId msgId);
void setLastMessage(HistoryItem *msg);
void setLastMessage(HistoryItem *msg, bool updatePosInDialogs = true);
void setPosInDialogsDate(const QDateTime &date);
void fixLastMessage(bool wasAtBottom);
MsgId minMsgId() const;
MsgId maxMsgId() const;
MsgId msgIdForRead() const;
int32 geomResize(int32 newWidth, int32 *ytransform = 0, bool dontRecountText = false); // return new size
int32 width, height, msgCount, unreadCount;
@ -293,7 +296,7 @@ struct History : public QList<HistoryBlock*> {
typedef QMap<QChar, DialogRow*> DialogLinks;
DialogLinks dialogs;
int32 posInDialogs;
uint64 posInDialogs; // like ((unixtime) << 32) | (incremented counter)
typedef QMap<UserData*, uint64> TypingUsers;
TypingUsers typing;
@ -357,26 +360,21 @@ struct DialogsList {
return (pos == current->pos) ? current : 0;
}
DialogRow *addToEnd(History *history, bool updatePos = true) {
DialogRow *addToEnd(History *history) {
DialogRow *result = new DialogRow(history, end->prev, end, end->pos);
end->pos++;
if (begin == end) {
begin = current = result;
if (sortMode == DialogsSortByDate && updatePos) history->posInDialogs = 0;
} else {
end->prev->next = result;
if (sortMode == DialogsSortByDate && updatePos) history->posInDialogs = end->prev->history->posInDialogs + 1;
}
rowByPeer.insert(history->peer->id, result);
++count;
return (end->prev = result);
}
void bringToTop(DialogRow *row, bool updatePos = true) {
if (sortMode == DialogsSortByDate && updatePos && row != begin) {
row->history->posInDialogs = begin->history->posInDialogs - 1;
end->prev = result;
if (sortMode == DialogsSortByDate) {
adjustByPos(result);
}
insertBefore(row, begin);
return result;
}
bool insertBefore(DialogRow *row, DialogRow *before) {
@ -467,25 +465,21 @@ struct DialogsList {
if (sortMode != DialogsSortByDate) return;
DialogRow *change = row;
while (change->prev && change->prev->history->posInDialogs > row->history->posInDialogs) {
if (change != begin && begin->history->posInDialogs < row->history->posInDialogs) {
change = begin;
} else while (change->prev && change->prev->history->posInDialogs < row->history->posInDialogs) {
change = change->prev;
}
if (!insertBefore(row, change)) {
while (change->next != end && change->next->history->posInDialogs < row->history->posInDialogs) {
if (change->next != end && end->prev->history->posInDialogs > row->history->posInDialogs) {
change = end->prev;
} else while (change->next != end && change->next->history->posInDialogs > row->history->posInDialogs) {
change = change->next;
}
insertAfter(row, change);
}
}
DialogRow *addByPos(History *history) {
if (sortMode != DialogsSortByDate) return 0;
DialogRow *row = addToEnd(history, false);
adjustByPos(row);
return row;
}
bool del(const PeerId &peerId, DialogRow *replacedBy = 0);
void remove(DialogRow *row) {
@ -563,14 +557,14 @@ struct DialogsIndexed {
return res;
}
void bringToTop(const History::DialogLinks &links) {
void adjustByPos(const History::DialogLinks &links) {
for (History::DialogLinks::const_iterator i = links.cbegin(), e = links.cend(); i != e; ++i) {
if (i.key() == QChar(0)) {
list.bringToTop(i.value());
list.adjustByPos(i.value());
} else {
DialogsIndex::iterator j = index.find(i.key());
if (j != index.cend()) {
j.value()->bringToTop(i.value());
j.value()->adjustByPos(i.value());
}
}
}
@ -1199,6 +1193,11 @@ public:
}
ImagePtr replyPreview();
virtual bool animating() const {
if (_asArticle || !data->photo || data->photo->full->loaded()) return false;
return data->photo->full->loading();
}
WebPageData *webpage() {
return data;
}

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()) {
if (uponSelected && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode() && !hist->peer->isChannel()) {
mimeData->setData(qsl("application/x-td-forward-selected"), "1");
}
drag->setMimeData(mimeData);
@ -553,16 +553,18 @@ 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),
dragByDate = (_dragCursorState == HistoryInDateCursorState);
dragSticker = dynamic_cast<HistorySticker*>(pressedItem ? pressedItem->getMedia() : 0) && !hist->peer->isChannel(),
dragByDate = (_dragCursorState == HistoryInDateCursorState) && !hist->peer->isChannel();
if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact || dragSticker || dragByDate) {
QDrag *drag = new QDrag(App::wnd());
QMimeData *mimeData = new QMimeData;
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 (!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 (lnkDocument) {
QString already = static_cast<DocumentOpenLink*>(textlnkDown().data())->document()->already(true);
@ -810,20 +812,20 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang(lng_context_delete_selected), historyWidget, SLOT(onDeleteSelected()));
_menu->addAction(lang(lng_context_clear_selection), historyWidget, SLOT(onClearSelected()));
} else if (App::hoveredLinkItem()) {
if (isUponSelected != -2) {
if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem()) && App::hoveredLinkItem()->id > 0) {
if (isUponSelected != -2 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem()) && App::hoveredLinkItem()->id > 0 && !hist->peer->isChannel()) {
_menu->addAction(lang(lng_context_forward_msg), historyWidget, SLOT(forwardMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_delete_msg), historyWidget, SLOT(deleteMessage()))->setEnabled(true);
}
if (App::hoveredLinkItem()->id > 0) {
if (App::hoveredLinkItem()->id > 0 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
_menu->addAction(lang(lng_context_select_msg), historyWidget, SLOT(selectMessage()))->setEnabled(true);
}
App::contextItem(App::hoveredLinkItem());
}
} else { // maybe cursor on some text history item?
bool canDelete = (item && item->itemType() == HistoryItem::MsgType);
bool canForward = canDelete && (item->id > 0) && !item->serviceMsg();
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();
HistoryMessage *msg = dynamic_cast<HistoryMessage*>(item);
HistoryServiceMsg *srv = dynamic_cast<HistoryServiceMsg*>(item);
@ -889,11 +891,11 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang((msg && msg->uploading()) ? lng_context_cancel_upload : lng_context_delete_msg), historyWidget, SLOT(deleteMessage()))->setEnabled(true);
}
}
if (item->id > 0) {
if (item->id > 0 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
_menu->addAction(lang(lng_context_select_msg), historyWidget, SLOT(selectMessage()))->setEnabled(true);
}
} else {
if (App::mousedItem() && App::mousedItem()->itemType() == HistoryItem::MsgType && App::mousedItem()->id > 0) {
if (App::mousedItem() && App::mousedItem()->itemType() == HistoryItem::MsgType && App::mousedItem()->id > 0 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
if (!_menu) _menu = new ContextMenu(this);
_menu->addAction(lang(lng_context_select_msg), historyWidget, SLOT(selectMessage()))->setEnabled(true);
item = App::mousedItem();
@ -1264,7 +1266,7 @@ bool HistoryList::canCopySelected() const {
}
bool HistoryList::canDeleteSelected() const {
return !_selected.isEmpty() && (_selected.cbegin().value() == FullItemSel);
return !_selected.isEmpty() && (_selected.cbegin().value() == FullItemSel) && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned);
}
void HistoryList::getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const {
@ -1409,6 +1411,7 @@ void HistoryList::onUpdateSelected() {
}
cur = textlnkDown() ? style::cur_pointer : style::cur_default;
if (_dragAction == Selecting) {
bool canSelectMany = hist && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned);
if (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) {
bool afterSymbol, uponSymbol;
uint16 second;
@ -1421,7 +1424,7 @@ void HistoryList::onUpdateSelected() {
setFocus();
}
updateDragSelection(0, 0, false);
} else {
} else if (canSelectMany) {
bool selectingDown = (_dragItem->block()->y < item->block()->y) || ((_dragItem->block() == item->block()) && (_dragItem->y < item->y || (_dragItem == item && _dragStartPos.y() < m.y())));
HistoryItem *dragSelFrom = _dragItem, *dragSelTo = item;
if (!dragSelFrom->hasPoint(_dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom
@ -1504,6 +1507,10 @@ void HistoryList::applyDragSelection() {
}
void HistoryList::applyDragSelection(SelectedItems *toItems) const {
if (hist && hist->peer->isChannel() && !hist->peer->asChannel()->adminned) {
toItems->clear();
return;
}
if (!toItems->isEmpty() && toItems->cbegin().value() != FullItemSel) {
toItems->clear();
}
@ -2942,7 +2949,7 @@ void HistoryWidget::updateControlsVisibility() {
} else if (_peer->isChat()) {
avail = !_peer->asChat()->forbidden && !_peer->asChat()->left;
} else if (_peer->isChannel()) {
avail = !_peer->asChannel()->forbidden && !_peer->asChannel()->left;
avail = !_peer->asChannel()->forbidden && !_peer->asChannel()->left && _peer->asChannel()->adminned;
}
if (avail) {
checkMentionDropdown();
@ -3472,7 +3479,13 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const
flags |= MTPDmessage::flag_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(MTP::authedId()), peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup, MTPnullEntities));
bool fromChannelName = p->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
} else {
flags |= MTPDmessage::flag_from_id;
}
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup, MTPnullEntities));
h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, h->sendRequestId);
App::historyRegRandom(randomId, newId);
@ -4352,13 +4365,18 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
int32 flags = newMessageFlags(h->peer) | MTPDmessage::flag_media; // unread, out
if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id;
bool fromChannelName = h->peer->isChannel();
if (fromChannelName) {
} else {
flags |= MTPDmessage::flag_from_id;
}
if (img.type == ToPreparePhoto) {
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(MTP::authedId()), peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup, MTPnullEntities));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup, MTPnullEntities));
} else if (img.type == ToPrepareDocument) {
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(MTP::authedId()), peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities));
} else if (img.type == ToPrepareAudio) {
flags |= MTPDmessage_flag_media_unread;
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(MTP::authedId()), peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities));
}
if (_peer && img.peer == _peer->id) {
@ -4387,6 +4405,10 @@ void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, const MTPInputFile &
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
bool fromChannelName = hist->peer->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
}
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedPhoto(file, MTP_string("")), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendPhotoFailed, randomId), 0, 0, hist->sendRequestId);
}
}
@ -4427,6 +4449,10 @@ void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, const MTPInputFil
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
bool fromChannelName = hist->peer->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
}
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedDocument(file, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
}
}
@ -4451,6 +4477,10 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, const MTPInp
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
bool fromChannelName = hist->peer->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
}
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedThumbDocument(file, thumb, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
}
}
@ -4473,6 +4503,10 @@ void HistoryWidget::onAudioUploaded(const FullMsgId &newId, const MTPInputFile &
if (replyTo) {
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
bool fromChannelName = hist->peer->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
}
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedAudio(file, MTP_int(audio->duration), MTP_string(audio->mime)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
}
}
@ -4661,7 +4695,7 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
} else if (_peer->isChat()) {
avail = (!_peer->asChat()->forbidden && !_peer->asChat()->left);
} else if (_peer->isChannel()) {
avail = (!_peer->asChannel()->forbidden && !_peer->asChannel()->left);
avail = (!_peer->asChannel()->forbidden && !_peer->asChannel()->left && _peer->asChannel()->adminned);
}
if (avail) {
newScrollHeight -= (_field.height() + 2 * st::sendPadding);
@ -4971,7 +5005,11 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) {
flags |= MTPDmessage::flag_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
_history->addToBackDocument(newId.msg, flags, replyToId(), date(MTP_int(unixtime())), MTP::authedId(), sticker);
bool fromChannelName = _history->peer->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
}
_history->addToBackDocument(newId.msg, flags, replyToId(), date(MTP_int(unixtime())), fromChannelName ? 0 : MTP::authedId(), sticker);
_history->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), _peer->input, MTP_int(replyToId()), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, _history->sendRequestId);
App::main()->finishForwarding(_history);

View file

@ -33,7 +33,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "audio.h"
TopBarWidget::TopBarWidget(MainWidget *w) : TWidget(w),
a_over(0), _drawShadow(true), _selCount(0), _selStrLeft(-st::topBarButton.width / 2), _selStrWidth(0), _animating(false),
a_over(0), _drawShadow(true), _selPeer(0), _selCount(0), _selStrLeft(-st::topBarButton.width / 2), _selStrWidth(0), _animating(false),
_clearSelection(this, lang(lng_selected_clear), st::topBarButton),
_forward(this, lang(lng_selected_forward), st::topBarActionButton),
_delete(this, lang(lng_selected_delete), st::topBarActionButton),
@ -201,7 +201,7 @@ void TopBarWidget::mousePressEvent(QMouseEvent *e) {
void TopBarWidget::resizeEvent(QResizeEvent *e) {
int32 r = width();
if (!_forward.isHidden()) {
if (!_forward.isHidden() || !_delete.isHidden()) {
int32 fullW = r - (_selectionButtonsWidth + (_selStrWidth - st::topBarButton.width) + st::topBarActionSkip);
int32 selectedClearWidth = st::topBarButton.width, forwardDeleteWidth = st::topBarActionButton.width - _forwardDeleteWidth, skip = st::topBarActionSkip;
while (fullW < 0) {
@ -242,8 +242,14 @@ void TopBarWidget::resizeEvent(QResizeEvent *e) {
_selStrLeft = -selectedClearWidth / 2;
int32 availX = _selStrLeft + _selStrWidth, availW = r - (_clearSelection.width() + selectedClearWidth / 2) - availX;
_forward.move(availX + (availW - _forward.width() - _delete.width() - skip) / 2, (st::topBarHeight - _forward.height()) / 2);
_delete.move(availX + (availW + _forward.width() - _delete.width() + skip) / 2, (st::topBarHeight - _forward.height()) / 2);
if (_forward.isHidden()) {
_delete.move(availX + (availW - _delete.width()) / 2, (st::topBarHeight - _forward.height()) / 2);
} else if (_delete.isHidden()) {
_forward.move(availX + (availW - _forward.width()) / 2, (st::topBarHeight - _forward.height()) / 2);
} else {
_forward.move(availX + (availW - _forward.width() - _delete.width() - skip) / 2, (st::topBarHeight - _forward.height()) / 2);
_delete.move(availX + (availW + _forward.width() - _delete.width() + skip) / 2, (st::topBarHeight - _forward.height()) / 2);
}
_clearSelection.move(r -= _clearSelection.width(), 0);
}
if (!_info.isHidden()) _info.move(r -= _info.width(), 0);
@ -316,7 +322,11 @@ void TopBarWidget::showAll() {
if (!p && _selCount) {
_clearSelection.show();
_delete.show();
_forward.show();
if (!_selPeer || _selPeer->isChannel()) {
_forward.hide();
} else {
_forward.show();
}
_mediaType.hide();
} else {
_clearSelection.hide();
@ -339,6 +349,7 @@ void TopBarWidget::showAll() {
void TopBarWidget::showSelected(uint32 selCount) {
PeerData *p = App::main() ? App::main()->profilePeer() : 0;
_selPeer = App::main()->overviewPeer() ? App::main()->overviewPeer() : App::main()->peer();
_selCount = selCount;
_selStr = (_selCount > 0) ? lng_selected_count(lt_count, _selCount) : QString();
_selStrWidth = st::btnDefLink.font->m.width(_selStr);
@ -1085,8 +1096,14 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill)));
flags |= MTPDmessage::flag_media;
}
bool fromChannelName = hist->peer->isChannel();
if (fromChannelName) {
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
} else {
flags |= MTPDmessage::flag_from_id;
}
MTPVector<MTPMessageEntity> localEntities = linksToMTP(textParseLinks(sendingText, itemTextParseOptions(hist, App::self()).flags));
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(MTP::authedId()), peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, localEntities));
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, localEntities));
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, localEntities), App::main()->rpcDone(&MainWidget::sentUpdatesReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
}
@ -1131,10 +1148,17 @@ void MainWidget::readServerHistory(History *hist, bool force) {
if (!hist || (!force && !hist->unreadCount)) return;
ReadRequests::const_iterator i = _readRequests.constFind(hist->peer);
MsgId upTo = hist->inboxRead(0);
if (i == _readRequests.cend()) {
hist->inboxRead(0);
_readRequests.insert(hist->peer, MTP::send(MTPmessages_ReadHistory(hist->peer->input, MTP_int(0), MTP_int(0)), rpcDone(&MainWidget::partWasRead, hist->peer)));
}
sendReadRequest(hist->peer, upTo);
} else {
ReadRequestsPending::iterator i = _readRequestsPending.find(hist->peer);
if (i == _readRequestsPending.cend()) {
_readRequestsPending.insert(hist->peer, upTo);
} else if (i.value() < upTo) {
i.value() = upTo;
}
}
}
uint64 MainWidget::animActiveTime(MsgId id) const {
@ -1447,18 +1471,47 @@ void MainWidget::photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpR
if (App::wnd()) App::wnd()->mediaOverviewUpdated(h->peer, type);
}
void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) {
if (!MTP::authedId()) return;
if (peer->isChannel()) {
_readRequests.insert(peer, MTP::send(MTPmessages_ReadChannelHistory(peer->input, MTP_int(upTo)), rpcDone(&MainWidget::channelWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)));
} else {
//_readRequests.insert(peer, MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo), MTP_int(0)), rpcDone(&MainWidget::partWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)));
}
}
void MainWidget::channelWasRead(PeerData *peer, const MTPBool &result) {
readRequestDone(peer);
}
void MainWidget::partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result) {
const MTPDmessages_affectedHistory &d(result.c_messages_affectedHistory());
updPtsUpdated(d.vpts.v, d.vpts_count.v);
int32 offset = d.voffset.v;
if (!MTP::authedId() || offset <= 0) {
_readRequests.remove(peer);
if (!MTP::authedId() || offset <= 0 || true) {
readRequestDone(peer);
} else {
_readRequests[peer] = MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(0), MTP_int(offset)), rpcDone(&MainWidget::partWasRead, peer));
// _readRequests[peer] = MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo), MTP_int(offset)), rpcDone(&MainWidget::partWasRead, peer));
}
}
bool MainWidget::readRequestFail(PeerData *peer, const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
readRequestDone(peer);
return false;
}
void MainWidget::readRequestDone(PeerData *peer) {
_readRequests.remove(peer);
ReadRequestsPending::iterator i = _readRequestsPending.find(peer);
if (i != _readRequestsPending.cend()) {
sendReadRequest(peer, i.value());
_readRequestsPending.erase(i);
}
}
void MainWidget::messagesAffected(const MTPmessages_AffectedMessages &result) {
const MTPDmessages_affectedMessages &d(result.c_messages_affectedMessages());
updPtsUpdated(d.vpts.v, d.vpts_count.v);
@ -2178,7 +2231,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
if (overview) {
_stack.push_back(new StackItemOverview(overview->peer(), overview->type(), overview->lastWidth(), overview->lastScrollTop()));
} else if (profile) {
_stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop(), profile->allMediaShown()));
_stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop()));
} else if (history.peer()) {
_peerInStack = history.peer();
_msgIdInStack = history.msgId();
@ -2219,7 +2272,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
App::wnd()->getTitle()->updateBackButton();
}
void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop, bool allMediaShown) {
void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop) {
App::wnd()->hideSettings();
if (profile && profile->peer() == peer) return;
@ -2232,7 +2285,7 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop,
if (overview) {
_stack.push_back(new StackItemOverview(overview->peer(), overview->type(), overview->lastWidth(), overview->lastScrollTop()));
} else if (profile) {
_stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop(), profile->allMediaShown()));
_stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop()));
} else {
_peerInStack = history.peer();
_msgIdInStack = history.msgId();
@ -2255,7 +2308,7 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop,
profile = new ProfileWidget(this, peer);
_topBar.show();
resizeEvent(0);
profile->animShow(animCache, animTopBarCache, back, lastScrollTop, allMediaShown);
profile->animShow(animCache, animTopBarCache, back, lastScrollTop);
history.animStop();
if (back) clearBotStartToken(history.peer());
history.showPeerHistory(0, 0);
@ -2291,7 +2344,7 @@ void MainWidget::showBackFromStack() {
if (histItem->kbWasHidden) history.setKbWasHidden();
} else if (item->type() == ProfileStackItem) {
StackItemProfile *profItem = static_cast<StackItemProfile*>(item);
showPeerProfile(profItem->peer, true, profItem->lastScrollTop, profItem->allMediaShown);
showPeerProfile(profItem->peer, true, profItem->lastScrollTop);
} else if (item->type() == OverviewStackItem) {
StackItemOverview *overItem = static_cast<StackItemOverview*>(item);
showMediaOverview(overItem->peer, overItem->mediaType, true, overItem->lastScrollTop);
@ -2866,7 +2919,7 @@ void MainWidget::openLocalUrl(const QString &url) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://resolve/?\\?domain=([a-zA-Z0-9\\.\\_]+)(&(start|startgroup)=([a-zA-Z0-9\\.\\_\\-]+))?(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
if (m.hasMatch()) {
QString start = m.captured(3), startToken = m.captured(4);
openUserByName(m.captured(1), (start == qsl("startgroup")), startToken);
openPeerByName(m.captured(1), (start == qsl("startgroup")), startToken);
}
} else if (u.startsWith(qstr("tg://join"), Qt::CaseInsensitive)) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
@ -2881,27 +2934,27 @@ void MainWidget::openLocalUrl(const QString &url) {
}
}
void MainWidget::openUserByName(const QString &username, bool toProfile, const QString &startToken) {
void MainWidget::openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
App::wnd()->hideMediaview();
UserData *user = App::userByName(username);
if (user) {
PeerData *peer = App::peerByName(username);
if (peer) {
if (toProfile) {
if (user->botInfo && !user->botInfo->cantJoinGroups && !startToken.isEmpty()) {
user->botInfo->startGroupToken = startToken;
App::wnd()->showLayer(new ContactsBox(user));
if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
peer->asUser()->botInfo->startGroupToken = startToken;
App::wnd()->showLayer(new ContactsBox(peer->asUser()));
} else {
showPeerProfile(user);
showPeerProfile(peer);
}
} else {
if (user->botInfo) {
user->botInfo->startToken = startToken;
if (user == history.peer()) {
if (peer->isUser() && peer->asUser()->botInfo) {
peer->asUser()->botInfo->startToken = startToken;
if (peer == history.peer()) {
history.updateControlsVisibility();
history.resizeEvent(0);
}
}
emit showPeerAsync(user->id, 0);
emit showPeerAsync(peer->id, 0);
}
} else {
MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(toProfile, startToken)), rpcFail(&MainWidget::usernameResolveFail, username));
@ -2925,25 +2978,33 @@ void MainWidget::onStickersInstalled(uint64 setId) {
history.stickersInstalled(setId);
}
void MainWidget::usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPUser &result) {
void MainWidget::usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPcontacts_ResolvedPeer &result) {
App::wnd()->hideLayer();
UserData *user = App::feedUsers(MTP_vector<MTPUser>(1, result));
if (result.type() != mtpc_contacts_resolvedPeer) return;
const MTPDcontacts_resolvedPeer &d(result.c_contacts_resolvedPeer());
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
PeerId peerId = peerFromMTP(d.vpeer);
if (!peerId) return;
PeerData *peer = App::peer(peerId);
if (toProfileStartToken.first) {
if (user->botInfo && !user->botInfo->cantJoinGroups && !toProfileStartToken.second.isEmpty()) {
user->botInfo->startGroupToken = toProfileStartToken.second;
App::wnd()->showLayer(new ContactsBox(user));
if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !toProfileStartToken.second.isEmpty()) {
peer->asUser()->botInfo->startGroupToken = toProfileStartToken.second;
App::wnd()->showLayer(new ContactsBox(peer->asUser()));
} else {
showPeerProfile(user);
showPeerProfile(peer);
}
} else {
if (user->botInfo) {
user->botInfo->startToken = toProfileStartToken.second;
if (user == history.peer()) {
if (peer->isUser() && peer->asUser()->botInfo) {
peer->asUser()->botInfo->startToken = toProfileStartToken.second;
if (peer == history.peer()) {
history.updateControlsVisibility();
history.resizeEvent(0);
}
}
showPeerHistory(user->id, ShowAtUnreadMsgId);
showPeerHistory(peer->id, ShowAtUnreadMsgId);
}
}
@ -3517,22 +3578,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
}
} break;
case mtpc_updateNewChannelMessage: {
const MTPDupdateNewChannelMessage &d(update.c_updateNewChannelMessage());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links overview
App::checkEntitiesUpdate(d.vmessage.c_message());
}
HistoryItem *item = App::histories().addToBack(d.vmessage);
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
}
} break;
case mtpc_updateMessageID: {
const MTPDupdateMessageID &d(update.c_updateMessageID());
FullMsgId msg = App::histItemByRandom(d.vrandom_id.v);
@ -3811,5 +3856,49 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updatePrivacy: {
const MTPDupdatePrivacy &d(update.c_updatePrivacy());
} break;
case mtpc_updateNewChannelMessage: {
const MTPDupdateNewChannelMessage &d(update.c_updateNewChannelMessage());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links overview
App::checkEntitiesUpdate(d.vmessage.c_message());
}
HistoryItem *item = App::histories().addToBack(d.vmessage);
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
}
} break;
case mtpc_updateReadChannelInbox: {
const MTPDupdateReadChannelInbox &d(update.c_updateReadChannelInbox());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
App::feedInboxRead(peerFromMTP(d.vpeer), d.vmax_id.v);
} break;
case mtpc_updateDeleteChannelMessages: {
const MTPDupdateDeleteChannelMessages &d(update.c_updateDeleteChannelMessages());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
App::feedWereDeleted(peerToChannel(peerFromMTP(d.vpeer)), d.vmessages.c_vector().v);
history.peerMessagesUpdated();
} break;
case mtpc_updateChannelGroup: {
const MTPDupdateChannelGroup &d(update.c_updateChannelGroup());
} break;
case mtpc_updateChannelTooLong: {
const MTPDupdateChannelTooLong &d(update.c_updateChannelTooLong());
} break;
}
}

View file

@ -77,6 +77,7 @@ private:
anim::fvalue a_over;
bool _drawShadow;
PeerData *_selPeer;
uint32 _selCount;
QString _selStr;
int32 _selStrLeft, _selStrWidth;
@ -124,13 +125,12 @@ msgId(msgId), replyReturns(replyReturns), kbWasHidden(kbWasHidden) {
class StackItemProfile : public StackItem {
public:
StackItemProfile(PeerData *peer, int32 lastScrollTop, bool allMediaShown) : StackItem(peer), lastScrollTop(lastScrollTop), allMediaShown(allMediaShown) {
StackItemProfile(PeerData *peer, int32 lastScrollTop) : StackItem(peer), lastScrollTop(lastScrollTop) {
}
StackItemType type() const {
return ProfileStackItem;
}
int32 lastScrollTop;
bool allMediaShown;
};
class StackItemOverview : public StackItem {
@ -200,7 +200,7 @@ public:
void start(const MTPUser &user);
void openLocalUrl(const QString &str);
void openUserByName(const QString &name, bool toProfile = false, const QString &startToken = QString());
void openPeerByName(const QString &name, bool toProfile = false, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);
void stickersBox(const MTPInputStickerSet &set);
@ -244,7 +244,7 @@ public:
PeerData *profilePeer();
PeerData *overviewPeer();
bool mediaTypeSwitch();
void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false);
void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1);
void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
void showBackFromStack();
void orderWidgets();
@ -385,7 +385,6 @@ signals:
void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void peerPhotoChanged(PeerData *peer);
void dialogRowReplaced(DialogRow *oldRow, DialogRow *newRow);
void dialogToTop(const History::DialogLinks &links);
void dialogsUpdated();
void showPeerAsync(quint64 peerId, qint32 showAtMsgId);
void stickersUpdated();
@ -448,7 +447,12 @@ public slots:
private:
void sendReadRequest(PeerData *peer, MsgId upTo);
void channelWasRead(PeerData *peer, const MTPBool &result);
void partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result);
bool readRequestFail(PeerData *peer, const RPCError &error);
void readRequestDone(PeerData *peer);
void messagesAffected(const MTPmessages_AffectedMessages &result);
void photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req);
@ -483,7 +487,7 @@ private:
void handleUpdates(const MTPUpdates &updates, uint64 randomId = 0);
bool updateFail(const RPCError &e);
void usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPUser &result);
void usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPcontacts_ResolvedPeer &result);
bool usernameResolveFail(QString name, const RPCError &error);
void inviteCheckDone(QString hash, const MTPChatInvite &invite);
@ -539,6 +543,8 @@ private:
typedef QMap<PeerData*, mtpRequestId> ReadRequests;
ReadRequests _readRequests;
typedef QMap<PeerData*, MsgId> ReadRequestsPending;
ReadRequestsPending _readRequestsPending;
typedef QMap<PeerData*, mtpRequestId> OverviewsPreload;
OverviewsPreload _overviewPreload[OverviewCount], _overviewLoad[OverviewCount];

View file

@ -314,7 +314,7 @@ void MediaView::updateDropdown() {
_btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty());
_btnSaveAs->setVisible(true);
_btnCopy->setVisible((_doc && !_current.isNull()) || (_photo && _photo->full->loaded()));
_btnForward->setVisible(_msgid > 0);
_btnForward->setVisible(_msgid > 0 && !_channel);
_btnDelete->setVisible(_msgid > 0 || (_photo && App::self() && App::self()->photoId == _photo->id) || (_photo && _photo->peer && _photo->peer->photoId == _photo->id));
_btnViewAll->setVisible((_overview != OverviewCount) && _history);
_btnViewAll->setText(lang(_doc ? lng_mediaview_files_all : lng_mediaview_photos_all));

View file

@ -28,6 +28,7 @@ enum {
MTPDmessage_flag_HAS_TEXT_LINKS = (1 << 31), // client side flag for having links
MTPmessages_SendMessage_flag_skipWebPage = (1 << 1),
MTPmessages_SendMessage_flag_broadcast = (1 << 4),
MTPDdcOption_flag_ipv6 = (1 << 0),
MTPDdcOption_flag_files = (1 << 1),
@ -56,6 +57,8 @@ enum {
MTPupdates_ChannelDifference_flag_final = (1 << 0),
MTPDchannelMessagesFilter_flag_only_important = (1 << 0),
MTPmessages_CreateChannel_flag_broadcast = (1 << 0),
};
static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector<MTPKeyboardButtonRow>(0));

View file

@ -1254,9 +1254,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
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(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" 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(" version: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" username: "); ++stages.back(); if (flag & MTPDchannel::flag_username) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 5: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" version: "); ++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;
@ -1288,14 +1289,15 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" read_inbox_max_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(" unread_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" unread_important_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" inviter_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" invite_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(" chat_photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" notify_settings: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 8: to.add(" exported_invite: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" about: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" read_inbox_max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" unread_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" unread_important_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" inviter_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" invite_date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" chat_photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 8: to.add(" notify_settings: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 9: to.add(" exported_invite: "); ++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;
@ -3614,19 +3616,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ sendMessageChooseContactAction }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_contactFound:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ contactFound");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++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_contacts_found:
if (stage) {
to.add(",\n").addSpaces(lev);
@ -3636,7 +3625,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
switch (stage) {
case 0: to.add(" results: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" users: "); ++stages.back(); types.push_back(00); 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;
@ -4646,6 +4636,21 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ channelMessagesFilterCollapsed }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_contacts_resolvedPeer:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ contacts_resolvedPeer");
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(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" users: "); ++stages.back(); types.push_back(00); 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_req_pq:
if (stage) {
to.add(",\n").addSpaces(lev);
@ -5119,6 +5124,48 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_messages_editChatAbout:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_editChatAbout");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" chat_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" about: "); ++stages.back(); types.push_back(mtpc_string); 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_messages_checkChannelUsername:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_checkChannelUsername");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" chat_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); 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_messages_updateChannelUsername:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messages_updateChannelUsername");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" chat_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); 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_upload_saveFilePart:
if (stage) {
to.add(",\n").addSpaces(lev);
@ -5439,19 +5486,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_contacts_resolveUsername:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ contacts_resolveUsername");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); 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_account_getWallPapers:
to.add("{ account_getWallPapers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
@ -5636,6 +5670,19 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_contacts_resolveUsername:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ contacts_resolveUsername");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" username: "); ++stages.back(); types.push_back(mtpc_string); 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_messages_getMessages:
if (stage) {
to.add(",\n").addSpaces(lev);

View file

@ -135,9 +135,9 @@ enum {
mtpc_chatEmpty = 0x9ba2d800,
mtpc_chat = 0x6e9c9bc7,
mtpc_chatForbidden = 0xfb0ccc41,
mtpc_channel = 0x8dbb1461,
mtpc_channel = 0x1bcc63f2,
mtpc_chatFull = 0x2e02a614,
mtpc_channelFull = 0xa09d2902,
mtpc_channelFull = 0x5a090258,
mtpc_chatParticipant = 0xc8d7493e,
mtpc_chatParticipantsForbidden = 0xfd2bb8a,
mtpc_chatParticipants = 0x7841b415,
@ -319,8 +319,7 @@ enum {
mtpc_sendMessageUploadDocumentAction = 0xaa0cd9e4,
mtpc_sendMessageGeoLocationAction = 0x176f8ba1,
mtpc_sendMessageChooseContactAction = 0x628cbc6f,
mtpc_contactFound = 0xea879f95,
mtpc_contacts_found = 0x566000e,
mtpc_contacts_found = 0x1aa1f784,
mtpc_inputPrivacyKeyStatusTimestamp = 0x4f96cb18,
mtpc_privacyKeyStatusTimestamp = 0xbc2eab30,
mtpc_inputPrivacyValueAllowContacts = 0xd09e07b,
@ -407,6 +406,7 @@ enum {
mtpc_channelMessagesFilterEmpty = 0x94d42ee7,
mtpc_channelMessagesFilter = 0xcd77d957,
mtpc_channelMessagesFilterCollapsed = 0xfa01232e,
mtpc_contacts_resolvedPeer = 0x7f077ad9,
mtpc_invokeAfterMsg = 0xcb9f372d,
mtpc_invokeAfterMsgs = 0x3dc4b4f0,
mtpc_initConnection = 0x69796de9,
@ -465,7 +465,7 @@ enum {
mtpc_contacts_exportCard = 0x84e53737,
mtpc_contacts_importCard = 0x4fe196fe,
mtpc_contacts_search = 0x11f812d8,
mtpc_contacts_resolveUsername = 0xbf0131c,
mtpc_contacts_resolveUsername = 0xf93ccba3,
mtpc_messages_getMessages = 0x4222fa74,
mtpc_messages_getDialogs = 0x859b3d3c,
mtpc_messages_getHistory = 0x8a8ec2da,
@ -513,6 +513,9 @@ enum {
mtpc_messages_readChannelHistory = 0x36a1210e,
mtpc_messages_createChannel = 0xe830f8cb,
mtpc_messages_deleteChannelMessages = 0x9995a84f,
mtpc_messages_editChatAbout = 0x8a969b93,
mtpc_messages_checkChannelUsername = 0xe6d2d8f4,
mtpc_messages_updateChannelUsername = 0xce2e9587,
mtpc_updates_getState = 0xedd4882a,
mtpc_updates_getDifference = 0xa041495,
mtpc_updates_getChannelDifference = 0x248af4f5,
@ -965,9 +968,6 @@ class MTPDsendMessageUploadAudioAction;
class MTPDsendMessageUploadPhotoAction;
class MTPDsendMessageUploadDocumentAction;
class MTPcontactFound;
class MTPDcontactFound;
class MTPcontacts_found;
class MTPDcontacts_found;
@ -1111,6 +1111,9 @@ class MTPDupdates_channelDifference;
class MTPchannelMessagesFilter;
class MTPDchannelMessagesFilter;
class MTPcontacts_resolvedPeer;
class MTPDcontacts_resolvedPeer;
// Boxed types definitions
typedef MTPBoxed<MTPresPQ> MTPResPQ;
@ -1220,7 +1223,6 @@ typedef MTPBoxed<MTPdocument> MTPDocument;
typedef MTPBoxed<MTPhelp_support> MTPhelp_Support;
typedef MTPBoxed<MTPnotifyPeer> MTPNotifyPeer;
typedef MTPBoxed<MTPsendMessageAction> MTPSendMessageAction;
typedef MTPBoxed<MTPcontactFound> MTPContactFound;
typedef MTPBoxed<MTPcontacts_found> MTPcontacts_Found;
typedef MTPBoxed<MTPinputPrivacyKey> MTPInputPrivacyKey;
typedef MTPBoxed<MTPprivacyKey> MTPPrivacyKey;
@ -1261,6 +1263,7 @@ typedef MTPBoxed<MTPmessageRange> MTPMessageRange;
typedef MTPBoxed<MTPmessageGroup> MTPMessageGroup;
typedef MTPBoxed<MTPupdates_channelDifference> MTPupdates_ChannelDifference;
typedef MTPBoxed<MTPchannelMessagesFilter> MTPChannelMessagesFilter;
typedef MTPBoxed<MTPcontacts_resolvedPeer> MTPcontacts_ResolvedPeer;
// Type classes definitions
@ -3177,7 +3180,7 @@ private:
friend MTPchat MTP_chatEmpty(MTPint _id);
friend MTPchat MTP_chat(MTPint _id, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _participants_count, MTPint _date, MTPBool _left, MTPint _version);
friend MTPchat MTP_chatForbidden(MTPint _id, const MTPstring &_title, MTPint _date);
friend MTPchat MTP_channel(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _date, MTPint _version);
friend MTPchat MTP_channel(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPstring &_username, const MTPChatPhoto &_photo, MTPint _date, MTPint _version);
mtpTypeId _type;
};
@ -3228,7 +3231,7 @@ private:
explicit MTPchatFull(MTPDchannelFull *_data);
friend MTPchatFull MTP_chatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite, const MTPVector<MTPBotInfo> &_bot_info);
friend MTPchatFull MTP_channelFull(MTPint _id, MTPint _read_inbox_max_id, MTPint _unread_count, MTPint _unread_important_count, MTPint _inviter_id, MTPint _invite_date, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite);
friend MTPchatFull MTP_channelFull(MTPint _id, const MTPstring &_about, MTPint _read_inbox_max_id, MTPint _unread_count, MTPint _unread_important_count, MTPint _inviter_id, MTPint _invite_date, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite);
mtpTypeId _type;
};
@ -6577,37 +6580,6 @@ private:
};
typedef MTPBoxed<MTPsendMessageAction> MTPSendMessageAction;
class MTPcontactFound : private mtpDataOwner {
public:
MTPcontactFound();
MTPcontactFound(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_contactFound) : mtpDataOwner(0) {
read(from, end, cons);
}
MTPDcontactFound &_contactFound() {
if (!data) throw mtpErrorUninitialized();
split();
return *(MTPDcontactFound*)data;
}
const MTPDcontactFound &c_contactFound() const {
if (!data) throw mtpErrorUninitialized();
return *(const MTPDcontactFound*)data;
}
uint32 innerLength() const;
mtpTypeId type() const;
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_contactFound);
void write(mtpBuffer &to) const;
typedef void ResponseType;
private:
explicit MTPcontactFound(MTPDcontactFound *_data);
friend MTPcontactFound MTP_contactFound(MTPint _user_id);
};
typedef MTPBoxed<MTPcontactFound> MTPContactFound;
class MTPcontacts_found : private mtpDataOwner {
public:
MTPcontacts_found();
@ -6635,7 +6607,7 @@ public:
private:
explicit MTPcontacts_found(MTPDcontacts_found *_data);
friend MTPcontacts_found MTP_contacts_found(const MTPVector<MTPContactFound> &_results, const MTPVector<MTPUser> &_users);
friend MTPcontacts_found MTP_contacts_found(const MTPVector<MTPPeer> &_results, const MTPVector<MTPChat> &_chats, const MTPVector<MTPUser> &_users);
};
typedef MTPBoxed<MTPcontacts_found> MTPcontacts_Found;
@ -8308,6 +8280,37 @@ private:
};
typedef MTPBoxed<MTPchannelMessagesFilter> MTPChannelMessagesFilter;
class MTPcontacts_resolvedPeer : private mtpDataOwner {
public:
MTPcontacts_resolvedPeer();
MTPcontacts_resolvedPeer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_contacts_resolvedPeer) : mtpDataOwner(0) {
read(from, end, cons);
}
MTPDcontacts_resolvedPeer &_contacts_resolvedPeer() {
if (!data) throw mtpErrorUninitialized();
split();
return *(MTPDcontacts_resolvedPeer*)data;
}
const MTPDcontacts_resolvedPeer &c_contacts_resolvedPeer() const {
if (!data) throw mtpErrorUninitialized();
return *(const MTPDcontacts_resolvedPeer*)data;
}
uint32 innerLength() const;
mtpTypeId type() const;
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_contacts_resolvedPeer);
void write(mtpBuffer &to) const;
typedef void ResponseType;
private:
explicit MTPcontacts_resolvedPeer(MTPDcontacts_resolvedPeer *_data);
friend MTPcontacts_resolvedPeer MTP_contacts_resolvedPeer(const MTPPeer &_peer, const MTPVector<MTPChat> &_chats, const MTPVector<MTPUser> &_users);
};
typedef MTPBoxed<MTPcontacts_resolvedPeer> MTPcontacts_ResolvedPeer;
// Type constructors with data
class MTPDresPQ : public mtpDataImpl<MTPDresPQ> {
@ -9193,16 +9196,23 @@ class MTPDchannel : public mtpDataImpl<MTPDchannel> {
public:
MTPDchannel() {
}
MTPDchannel(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _date, MTPint _version) : vflags(_flags), vid(_id), vaccess_hash(_access_hash), vtitle(_title), vphoto(_photo), vdate(_date), vversion(_version) {
MTPDchannel(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPstring &_username, const MTPChatPhoto &_photo, MTPint _date, MTPint _version) : vflags(_flags), vid(_id), vaccess_hash(_access_hash), vtitle(_title), vusername(_username), vphoto(_photo), vdate(_date), vversion(_version) {
}
MTPint vflags;
MTPint vid;
MTPlong vaccess_hash;
MTPstring vtitle;
MTPstring vusername;
MTPChatPhoto vphoto;
MTPint vdate;
MTPint vversion;
enum {
flag_username = (1 << 2),
};
bool has_username() const { return vflags.v & flag_username; }
};
class MTPDchatFull : public mtpDataImpl<MTPDchatFull> {
@ -9224,10 +9234,11 @@ class MTPDchannelFull : public mtpDataImpl<MTPDchannelFull> {
public:
MTPDchannelFull() {
}
MTPDchannelFull(MTPint _id, MTPint _read_inbox_max_id, MTPint _unread_count, MTPint _unread_important_count, MTPint _inviter_id, MTPint _invite_date, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite) : vid(_id), vread_inbox_max_id(_read_inbox_max_id), vunread_count(_unread_count), vunread_important_count(_unread_important_count), vinviter_id(_inviter_id), vinvite_date(_invite_date), vchat_photo(_chat_photo), vnotify_settings(_notify_settings), vexported_invite(_exported_invite) {
MTPDchannelFull(MTPint _id, const MTPstring &_about, MTPint _read_inbox_max_id, MTPint _unread_count, MTPint _unread_important_count, MTPint _inviter_id, MTPint _invite_date, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite) : vid(_id), vabout(_about), vread_inbox_max_id(_read_inbox_max_id), vunread_count(_unread_count), vunread_important_count(_unread_important_count), vinviter_id(_inviter_id), vinvite_date(_invite_date), vchat_photo(_chat_photo), vnotify_settings(_notify_settings), vexported_invite(_exported_invite) {
}
MTPint vid;
MTPstring vabout;
MTPint vread_inbox_max_id;
MTPint vunread_count;
MTPint vunread_important_count;
@ -11032,24 +11043,15 @@ public:
MTPint vprogress;
};
class MTPDcontactFound : public mtpDataImpl<MTPDcontactFound> {
public:
MTPDcontactFound() {
}
MTPDcontactFound(MTPint _user_id) : vuser_id(_user_id) {
}
MTPint vuser_id;
};
class MTPDcontacts_found : public mtpDataImpl<MTPDcontacts_found> {
public:
MTPDcontacts_found() {
}
MTPDcontacts_found(const MTPVector<MTPContactFound> &_results, const MTPVector<MTPUser> &_users) : vresults(_results), vusers(_users) {
MTPDcontacts_found(const MTPVector<MTPPeer> &_results, const MTPVector<MTPChat> &_chats, const MTPVector<MTPUser> &_users) : vresults(_results), vchats(_chats), vusers(_users) {
}
MTPVector<MTPContactFound> vresults;
MTPVector<MTPPeer> vresults;
MTPVector<MTPChat> vchats;
MTPVector<MTPUser> vusers;
};
@ -11834,6 +11836,18 @@ public:
MTPVector<MTPMessageRange> vranges;
};
class MTPDcontacts_resolvedPeer : public mtpDataImpl<MTPDcontacts_resolvedPeer> {
public:
MTPDcontacts_resolvedPeer() {
}
MTPDcontacts_resolvedPeer(const MTPPeer &_peer, const MTPVector<MTPChat> &_chats, const MTPVector<MTPUser> &_users) : vpeer(_peer), vchats(_chats), vusers(_users) {
}
MTPPeer vpeer;
MTPVector<MTPChat> vchats;
MTPVector<MTPUser> vusers;
};
// RPC methods
class MTPreq_pq { // RPC method 'req_pq'
@ -14562,7 +14576,7 @@ public:
vusername.write(to);
}
typedef MTPUser ResponseType;
typedef MTPcontacts_ResolvedPeer ResponseType;
};
class MTPcontacts_ResolveUsername : public MTPBoxed<MTPcontacts_resolveUsername> {
public:
@ -16637,6 +16651,132 @@ public:
}
};
class MTPmessages_editChatAbout { // RPC method 'messages.editChatAbout'
public:
MTPInputChat vchat_id;
MTPstring vabout;
MTPmessages_editChatAbout() {
}
MTPmessages_editChatAbout(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_editChatAbout) {
read(from, end, cons);
}
MTPmessages_editChatAbout(const MTPInputChat &_chat_id, const MTPstring &_about) : vchat_id(_chat_id), vabout(_about) {
}
uint32 innerLength() const {
return vchat_id.innerLength() + vabout.innerLength();
}
mtpTypeId type() const {
return mtpc_messages_editChatAbout;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_editChatAbout) {
vchat_id.read(from, end);
vabout.read(from, end);
}
void write(mtpBuffer &to) const {
vchat_id.write(to);
vabout.write(to);
}
typedef MTPBool ResponseType;
};
class MTPmessages_EditChatAbout : public MTPBoxed<MTPmessages_editChatAbout> {
public:
MTPmessages_EditChatAbout() {
}
MTPmessages_EditChatAbout(const MTPmessages_editChatAbout &v) : MTPBoxed<MTPmessages_editChatAbout>(v) {
}
MTPmessages_EditChatAbout(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_editChatAbout>(from, end, cons) {
}
MTPmessages_EditChatAbout(const MTPInputChat &_chat_id, const MTPstring &_about) : MTPBoxed<MTPmessages_editChatAbout>(MTPmessages_editChatAbout(_chat_id, _about)) {
}
};
class MTPmessages_checkChannelUsername { // RPC method 'messages.checkChannelUsername'
public:
MTPInputChat vchat_id;
MTPstring vusername;
MTPmessages_checkChannelUsername() {
}
MTPmessages_checkChannelUsername(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_checkChannelUsername) {
read(from, end, cons);
}
MTPmessages_checkChannelUsername(const MTPInputChat &_chat_id, const MTPstring &_username) : vchat_id(_chat_id), vusername(_username) {
}
uint32 innerLength() const {
return vchat_id.innerLength() + vusername.innerLength();
}
mtpTypeId type() const {
return mtpc_messages_checkChannelUsername;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_checkChannelUsername) {
vchat_id.read(from, end);
vusername.read(from, end);
}
void write(mtpBuffer &to) const {
vchat_id.write(to);
vusername.write(to);
}
typedef MTPBool ResponseType;
};
class MTPmessages_CheckChannelUsername : public MTPBoxed<MTPmessages_checkChannelUsername> {
public:
MTPmessages_CheckChannelUsername() {
}
MTPmessages_CheckChannelUsername(const MTPmessages_checkChannelUsername &v) : MTPBoxed<MTPmessages_checkChannelUsername>(v) {
}
MTPmessages_CheckChannelUsername(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_checkChannelUsername>(from, end, cons) {
}
MTPmessages_CheckChannelUsername(const MTPInputChat &_chat_id, const MTPstring &_username) : MTPBoxed<MTPmessages_checkChannelUsername>(MTPmessages_checkChannelUsername(_chat_id, _username)) {
}
};
class MTPmessages_updateChannelUsername { // RPC method 'messages.updateChannelUsername'
public:
MTPInputChat vchat_id;
MTPstring vusername;
MTPmessages_updateChannelUsername() {
}
MTPmessages_updateChannelUsername(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_updateChannelUsername) {
read(from, end, cons);
}
MTPmessages_updateChannelUsername(const MTPInputChat &_chat_id, const MTPstring &_username) : vchat_id(_chat_id), vusername(_username) {
}
uint32 innerLength() const {
return vchat_id.innerLength() + vusername.innerLength();
}
mtpTypeId type() const {
return mtpc_messages_updateChannelUsername;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_updateChannelUsername) {
vchat_id.read(from, end);
vusername.read(from, end);
}
void write(mtpBuffer &to) const {
vchat_id.write(to);
vusername.write(to);
}
typedef MTPBool ResponseType;
};
class MTPmessages_UpdateChannelUsername : public MTPBoxed<MTPmessages_updateChannelUsername> {
public:
MTPmessages_UpdateChannelUsername() {
}
MTPmessages_UpdateChannelUsername(const MTPmessages_updateChannelUsername &v) : MTPBoxed<MTPmessages_updateChannelUsername>(v) {
}
MTPmessages_UpdateChannelUsername(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_updateChannelUsername>(from, end, cons) {
}
MTPmessages_UpdateChannelUsername(const MTPInputChat &_chat_id, const MTPstring &_username) : MTPBoxed<MTPmessages_updateChannelUsername>(MTPmessages_updateChannelUsername(_chat_id, _username)) {
}
};
class MTPupdates_getState { // RPC method 'updates.getState'
public:
MTPupdates_getState() {
@ -19773,7 +19913,7 @@ inline uint32 MTPchat::innerLength() const {
}
case mtpc_channel: {
const MTPDchannel &v(c_channel());
return v.vflags.innerLength() + v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vtitle.innerLength() + v.vphoto.innerLength() + v.vdate.innerLength() + v.vversion.innerLength();
return v.vflags.innerLength() + v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vtitle.innerLength() + (v.has_username() ? v.vusername.innerLength() : 0) + v.vphoto.innerLength() + v.vdate.innerLength() + v.vversion.innerLength();
}
}
return 0;
@ -19815,6 +19955,7 @@ inline void MTPchat::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId
v.vid.read(from, end);
v.vaccess_hash.read(from, end);
v.vtitle.read(from, end);
if (v.has_username()) { v.vusername.read(from, end); } else { v.vusername = MTPstring(); }
v.vphoto.read(from, end);
v.vdate.read(from, end);
v.vversion.read(from, end);
@ -19850,6 +19991,7 @@ inline void MTPchat::write(mtpBuffer &to) const {
v.vid.write(to);
v.vaccess_hash.write(to);
v.vtitle.write(to);
if (v.has_username()) v.vusername.write(to);
v.vphoto.write(to);
v.vdate.write(to);
v.vversion.write(to);
@ -19882,8 +20024,8 @@ inline MTPchat MTP_chat(MTPint _id, const MTPstring &_title, const MTPChatPhoto
inline MTPchat MTP_chatForbidden(MTPint _id, const MTPstring &_title, MTPint _date) {
return MTPchat(new MTPDchatForbidden(_id, _title, _date));
}
inline MTPchat MTP_channel(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPChatPhoto &_photo, MTPint _date, MTPint _version) {
return MTPchat(new MTPDchannel(_flags, _id, _access_hash, _title, _photo, _date, _version));
inline MTPchat MTP_channel(MTPint _flags, MTPint _id, const MTPlong &_access_hash, const MTPstring &_title, const MTPstring &_username, const MTPChatPhoto &_photo, MTPint _date, MTPint _version) {
return MTPchat(new MTPDchannel(_flags, _id, _access_hash, _title, _username, _photo, _date, _version));
}
inline uint32 MTPchatFull::innerLength() const {
@ -19894,7 +20036,7 @@ inline uint32 MTPchatFull::innerLength() const {
}
case mtpc_channelFull: {
const MTPDchannelFull &v(c_channelFull());
return v.vid.innerLength() + v.vread_inbox_max_id.innerLength() + v.vunread_count.innerLength() + v.vunread_important_count.innerLength() + v.vinviter_id.innerLength() + v.vinvite_date.innerLength() + v.vchat_photo.innerLength() + v.vnotify_settings.innerLength() + v.vexported_invite.innerLength();
return v.vid.innerLength() + v.vabout.innerLength() + v.vread_inbox_max_id.innerLength() + v.vunread_count.innerLength() + v.vunread_important_count.innerLength() + v.vinviter_id.innerLength() + v.vinvite_date.innerLength() + v.vchat_photo.innerLength() + v.vnotify_settings.innerLength() + v.vexported_invite.innerLength();
}
}
return 0;
@ -19920,6 +20062,7 @@ inline void MTPchatFull::read(const mtpPrime *&from, const mtpPrime *end, mtpTyp
if (!data) setData(new MTPDchannelFull());
MTPDchannelFull &v(_channelFull());
v.vid.read(from, end);
v.vabout.read(from, end);
v.vread_inbox_max_id.read(from, end);
v.vunread_count.read(from, end);
v.vunread_important_count.read(from, end);
@ -19946,6 +20089,7 @@ inline void MTPchatFull::write(mtpBuffer &to) const {
case mtpc_channelFull: {
const MTPDchannelFull &v(c_channelFull());
v.vid.write(to);
v.vabout.write(to);
v.vread_inbox_max_id.write(to);
v.vunread_count.write(to);
v.vunread_important_count.write(to);
@ -19971,8 +20115,8 @@ inline MTPchatFull::MTPchatFull(MTPDchannelFull *_data) : mtpDataOwner(_data), _
inline MTPchatFull MTP_chatFull(MTPint _id, const MTPChatParticipants &_participants, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite, const MTPVector<MTPBotInfo> &_bot_info) {
return MTPchatFull(new MTPDchatFull(_id, _participants, _chat_photo, _notify_settings, _exported_invite, _bot_info));
}
inline MTPchatFull MTP_channelFull(MTPint _id, MTPint _read_inbox_max_id, MTPint _unread_count, MTPint _unread_important_count, MTPint _inviter_id, MTPint _invite_date, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite) {
return MTPchatFull(new MTPDchannelFull(_id, _read_inbox_max_id, _unread_count, _unread_important_count, _inviter_id, _invite_date, _chat_photo, _notify_settings, _exported_invite));
inline MTPchatFull MTP_channelFull(MTPint _id, const MTPstring &_about, MTPint _read_inbox_max_id, MTPint _unread_count, MTPint _unread_important_count, MTPint _inviter_id, MTPint _invite_date, const MTPPhoto &_chat_photo, const MTPPeerNotifySettings &_notify_settings, const MTPExportedChatInvite &_exported_invite) {
return MTPchatFull(new MTPDchannelFull(_id, _about, _read_inbox_max_id, _unread_count, _unread_important_count, _inviter_id, _invite_date, _chat_photo, _notify_settings, _exported_invite));
}
inline MTPchatParticipant::MTPchatParticipant() : mtpDataOwner(new MTPDchatParticipant()) {
@ -24641,39 +24785,12 @@ inline MTPsendMessageAction MTP_sendMessageChooseContactAction() {
return MTPsendMessageAction(mtpc_sendMessageChooseContactAction);
}
inline MTPcontactFound::MTPcontactFound() : mtpDataOwner(new MTPDcontactFound()) {
}
inline uint32 MTPcontactFound::innerLength() const {
const MTPDcontactFound &v(c_contactFound());
return v.vuser_id.innerLength();
}
inline mtpTypeId MTPcontactFound::type() const {
return mtpc_contactFound;
}
inline void MTPcontactFound::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
if (cons != mtpc_contactFound) throw mtpErrorUnexpected(cons, "MTPcontactFound");
if (!data) setData(new MTPDcontactFound());
MTPDcontactFound &v(_contactFound());
v.vuser_id.read(from, end);
}
inline void MTPcontactFound::write(mtpBuffer &to) const {
const MTPDcontactFound &v(c_contactFound());
v.vuser_id.write(to);
}
inline MTPcontactFound::MTPcontactFound(MTPDcontactFound *_data) : mtpDataOwner(_data) {
}
inline MTPcontactFound MTP_contactFound(MTPint _user_id) {
return MTPcontactFound(new MTPDcontactFound(_user_id));
}
inline MTPcontacts_found::MTPcontacts_found() : mtpDataOwner(new MTPDcontacts_found()) {
}
inline uint32 MTPcontacts_found::innerLength() const {
const MTPDcontacts_found &v(c_contacts_found());
return v.vresults.innerLength() + v.vusers.innerLength();
return v.vresults.innerLength() + v.vchats.innerLength() + v.vusers.innerLength();
}
inline mtpTypeId MTPcontacts_found::type() const {
return mtpc_contacts_found;
@ -24684,17 +24801,19 @@ inline void MTPcontacts_found::read(const mtpPrime *&from, const mtpPrime *end,
if (!data) setData(new MTPDcontacts_found());
MTPDcontacts_found &v(_contacts_found());
v.vresults.read(from, end);
v.vchats.read(from, end);
v.vusers.read(from, end);
}
inline void MTPcontacts_found::write(mtpBuffer &to) const {
const MTPDcontacts_found &v(c_contacts_found());
v.vresults.write(to);
v.vchats.write(to);
v.vusers.write(to);
}
inline MTPcontacts_found::MTPcontacts_found(MTPDcontacts_found *_data) : mtpDataOwner(_data) {
}
inline MTPcontacts_found MTP_contacts_found(const MTPVector<MTPContactFound> &_results, const MTPVector<MTPUser> &_users) {
return MTPcontacts_found(new MTPDcontacts_found(_results, _users));
inline MTPcontacts_found MTP_contacts_found(const MTPVector<MTPPeer> &_results, const MTPVector<MTPChat> &_chats, const MTPVector<MTPUser> &_users) {
return MTPcontacts_found(new MTPDcontacts_found(_results, _chats, _users));
}
inline uint32 MTPinputPrivacyKey::innerLength() const {
@ -26818,6 +26937,37 @@ inline MTPchannelMessagesFilter MTP_channelMessagesFilterCollapsed() {
return MTPchannelMessagesFilter(mtpc_channelMessagesFilterCollapsed);
}
inline MTPcontacts_resolvedPeer::MTPcontacts_resolvedPeer() : mtpDataOwner(new MTPDcontacts_resolvedPeer()) {
}
inline uint32 MTPcontacts_resolvedPeer::innerLength() const {
const MTPDcontacts_resolvedPeer &v(c_contacts_resolvedPeer());
return v.vpeer.innerLength() + v.vchats.innerLength() + v.vusers.innerLength();
}
inline mtpTypeId MTPcontacts_resolvedPeer::type() const {
return mtpc_contacts_resolvedPeer;
}
inline void MTPcontacts_resolvedPeer::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
if (cons != mtpc_contacts_resolvedPeer) throw mtpErrorUnexpected(cons, "MTPcontacts_resolvedPeer");
if (!data) setData(new MTPDcontacts_resolvedPeer());
MTPDcontacts_resolvedPeer &v(_contacts_resolvedPeer());
v.vpeer.read(from, end);
v.vchats.read(from, end);
v.vusers.read(from, end);
}
inline void MTPcontacts_resolvedPeer::write(mtpBuffer &to) const {
const MTPDcontacts_resolvedPeer &v(c_contacts_resolvedPeer());
v.vpeer.write(to);
v.vchats.write(to);
v.vusers.write(to);
}
inline MTPcontacts_resolvedPeer::MTPcontacts_resolvedPeer(MTPDcontacts_resolvedPeer *_data) : mtpDataOwner(_data) {
}
inline MTPcontacts_resolvedPeer MTP_contacts_resolvedPeer(const MTPPeer &_peer, const MTPVector<MTPChat> &_chats, const MTPVector<MTPUser> &_users) {
return MTPcontacts_resolvedPeer(new MTPDcontacts_resolvedPeer(_peer, _chats, _users));
}
// Human-readable text serialization
#if (defined _DEBUG || defined _WITH_DEBUG)

View file

@ -218,10 +218,10 @@ userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#9ba2d800 id:int = Chat;
chat#6e9c9bc7 id:int title:string photo:ChatPhoto participants_count:int date:int left:Bool version:int = Chat;
chatForbidden#fb0ccc41 id:int title:string date:int = Chat;
channel#8dbb1461 flags:# id:int access_hash:long title:string photo:ChatPhoto date:int version:int = Chat;
channel#1bcc63f2 flags:# id:int access_hash:long title:string username:flags.2?string photo:ChatPhoto date:int version:int = Chat;
chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> = ChatFull;
channelFull#a09d2902 id:int read_inbox_max_id:int unread_count:int unread_important_count:int inviter_id:int invite_date:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite = ChatFull;
channelFull#5a090258 id:int about:string read_inbox_max_id:int unread_count:int unread_important_count:int inviter_id:int invite_date:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite = ChatFull;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
@ -468,9 +468,7 @@ sendMessageUploadDocumentAction#aa0cd9e4 progress:int = SendMessageAction;
sendMessageGeoLocationAction#176f8ba1 = SendMessageAction;
sendMessageChooseContactAction#628cbc6f = SendMessageAction;
contactFound#ea879f95 user_id:int = ContactFound;
contacts.found#566000e results:Vector<ContactFound> users:Vector<User> = contacts.Found;
contacts.found#1aa1f784 results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;
inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
@ -597,6 +595,8 @@ channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
channelMessagesFilter#cd77d957 flags:# ranges:Vector<MessageRange> = ChannelMessagesFilter;
channelMessagesFilterCollapsed#fa01232e = ChannelMessagesFilter;
contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector<Chat> users:Vector<User> = contacts.ResolvedPeer;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -661,7 +661,7 @@ contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
contacts.exportCard#84e53737 = Vector<int>;
contacts.importCard#4fe196fe export_card:Vector<int> = User;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.resolveUsername#bf0131c username:string = User;
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
messages.getMessages#4222fa74 id:Vector<int> = messages.Messages;
messages.getDialogs#859b3d3c offset:int limit:int = messages.Dialogs;
@ -710,6 +710,9 @@ messages.getImportantHistory#24af43a5 peer:InputPeer offset_id:int add_offset:in
messages.readChannelHistory#36a1210e peer:InputPeer max_id:int = Bool;
messages.createChannel#e830f8cb flags:# title:string users:Vector<InputUser> = Updates;
messages.deleteChannelMessages#9995a84f peer:InputPeer id:Vector<int> = messages.AffectedMessages;
messages.editChatAbout#8a969b93 chat_id:InputChat about:string = Bool;
messages.checkChannelUsername#e6d2d8f4 chat_id:InputChat username:string = Bool;
messages.updateChannelUsername#ce2e9587 chat_id:InputChat username:string = Bool;
updates.getState#edd4882a = updates.State;
updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;

View file

@ -783,7 +783,7 @@ void OverviewInner::onDragExec() {
QList<QUrl> urls;
bool forwardSelected = false;
if (uponSelected) {
forwardSelected = !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode();
forwardSelected = !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && cWideMode() && !_hist->peer->isChannel();
} else if (textlnkDown()) {
sel = textlnkDown()->encoded();
if (!sel.isEmpty() && sel.at(0) != '/' && sel.at(0) != '@' && sel.at(0) != '#') {
@ -827,7 +827,9 @@ void OverviewInner::onDragExec() {
QDrag *drag = new QDrag(App::wnd());
QMimeData *mimeData = new QMimeData;
mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1");
if (!_hist->peer->isChannel()) {
mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1");
}
if (lnkDocument) {
QString already = static_cast<DocumentOpenLink*>(textlnkDown().data())->document()->already(true);
if (!already.isEmpty()) {
@ -1496,12 +1498,13 @@ void OverviewInner::onUpdateSelected() {
}
cur = (textlnkDown() || _lnkDownIndex) ? style::cur_pointer : style::cur_default;
if (_dragAction == Selecting) {
bool canSelectMany = _peer && (!_peer->isChannel() || _peer->asChannel()->adminned);
if (_mousedItem == _dragItem && (lnk || lnkIndex) && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) {
bool afterSymbol = false, uponSymbol = false;
uint16 second = 0;
_selected[_dragItem] = 0;
updateDragSelection(0, -1, 0, -1, false);
} else {
} else if (canSelectMany) {
bool selectingDown = ((_type == OverviewPhotos || _type == OverviewAudioDocuments || _type == OverviewLinks) ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y())));
MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem;
int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex;
@ -1778,7 +1781,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 (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem())) {
if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem()) && !_hist->peer->isChannel()) {
_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
@ -1812,7 +1815,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected()));
} else {
if (isUponSelected != -2) {
if (dynamic_cast<HistoryMessage*>(App::mousedItem())) {
if (dynamic_cast<HistoryMessage*>(App::mousedItem()) && !_hist->peer->isChannel()) {
_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);

View file

@ -33,6 +33,8 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
_peerUser(_peer->asUser()), _peerChat(_peer->asChat()), _peerChannel(_peer->asChannel()), _hist(App::history(peer->id)),
_isAdmin(_peerChat ? (_peerChat->admin == MTP::authedId()) : (_peerChannel ? _peerChannel->adminned : false)),
_width(0), _left(0), _addToHeight(0),
// profile
_nameCache(peer->name),
_uploadPhoto(this, lang(lng_profile_set_group_photo), st::btnShareContact),
@ -57,8 +59,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
_enableNotifications(this, lang(lng_profile_enable_notifications)),
// shared media
_allMediaTypes(false),
_mediaShowAll(this, lang(lng_profile_show_all_types)),
_notAllMediaLoaded(false),
// actions
_searchInPeer(this, lang(lng_profile_search_messages)),
@ -106,6 +107,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
if (_peerChannel->photoId == UnknownPeerPhotoId) {
App::api()->requestFullPeer(_peer);
}
// MTP::send(MTPmessages_UpdateChannelUsername(_peerChannel->inputChat, MTP_string("tdesktop_channel")));
}
// profile
@ -164,13 +166,12 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
connect(&_enableNotifications, SIGNAL(clicked()), this, SLOT(onEnableNotifications()));
// shared media
connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll()));
connect((_mediaButtons[OverviewPhotos] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaPhotos()));
connect((_mediaButtons[OverviewVideos] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaVideos()));
connect((_mediaButtons[OverviewDocuments] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaDocuments()));
connect((_mediaButtons[OverviewAudios] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaAudios()));
connect((_mediaButtons[OverviewLinks] = new LinkButton(this, QString())), SIGNAL(clicked()), this, SLOT(onMediaLinks()));
App::main()->preloadOverviews(_peer);
updateMediaLinks();
// actions
connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer()));
@ -343,12 +344,6 @@ void ProfileInner::onPhotoUpdateDone(PeerId peer) {
update();
}
void ProfileInner::onMediaShowAll() {
_allMediaTypes = true;
resizeEvent(0);
showAll();
}
void ProfileInner::onMediaPhotos() {
App::main()->showMediaOverview(_peer, OverviewPhotos);
}
@ -370,29 +365,33 @@ void ProfileInner::onMediaLinks() {
}
void ProfileInner::onInvitationLink() {
if (!_peerChat) return;
if (!_peerChat && !_peerChannel) return;
QApplication::clipboard()->setText(_peerChat->invitationUrl);
QApplication::clipboard()->setText(_peerChat ? _peerChat->invitationUrl : (_peerChannel ? _peerChannel->invitationUrl : QString()));
App::wnd()->showLayer(new ConfirmBox(lang(lng_group_invite_copied), true));
}
void ProfileInner::onCreateInvitationLink() {
if (!_peerChat) return;
if (!_peerChat && !_peerChannel) return;
ConfirmBox *box = new ConfirmBox(lang(_peerChat->invitationUrl.isEmpty() ? lng_group_invite_about : lng_group_invite_about_new));
ConfirmBox *box = new ConfirmBox(lang(((_peerChat && _peerChat->invitationUrl.isEmpty()) || (_peerChannel && _peerChannel->invitationUrl.isEmpty())) ? (_peerChat ? lng_group_invite_about : lng_channel_invite_about) : lng_group_invite_about_new));
connect(box, SIGNAL(confirmed()), this, SLOT(onCreateInvitationLinkSure()));
App::wnd()->showLayer(box);
}
void ProfileInner::onCreateInvitationLinkSure() {
if (!_peerChat) return;
MTP::send(MTPmessages_ExportChatInvite(_peerChat->inputChat), rpcDone(&ProfileInner::chatInviteDone));
if (!_peerChat && !_peerChannel) return;
MTP::send(MTPmessages_ExportChatInvite(_peerChat ? _peerChat->inputChat : _peerChannel->inputChat), rpcDone(&ProfileInner::chatInviteDone));
}
void ProfileInner::chatInviteDone(const MTPExportedChatInvite &result) {
if (!_peerChat) return;
if (!_peerChat && !_peerChannel) return;
_peerChat->invitationUrl = (result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString();
if (_peerChat) {
_peerChat->invitationUrl = (result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString();
} else {
_peerChannel->invitationUrl = (result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString();
}
updateInvitationLink();
showAll();
resizeEvent(0);
@ -666,43 +665,26 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
p.setFont(st::linkFont->f);
p.setPen(st::black->p);
int oneState = 0; // < 0 - loading, 0 - no media, > 0 - link shown
bool mediaFound = false;
for (int i = 0; i < OverviewCount; ++i) {
if (i == OverviewAudioDocuments) continue;
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
if (count < 0) {
if (!oneState) oneState = count;
if (!_allMediaTypes) {
p.drawText(_left, top + st::linkFont->ascent, lang(lng_profile_loading));
break;
}
} else if (count > 0) {
oneState = count;
if (!_allMediaTypes) {
break;
}
if (!_mediaButtons[i]->isHidden()) {
mediaFound = true;
top += _mediaButtons[i]->height() + st::setLittleSkip;
}
}
if (_allMediaTypes) {
if (oneState > 0) {
top -= st::setLittleSkip;
} else {
p.drawText(_left, top + st::linkFont->ascent, lang(oneState < 0 ? lng_profile_loading : lng_profile_no_media));
top += _mediaButtons[OverviewPhotos]->height();
}
} else {
if (!oneState) {
p.drawText(_left, top + st::linkFont->ascent, lang(lng_profile_no_media));
}
if (_notAllMediaLoaded || !mediaFound) {
p.drawText(_left, top + st::linkFont->ascent, lang(_notAllMediaLoaded ? lng_profile_loading : lng_profile_no_media));
top += _mediaButtons[OverviewPhotos]->height();
} else {
top -= st::setLittleSkip;
}
// actions
p.setFont(st::profileHeaderFont->f);
p.setPen(st::profileHeaderColor->p);
if (!_peerChannel) p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
top += st::profileHeaderSkip;
top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
@ -906,6 +888,87 @@ void ProfileInner::leaveToChildEvent(QEvent *e) {
return TWidget::leaveToChildEvent(e);
}
bool ProfileInner::updateMediaLinks(int32 *addToScroll) {
QPoint p(addToScroll ? mapFromGlobal(QCursor::pos()) : QPoint(0, 0));
bool oneWasShown = false;
for (int i = 0; i < OverviewCount; ++i) {
if (i == OverviewAudioDocuments) continue;
if (!_mediaButtons[i]->isHidden()) {
oneWasShown = true;
break;
}
}
bool newNotAllMediaLoaded = false, changed = false, substracted = !_notAllMediaLoaded && oneWasShown;
bool oneIsShown = false;
int32 y = _mediaButtons[OverviewPhotos]->y();
if (addToScroll) *addToScroll = 0;
for (int i = 0; i < OverviewCount; ++i) {
if (i == OverviewAudioDocuments) continue;
int32 addToY = _mediaButtons[i]->height() + st::setLittleSkip;
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
if (count > 0) {
_mediaButtons[i]->setText(overviewLinkText(i, count));
if (_mediaButtons[i]->isHidden()) {
_mediaButtons[i]->show();
changed = true;
if (addToScroll && p.y() >= y) {
p.setY(p.y() + addToY);
*addToScroll += addToY;
}
}
y += addToY;
oneIsShown = true;
} else {
if (!_mediaButtons[i]->isHidden()) {
_mediaButtons[i]->hide();
changed = true;
if (addToScroll && p.y() >= y + addToY) {
p.setY(p.y() - addToY);
*addToScroll -= addToY;
}
}
if (count < 0) {
newNotAllMediaLoaded = true;
}
}
}
if (newNotAllMediaLoaded != _notAllMediaLoaded) {
_notAllMediaLoaded = newNotAllMediaLoaded;
changed = true;
int32 addToY = _mediaButtons[OverviewPhotos]->height();
if (_notAllMediaLoaded) {
if (addToScroll && p.y() >= y) {
p.setY(p.y() + addToY);
*addToScroll += addToY;
}
} else {
if (addToScroll && p.y() >= y + addToY) {
p.setY(p.y() - addToY);
*addToScroll -= addToY;
}
}
if (App::main()) App::main()->preloadOverviews(_peer);
}
bool newSubstracted = !_notAllMediaLoaded && oneIsShown;
if (newSubstracted && newSubstracted != substracted) {
int32 addToY = st::setLittleSkip;
if (addToScroll && p.y() >= y + addToY) {
p.setY(p.y() - addToY);
*addToScroll -= addToY;
}
}
return changed;
}
void ProfileInner::resizeEvent(QResizeEvent *e) {
_width = qMin(width() - st::profilePadding.left() - st::profilePadding.right(), int(st::profileMaxWidth));
_left = (width() - _width) / 2;
@ -960,30 +1023,20 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
// shared media
top += st::profileHeaderSkip;
_mediaShowAll.move(_left + _width - _mediaShowAll.width(), top);
int wasCount = 0; // < 0 - loading, 0 - no media, > 0 - link shown
bool mediaFound = false;
for (int i = 0; i < OverviewCount; ++i) {
if (i == OverviewAudioDocuments) continue;
if (_allMediaTypes) {
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
if (count > 0) {
if (wasCount) top += _mediaButtons[i]->height() + st::setLittleSkip;
wasCount = count;
}
}
_mediaButtons[i]->move(_left, top);
if (!_mediaButtons[i]->isHidden()) {
mediaFound = true;
top += _mediaButtons[i]->height() + st::setLittleSkip;
}
}
top += _mediaButtons[OverviewPhotos]->height();
// actions
top += st::profileHeaderSkip;
_searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip;
_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
_deleteConversation.move(_left, top); top += _deleteConversation.height();
if (_peerUser && peerToUser(_peerUser->id) != MTP::authedId()) {
top += st::setSectionSkip;
_blockUser.move(_left, top); top += _blockUser.height();
if (_notAllMediaLoaded || !mediaFound) {
top += _mediaButtons[OverviewPhotos]->height();
} else {
top -= st::setLittleSkip;
}
// actions
@ -1062,10 +1115,6 @@ PeerData *ProfileInner::peer() const {
return _peer;
}
bool ProfileInner::allMediaShown() const {
return _allMediaTypes;
}
ProfileInner::~ProfileInner() {
for (ParticipantsData::iterator i = _participantsData.begin(), e = _participantsData.end(); i != e; ++i) {
delete *i;
@ -1083,11 +1132,28 @@ void ProfileInner::updateNotifySettings() {
_enableNotifications.setChecked(_peer->notify == EmptyNotifySettings || _peer->notify == UnknownNotifySettings || _peer->notify->mute < unixtime());
}
void ProfileInner::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
int32 ProfileInner::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
int32 result = 0;
if (peer == _peer) {
resizeEvent(0);
if (updateMediaLinks(&result)) {
resizeEvent(0);
update();
}
}
return result;
}
void ProfileInner::requestHeight(int32 newHeight) {
if (newHeight > height()) {
_addToHeight += newHeight - height();
showAll();
}
}
void ProfileInner::allowDecreaseHeight(int32 decreaseBy) {
if (decreaseBy > 0 && _addToHeight > 0) {
_addToHeight -= qMin(decreaseBy, _addToHeight);
showAll();
update();
}
}
@ -1195,42 +1261,6 @@ void ProfileInner::showAll() {
_enableNotifications.show();
updateNotifySettings();
// shared media
bool first = false, wasCount = false, manyCounts = false;
for (int i = 0; i < OverviewCount; ++i) {
if (i == OverviewAudioDocuments) continue;
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
if (count > 0) {
if (wasCount) {
manyCounts = true;
} else {
wasCount = true;
}
}
if (!first || _allMediaTypes) {
if (count > 0 || count < 0) {
first = true;
} else if (!_allMediaTypes) {
_mediaButtons[i]->hide();
continue;
}
if (count > 0) {
_mediaButtons[i]->setText(overviewLinkText(i, count));
_mediaButtons[i]->show();
} else {
_mediaButtons[i]->hide();
}
} else {
_mediaButtons[i]->hide();
}
}
if (_allMediaTypes || !manyCounts) {
_mediaShowAll.hide();
} else {
_mediaShowAll.show();
}
// participants
reorderParticipants();
int32 h;
@ -1250,17 +1280,17 @@ void ProfileInner::showAll() {
} else if (_peerChannel) {
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
}
resize(width(), h);
resize(width(), h + _addToHeight);
}
void ProfileInner::updateInvitationLink() {
if (!_peerChat) return;
if (!_peerChat && !_peerChannel) return;
if (_peerChat->invitationUrl.isEmpty()) {
if ((_peerChat && _peerChat->invitationUrl.isEmpty()) || (_peerChannel && _peerChannel->invitationUrl.isEmpty())) {
_createInvitationLink.setText(lang(lng_group_invite_create));
} else {
_createInvitationLink.setText(lang(lng_group_invite_create_new));
_invitationText = _peerChat->invitationUrl;
_invitationText = _peerChat ? _peerChat->invitationUrl : _peerChannel->invitationUrl;
if (_invitationText.startsWith(qstr("http://"), Qt::CaseInsensitive)) {
_invitationText = _invitationText.mid(7);
} else if (_invitationText.startsWith(qstr("https://"), Qt::CaseInsensitive)) {
@ -1312,6 +1342,9 @@ ProfileWidget::ProfileWidget(QWidget *parent, const PeerData *peer) : QWidget(pa
void ProfileWidget::onScroll() {
_inner.loadProfilePhotos(_scroll.scrollTop());
if (!_scroll.isHidden() && _scroll.scrollTop() < _scroll.scrollTopMax()) {
_inner.allowDecreaseHeight(_scroll.scrollTopMax() - _scroll.scrollTop());
}
}
void ProfileWidget::resizeEvent(QResizeEvent *e) {
@ -1319,8 +1352,13 @@ void ProfileWidget::resizeEvent(QResizeEvent *e) {
int32 newScrollY = _scroll.scrollTop() + addToY;
_scroll.resize(size());
_inner.resize(width(), _inner.height());
if (addToY) {
_scroll.scrollToY(newScrollY);
if (!_scroll.isHidden()) {
if (addToY) {
_scroll.scrollToY(newScrollY);
}
if (_scroll.scrollTop() < _scroll.scrollTopMax()) {
_inner.allowDecreaseHeight(_scroll.scrollTopMax() - _scroll.scrollTop());
}
}
}
@ -1379,15 +1417,10 @@ int32 ProfileWidget::lastScrollTop() const {
return _scroll.scrollTop();
}
bool ProfileWidget::allMediaShown() const {
return _inner.allMediaShown();
}
void ProfileWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back, int32 lastScrollTop, bool allMediaShown) {
void ProfileWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back, int32 lastScrollTop) {
stopGif();
_bgAnimCache = bgAnimCache;
_bgAnimTopBarCache = bgAnimTopBarCache;
if (allMediaShown) _inner.onMediaShowAll();
if (lastScrollTop >= 0) _scroll.scrollToY(lastScrollTop);
_animCache = myGrab(this, rect());
App::main()->topBar()->stopAnim();
@ -1445,7 +1478,13 @@ void ProfileWidget::updateNotifySettings() {
}
void ProfileWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
_inner.mediaOverviewUpdated(peer, type);
int32 addToScroll = _inner.mediaOverviewUpdated(peer, type);
if (!_scroll.isHidden() && addToScroll && _scroll.geometry().contains(mapFromGlobal(QCursor::pos()))) {
if (addToScroll > 0 && _scroll.scrollTop() + addToScroll > _scroll.scrollTopMax()) {
_inner.requestHeight(_scroll.scrollTop() + addToScroll + _scroll.height());
}
_scroll.scrollToY(_scroll.scrollTop() + addToScroll);
}
}
void ProfileWidget::clear() {

View file

@ -53,7 +53,10 @@ public:
void loadProfilePhotos(int32 yFrom);
void updateNotifySettings();
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
int32 mediaOverviewUpdated(PeerData *peer, MediaOverviewType type); // returns scroll shift
void requestHeight(int32 newHeight);
void allowDecreaseHeight(int32 decreaseBy);
~ProfileInner();
@ -87,7 +90,6 @@ public slots:
void onKickConfirm();
void onMediaShowAll();
void onMediaPhotos();
void onMediaVideos();
void onMediaDocuments();
@ -114,6 +116,7 @@ private:
void updateBotLinksVisibility();
void chatInviteDone(const MTPExportedChatInvite &result);
bool updateMediaLinks(int32 *addToScroll = 0); // returns if anything changed
ProfileWidget *_profile;
ScrollArea *_scroll;
@ -125,7 +128,7 @@ private:
History *_hist;
bool _isAdmin;
int32 _width, _left;
int32 _width, _left, _addToHeight;
// profile
Text _nameText;
@ -150,8 +153,7 @@ private:
FlatCheckbox _enableNotifications;
// shared media
bool _allMediaTypes;
LinkButton _mediaShowAll;
bool _notAllMediaLoaded;
LinkButton *_mediaButtons[OverviewCount];
QString overviewLinkText(int32 type, int32 count);
@ -206,9 +208,8 @@ public:
PeerData *peer() const;
int32 lastScrollTop() const;
bool allMediaShown() const;
void animShow(const QPixmap &oldAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false);
void animShow(const QPixmap &oldAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false, int32 lastScrollTop = -1);
bool animStep(float64 ms);
void updateOnlineDisplay();

View file

@ -92,7 +92,7 @@ PeerData::PeerData(const PeerId &id) : id(id), lnk(new PeerLink(this))
, nameVersion(0)
, notify(UnknownNotifySettings)
{
if (!peerIsUser(id)) updateName(QString(), QString(), QString());
if (!peerIsUser(id) && !peerIsChannel(id)) updateName(QString(), QString(), QString());
}
void PeerData::updateName(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) {
@ -167,14 +167,6 @@ void PeerData::fillNames() {
}
}
const Text &PeerData::dialogName() const {
return (isUser() && !asUser()->phoneText.isEmpty()) ? asUser()->phoneText : nameText;
}
const QString &PeerData::shortName() const {
return isUser() ? asUser()->firstName : name;
}
void UserData::setName(const QString &first, const QString &last, const QString &phoneName, const QString &usern) {
bool updName = !first.isEmpty() || !last.isEmpty(), updUsername = (username != usern);
@ -359,6 +351,17 @@ void ChannelData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see
}
}
void ChannelData::setName(const QString &newName, const QString &usern) {
bool updName = !newName.isEmpty(), updUsername = (username != usern);
updateName(newName.isEmpty() ? name : newName, QString(), usern);
if (updUsername) {
if (App::main()) {
App::main()->peerUsernameChanged(this);
}
}
}
void PhotoLink::onClick(Qt::MouseButton button) const {
if (button == Qt::LeftButton) {
App::wnd()->showPhoto(this, App::hoveredLinkItem());

View file

@ -146,6 +146,11 @@ ImagePtr chatDefPhoto(int32 index);
static const PhotoId UnknownPeerPhotoId = 0xFFFFFFFFFFFFFFFFULL;
inline const QString &emptyUsername() {
static QString empty;
return empty;
}
class UserData;
class ChatData;
class ChannelData;
@ -181,6 +186,7 @@ public:
const Text &dialogName() const;
const QString &shortName() const;
const QString &userName() const;
const PeerId id;
int32 bareId() const {
@ -352,13 +358,16 @@ class ChannelData : public PeerData {
public:
ChannelData(const PeerId &id) : PeerData(id), access(0), inputChat(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))), date(0), version(0), adminned(false), left(false), forbidden(true), botStatus(-1) {
setName(QString(), QString());
}
void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
void setName(const QString &name, const QString &username);
uint64 access;
MTPInputChat inputChat;
QString username;
int32 date;
int32 version;
bool adminned;
@ -388,6 +397,16 @@ inline ChannelData *PeerData::asChannel() {
inline const ChannelData *PeerData::asChannel() const {
return isChannel() ? static_cast<const ChannelData*>(this) : 0;
}
inline const Text &PeerData::dialogName() const {
return (isUser() && !asUser()->phoneText.isEmpty()) ? asUser()->phoneText : nameText;
}
inline const QString &PeerData::shortName() const {
return isUser() ? asUser()->firstName : name;
}
inline const QString &PeerData::userName() const {
return isUser() ? asUser()->username : (isChannel() ? asChannel()->username : emptyUsername());
}
inline int32 newMessageFlags(PeerData *p) {
return (p->input.type() == mtpc_inputPeerSelf) ? 0 : (((p->isChat() || (p->isUser() && !p->asUser()->botInfo)) ? MTPDmessage_flag_unread : 0) | MTPDmessage_flag_out);

View file

@ -80,7 +80,7 @@ namespace {
volatile int32 unixtimeDelta = 0;
volatile bool unixtimeWasSet = false;
volatile uint64 _msgIdStart, _msgIdLocal = 0, _msgIdMsStart;
uint32 _reqId = 0;
int32 _reqId = 0;
void _initMsgIdConstants() {
#ifdef Q_OS_WIN
@ -349,8 +349,11 @@ uint64 msgid() {
return result + (_msgIdLocal += 4);
}
uint32 reqid() {
int32 reqid() {
QWriteLocker locker(&unixtimeLock);
if (_reqId == INT_MAX) {
_reqId = 0;
}
return ++_reqId;
}

View file

@ -78,7 +78,7 @@ void unixtimeSet(int32 servertime, bool force = false);
int32 unixtime();
int32 fromServerTime(const MTPint &serverTime);
uint64 msgid();
uint32 reqid();
int32 reqid();
inline QDateTime date(int32 time = -1) {
QDateTime result;