2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

added channels scheme, made Channel peers and composite ChannelId,MsgId message ids

This commit is contained in:
John Preston
2015-09-03 13:48:40 +03:00
parent 42d297f192
commit 04e1da81f3
38 changed files with 5487 additions and 3141 deletions

View File

@@ -62,6 +62,9 @@ namespace {
typedef QMap<MsgId, ReplyMarkup> ReplyMarkups;
ReplyMarkups replyMarkups;
ReplyMarkup zeroMarkup(MTPDreplyKeyboardMarkup_flag_ZERO);
typedef QMap<ChannelId, ReplyMarkups> ChannelReplyMarkups;
ChannelReplyMarkups channelReplyMarkups;
VideoItems videoItems;
AudioItems audioItems;
@@ -77,13 +80,14 @@ namespace {
typedef QHash<MsgId, HistoryItem*> MsgsData;
MsgsData msgsData;
int32 maxMsgId = 0;
typedef QMap<ChannelId, MsgsData> ChannelMsgsData;
ChannelMsgsData channelMsgsData;
typedef QMap<uint64, MsgId> RandomData;
typedef QMap<uint64, FullMsgId> RandomData;
RandomData randomData;
typedef QMap<uint64, QString> SentTextData;
SentTextData sentTextData;
typedef QMap<uint64, QPair<PeerId, QString> > SentData;
SentData sentData;
HistoryItem *hoveredItem = 0, *pressedItem = 0, *hoveredLinkItem = 0, *pressedLinkItem = 0, *contextItem = 0, *mousedItem = 0;
@@ -213,33 +217,6 @@ namespace App {
}
}
PeerId peerFromMTP(const MTPPeer &peer_id) {
switch (peer_id.type()) {
case mtpc_peerChat: return peerFromChat(peer_id.c_peerChat().vchat_id);
case mtpc_peerUser: return peerFromUser(peer_id.c_peerUser().vuser_id);
}
return 0;
}
PeerId peerFromChat(int32 chat_id) {
return 0x100000000L | uint64(uint32(chat_id));
}
PeerId peerFromUser(int32 user_id) {
return uint64(uint32(user_id));
}
MTPpeer peerToMTP(const PeerId &peer_id) {
return (peer_id & 0x100000000L) ? MTP_peerChat(MTP_int(int32(peer_id & 0xFFFFFFFFL))) : MTP_peerUser(MTP_int(int32(peer_id & 0xFFFFFFFFL)));
}
int32 userFromPeer(const PeerId &peer_id) {
return (peer_id & 0x100000000L) ? 0 : int32(peer_id & 0xFFFFFFFFL);
}
int32 chatFromPeer(const PeerId &peer_id) {
return (peer_id & 0x100000000L) ? int32(peer_id & 0xFFFFFFFFL) : 0;
}
int32 onlineForSort(UserData *user, int32 now) {
if (isServiceUser(user->id) || user->botInfo) {
return -1;
@@ -469,12 +446,12 @@ namespace App {
case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break;
}
if (data->contact < 0 && !data->phone.isEmpty() && int32(data->id & 0xFFFFFFFF) != MTP::authedId()) {
if (data->contact < 0 && !data->phone.isEmpty() && peerToUser(data->id) != MTP::authedId()) {
data->contact = 0;
}
if (App::main()) {
if (data->contact > 0 && !wasContact) {
App::main()->addNewContact(data->id & 0xFFFFFFFF, false);
App::main()->addNewContact(peerToUser(data->id), false);
} else if (wasContact && data->contact <= 0) {
App::main()->removeContact(data);
}
@@ -490,8 +467,8 @@ namespace App {
return data;
}
ChatData *feedChats(const MTPVector<MTPChat> &chats, bool emitPeerUpdated) {
ChatData *data = 0;
PeerData *feedChats(const MTPVector<MTPChat> &chats, bool emitPeerUpdated) {
PeerData *data = 0;
const QVector<MTPChat> &v(chats.c_vector().v);
for (QVector<MTPChat>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
const MTPchat &chat(*i);
@@ -502,32 +479,53 @@ namespace App {
const MTPDchat &d(chat.c_chat());
title = qs(d.vtitle);
PeerId peer(peerFromChat(d.vid.v));
data = App::chat(peer);
data = App::chat(peerFromChat(d.vid.v));
data->input = MTP_inputPeerChat(d.vid);
data->setPhoto(d.vphoto);
data->date = d.vdate.v;
data->count = d.vparticipants_count.v;
data->left = d.vleft.v;
data->forbidden = false;
if (data->version < d.vversion.v) {
data->version = d.vversion.v;
data->participants = ChatData::Participants();
data->botStatus = 0;
ChatData *cdata = data->asChat();
cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v;
cdata->count = d.vparticipants_count.v;
cdata->left = d.vleft.v;
cdata->forbidden = false;
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
cdata->participants = ChatData::Participants();
cdata->botStatus = 0;
}
} break;
case mtpc_chatForbidden: {
const MTPDchatForbidden &d(chat.c_chatForbidden());
title = qs(d.vtitle);
PeerId peer(peerFromChat(d.vid.v));
data = App::chat(peer);
data = App::chat(peerFromChat(d.vid.v));
data->input = MTP_inputPeerChat(d.vid);
data->setPhoto(MTP_chatPhotoEmpty());
data->date = 0;
data->count = -1;
data->left = false;
data->forbidden = true;
ChatData *cdata = data->asChat();
cdata->setPhoto(MTP_chatPhotoEmpty());
cdata->date = 0;
cdata->count = -1;
cdata->left = false;
cdata->forbidden = true;
} break;
case mtpc_channel: {
const MTPDchannel &d(chat.c_channel());
title = qs(d.vtitle);
PeerId peer(peerFromChannel(d.vid.v));
data = App::channel(peer);
data->input = MTP_inputPeerChannel(d.vid, d.vaccess_hash);
ChannelData *cdata = data->asChannel();
cdata->inputChat = MTP_inputChannel(d.vid, d.vaccess_hash);
cdata->access = d.vaccess_hash.v;
cdata->setPhoto(d.vphoto);
cdata->date = d.vdate.v;
cdata->left = false;
cdata->forbidden = false;
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
}
} break;
}
if (!data) continue;
@@ -703,7 +701,11 @@ namespace App {
}
void checkEntitiesUpdate(const MTPDmessage &m) {
if (HistoryItem *existing = App::histItemById(m.vid.v)) {
PeerId peerId = peerFromMTP(m.vto_id);
if (m.has_from_id() && peerToUser(peerId) == MTP::authedId()) {
peerId = peerFromUser(m.vfrom_id);
}
if (HistoryItem *existing = App::histItemById(peerToChannel(peerId), m.vid.v)) {
bool hasLinks = m.has_entities() && !m.ventities.c_vector().v.isEmpty();
if ((hasLinks && !existing->hasTextLinks()) || (!hasLinks && existing->textHasLinks())) {
existing->setText(qs(m.vmessage), m.has_entities() ? linksFromMTP(m.ventities.c_vector().v) : LinksInText());
@@ -738,10 +740,6 @@ namespace App {
}
}
int32 maxMsgId() {
return ::maxMsgId;
}
ImagePtr image(const MTPPhotoSize &size) {
switch (size.type()) {
case mtpc_photoSize: {
@@ -789,38 +787,45 @@ namespace App {
}
return StorageImageLocation();
}
void feedWereRead(const QVector<MTPint> &msgsIds) {
for (QVector<MTPint>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
MsgsData::const_iterator j = msgsData.constFind(i->v);
if (j != msgsData.cend()) {
(*j)->markRead();
}
}
}
void feedInboxRead(const PeerId &peer, int32 upTo) {
void feedInboxRead(const PeerId &peer, MsgId upTo) {
History *h = App::historyLoaded(peer);
if (h) {
h->inboxRead(upTo);
}
}
void feedOutboxRead(const PeerId &peer, int32 upTo) {
void feedOutboxRead(const PeerId &peer, MsgId upTo) {
History *h = App::historyLoaded(peer);
if (h) {
h->outboxRead(upTo);
if (!h->peer->chat) {
if (h->peer->isUser()) {
h->peer->asUser()->madeAction();
}
}
}
void feedWereDeleted(const QVector<MTPint> &msgsIds) {
inline MsgsData *fetchMsgsData(ChannelId channelId, bool insert = true) {
if (channelId == NoChannel) return &msgsData;
ChannelMsgsData::iterator i = channelMsgsData.find(channelId);
if (i == channelMsgsData.cend()) {
if (insert) {
i = channelMsgsData.insert(channelId, MsgsData());
} else {
return 0;
}
}
return &(*i);
}
void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds) {
bool resized = false;
MsgsData *data = fetchMsgsData(channelId, false);
if (!data) return;
for (QVector<MTPint>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
MsgsData::const_iterator j = msgsData.constFind(i->v);
if (j != msgsData.cend()) {
MsgsData::const_iterator j = data->constFind(i->v);
if (j != data->cend()) {
History *h = (*j)->history();
(*j)->destroy();
if (App::main() && h->peer == App::main()->peer()) {
@@ -875,10 +880,10 @@ namespace App {
}
if (user->contact > 0) {
if (!wasContact) {
App::main()->addNewContact(App::userFromPeer(user->id), false);
App::main()->addNewContact(peerToUser(user->id), false);
}
} else {
if (user->contact < 0 && !user->phone.isEmpty() && App::userFromPeer(user->id) != MTP::authedId()) {
if (user->contact < 0 && !user->phone.isEmpty() && peerToUser(user->id) != MTP::authedId()) {
user->contact = 0;
}
if (wasContact) {
@@ -1098,50 +1103,73 @@ namespace App {
return 0;
}
UserData *userLoaded(const PeerId &user) {
PeerData *peer = peerLoaded(user);
return (peer && peer->loaded) ? peer->asUser() : 0;
}
ChatData *chatLoaded(const PeerId &chat) {
PeerData *peer = peerLoaded(chat);
return (peer && peer->loaded) ? peer->asChat() : 0;
}
PeerData *peerLoaded(const PeerId &peer) {
PeersData::const_iterator i = peersData.constFind(peer);
return (i != peersData.cend()) ? i.value() : 0;
}
UserData *userLoaded(int32 user) {
return userLoaded(App::peerFromUser(user));
UserData *userLoaded(const PeerId &id) {
PeerData *peer = peerLoaded(id);
return (peer && peer->loaded) ? peer->asUser() : 0;
}
ChatData *chatLoaded(int32 chat) {
return chatLoaded(App::peerFromChat(chat));
ChatData *chatLoaded(const PeerId &id) {
PeerData *peer = peerLoaded(id);
return (peer && peer->loaded) ? peer->asChat() : 0;
}
ChannelData *channelLoaded(const PeerId &id) {
PeerData *peer = peerLoaded(id);
return (peer && peer->loaded) ? peer->asChannel() : 0;
}
UserData *userLoaded(int32 user_id) {
return userLoaded(peerFromUser(user_id));
}
ChatData *chatLoaded(int32 chat_id) {
return chatLoaded(peerFromChat(chat_id));
}
ChannelData *channelLoaded(int32 channel_id) {
return channelLoaded(peerFromChannel(channel_id));
}
UserData *curUser() {
return user(MTP::authedId());
}
PeerData *peer(const PeerId &peer) {
PeersData::const_iterator i = peersData.constFind(peer);
PeerData *peer(const PeerId &id) {
PeersData::const_iterator i = peersData.constFind(id);
if (i == peersData.cend()) {
PeerData *newData = App::isChat(peer) ? (PeerData*)(new ChatData(peer)) : (PeerData*)(new UserData(peer));
PeerData *newData = 0;
if (peerIsUser(id)) {
newData = new UserData(id);
} else if (peerIsChat(id)) {
newData = new ChatData(id);
} else if (peerIsChannel(id)) {
newData = new ChannelData(id);
}
if (!newData) return 0;
newData->input = MTPinputPeer(MTP_inputPeerEmpty());
i = peersData.insert(peer, newData);
i = peersData.insert(id, newData);
}
return i.value();
}
UserData *user(const PeerId &peer) {
PeerData *d = App::peer(peer);
return d->asUser();
UserData *user(const PeerId &id) {
return peer(id)->asUser();
}
UserData *user(int32 user) {
return App::peer(App::peerFromUser(user))->asUser();
ChatData *chat(const PeerId &id) {
return peer(id)->asChat();
}
ChannelData *channel(const PeerId &id) {
return peer(id)->asChannel();
}
UserData *user(int32 user_id) {
return user(peerFromUser(user_id));
}
ChatData *chat(int32 chat_id) {
return chat(peerFromChat(chat_id));
}
ChannelData *channel(int32 channel_id) {
return channel(peerFromChannel(channel_id));
}
UserData *self() {
@@ -1150,22 +1178,13 @@ namespace App {
UserData *userByName(const QString &username) {
for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
if (!i.value()->chat && !i.value()->asUser()->username.compare(username.trimmed(), Qt::CaseInsensitive)) {
if (i.value()->isUser() && !i.value()->asUser()->username.compare(username.trimmed(), Qt::CaseInsensitive)) {
return i.value()->asUser();
}
}
return 0;
}
ChatData *chat(const PeerId &peer) {
PeerData *d = App::peer(peer);
return d->asChat();
}
ChatData *chat(int32 chat) {
return App::peer(App::peerFromChat(chat))->asChat();
}
PhotoData *photo(const PhotoId &photo) {
PhotosData::const_iterator i = photosData.constFind(photo);
if (i == photosData.cend()) {
@@ -1575,9 +1594,12 @@ namespace App {
return (i == ::histories.cend()) ? 0 : i.value();
}
HistoryItem *histItemById(MsgId itemId) {
MsgsData::const_iterator i = msgsData.constFind(itemId);
if (i != msgsData.cend()) {
HistoryItem *histItemById(ChannelId channelId, MsgId itemId) {
MsgsData *data = fetchMsgsData(channelId, false);
if (!data) return 0;
MsgsData::const_iterator i = data->constFind(itemId);
if (i != data->cend()) {
return i.value();
}
return 0;
@@ -1611,16 +1633,16 @@ namespace App {
}
HistoryItem *historyRegItem(HistoryItem *item) {
MsgsData::const_iterator i = msgsData.constFind(item->id);
if (i == msgsData.cend()) {
msgsData.insert(item->id, item);
if (item->id > ::maxMsgId) ::maxMsgId = item->id;
MsgsData *data = fetchMsgsData(item->channelId());
MsgsData::const_iterator i = data->constFind(item->id);
if (i == data->cend()) {
data->insert(item->id, item);
return 0;
}
if (i.value() != item && !i.value()->block() && item->block()) { // replace search item
itemReplaced(i.value(), item);
delete i.value();
msgsData.insert(item->id, item);
data->insert(item->id, item);
return 0;
}
return (i.value() == item) ? 0 : i.value();
@@ -1651,10 +1673,13 @@ namespace App {
}
void historyUnregItem(HistoryItem *item) {
MsgsData::iterator i = msgsData.find(item->id);
if (i != msgsData.cend()) {
MsgsData *data = fetchMsgsData(item->channelId(), false);
if (!data) return;
MsgsData::iterator i = data->find(item->id);
if (i != data->cend()) {
if (i.value() == item) {
msgsData.erase(i);
data->erase(i);
}
}
historyItemDetached(item);
@@ -1677,19 +1702,26 @@ namespace App {
toDelete.push_back(*i);
}
}
for (ChannelMsgsData::const_iterator j = channelMsgsData.cbegin(), end = channelMsgsData.cend(); j != end; ++j) {
for (MsgsData::const_iterator i = j->cbegin(), e = j->cend(); i != e; ++i) {
toDelete.push_back(*i);
}
}
msgsData.clear();
for (int i = 0, l = toDelete.size(); i < l; ++i) {
channelMsgsData.clear();
for (int32 i = 0, l = toDelete.size(); i < l; ++i) {
delete toDelete[i];
}
::maxMsgId = 0;
::hoveredItem = ::pressedItem = ::hoveredLinkItem = ::pressedLinkItem = ::contextItem = 0;
replyMarkups.clear();
channelReplyMarkups.clear();
}
void historyClearItems() {
historyClearMsgs();
randomData.clear();
sentTextData.clear();
sentData.clear();
mutedPeers.clear();
updatedPeers.clear();
cSetSavedPeers(SavedPeers());
@@ -1750,7 +1782,7 @@ namespace App {
}
}
void historyRegRandom(uint64 randomId, MsgId itemId) {
void historyRegRandom(uint64 randomId, const FullMsgId &itemId) {
randomData.insert(randomId, itemId);
}
@@ -1758,24 +1790,26 @@ namespace App {
randomData.remove(randomId);
}
MsgId histItemByRandom(uint64 randomId) {
FullMsgId histItemByRandom(uint64 randomId) {
RandomData::const_iterator i = randomData.constFind(randomId);
if (i != randomData.cend()) {
return i.value();
}
return 0;
return FullMsgId();
}
void historyRegSentText(uint64 randomId, const QString &text) {
sentTextData.insert(randomId, text);
void historyRegSentData(uint64 randomId, const PeerId &peerId, const QString &text) {
sentData.insert(randomId, qMakePair(peerId, text));
}
void historyUnregSentText(uint64 randomId) {
sentTextData.remove(randomId);
void historyUnregSentData(uint64 randomId) {
sentData.remove(randomId);
}
QString histSentTextByItem(uint64 randomId) {
return sentTextData.value(randomId);
void histSentDataByItem(uint64 randomId, PeerId &peerId, QString &text) {
QPair<PeerId, QString> d = sentData.value(randomId);
peerId = d.first;
text = d.second;
}
void prepareCorners(RoundCorners index, int32 radius, const style::color &color, const style::color *shadow = 0, QImage *cors = 0) {
@@ -2157,7 +2191,15 @@ namespace App {
if (changeInMin) App::main()->updateMutedIn(changeInMin);
}
void feedReplyMarkup(MsgId msgId, const MTPReplyMarkup &markup) {
inline void insertReplyMarkup(ChannelId channelId, MsgId msgId, const ReplyMarkup &markup) {
if (channelId == NoChannel) {
replyMarkups.insert(msgId, markup);
} else {
channelReplyMarkups[channelId].insert(msgId, markup);
}
}
void feedReplyMarkup(ChannelId channelId, MsgId msgId, const MTPReplyMarkup &markup) {
ReplyMarkup data;
ReplyMarkup::Commands &commands(data.commands);
switch (markup.type()) {
@@ -2189,7 +2231,7 @@ namespace App {
}
}
if (!commands.isEmpty()) {
replyMarkups.insert(msgId, data);
insertReplyMarkup(channelId, msgId, data);
}
}
} break;
@@ -2197,27 +2239,44 @@ namespace App {
case mtpc_replyKeyboardHide: {
const MTPDreplyKeyboardHide &d(markup.c_replyKeyboardHide());
if (d.vflags.v) {
replyMarkups.insert(msgId, ReplyMarkup(d.vflags.v | MTPDreplyKeyboardMarkup_flag_ZERO));
insertReplyMarkup(channelId, msgId, ReplyMarkup(d.vflags.v | MTPDreplyKeyboardMarkup_flag_ZERO));
}
} break;
case mtpc_replyKeyboardForceReply: {
const MTPDreplyKeyboardForceReply &d(markup.c_replyKeyboardForceReply());
replyMarkups.insert(msgId, ReplyMarkup(d.vflags.v | MTPDreplyKeyboardMarkup_flag_FORCE_REPLY));
insertReplyMarkup(channelId, msgId, ReplyMarkup(d.vflags.v | MTPDreplyKeyboardMarkup_flag_FORCE_REPLY));
} break;
}
}
void clearReplyMarkup(MsgId msgId) {
replyMarkups.remove(msgId);
void clearReplyMarkup(ChannelId channelId, MsgId msgId) {
if (channelId == NoChannel) {
replyMarkups.remove(msgId);
} else {
ChannelReplyMarkups::iterator i = channelReplyMarkups.find(channelId);
if (i != channelReplyMarkups.cend()) {
i->remove(msgId);
}
if (i->isEmpty()) {
channelReplyMarkups.erase(i);
}
}
}
const ReplyMarkup &replyMarkup(MsgId msgId) {
static ReplyMarkup zeroMarkup(MTPDreplyKeyboardMarkup_flag_ZERO);
inline const ReplyMarkup &replyMarkup(const ReplyMarkups &markups, MsgId msgId) {
ReplyMarkups::const_iterator i = replyMarkups.constFind(msgId);
if (i == replyMarkups.cend()) return zeroMarkup;
if (i == replyMarkups.cend()) return zeroMarkup;
return i.value();
}
const ReplyMarkup &replyMarkup(ChannelId channelId, MsgId msgId) {
if (channelId == NoChannel) {
return replyMarkup(replyMarkups, msgId);
}
ChannelReplyMarkups::const_iterator j = channelReplyMarkups.constFind(channelId);
if (j == channelReplyMarkups.cend()) return zeroMarkup;
return replyMarkup(*j, msgId);
}
void setProxySettings(QNetworkAccessManager &manager) {
if (cConnectionType() == dbictHttpProxy) {