Peer observers get notified about name/username changes.

All peer observer notifications are async (delayed).
This commit is contained in:
John Preston 2016-05-25 15:09:05 +03:00
parent e3e49dbeb8
commit a510bb54ec
19 changed files with 413 additions and 317 deletions

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h" #include "stdafx.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "observer_peer.h"
#include "lang.h" #include "lang.h"
#include "application.h" #include "application.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -178,8 +179,8 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
badVersion = (!vc.isEmpty() && vc.at(0).type() == mtpc_channel && vc.at(0).c_channel().vversion.v < peer->asChannel()->version); badVersion = (!vc.isEmpty() && vc.at(0).type() == mtpc_channel && vc.at(0).c_channel().vversion.v < peer->asChannel()->version);
} }
App::feedUsers(d.vusers, false); App::feedUsersDelayed(d.vusers);
App::feedChats(d.vchats, false); App::feedChatsDelayed(d.vchats);
if (peer->isChat()) { if (peer->isChat()) {
if (d.vfull_chat.type() != mtpc_chatFull) { if (d.vfull_chat.type() != mtpc_chatFull) {
@ -317,16 +318,17 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
} }
App::clearPeerUpdated(peer); App::clearPeerUpdated(peer);
emit fullPeerUpdated(peer); emit fullPeerUpdated(peer);
App::emitPeerUpdated();
Notify::peerUpdatedSendDelayed();
} }
void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestId req) { void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestId req) {
const auto &d(result.c_userFull()); const auto &d(result.c_userFull());
App::feedUsers(MTP_vector<MTPUser>(1, d.vuser), false); App::feedUsersDelayed(MTP_vector<MTPUser>(1, d.vuser));
if (d.has_profile_photo()) { if (d.has_profile_photo()) {
App::feedPhoto(d.vprofile_photo); App::feedPhoto(d.vprofile_photo);
} }
App::feedUserLink(MTP_int(peerToUser(peer->id)), d.vlink.c_contacts_link().vmy_link, d.vlink.c_contacts_link().vforeign_link, false); App::feedUserLinkDelayed(MTP_int(peerToUser(peer->id)), d.vlink.c_contacts_link().vmy_link, d.vlink.c_contacts_link().vforeign_link);
if (App::main()) { if (App::main()) {
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings); App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings);
} }
@ -347,7 +349,8 @@ void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestI
} }
App::clearPeerUpdated(peer); App::clearPeerUpdated(peer);
emit fullPeerUpdated(peer); emit fullPeerUpdated(peer);
App::emitPeerUpdated();
Notify::peerUpdatedSendDelayed();
} }
bool ApiWrap::gotPeerFullFailed(PeerData *peer, const RPCError &error) { bool ApiWrap::gotPeerFullFailed(PeerData *peer, const RPCError &error) {

View File

@ -365,7 +365,7 @@ namespace {
return (online > now); return (online > now);
} }
UserData *feedUsers(const MTPVector<MTPUser> &users, bool emitPeerUpdated) { UserData *feedUsersDelayed(const MTPVector<MTPUser> &users) {
UserData *result = nullptr; UserData *result = nullptr;
for_const (auto &user, users.c_vector().v) { for_const (auto &user, users.c_vector().v) {
UserData *data = nullptr; UserData *data = nullptr;
@ -385,7 +385,7 @@ namespace {
data->input = MTP_inputPeerUser(d.vid, MTP_long(0)); data->input = MTP_inputPeerUser(d.vid, MTP_long(0));
data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
data->setName(lang(lng_deleted), QString(), QString(), QString()); data->setNameDelayed(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty()); data->setPhoto(MTP_userProfilePhotoEmpty());
data->access = UserNoAccess; data->access = UserNoAccess;
data->flags = 0; data->flags = 0;
@ -426,7 +426,7 @@ namespace {
} }
if (d.is_deleted()) { if (d.is_deleted()) {
data->setPhone(QString()); data->setPhone(QString());
data->setName(lang(lng_deleted), QString(), QString(), QString()); data->setNameDelayed(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty()); data->setPhoto(MTP_userProfilePhotoEmpty());
data->access = UserNoAccess; data->access = UserNoAccess;
status = &emptyStatus; status = &emptyStatus;
@ -459,7 +459,7 @@ namespace {
if (!minimal && d.is_self() && uname != data->username) { if (!minimal && d.is_self() && uname != data->username) {
SignalHandlers::setCrashAnnotation("Username", uname); SignalHandlers::setCrashAnnotation("Username", uname);
} }
data->setName(fname, lname, pname, uname); data->setNameDelayed(fname, lname, pname, uname);
if (d.has_photo()) { if (d.has_photo()) {
data->setPhoto(d.vphoto); data->setPhoto(d.vphoto);
} else { } else {
@ -525,27 +525,19 @@ namespace {
Notify::userIsContactChanged(data); Notify::userIsContactChanged(data);
} }
if (emitPeerUpdated) {
App::main()->peerUpdated(data);
if (update.flags) {
update.peer = data;
Notify::peerUpdated(update);
}
} else {
markPeerUpdated(data); markPeerUpdated(data);
if (update.flags) { if (update.flags) {
update.peer = data; update.peer = data;
Notify::peerUpdatedDelayed(update); Notify::peerUpdatedDelayed(update);
} }
} }
}
result = data; result = data;
} }
return result; return result;
} }
PeerData *feedChats(const MTPVector<MTPChat> &chats, bool emitPeerUpdated) { PeerData *feedChatsDelayed(const MTPVector<MTPChat> &chats) {
PeerData *result = nullptr; PeerData *result = nullptr;
for_const (auto &chat, chats.c_vector().v) { for_const (auto &chat, chats.c_vector().v) {
PeerData *data = nullptr; PeerData *data = nullptr;
@ -561,9 +553,8 @@ namespace {
data = App::chat(peerFromChat(d.vid.v)); data = App::chat(peerFromChat(d.vid.v));
data->input = MTP_inputPeerChat(d.vid); data->input = MTP_inputPeerChat(d.vid);
data->updateName(qs(d.vtitle), QString(), QString());
ChatData *cdata = data->asChat(); ChatData *cdata = data->asChat();
cdata->setNameDelayed(qs(d.vtitle));
cdata->setPhoto(d.vphoto); cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v; cdata->date = d.vdate.v;
@ -620,9 +611,8 @@ namespace {
data = App::chat(peerFromChat(d.vid.v)); data = App::chat(peerFromChat(d.vid.v));
data->input = MTP_inputPeerChat(d.vid); data->input = MTP_inputPeerChat(d.vid);
data->updateName(qs(d.vtitle), QString(), QString());
ChatData *cdata = data->asChat(); ChatData *cdata = data->asChat();
cdata->setNameDelayed(qs(d.vtitle));
cdata->setPhoto(MTP_chatPhotoEmpty()); cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0; cdata->date = 0;
cdata->count = -1; cdata->count = -1;
@ -666,7 +656,7 @@ namespace {
} }
} }
QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString(); QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString();
cdata->setName(qs(d.vtitle), uname); cdata->setNameDelayed(qs(d.vtitle), uname);
cdata->isForbidden = false; cdata->isForbidden = false;
cdata->flagsUpdated(); cdata->flagsUpdated();
@ -688,7 +678,7 @@ namespace {
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
cdata->setName(qs(d.vtitle), QString()); cdata->setNameDelayed(qs(d.vtitle), QString());
cdata->access = d.vaccess_hash.v; cdata->access = d.vaccess_hash.v;
cdata->setPhoto(MTP_chatPhotoEmpty()); cdata->setPhoto(MTP_chatPhotoEmpty());
@ -711,25 +701,29 @@ namespace {
data->loadedStatus = PeerData::FullLoaded; data->loadedStatus = PeerData::FullLoaded;
} }
if (App::main()) { if (App::main()) {
if (emitPeerUpdated) {
App::main()->peerUpdated(data);
if (update.flags) {
update.peer = data;
Notify::peerUpdated(update);
}
} else {
markPeerUpdated(data); markPeerUpdated(data);
if (update.flags) { if (update.flags) {
update.peer = data; update.peer = data;
Notify::peerUpdatedDelayed(update); Notify::peerUpdatedDelayed(update);
} }
} }
}
result = data; result = data;
} }
return result; return result;
} }
UserData *feedUsers(const MTPVector<MTPUser> &users) {
auto result = feedUsersDelayed(users);
Notify::peerUpdatedSendDelayed();
return result;
}
PeerData *feedChats(const MTPVector<MTPChat> &chats) {
auto result = feedChatsDelayed(chats);
Notify::peerUpdatedSendDelayed();
return result;
}
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated) { void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated) {
ChatData *chat = 0; ChatData *chat = 0;
switch (p.type()) { switch (p.type()) {
@ -1206,30 +1200,7 @@ namespace {
} }
} }
void feedUserLinks(const MTPVector<MTPcontacts_Link> &links, bool emitPeerUpdated) { void feedUserLinkDelayed(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink) {
const auto &v(links.c_vector().v);
for (QVector<MTPcontacts_Link>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
const auto &dv(i->c_contacts_link());
UserData *user = feedUsers(MTP_vector<MTPUser>(1, dv.vuser), false);
MTPint userId(MTP_int(0));
switch (dv.vuser.type()) {
case mtpc_userEmpty: userId = dv.vuser.c_userEmpty().vid; break;
case mtpc_user: userId = dv.vuser.c_user().vid; break;
}
if (userId.v) {
feedUserLink(userId, dv.vmy_link, dv.vforeign_link, false);
}
if (user && App::main()) {
if (emitPeerUpdated) {
App::main()->peerUpdated(user);
} else {
markPeerUpdated(user);
}
}
}
}
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink, bool emitPeerUpdated) {
UserData *user = userLoaded(userId.v); UserData *user = userLoaded(userId.v);
if (user) { if (user) {
bool wasContact = (user->contact > 0); bool wasContact = (user->contact > 0);
@ -1262,17 +1233,11 @@ namespace {
bool showPhone = !isServiceUser(user->id) && !user->isSelf() && !user->contact; bool showPhone = !isServiceUser(user->id) && !user->isSelf() && !user->contact;
bool showPhoneChanged = !isServiceUser(user->id) && !user->isSelf() && ((showPhone && !wasShowPhone) || (!showPhone && wasShowPhone)); bool showPhoneChanged = !isServiceUser(user->id) && !user->isSelf() && ((showPhone && !wasShowPhone) || (!showPhone && wasShowPhone));
if (showPhoneChanged) { if (showPhoneChanged) {
user->setName(textOneLine(user->firstName), textOneLine(user->lastName), showPhone ? App::formatPhone(user->phone) : QString(), textOneLine(user->username)); user->setNameDelayed(textOneLine(user->firstName), textOneLine(user->lastName), showPhone ? App::formatPhone(user->phone) : QString(), textOneLine(user->username));
} }
if (App::main()) {
if (emitPeerUpdated) {
App::main()->peerUpdated(user);
} else {
markPeerUpdated(user); markPeerUpdated(user);
} }
} }
}
}
void markPeerUpdated(PeerData *data) { void markPeerUpdated(PeerData *data) {
updatedPeers.insert(data, true); updatedPeers.insert(data, true);
@ -1291,7 +1256,6 @@ namespace {
App::main()->peerUpdated(i.key()); App::main()->peerUpdated(i.key());
} }
} }
Notify::peerUpdatedSendDelayed();
} }
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert) { PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert) {

View File

@ -64,8 +64,13 @@ namespace App {
QString onlineText(UserData *user, int32 nowOnServer, bool precise = false); QString onlineText(UserData *user, int32 nowOnServer, bool precise = false);
bool onlineColorUse(UserData *user, int32 now); bool onlineColorUse(UserData *user, int32 now);
UserData *feedUsers(const MTPVector<MTPUser> &users, bool emitPeerUpdated = true); // returns last user UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
PeerData *feedChats(const MTPVector<MTPChat> &chats, bool emitPeerUpdated = true); // returns last chat PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
// Requires Notify::peerUpdatedSendDelayed() call after.
UserData *feedUsersDelayed(const MTPVector<MTPUser> &users); // returns last user
PeerData *feedChatsDelayed(const MTPVector<MTPChat> &chats); // returns last chat
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true); void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true);
void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d, bool emitPeerUpdated = true); void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d, bool emitPeerUpdated = true);
void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d, bool emitPeerUpdated = true); void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d, bool emitPeerUpdated = true);
@ -80,12 +85,10 @@ namespace App {
void feedInboxRead(const PeerId &peer, MsgId upTo); void feedInboxRead(const PeerId &peer, MsgId upTo);
void feedOutboxRead(const PeerId &peer, MsgId upTo); void feedOutboxRead(const PeerId &peer, MsgId upTo);
void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds); void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds);
void feedUserLinks(const MTPVector<MTPcontacts_Link> &links, bool emitPeerUpdated = true); void feedUserLinkDelayed(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink);
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink, bool emitPeerUpdated = true);
void markPeerUpdated(PeerData *data); void markPeerUpdated(PeerData *data);
void clearPeerUpdated(PeerData *data); void clearPeerUpdated(PeerData *data);
void emitPeerUpdated();
ImagePtr image(const MTPPhotoSize &size); ImagePtr image(const MTPPhotoSize &size);
StorageImageLocation imageLocation(int32 w, int32 h, const MTPFileLocation &loc); StorageImageLocation imageLocation(int32 w, int32 h, const MTPFileLocation &loc);

View File

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "langloaderplain.h" #include "langloaderplain.h"
#include "localstorage.h" #include "localstorage.h"
#include "autoupdater.h" #include "autoupdater.h"
#include "core/observer.h"
namespace { namespace {
void mtpStateChanged(int32 dc, int32 state) { void mtpStateChanged(int32 dc, int32 state) {
@ -200,6 +201,7 @@ void Application::singleInstanceChecked() {
Logs::multipleInstances(); Logs::multipleInstances();
} }
Notify::startObservers();
Sandbox::start(); Sandbox::start();
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) { if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
@ -336,6 +338,8 @@ void Application::closeApplication() {
if (_updateThread) _updateThread->quit(); if (_updateThread) _updateThread->quit();
_updateThread = 0; _updateThread = 0;
#endif #endif
Notify::finishObservers();
} }
#ifndef TDESKTOP_DISABLE_AUTOUPDATE #ifndef TDESKTOP_DISABLE_AUTOUPDATE

View File

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "observer_peer.h"
AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth) AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth)
, _user(0) , _user(0)
@ -206,7 +207,7 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) {
QString err(error.type()); QString err(error.type());
QString firstName = _first.getLastText().trimmed(), lastName = _last.getLastText().trimmed(); QString firstName = _first.getLastText().trimmed(), lastName = _last.getLastText().trimmed();
if (err == "CHAT_TITLE_NOT_MODIFIED") { if (err == "CHAT_TITLE_NOT_MODIFIED") {
_user->updateName(firstName, QString(), QString()); _user->setName(firstName, lastName, _user->nameOrPhone, _user->username);
emit closed(); emit closed();
return true; return true;
} else if (err == "NO_CHAT_TITLE") { } else if (err == "NO_CHAT_TITLE") {
@ -222,8 +223,7 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
if (isHidden() || !App::main()) return; if (isHidden() || !App::main()) return;
const auto &d(res.c_contacts_importedContacts()); const auto &d(res.c_contacts_importedContacts());
App::feedUsers(d.vusers, false); App::feedUsers(d.vusers);
App::emitPeerUpdated();
const auto &v(d.vimported.c_vector().v); const auto &v(d.vimported.c_vector().v);
UserData *user = nullptr; UserData *user = nullptr;
@ -1157,7 +1157,9 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) {
_requestId = 0; _requestId = 0;
QString err(error.type()); QString err(error.type());
if (err == qstr("CHAT_TITLE_NOT_MODIFIED") || err == qstr("CHAT_NOT_MODIFIED")) { if (err == qstr("CHAT_TITLE_NOT_MODIFIED") || err == qstr("CHAT_NOT_MODIFIED")) {
_peer->updateName(_sentName, QString(), QString()); if (auto chatData = _peer->asChat()) {
chatData->setName(_sentName);
}
emit closed(); emit closed();
return true; return true;
} else if (err == qstr("NO_CHAT_TITLE")) { } else if (err == qstr("NO_CHAT_TITLE")) {

View File

@ -24,10 +24,45 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Notify { namespace Notify {
namespace { namespace {
UnregisterObserverCallback UnregisterCallbacks[256]; using StartCallbacksList = QVector<StartObservedEventCallback>;
using FinishCallbacksList = QVector<FinishObservedEventCallback>;
NeverFreedPointer<StartCallbacksList> StartCallbacks;
NeverFreedPointer<FinishCallbacksList> FinishCallbacks;
UnregisterObserverCallback UnregisterCallbacks[256]/* = { nullptr }*/;
} // namespace } // namespace
void startObservers() {
if (!StartCallbacks) return;
for (auto &callback : *StartCallbacks) {
callback();
}
}
void finishObservers() {
if (!FinishCallbacks) return;
for (auto &callback : *FinishCallbacks) {
callback();
}
StartCallbacks.clear();
FinishCallbacks.clear();
}
ObservedEventRegistrator::ObservedEventRegistrator(ObservedEvent event
, StartObservedEventCallback startCallback
, FinishObservedEventCallback finishCallback
, UnregisterObserverCallback unregisterCallback) {
StartCallbacks.makeIfNull();
StartCallbacks->push_back(startCallback);
FinishCallbacks.makeIfNull();
FinishCallbacks->push_back(finishCallback);
UnregisterCallbacks[event] = unregisterCallback;
}
// Observer base interface. // Observer base interface.
Observer::~Observer() { Observer::~Observer() {
for_const (auto connection, _connections) { for_const (auto connection, _connections) {
@ -47,10 +82,6 @@ void unregisterObserver(ConnectionId connection) {
} }
} }
UnregisterObserverCallbackCreator::UnregisterObserverCallbackCreator(ObservedEvent event, UnregisterObserverCallback callback) {
UnregisterCallbacks[event] = callback;
}
namespace internal { namespace internal {
void observerRegisteredDefault(Observer *observer, ConnectionId connection) { void observerRegisteredDefault(Observer *observer, ConnectionId connection) {
@ -58,5 +89,4 @@ void observerRegisteredDefault(Observer *observer, ConnectionId connection) {
} }
} // namespace internal } // namespace internal
} // namespace Notify } // namespace Notify

View File

@ -24,13 +24,36 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Notify { namespace Notify {
class Observer; using ObservedEvent = uchar;
using ConnectionId = uint32; using ConnectionId = uint32;
// startObservers() must be called after main() started (not in a global variable constructor).
// finishObservers() must be called before main() finished (not in a global variable destructor).
void startObservers();
void finishObservers();
using StartObservedEventCallback = void(*)();
using UnregisterObserverCallback = void(*)(int connectionIndex);
using FinishObservedEventCallback = void(*)();
// Objects of this class should be constructed in global scope.
// startCallback will be called from Notify::startObservers().
// finishCallback will be called from Notify::finishObservers().
// unregisterCallback will be used to destroy connections.
class ObservedEventRegistrator {
public:
ObservedEventRegistrator(ObservedEvent event
, StartObservedEventCallback startCallback
, FinishObservedEventCallback finishCallback
, UnregisterObserverCallback unregisterCallback);
};
// Each observer type should have observerRegistered(Notify::ConnectionId connection) method. // Each observer type should have observerRegistered(Notify::ConnectionId connection) method.
// Usually it is done by deriving the type from the Notify::Observer base class. // Usually it is done by deriving the type from the Notify::Observer base class.
// In destructor it should call Notify::unregisterObserver(connection) for all the connections. // In destructor it should call Notify::unregisterObserver(connection) for all the connections.
class Observer;
namespace internal { namespace internal {
void observerRegisteredDefault(Observer *observer, ConnectionId connection); void observerRegisteredDefault(Observer *observer, ConnectionId connection);
} // namespace internal } // namespace internal
@ -49,21 +72,11 @@ private:
}; };
using ObservedEvent = uchar;
inline ConnectionId observerConnectionId(ObservedEvent event, int connectionIndex) { inline ConnectionId observerConnectionId(ObservedEvent event, int connectionIndex) {
t_assert(connectionIndex >= 0 && connectionIndex < 0x01000000); t_assert(connectionIndex >= 0 && connectionIndex < 0x01000000);
return (static_cast<uint32>(event) << 24) | (connectionIndex + 1); return (static_cast<uint32>(event) << 24) | (connectionIndex + 1);
} }
using UnregisterObserverCallback = void(*)(int connectionIndex);
// Usage: UnregisterObserverCallbackCreator creator(myEvent, myCallback); in global scope.
class UnregisterObserverCallbackCreator {
public:
UnregisterObserverCallbackCreator(ObservedEvent event, UnregisterObserverCallback callback);
};
// Handler is one of Function<> instantiations. // Handler is one of Function<> instantiations.
template <typename Flags, typename Handler> template <typename Flags, typename Handler>
struct ObserversList { struct ObserversList {

View File

@ -1153,9 +1153,10 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
} break; } break;
case mtpc_messageActionChatEditTitle: { case mtpc_messageActionChatEditTitle: {
const auto &d(action.c_messageActionChatEditTitle()); auto &d(action.c_messageActionChatEditTitle());
ChatData *chat = peer->asChat(); if (auto chat = peer->asChat()) {
if (chat) chat->updateName(qs(d.vtitle), QString(), QString()); chat->setName(qs(d.vtitle));
}
} break; } break;
case mtpc_messageActionChatMigrateTo: { case mtpc_messageActionChatMigrateTo: {

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "serialize/serialize_document.h" #include "serialize/serialize_document.h"
#include "serialize/serialize_common.h" #include "serialize/serialize_common.h"
#include "observer_peer.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "lang.h" #include "lang.h"
@ -3489,7 +3490,7 @@ namespace Local {
QString pname = (showPhone && !phone.isEmpty()) ? App::formatPhone(phone) : QString(); QString pname = (showPhone && !phone.isEmpty()) ? App::formatPhone(phone) : QString();
if (!wasLoaded) { if (!wasLoaded) {
user->setName(first, last, pname, username); user->setNameDelayed(first, last, pname, username);
user->access = access; user->access = access;
user->flags = MTPDuser::Flags(flags); user->flags = MTPDuser::Flags(flags);
@ -3524,7 +3525,7 @@ namespace Local {
flags = (flagsData == 1) ? MTPDchat::Flags(MTPDchat::Flag::f_left) : MTPDchat::Flags(0); flags = (flagsData == 1) ? MTPDchat::Flags(MTPDchat::Flag::f_left) : MTPDchat::Flags(0);
} }
if (!wasLoaded) { if (!wasLoaded) {
chat->updateName(name, QString(), QString()); chat->setNameDelayed(name);
chat->count = count; chat->count = count;
chat->date = date; chat->date = date;
chat->version = version; chat->version = version;
@ -3547,7 +3548,7 @@ namespace Local {
from.stream >> name >> access >> date >> version >> forbidden >> flags >> invitationUrl; from.stream >> name >> access >> date >> version >> forbidden >> flags >> invitationUrl;
if (!wasLoaded) { if (!wasLoaded) {
channel->updateName(name, QString(), QString()); channel->setNameDelayed(name, QString());
channel->access = access; channel->access = access;
channel->date = date; channel->date = date;
channel->version = version; channel->version = version;
@ -3743,7 +3744,8 @@ namespace Local {
cRefSavedPeersByTime().insert(t, peer); cRefSavedPeersByTime().insert(t, peer);
peers.push_back(peer); peers.push_back(peer);
} }
App::emitPeerUpdated();
Notify::peerUpdatedSendDelayed();
if (App::api()) App::api()->requestPeers(peers); if (App::api()) App::api()->requestPeers(peers);
} }

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "window/section_memento.h" #include "window/section_memento.h"
#include "window/section_widget.h" #include "window/section_widget.h"
#include "window/top_bar_widget.h" #include "window/top_bar_widget.h"
#include "observer_peer.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "dialogswidget.h" #include "dialogswidget.h"
#include "historywidget.h" #include "historywidget.h"
@ -696,12 +697,12 @@ void MainWidget::deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHis
if (peer && peer->isChannel()) { if (peer && peer->isChannel()) {
if (peer->asChannel()->ptsUpdated(d.vpts.v, d.vpts_count.v)) { if (peer->asChannel()->ptsUpdated(d.vpts.v, d.vpts_count.v)) {
peer->asChannel()->ptsApplySkippedUpdates(); peer->asChannel()->ptsApplySkippedUpdates();
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
} else { } else {
if (ptsUpdated(d.vpts.v, d.vpts_count.v)) { if (ptsUpdated(d.vpts.v, d.vpts_count.v)) {
ptsApplySkippedUpdates(); ptsApplySkippedUpdates();
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
} }
@ -725,10 +726,10 @@ void MainWidget::deleteMessages(PeerData *peer, const QVector<MTPint> &ids) {
} }
void MainWidget::deletedContact(UserData *user, const MTPcontacts_Link &result) { void MainWidget::deletedContact(UserData *user, const MTPcontacts_Link &result) {
const auto &d(result.c_contacts_link()); auto &d(result.c_contacts_link());
App::feedUsers(MTP_vector<MTPUser>(1, d.vuser), false); App::feedUsersDelayed(MTP_vector<MTPUser>(1, d.vuser));
App::feedUserLink(MTP_int(peerToUser(user->id)), d.vmy_link, d.vforeign_link, false); App::feedUserLinkDelayed(MTP_int(peerToUser(user->id)), d.vmy_link, d.vforeign_link);
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
void MainWidget::removeDialog(History *history) { void MainWidget::removeDialog(History *history) {
@ -790,7 +791,7 @@ void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTP
const auto &d(result.c_messages_affectedHistory()); const auto &d(result.c_messages_affectedHistory());
if (params.channel->ptsUpdated(d.vpts.v, d.vpts_count.v)) { if (params.channel->ptsUpdated(d.vpts.v, d.vpts_count.v)) {
params.channel->ptsApplySkippedUpdates(); params.channel->ptsApplySkippedUpdates();
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
int32 offset = d.voffset.v; int32 offset = d.voffset.v;
@ -1381,15 +1382,6 @@ void MainWidget::loadMediaBack(PeerData *peer, MediaOverviewType type, bool many
_overviewLoad[type].insert(peer, MTP::send(MTPmessages_Search(MTP_flags(flags), peer->input, MTPstring(), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MainWidget::overviewLoaded, history))); _overviewLoad[type].insert(peer, MTP::send(MTPmessages_Search(MTP_flags(flags), peer->input, MTPstring(), filter, MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MainWidget::overviewLoaded, history)));
} }
void MainWidget::peerUsernameChanged(PeerData *peer) {
//if (_profile && _profile->peer() == peer) { TODO
// _profile->peerUsernameChanged();
//}
if (App::settings() && peer == App::self()) {
App::settings()->usernameChanged();
}
}
void MainWidget::checkLastUpdate(bool afterSleep) { void MainWidget::checkLastUpdate(bool afterSleep) {
uint64 n = getms(true); uint64 n = getms(true);
if (_lastUpdateTime && n > _lastUpdateTime + (afterSleep ? NoUpdatesAfterSleepTimeout : NoUpdatesTimeout)) { if (_lastUpdateTime && n > _lastUpdateTime + (afterSleep ? NoUpdatesAfterSleepTimeout : NoUpdatesTimeout)) {
@ -1463,12 +1455,12 @@ void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMess
if (peer && peer->isChannel()) { if (peer && peer->isChannel()) {
if (peer->asChannel()->ptsUpdated(d.vpts.v, d.vpts_count.v)) { if (peer->asChannel()->ptsUpdated(d.vpts.v, d.vpts_count.v)) {
peer->asChannel()->ptsApplySkippedUpdates(); peer->asChannel()->ptsApplySkippedUpdates();
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
} else { } else {
if (ptsUpdated(d.vpts.v, d.vpts_count.v)) { if (ptsUpdated(d.vpts.v, d.vpts_count.v)) {
ptsApplySkippedUpdates(); ptsApplySkippedUpdates();
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
} }
if (History *h = App::historyLoaded(peer ? peer->id : 0)) { if (History *h = App::historyLoaded(peer ? peer->id : 0)) {
@ -2426,7 +2418,7 @@ void MainWidget::windowShown() {
void MainWidget::sentUpdatesReceived(uint64 randomId, const MTPUpdates &result) { void MainWidget::sentUpdatesReceived(uint64 randomId, const MTPUpdates &result) {
feedUpdates(result, randomId); feedUpdates(result, randomId);
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
bool MainWidget::deleteChannelFailed(const RPCError &error) { bool MainWidget::deleteChannelFailed(const RPCError &error) {
@ -2874,8 +2866,8 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
case mtpc_updates_channelDifference: { case mtpc_updates_channelDifference: {
const auto &d(diff.c_updates_channelDifference()); const auto &d(diff.c_updates_channelDifference());
App::feedUsers(d.vusers); App::feedUsersDelayed(d.vusers);
App::feedChats(d.vchats, false); App::feedChatsDelayed(d.vchats);
_handlingChannelDifference = true; _handlingChannelDifference = true;
feedMessageIds(d.vother_updates); feedMessageIds(d.vother_updates);
@ -2945,7 +2937,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
channel->ptsWaitingForShortPoll(timeout ? (timeout * 1000) : WaitForChannelGetDifference); channel->ptsWaitingForShortPoll(timeout ? (timeout * 1000) : WaitForChannelGetDifference);
} }
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) { void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) {
@ -2961,8 +2953,8 @@ void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_Chann
case mtpc_updates_channelDifferenceTooLong: { case mtpc_updates_channelDifferenceTooLong: {
const auto &d(diff.c_updates_channelDifferenceTooLong()); const auto &d(diff.c_updates_channelDifferenceTooLong());
App::feedUsers(d.vusers); App::feedUsersDelayed(d.vusers);
App::feedChats(d.vchats); App::feedChatsDelayed(d.vchats);
nextRequestPts = d.vpts.v; nextRequestPts = d.vpts.v;
isFinal = d.is_final(); isFinal = d.is_final();
@ -2971,8 +2963,8 @@ void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_Chann
case mtpc_updates_channelDifference: { case mtpc_updates_channelDifference: {
const auto &d(diff.c_updates_channelDifference()); const auto &d(diff.c_updates_channelDifference());
App::feedUsers(d.vusers); App::feedUsersDelayed(d.vusers);
App::feedChats(d.vchats, false); App::feedChatsDelayed(d.vchats);
_handlingChannelDifference = true; _handlingChannelDifference = true;
feedMessageIds(d.vother_updates); feedMessageIds(d.vother_updates);
@ -2992,7 +2984,7 @@ void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_Chann
} }
} }
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
bool MainWidget::failChannelDifference(ChannelData *channel, const RPCError &error) { bool MainWidget::failChannelDifference(ChannelData *channel, const RPCError &error) {
@ -3014,7 +3006,7 @@ void MainWidget::gotState(const MTPupdates_State &state) {
_dialogs->loadDialogs(); _dialogs->loadDialogs();
updateOnline(); updateOnline();
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} }
void MainWidget::gotDifference(const MTPupdates_Difference &diff) { void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
@ -3029,8 +3021,6 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
noUpdatesTimer.start(NoUpdatesTimeout); noUpdatesTimer.start(NoUpdatesTimeout);
_ptsWaiter.setRequesting(false); _ptsWaiter.setRequesting(false);
App::emitPeerUpdated();
} break; } break;
case mtpc_updates_differenceSlice: { case mtpc_updates_differenceSlice: {
const auto &d(diff.c_updates_differenceSlice()); const auto &d(diff.c_updates_differenceSlice());
@ -3043,8 +3033,6 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
MTP_LOG(0, ("getDifference { good - after a slice of difference was received }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference { good - after a slice of difference was received }%1").arg(cTestMode() ? " TESTMODE" : ""));
getDifference(); getDifference();
App::emitPeerUpdated();
} break; } break;
case mtpc_updates_difference: { case mtpc_updates_difference: {
const auto &d(diff.c_updates_difference()); const auto &d(diff.c_updates_difference());
@ -3053,6 +3041,7 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
gotState(d.vstate); gotState(d.vstate);
} break; } break;
}; };
Notify::peerUpdatedSendDelayed();
} }
bool MainWidget::getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, uint64 &curTime) { bool MainWidget::getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, uint64 &curTime) {
@ -3142,8 +3131,8 @@ void MainWidget::ptsApplySkippedUpdates() {
void MainWidget::feedDifference(const MTPVector<MTPUser> &users, const MTPVector<MTPChat> &chats, const MTPVector<MTPMessage> &msgs, const MTPVector<MTPUpdate> &other) { void MainWidget::feedDifference(const MTPVector<MTPUser> &users, const MTPVector<MTPChat> &chats, const MTPVector<MTPMessage> &msgs, const MTPVector<MTPUpdate> &other) {
App::wnd()->checkAutoLock(); App::wnd()->checkAutoLock();
App::feedUsers(users, false); App::feedUsersDelayed(users);
App::feedChats(chats, false); App::feedChatsDelayed(chats);
feedMessageIds(other); feedMessageIds(other);
App::feedMsgs(msgs, NewMessageUnread); App::feedMsgs(msgs, NewMessageUnread);
feedUpdateVector(other, true); feedUpdateVector(other, true);
@ -3875,7 +3864,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
if (!_ptsWaiter.requesting()) { if (!_ptsWaiter.requesting()) {
feedUpdates(updates); feedUpdates(updates);
} }
App::emitPeerUpdated(); Notify::peerUpdatedSendDelayed();
} catch (mtpErrorUnexpected &) { // just some other type } catch (mtpErrorUnexpected &) { // just some other type
} }
} }
@ -3995,8 +3984,8 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
} }
} }
App::feedUsers(d.vusers, false); App::feedUsersDelayed(d.vusers);
App::feedChats(d.vchats, false); App::feedChatsDelayed(d.vchats);
feedUpdateVector(d.vupdates); feedUpdateVector(d.vupdates);
updSetState(0, d.vdate.v, updQts, d.vseq.v); updSetState(0, d.vdate.v, updQts, d.vseq.v);
@ -4012,8 +4001,8 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
} }
} }
App::feedUsers(d.vusers, false); App::feedUsersDelayed(d.vusers);
App::feedChats(d.vchats, false); App::feedChatsDelayed(d.vchats);
feedUpdateVector(d.vupdates); feedUpdateVector(d.vupdates);
updSetState(0, d.vdate.v, updQts, d.vseq.v); updSetState(0, d.vdate.v, updQts, d.vseq.v);
@ -4338,13 +4327,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
} break; } break;
case mtpc_updateUserName: { case mtpc_updateUserName: {
const auto &d(update.c_updateUserName()); auto &d(update.c_updateUserName());
UserData *user = App::userLoaded(d.vuser_id.v); if (auto user = App::userLoaded(d.vuser_id.v)) {
if (user) {
if (user->contact <= 0) { if (user->contact <= 0) {
user->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), user->nameOrPhone, textOneLine(qs(d.vusername))); user->setNameDelayed(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), user->nameOrPhone, textOneLine(qs(d.vusername)));
} else { } else {
user->setName(textOneLine(user->firstName), textOneLine(user->lastName), user->nameOrPhone, textOneLine(qs(d.vusername))); user->setNameDelayed(textOneLine(user->firstName), textOneLine(user->lastName), user->nameOrPhone, textOneLine(qs(d.vusername)));
} }
App::markPeerUpdated(user); App::markPeerUpdated(user);
} }
@ -4385,7 +4373,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateContactLink: { case mtpc_updateContactLink: {
const auto &d(update.c_updateContactLink()); const auto &d(update.c_updateContactLink());
App::feedUserLink(d.vuser_id, d.vmy_link, d.vforeign_link, false); App::feedUserLinkDelayed(d.vuser_id, d.vmy_link, d.vforeign_link);
} break; } break;
case mtpc_updateNotifySettings: { case mtpc_updateNotifySettings: {
@ -4399,11 +4387,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
} break; } break;
case mtpc_updateUserPhone: { case mtpc_updateUserPhone: {
const auto &d(update.c_updateUserPhone()); auto &d(update.c_updateUserPhone());
UserData *user = App::userLoaded(d.vuser_id.v); if (auto user = App::userLoaded(d.vuser_id.v)) {
if (user) {
user->setPhone(qs(d.vphone)); user->setPhone(qs(d.vphone));
user->setName(user->firstName, user->lastName, (user->contact || isServiceUser(user->id) || user->isSelf() || user->phone.isEmpty()) ? QString() : App::formatPhone(user->phone), user->username); user->setNameDelayed(user->firstName, user->lastName, (user->contact || isServiceUser(user->id) || user->isSelf() || user->phone.isEmpty()) ? QString() : App::formatPhone(user->phone), user->username);
App::markPeerUpdated(user); App::markPeerUpdated(user);
} }
} break; } break;

View File

@ -322,7 +322,6 @@ public:
void itemEdited(HistoryItem *item); void itemEdited(HistoryItem *item);
void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false); void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false);
void peerUsernameChanged(PeerData *peer);
void checkLastUpdate(bool afterSleep); void checkLastUpdate(bool afterSleep);
void showAddContact(); void showAddContact();

View File

@ -23,81 +23,112 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/observer.h" #include "core/observer.h"
namespace App {
// Temp forward declaration (while all peer updates are not done through observers).
void emitPeerUpdated();
} // namespace App
namespace Notify { namespace Notify {
namespace internal { namespace internal {
namespace { namespace {
constexpr ObservedEvent PeerUpdateEvent = 0x01; constexpr ObservedEvent PeerUpdateEvent = 0x01;
ObserversList<PeerUpdateFlags, PeerUpdateHandler> PeerUpdateObservers; using PeerObserversList = ObserversList<PeerUpdateFlags, PeerUpdateHandler>;
NeverFreedPointer<PeerObserversList> PeerUpdateObservers;
void UnregisterCallback(int connectionIndex) { using SmallUpdatesList = QVector<PeerUpdate>;
unregisterObserver(PeerUpdateObservers, connectionIndex); NeverFreedPointer<SmallUpdatesList> SmallUpdates;
using AllUpdatesList = QMap<PeerData*, PeerUpdate>;
NeverFreedPointer<AllUpdatesList> AllUpdates;
void StartCallback() {
PeerUpdateObservers.makeIfNull();
SmallUpdates.makeIfNull();
AllUpdates.makeIfNull();
} }
UnregisterObserverCallbackCreator creator(PeerUpdateEvent, UnregisterCallback); void FinishCallback() {
PeerUpdateObservers.clear();
SmallUpdates.clear();
AllUpdates.clear();
}
void UnregisterCallback(int connectionIndex) {
t_assert(!PeerUpdateObservers.isNull());
unregisterObserver(*PeerUpdateObservers, connectionIndex);
}
ObservedEventRegistrator creator(PeerUpdateEvent, StartCallback, FinishCallback, UnregisterCallback);
QVector<PeerUpdate> SmallPeerUpdates; bool Started() {
QMap<PeerData*, PeerUpdate> AllPeerUpdates; return !PeerUpdateObservers.isNull();
}
} // namespace } // namespace
ConnectionId plainRegisterPeerObserver(PeerUpdateFlags events, PeerUpdateHandler &&handler) { ConnectionId plainRegisterPeerObserver(PeerUpdateFlags events, PeerUpdateHandler &&handler) {
auto connectionId = registerObserver(PeerUpdateObservers, events, std_::forward<PeerUpdateHandler>(handler)); t_assert(Started());
auto connectionId = registerObserver(*PeerUpdateObservers, events, std_::forward<PeerUpdateHandler>(handler));
t_assert(connectionId >= 0 && connectionId < 0x01000000); t_assert(connectionId >= 0 && connectionId < 0x01000000);
return (static_cast<uint32>(PeerUpdateEvent) << 24) | static_cast<uint32>(connectionId + 1); return (static_cast<uint32>(PeerUpdateEvent) << 24) | static_cast<uint32>(connectionId + 1);
} }
void mergePeerUpdate(PeerUpdate &mergeTo, const PeerUpdate &mergeFrom) { void mergePeerUpdate(PeerUpdate &mergeTo, const PeerUpdate &mergeFrom) {
if (!(mergeTo.flags & PeerUpdateFlag::NameChanged)) {
if (mergeFrom.flags & PeerUpdateFlag::NameChanged) {
mergeTo.oldNames = mergeFrom.oldNames;
mergeTo.oldNameFirstChars = mergeFrom.oldNameFirstChars;
}
}
mergeTo.flags |= mergeFrom.flags; mergeTo.flags |= mergeFrom.flags;
// merge fields used in mergeFrom.flags
} }
} // namespace internal } // namespace internal
void peerUpdated(const PeerUpdate &update) {
notifyObservers(internal::PeerUpdateObservers, update.flags, update);
}
void peerUpdatedDelayed(const PeerUpdate &update) { void peerUpdatedDelayed(const PeerUpdate &update) {
int alreadySavedCount = internal::SmallPeerUpdates.size(); t_assert(internal::Started());
for (int i = 0; i < alreadySavedCount; ++i) {
if (internal::SmallPeerUpdates.at(i).peer == update.peer) { int existingUpdatesCount = internal::SmallUpdates->size();
internal::mergePeerUpdate(internal::SmallPeerUpdates[i], update); for (int i = 0; i < existingUpdatesCount; ++i) {
auto &existingUpdate = (*internal::SmallUpdates)[i];
if (existingUpdate.peer == update.peer) {
internal::mergePeerUpdate(existingUpdate, update);
return; return;
} }
} }
if (internal::AllPeerUpdates.isEmpty()) { if (internal::AllUpdates->isEmpty()) {
if (alreadySavedCount < 5) { if (existingUpdatesCount < 5) {
internal::SmallPeerUpdates.push_back(update); internal::SmallUpdates->push_back(update);
} else { } else {
internal::AllPeerUpdates.insert(update.peer, update); internal::AllUpdates->insert(update.peer, update);
} }
} else { } else {
auto it = internal::AllPeerUpdates.find(update.peer); auto it = internal::AllUpdates->find(update.peer);
if (it != internal::AllPeerUpdates.cend()) { if (it != internal::AllUpdates->cend()) {
internal::mergePeerUpdate(it.value(), update); internal::mergePeerUpdate(it.value(), update);
return; return;
} }
internal::AllPeerUpdates.insert(update.peer, update); internal::AllUpdates->insert(update.peer, update);
} }
} }
void peerUpdatedSendDelayed() { void peerUpdatedSendDelayed() {
if (internal::SmallPeerUpdates.isEmpty()) return; App::emitPeerUpdated();
decltype(internal::SmallPeerUpdates) smallList; t_assert(internal::Started());
decltype(internal::AllPeerUpdates) allList;
std::swap(smallList, internal::SmallPeerUpdates); if (internal::SmallUpdates->isEmpty()) return;
std::swap(allList, internal::AllPeerUpdates);
internal::SmallUpdatesList smallList;
internal::AllUpdatesList allList;
std::swap(smallList, *internal::SmallUpdates);
std::swap(allList, *internal::AllUpdates);
for_const (auto &update, smallList) { for_const (auto &update, smallList) {
peerUpdated(update); notifyObservers(*internal::PeerUpdateObservers, update.flags, update);
} }
for_const (auto &update, allList) { for_const (auto &update, allList) {
peerUpdated(update); notifyObservers(*internal::PeerUpdateObservers, update.flags, update);
} }
if (internal::SmallPeerUpdates.isEmpty()) { if (internal::SmallUpdates->isEmpty()) {
std::swap(smallList, internal::SmallPeerUpdates); std::swap(smallList, *internal::SmallUpdates);
internal::SmallPeerUpdates.resize(0); internal::SmallUpdates->resize(0);
} }
} }

View File

@ -26,27 +26,35 @@ namespace Notify {
// Generic notifications about updates of some PeerData. // Generic notifications about updates of some PeerData.
// You can subscribe to them by Notify::registerPeerObserver(). // You can subscribe to them by Notify::registerPeerObserver().
// 0x0000FFFFU for general peer updates (valid for any peer).
// 0xFFFF0000U for specific peer updates (valid for user / chat / channel).
enum class PeerUpdateFlag { enum class PeerUpdateFlag {
//PeerNameChanged = 0x0001, NameChanged = 0x00000001U,
UsernameChanged = 0x00000002U,
UserCanShareContact = 0x1001, UserCanShareContact = 0x00010000U,
ChatCanEdit = 0x2001, ChatCanEdit = 0x00010000U,
MegagroupCanEditPhoto = 0x4001, ChannelAmIn = 0x00010000U,
MegagroupCanAddMembers = 0x4002, MegagroupCanEditPhoto = 0x00020000U,
MegagroupCanAddMembers = 0x00040000U,
ChannelAmIn = 0x8001,
}; };
Q_DECLARE_FLAGS(PeerUpdateFlags, PeerUpdateFlag); Q_DECLARE_FLAGS(PeerUpdateFlags, PeerUpdateFlag);
Q_DECLARE_OPERATORS_FOR_FLAGS(PeerUpdateFlags); Q_DECLARE_OPERATORS_FOR_FLAGS(PeerUpdateFlags);
struct PeerUpdate { struct PeerUpdate {
PeerData *peer = nullptr; PeerUpdate(PeerData *updated = nullptr) : peer(updated) {
}
PeerData *peer;
PeerUpdateFlags flags = 0; PeerUpdateFlags flags = 0;
// NameChanged data
PeerData::Names oldNames;
PeerData::NameFirstChars oldNameFirstChars;
}; };
void peerUpdated(const PeerUpdate &update);
void peerUpdatedDelayed(const PeerUpdate &update); void peerUpdatedDelayed(const PeerUpdate &update);
void peerUpdatedSendDelayed(); void peerUpdatedSendDelayed();

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_profile.h" #include "styles/style_profile.h"
#include "ui/buttons/round_button.h" #include "ui/buttons/round_button.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "boxes/contactsbox.h"
#include "lang.h" #include "lang.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -98,17 +99,16 @@ CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent)
, _photoButton(this, peer) { , _photoButton(this, peer) {
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
using Flag = Notify::PeerUpdateFlag; auto observeEvents = ButtonsUpdateFlags | Notify::PeerUpdateFlag::NameChanged;
auto observeEvents = ButtonsUpdateFlags;
Notify::registerPeerObserver(observeEvents, this, &CoverWidget::notifyPeerUpdated); Notify::registerPeerObserver(observeEvents, this, &CoverWidget::notifyPeerUpdated);
_photoButton->photoUpdated(); _photoButton->photoUpdated();
connect(_photoButton, SIGNAL(clicked()), this, SLOT(onPhotoShow())); connect(_photoButton, SIGNAL(clicked()), this, SLOT(onPhotoShow()));
_nameText.setText(st::profileNameFont, App::peerName(_peer)); refreshNameText();
updateStatusText(); refreshStatusText();
updateButtons(); refreshButtons();
} }
void CoverWidget::onPhotoShow() { void CoverWidget::onPhotoShow() {
@ -121,31 +121,6 @@ void CoverWidget::onPhotoShow() {
} }
} }
void CoverWidget::onSendMessage() {
}
void CoverWidget::onShareContact() {
}
void CoverWidget::onSetPhoto() {
}
void CoverWidget::onAddMember() {
}
void CoverWidget::onJoin() {
}
void CoverWidget::onViewChannel() {
}
void CoverWidget::resizeToWidth(int newWidth) { void CoverWidget::resizeToWidth(int newWidth) {
int newHeight = 0; int newHeight = 0;
@ -202,7 +177,23 @@ void CoverWidget::paintDivider(Painter &p) {
st::profileDividerFill.fill(p, toFill); st::profileDividerFill.fill(p, toFill);
} }
void CoverWidget::updateStatusText() { void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.peer == _peer) {
if ((update.flags & ButtonsUpdateFlags) != 0) {
refreshButtons();
}
if (update.flags & Notify::PeerUpdateFlag::NameChanged) {
refreshNameText();
}
}
}
void CoverWidget::refreshNameText() {
_nameText.setText(st::profileNameFont, App::peerName(_peer));
update();
}
void CoverWidget::refreshStatusText() {
int currentTime = unixtime(); int currentTime = unixtime();
if (_peerUser) { if (_peerUser) {
_statusText = App::onlineText(_peerUser, currentTime, true); _statusText = App::onlineText(_peerUser, currentTime, true);
@ -235,6 +226,7 @@ void CoverWidget::updateStatusText() {
} else { } else {
_statusText = lang(lng_chat_status_unaccessible); _statusText = lang(lng_chat_status_unaccessible);
} }
update();
} }
bool CoverWidget::isUsingMegagroupOnlineCount() const { bool CoverWidget::isUsingMegagroupOnlineCount() const {
@ -254,13 +246,7 @@ bool CoverWidget::isUsingMegagroupOnlineCount() const {
return true; return true;
} }
void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { void CoverWidget::refreshButtons() {
if (update.flags & ButtonsUpdateFlags) {
updateButtons();
}
}
void CoverWidget::updateButtons() {
if (_peerUser) { if (_peerUser) {
setUserButtons(); setUserButtons();
} else if (_peerChat) { } else if (_peerChat) {
@ -336,4 +322,36 @@ void CoverWidget::setSecondaryButton(const QString &text, const char *slot) {
} }
} }
void CoverWidget::onSendMessage() {
Ui::showPeerHistory(_peer, ShowAtUnreadMsgId);
}
void CoverWidget::onShareContact() {
App::main()->shareContactLayer(_peerUser);
}
void CoverWidget::onSetPhoto() {
}
void CoverWidget::onAddMember() {
if (_peerChat) {
Ui::showLayer(new ContactsBox(_peerChat, MembersFilterRecent));
} else if (_peerChannel && _peerChannel->mgInfo) {
MembersAlreadyIn already;
for (MegagroupInfo::LastParticipants::const_iterator i = _peerChannel->mgInfo->lastParticipants.cbegin(), e = _peerChannel->mgInfo->lastParticipants.cend(); i != e; ++i) {
already.insert(*i, true);
}
Ui::showLayer(new ContactsBox(_peerChannel, MembersFilterRecent, already));
}
}
void CoverWidget::onJoin() {
}
void CoverWidget::onViewChannel() {
Ui::showPeerHistory(_peer, ShowAtUnreadMsgId);
}
} // namespace Profile } // namespace Profile

View File

@ -58,13 +58,14 @@ protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
private: private:
void updateStatusText();
bool isUsingMegagroupOnlineCount() const;
// Observed notifications. // Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update); void notifyPeerUpdated(const Notify::PeerUpdate &update);
void updateButtons(); void refreshNameText();
void refreshStatusText();
bool isUsingMegagroupOnlineCount() const;
void refreshButtons();
void setUserButtons(); void setUserButtons();
void setChatButtons(); void setChatButtons();
void setMegagroupButtons(); void setMegagroupButtons();

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h" #include "stdafx.h"
#include "settingswidget.h" #include "settingswidget.h"
#include "observer_peer.h"
#include "lang.h" #include "lang.h"
#include "boxes/aboutbox.h" #include "boxes/aboutbox.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -205,6 +206,8 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
, _telegramFAQ(this, lang(lng_settings_faq)) , _telegramFAQ(this, lang(lng_settings_faq))
, _logOut(this, lang(lng_settings_logout), st::btnRedLink) , _logOut(this, lang(lng_settings_logout), st::btnRedLink)
, _supportGetRequest(0) { , _supportGetRequest(0) {
Notify::registerPeerObserver(Notify::PeerUpdateFlag::UsernameChanged, this, &SettingsInner::notifyPeerUpdated);
if (self()) { if (self()) {
self()->loadUserpic(); self()->loadUserpic();
@ -349,6 +352,14 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
setMouseTracking(true); setMouseTracking(true);
} }
void SettingsInner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.peer == App::self()) {
if (update.flags & Notify::PeerUpdateFlag::UsernameChanged) {
usernameChanged();
}
}
}
void SettingsInner::peerUpdated(PeerData *data) { void SettingsInner::peerUpdated(PeerData *data) {
if (self() && data == self()) { if (self() && data == self()) {
if (self()->photoId && self()->photoId != UnknownPeerPhotoId) { if (self()->photoId && self()->photoId != UnknownPeerPhotoId) {
@ -1977,10 +1988,6 @@ void SettingsWidget::rpcClear() {
_inner.rpcClear(); _inner.rpcClear();
} }
void SettingsWidget::usernameChanged() {
_inner.usernameChanged();
}
void SettingsWidget::setInnerFocus() { void SettingsWidget::setInnerFocus() {
_inner.setFocus(); _inner.setFocus();
} }

View File

@ -23,8 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/flatbutton.h" #include "ui/flatbutton.h"
#include "ui/flatcheckbox.h" #include "ui/flatcheckbox.h"
#include "sysbuttons.h" #include "sysbuttons.h"
#include "core/observer.h"
#include <QtWidgets/QWidget>
class MainWindow; class MainWindow;
class Settings; class Settings;
@ -57,7 +56,11 @@ private:
}; };
class SettingsInner : public TWidget, public RPCSender { namespace Notify {
struct PeerUpdate;
} // namespace Notify
class SettingsInner : public TWidget, public RPCSender, public Notify::Observer {
Q_OBJECT Q_OBJECT
public: public:
@ -188,6 +191,7 @@ public slots:
void onTelegramFAQ(); void onTelegramFAQ();
private: private:
void notifyPeerUpdated(const Notify::PeerUpdate &update);
void saveError(const QString &str = QString()); void saveError(const QString &str = QString());
@ -332,7 +336,6 @@ public:
void updateDisplayNotify(); void updateDisplayNotify();
void rpcClear(); void rpcClear();
void usernameChanged();
void setInnerFocus(); void setInnerFocus();
void needBackgroundUpdate(bool tile); void needBackgroundUpdate(bool tile);

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "lang.h" #include "lang.h"
#include "inline_bots/inline_bot_layout_item.h" #include "inline_bots/inline_bot_layout_item.h"
#include "observer_peer.h"
#include "history.h" #include "history.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "application.h" #include "application.h"
@ -99,18 +100,14 @@ NotifySettings globalNotifyAll, globalNotifyUsers, globalNotifyChats;
NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersPtr = UnknownNotifySettings, globalNotifyChatsPtr = UnknownNotifySettings; NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersPtr = UnknownNotifySettings, globalNotifyChatsPtr = UnknownNotifySettings;
PeerData::PeerData(const PeerId &id) : id(id) PeerData::PeerData(const PeerId &id) : id(id)
, loadedStatus(NotLoaded)
, colorIndex(peerColorIndex(id)) , colorIndex(peerColorIndex(id))
, color(peerColor(colorIndex)) , color(peerColor(colorIndex))
, photoId(UnknownPeerPhotoId)
, nameVersion(0)
, notify(UnknownNotifySettings)
, _userpic(isUser() ? userDefPhoto(colorIndex) : ((isChat() || isMegagroup()) ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex))) { , _userpic(isUser() ? userDefPhoto(colorIndex) : ((isChat() || isMegagroup()) ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex))) {
if (!peerIsUser(id) && !peerIsChannel(id)) updateName(QString(), QString(), QString()); nameText.setText(st::msgNameFont, QString(), _textNameOptions);
} }
void PeerData::updateName(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) { void PeerData::updateNameDelayed(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) {
if (name == newName && nameVersion > 0) { if (name == newName) {
if (isUser()) { if (isUser()) {
if (asUser()->nameOrPhone == newNameOrPhone && asUser()->username == newUsername) { if (asUser()->nameOrPhone == newNameOrPhone && asUser()->username == newUsername) {
return; return;
@ -127,8 +124,17 @@ void PeerData::updateName(const QString &newName, const QString &newNameOrPhone,
++nameVersion; ++nameVersion;
name = newName; name = newName;
nameText.setText(st::msgNameFont, name, _textNameOptions); nameText.setText(st::msgNameFont, name, _textNameOptions);
Notify::PeerUpdate update(this);
update.flags |= Notify::PeerUpdateFlag::NameChanged;
update.oldNames = names;
update.oldNameFirstChars = chars;
if (isUser()) { if (isUser()) {
if (asUser()->username != newUsername) {
asUser()->username = newUsername; asUser()->username = newUsername;
update.flags |= Notify::PeerUpdateFlag::UsernameChanged;
}
asUser()->setNameOrPhone(newNameOrPhone); asUser()->setNameOrPhone(newNameOrPhone);
} else if (isChannel()) { } else if (isChannel()) {
if (asChannel()->username != newUsername) { if (asChannel()->username != newUsername) {
@ -138,19 +144,14 @@ void PeerData::updateName(const QString &newName, const QString &newNameOrPhone,
} else { } else {
asChannel()->flags |= MTPDchannel::Flag::f_username; asChannel()->flags |= MTPDchannel::Flag::f_username;
} }
if (App::main()) { update.flags |= Notify::PeerUpdateFlag::UsernameChanged;
App::main()->peerUsernameChanged(this);
} }
} }
}
Names oldNames = names;
NameFirstChars oldChars = chars;
fillNames(); fillNames();
if (App::main()) { if (App::main()) {
emit App::main()->peerNameChanged(this, oldNames, oldChars); emit App::main()->peerNameChanged(this, update.oldNames, update.oldNameFirstChars);
} }
Notify::peerUpdatedDelayed(update);
} }
void PeerData::setUserpic(ImagePtr userpic) { void PeerData::setUserpic(ImagePtr userpic) {
@ -253,25 +254,27 @@ void PeerData::fillNames() {
} }
} }
void UserData::setName(const QString &first, const QString &last, const QString &phoneName, const QString &usern) { void UserData::setName(const QString &newFirstName, const QString &newLastName, const QString &newPhoneName, const QString &newUsername) {
bool updName = !first.isEmpty() || !last.isEmpty(), updUsername = (username != usern); setNameDelayed(newFirstName, newLastName, newPhoneName, newUsername);
Notify::peerUpdatedSendDelayed();
}
if (updName && first.trimmed().isEmpty()) { void UserData::setNameDelayed(const QString &newFirstName, const QString &newLastName, const QString &newPhoneName, const QString &newUsername) {
firstName = last; bool changeName = !newFirstName.isEmpty() || !newLastName.isEmpty();
QString newFullName;
if (changeName && newFirstName.trimmed().isEmpty()) {
firstName = newLastName;
lastName = QString(); lastName = QString();
updateName(firstName, phoneName, usern); newFullName = firstName;
} else { } else {
if (updName) { if (changeName) {
firstName = first; firstName = newFirstName;
lastName = last; lastName = newLastName;
}
updateName(lastName.isEmpty() ? firstName : lng_full_name(lt_first_name, firstName, lt_last_name, lastName), phoneName, usern);
}
if (updUsername) {
if (App::main()) {
App::main()->peerUsernameChanged(this);
} }
newFullName = lastName.isEmpty() ? firstName : lng_full_name(lt_first_name, firstName, lt_last_name, lastName);
} }
updateNameDelayed(newFullName, newPhoneName, newUsername);
} }
void UserData::setPhone(const QString &newPhone) { void UserData::setPhone(const QString &newPhone) {
@ -401,6 +404,15 @@ void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see Loc
} }
} }
void ChatData::setName(const QString &newName) {
setNameDelayed(newName);
Notify::peerUpdatedSendDelayed();
}
void ChatData::setNameDelayed(const QString &newName) {
updateNameDelayed(newName.isEmpty() ? name : newName, QString(), QString());
}
void ChannelData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see Local::readPeer as well void ChannelData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see Local::readPeer as well
PhotoId newPhotoId = photoId; PhotoId newPhotoId = photoId;
ImagePtr newPhoto = _userpic; ImagePtr newPhoto = _userpic;
@ -430,10 +442,13 @@ void ChannelData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see
} }
} }
void ChannelData::setName(const QString &newName, const QString &usern) { void ChannelData::setName(const QString &newName, const QString &newUsername) {
bool updName = !newName.isEmpty(), updUsername = (username != usern); setNameDelayed(newName, newUsername);
Notify::peerUpdatedSendDelayed();
}
updateName(newName.isEmpty() ? name : newName, QString(), usern); void ChannelData::setNameDelayed(const QString &newName, const QString &newUsername) {
updateNameDelayed(newName.isEmpty() ? name : newName, QString(), newUsername);
} }
void ChannelData::updateFull(bool force) { void ChannelData::updateFull(bool force) {

View File

@ -274,10 +274,6 @@ public:
ChatData *migrateFrom() const; ChatData *migrateFrom() const;
ChannelData *migrateTo() const; ChannelData *migrateTo() const;
void updateName(const QString &newName, const QString &newNameOrPhone, const QString &newUsername);
void fillNames();
const Text &dialogName() const; const Text &dialogName() const;
const QString &shortName() const; const QString &shortName() const;
const QString &userName() const; const QString &userName() const;
@ -299,7 +295,7 @@ public:
MinimalLoaded = 0x01, MinimalLoaded = 0x01,
FullLoaded = 0x02, FullLoaded = 0x02,
}; };
LoadedStatus loadedStatus; LoadedStatus loadedStatus = NotLoaded;
MTPinputPeer input; MTPinputPeer input;
int colorIndex; int colorIndex;
@ -317,12 +313,12 @@ public:
void saveUserpic(const QString &path) const; void saveUserpic(const QString &path) const;
QPixmap genUserpic(int size) const; QPixmap genUserpic(int size) const;
PhotoId photoId; PhotoId photoId = UnknownPeerPhotoId;
StorageImageLocation photoLoc; StorageImageLocation photoLoc;
int nameVersion; int nameVersion = 1;
NotifySettingsPtr notify; NotifySettingsPtr notify = UnknownNotifySettings;
// if this string is not empty we must not allow to open the // if this string is not empty we must not allow to open the
// conversation and we must show this string instead // conversation and we must show this string instead
@ -338,10 +334,15 @@ public:
} }
protected: protected:
// Requires Notify::peerUpdatedSendDelayed() call after.
void updateNameDelayed(const QString &newName, const QString &newNameOrPhone, const QString &newUsername);
ImagePtr _userpic; ImagePtr _userpic;
ImagePtr currentUserpic() const; ImagePtr currentUserpic() const;
private: private:
void fillNames();
ClickHandlerPtr _openLink; ClickHandlerPtr _openLink;
}; };
@ -395,10 +396,16 @@ class UserData : public PeerData {
public: public:
UserData(const PeerId &id) : PeerData(id) { UserData(const PeerId &id) : PeerData(id) {
setName(QString(), QString(), QString(), QString());
} }
void setPhoto(const MTPUserProfilePhoto &photo); void setPhoto(const MTPUserProfilePhoto &photo);
void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username);
void setName(const QString &newFirstName, const QString &newLastName
, const QString &newPhoneName, const QString &newUsername);
// Requires Notify::peerUpdatedSendDelayed() call after.
void setNameDelayed(const QString &newFirstName, const QString &newLastName
, const QString &newPhoneName, const QString &newUsername);
void setPhone(const QString &newPhone); void setPhone(const QString &newPhone);
void setBotInfoVersion(int version); void setBotInfoVersion(int version);
void setBotInfo(const MTPBotInfo &info); void setBotInfo(const MTPBotInfo &info);
@ -458,18 +465,15 @@ private:
class ChatData : public PeerData { class ChatData : public PeerData {
public: public:
ChatData(const PeerId &id) : PeerData(id) ChatData(const PeerId &id) : PeerData(id), inputChat(MTP_int(bareId())) {
, inputChat(MTP_int(bareId()))
, migrateToPtr(0)
, count(0)
, date(0)
, version(0)
, creator(0)
, flags(0)
, isForbidden(false)
, botStatus(0) {
} }
void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId); void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
void setName(const QString &newName);
// Requires Notify::peerUpdatedSendDelayed() call after.
void setNameDelayed(const QString &newName);
void invalidateParticipants() { void invalidateParticipants() {
participants = ChatData::Participants(); participants = ChatData::Participants();
admins = ChatData::Admins(); admins = ChatData::Admins();
@ -483,15 +487,15 @@ public:
MTPint inputChat; MTPint inputChat;
ChannelData *migrateToPtr; ChannelData *migrateToPtr = nullptr;
int count; int count = 0;
TimeId date; TimeId date = 0;
int version; int version = 0;
UserId creator; UserId creator = 0;
MTPDchat::Flags flags; MTPDchat::Flags flags = 0;
bool isForbidden; bool isForbidden = false;
bool amIn() const { bool amIn() const {
return !isForbidden && !haveLeft() && !wasKicked(); return !isForbidden && !haveLeft() && !wasKicked();
} }
@ -532,7 +536,7 @@ public:
LastAuthors lastAuthors; LastAuthors lastAuthors;
typedef OrderedSet<PeerData*> MarkupSenders; typedef OrderedSet<PeerData*> MarkupSenders;
MarkupSenders markupSenders; MarkupSenders markupSenders;
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other int botStatus = 0; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
// ImagePtr photoFull; // ImagePtr photoFull;
QString invitationUrl; QString invitationUrl;
}; };
@ -634,14 +638,15 @@ struct MegagroupInfo {
class ChannelData : public PeerData { class ChannelData : public PeerData {
public: public:
ChannelData(const PeerId &id) : PeerData(id) ChannelData(const PeerId &id) : PeerData(id), inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))) {
, inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0)))
, mgInfo(nullptr) {
setName(QString(), QString());
} }
void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId); void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
void setName(const QString &name, const QString &username); void setName(const QString &name, const QString &username);
// Requires Notify::peerUpdatedSendDelayed() call after.
void setNameDelayed(const QString &name, const QString &username);
void updateFull(bool force = false); void updateFull(bool force = false);
void fullUpdated(); void fullUpdated();