mirror of https://github.com/procxx/kepka.git
Improve update handling for legacy chats.
This commit is contained in:
parent
215856adc3
commit
67d12fa6d2
|
@ -395,7 +395,7 @@ void ApiWrap::importChatInvite(const QString &hash) {
|
||||||
"(MainWidget::inviteImportDone)").arg(result.type()));
|
"(MainWidget::inviteImportDone)").arg(result.type()));
|
||||||
});
|
});
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
const auto type = error.type();
|
const auto &type = error.type();
|
||||||
if (type == qstr("CHANNELS_TOO_MUCH")) {
|
if (type == qstr("CHANNELS_TOO_MUCH")) {
|
||||||
Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
|
Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
|
||||||
} else if (error.code() == 400) {
|
} else if (error.code() == 400) {
|
||||||
|
@ -416,7 +416,7 @@ void ApiWrap::savePinnedOrder() {
|
||||||
const auto &order = _session->data().pinnedDialogsOrder();
|
const auto &order = _session->data().pinnedDialogsOrder();
|
||||||
auto peers = QVector<MTPInputDialogPeer>();
|
auto peers = QVector<MTPInputDialogPeer>();
|
||||||
peers.reserve(order.size());
|
peers.reserve(order.size());
|
||||||
for (const auto pinned : base::reversed(order)) {
|
for (const auto &pinned : base::reversed(order)) {
|
||||||
if (const auto history = pinned.history()) {
|
if (const auto history = pinned.history()) {
|
||||||
peers.push_back(MTP_inputDialogPeer(history->peer->input));
|
peers.push_back(MTP_inputDialogPeer(history->peer->input));
|
||||||
} else if (const auto feed = pinned.feed()) {
|
} else if (const auto feed = pinned.feed()) {
|
||||||
|
@ -510,7 +510,9 @@ ApiWrap::MessageDataRequests *ApiWrap::messageDataRequests(ChannelData *channel,
|
||||||
if (channel) {
|
if (channel) {
|
||||||
auto i = _channelMessageDataRequests.find(channel);
|
auto i = _channelMessageDataRequests.find(channel);
|
||||||
if (i == _channelMessageDataRequests.cend()) {
|
if (i == _channelMessageDataRequests.cend()) {
|
||||||
if (onlyExisting) return 0;
|
if (onlyExisting) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
i = _channelMessageDataRequests.insert(channel, MessageDataRequests());
|
i = _channelMessageDataRequests.insert(channel, MessageDataRequests());
|
||||||
}
|
}
|
||||||
return &i.value();
|
return &i.value();
|
||||||
|
@ -694,7 +696,7 @@ void ApiWrap::requestDialogEntry(
|
||||||
}
|
}
|
||||||
const auto finalize = [=] {
|
const auto finalize = [=] {
|
||||||
if (const auto callbacks = _dialogRequests.take(history)) {
|
if (const auto callbacks = _dialogRequests.take(history)) {
|
||||||
for (const auto callback : *callbacks) {
|
for (const auto &callback : *callbacks) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,7 +733,7 @@ void ApiWrap::requestDialogEntries(
|
||||||
const auto finalize = [=](std::vector<not_null<History*>> histories) {
|
const auto finalize = [=](std::vector<not_null<History*>> histories) {
|
||||||
for (const auto history : histories) {
|
for (const auto history : histories) {
|
||||||
if (const auto callbacks = _dialogRequests.take(history)) {
|
if (const auto callbacks = _dialogRequests.take(history)) {
|
||||||
for (const auto callback : *callbacks) {
|
for (const auto &callback : *callbacks) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -846,7 +848,7 @@ void ApiWrap::applyFeedDialogs(
|
||||||
if (peerIsChannel(peerId)) {
|
if (peerIsChannel(peerId)) {
|
||||||
const auto history = App::history(peerId);
|
const auto history = App::history(peerId);
|
||||||
history->applyDialog(dialog.c_dialog());
|
history->applyDialog(dialog.c_dialog());
|
||||||
channels.push_back(history->peer->asChannel());
|
channels.emplace_back(history->peer->asChannel());
|
||||||
} else {
|
} else {
|
||||||
LOG(("API Error: "
|
LOG(("API Error: "
|
||||||
"Unexpected non-channel in feed dialogs list."));
|
"Unexpected non-channel in feed dialogs list."));
|
||||||
|
@ -932,18 +934,8 @@ void ApiWrap::gotChatFull(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const MTPmessages_ChatFull &result,
|
const MTPmessages_ChatFull &result,
|
||||||
mtpRequestId req) {
|
mtpRequestId req) {
|
||||||
auto &d = result.c_messages_chatFull();
|
const auto &d = result.c_messages_chatFull();
|
||||||
auto &vc = d.vchats.v;
|
_session->data().applyMaximumChatVersions(d.vchats);
|
||||||
auto badVersion = false;
|
|
||||||
if (const auto chat = peer->asChat()) {
|
|
||||||
badVersion = !vc.isEmpty()
|
|
||||||
&& (vc[0].type() == mtpc_chat)
|
|
||||||
&& (vc[0].c_chat().vversion.v < chat->version);
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
badVersion = !vc.isEmpty()
|
|
||||||
&& (vc[0].type() == mtpc_channel)
|
|
||||||
&& (vc[0].c_channel().vversion.v < channel->version);
|
|
||||||
}
|
|
||||||
|
|
||||||
App::feedUsers(d.vusers);
|
App::feedUsers(d.vusers);
|
||||||
App::feedChats(d.vchats);
|
App::feedChats(d.vchats);
|
||||||
|
@ -956,7 +948,7 @@ void ApiWrap::gotChatFull(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto &f = d.vfull_chat.c_chatFull();
|
auto &f = d.vfull_chat.c_chatFull();
|
||||||
App::feedParticipants(f.vparticipants, false);
|
Data::ApplyChatParticipants(chat, f.vparticipants);
|
||||||
if (f.has_bot_info()) {
|
if (f.has_bot_info()) {
|
||||||
for (const auto &item : f.vbot_info.v) {
|
for (const auto &item : f.vbot_info.v) {
|
||||||
item.match([&](const MTPDbotInfo &data) {
|
item.match([&](const MTPDbotInfo &data) {
|
||||||
|
@ -1087,14 +1079,6 @@ void ApiWrap::gotChatFull(
|
||||||
_fullPeerRequests.erase(i);
|
_fullPeerRequests.erase(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (badVersion) {
|
|
||||||
if (const auto chat = peer->asChat()) {
|
|
||||||
chat->version = vc[0].c_chat().vversion.v;
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
channel->version = vc[0].c_channel().vversion.v;
|
|
||||||
}
|
|
||||||
requestPeer(peer);
|
|
||||||
}
|
|
||||||
fullPeerUpdated().notify(peer);
|
fullPeerUpdated().notify(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,31 +1141,11 @@ void ApiWrap::requestPeer(not_null<PeerData*> peer) {
|
||||||
};
|
};
|
||||||
const auto chatHandler = [=](const MTPmessages_Chats &result) {
|
const auto chatHandler = [=](const MTPmessages_Chats &result) {
|
||||||
_peerRequests.remove(peer);
|
_peerRequests.remove(peer);
|
||||||
|
const auto &chats = result.match([](const auto &data) {
|
||||||
if (const auto chats = Api::getChatsFromMessagesChats(result)) {
|
return data.vchats;
|
||||||
auto &v = chats->v;
|
});
|
||||||
bool badVersion = false;
|
_session->data().applyMaximumChatVersions(chats);
|
||||||
if (const auto chat = peer->asChat()) {
|
App::feedChats(chats);
|
||||||
badVersion = !v.isEmpty()
|
|
||||||
&& (v[0].type() == mtpc_chat)
|
|
||||||
&& (v[0].c_chat().vversion.v < chat->version);
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
badVersion = !v.isEmpty()
|
|
||||||
&& (v[0].type() == mtpc_channel)
|
|
||||||
&& (v[0].c_channel().vversion.v < channel->version);
|
|
||||||
}
|
|
||||||
const auto chat = App::feedChats(*chats);
|
|
||||||
if (chat == peer) {
|
|
||||||
if (badVersion) {
|
|
||||||
if (const auto chat = peer->asChat()) {
|
|
||||||
chat->version = v[0].c_chat().vversion.v;
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
channel->version = v[0].c_channel().vversion.v;
|
|
||||||
}
|
|
||||||
requestPeer(peer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if (const auto user = peer->asUser()) {
|
if (const auto user = peer->asUser()) {
|
||||||
return request(MTPusers_GetUsers(
|
return request(MTPusers_GetUsers(
|
||||||
|
@ -1272,36 +1236,47 @@ void ApiWrap::requestPeers(const QList<PeerData*> &peers) {
|
||||||
chats.reserve(peers.size());
|
chats.reserve(peers.size());
|
||||||
channels.reserve(peers.size());
|
channels.reserve(peers.size());
|
||||||
users.reserve(peers.size());
|
users.reserve(peers.size());
|
||||||
for (QList<PeerData*>::const_iterator i = peers.cbegin(), e = peers.cend(); i != e; ++i) {
|
for (const auto peer : peers) {
|
||||||
if (!*i || _fullPeerRequests.contains(*i) || _peerRequests.contains(*i)) continue;
|
if (!peer
|
||||||
if ((*i)->isUser()) {
|
|| _fullPeerRequests.contains(peer)
|
||||||
users.push_back((*i)->asUser()->inputUser);
|
|| _peerRequests.contains(peer)) {
|
||||||
} else if ((*i)->isChat()) {
|
continue;
|
||||||
chats.push_back((*i)->asChat()->inputChat);
|
}
|
||||||
} else if ((*i)->isChannel()) {
|
if (const auto user = peer->asUser()) {
|
||||||
channels.push_back((*i)->asChannel()->inputChannel);
|
users.push_back(user->inputUser);
|
||||||
|
} else if (const auto chat = peer->asChat()) {
|
||||||
|
chats.push_back(chat->inputChat);
|
||||||
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
|
channels.push_back(channel->inputChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto handleChats = [=](const MTPmessages_Chats &result) {
|
const auto handleChats = [=](const MTPmessages_Chats &result) {
|
||||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
App::feedChats(result.match([](const auto &data) {
|
||||||
App::feedChats(*chats);
|
return data.vchats;
|
||||||
}
|
}));
|
||||||
};
|
};
|
||||||
if (!chats.isEmpty()) {
|
if (!chats.isEmpty()) {
|
||||||
request(MTPmessages_GetChats(MTP_vector<MTPint>(chats))).done(handleChats).send();
|
request(MTPmessages_GetChats(
|
||||||
|
MTP_vector<MTPint>(chats)
|
||||||
|
)).done(handleChats).send();
|
||||||
}
|
}
|
||||||
if (!channels.isEmpty()) {
|
if (!channels.isEmpty()) {
|
||||||
request(MTPchannels_GetChannels(MTP_vector<MTPInputChannel>(channels))).done(handleChats).send();
|
request(MTPchannels_GetChannels(
|
||||||
|
MTP_vector<MTPInputChannel>(channels)
|
||||||
|
)).done(handleChats).send();
|
||||||
}
|
}
|
||||||
if (!users.isEmpty()) {
|
if (!users.isEmpty()) {
|
||||||
request(MTPusers_GetUsers(MTP_vector<MTPInputUser>(users))).done([=](const MTPVector<MTPUser> &result) {
|
request(MTPusers_GetUsers(
|
||||||
|
MTP_vector<MTPInputUser>(users)
|
||||||
|
)).done([=](const MTPVector<MTPUser> &result) {
|
||||||
App::feedUsers(result);
|
App::feedUsers(result);
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::requestLastParticipants(not_null<ChannelData*> channel) {
|
void ApiWrap::requestLastParticipants(not_null<ChannelData*> channel) {
|
||||||
if (!channel->isMegagroup() || _participantsRequests.contains(channel)) {
|
if (!channel->isMegagroup()
|
||||||
|
|| _participantsRequests.contains(channel)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1313,7 +1288,7 @@ void ApiWrap::requestLastParticipants(not_null<ChannelData*> channel) {
|
||||||
MTP_int(offset),
|
MTP_int(offset),
|
||||||
MTP_int(Global::ChatSizeMax()),
|
MTP_int(Global::ChatSizeMax()),
|
||||||
MTP_int(participantsHash)
|
MTP_int(participantsHash)
|
||||||
)).done([this, channel](const MTPchannels_ChannelParticipants &result) {
|
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||||
_participantsRequests.remove(channel);
|
_participantsRequests.remove(channel);
|
||||||
parseChannelParticipants(channel, result, [&](
|
parseChannelParticipants(channel, result, [&](
|
||||||
int availableCount,
|
int availableCount,
|
||||||
|
@ -4357,7 +4332,7 @@ void ApiWrap::sendFiles(
|
||||||
_sendingAlbums.emplace(album->groupId, album);
|
_sendingAlbums.emplace(album->groupId, album);
|
||||||
album->items.reserve(tasks.size());
|
album->items.reserve(tasks.size());
|
||||||
for (const auto &task : tasks) {
|
for (const auto &task : tasks) {
|
||||||
album->items.push_back(SendingAlbum::Item(task->id()));
|
album->items.emplace_back(task->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_fileLoader->addTasks(std::move(tasks));
|
_fileLoader->addTasks(std::move(tasks));
|
||||||
|
|
|
@ -47,14 +47,6 @@ struct CloudPasswordState;
|
||||||
|
|
||||||
namespace Api {
|
namespace Api {
|
||||||
|
|
||||||
inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Chats &chats) {
|
|
||||||
switch (chats.type()) {
|
|
||||||
case mtpc_messages_chats: return &chats.c_messages_chats().vchats;
|
|
||||||
case mtpc_messages_chatsSlice: return &chats.c_messages_chatsSlice().vchats;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename IntRange>
|
template <typename IntRange>
|
||||||
inline int32 CountHash(IntRange &&range) {
|
inline int32 CountHash(IntRange &&range) {
|
||||||
uint32 acc = 0;
|
uint32 acc = 0;
|
||||||
|
|
|
@ -146,224 +146,6 @@ namespace App {
|
||||||
return Auth().data().processChats(chats);
|
return Auth().data().processChats(chats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos) {
|
|
||||||
ChatData *chat = 0;
|
|
||||||
switch (p.type()) {
|
|
||||||
case mtpc_chatParticipantsForbidden: {
|
|
||||||
const auto &d(p.c_chatParticipantsForbidden());
|
|
||||||
chat = App::chat(d.vchat_id.v);
|
|
||||||
chat->count = -1;
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case mtpc_chatParticipants: {
|
|
||||||
const auto &d(p.c_chatParticipants());
|
|
||||||
chat = App::chat(d.vchat_id.v);
|
|
||||||
if (!requestBotInfos || chat->version <= d.vversion.v) { // !requestBotInfos is true on getFullChat result
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
auto &v = d.vparticipants.v;
|
|
||||||
chat->count = v.size();
|
|
||||||
int32 pversion = chat->participants.empty()
|
|
||||||
? 1
|
|
||||||
: (chat->participants.begin()->second + 1);
|
|
||||||
chat->invitedByMe.clear();
|
|
||||||
chat->admins.clear();
|
|
||||||
// #TODO groups
|
|
||||||
//chat->removeFlags(MTPDchat::Flag::f_admin);
|
|
||||||
for (auto i = v.cbegin(), e = v.cend(); i != e; ++i) {
|
|
||||||
int32 uid = 0, inviter = 0;
|
|
||||||
switch (i->type()) {
|
|
||||||
case mtpc_chatParticipantCreator: {
|
|
||||||
const auto &p(i->c_chatParticipantCreator());
|
|
||||||
uid = p.vuser_id.v;
|
|
||||||
chat->creator = uid;
|
|
||||||
} break;
|
|
||||||
case mtpc_chatParticipantAdmin: {
|
|
||||||
const auto &p(i->c_chatParticipantAdmin());
|
|
||||||
uid = p.vuser_id.v;
|
|
||||||
inviter = p.vinviter_id.v;
|
|
||||||
} break;
|
|
||||||
case mtpc_chatParticipant: {
|
|
||||||
const auto &p(i->c_chatParticipant());
|
|
||||||
uid = p.vuser_id.v;
|
|
||||||
inviter = p.vinviter_id.v;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
if (!uid) continue;
|
|
||||||
|
|
||||||
UserData *user = App::userLoaded(uid);
|
|
||||||
if (user) {
|
|
||||||
chat->participants[user] = pversion;
|
|
||||||
if (inviter == Auth().userId()) {
|
|
||||||
chat->invitedByMe.insert(user);
|
|
||||||
}
|
|
||||||
if (i->type() == mtpc_chatParticipantAdmin) {
|
|
||||||
chat->admins.insert(user);
|
|
||||||
if (user->isSelf()) {
|
|
||||||
// #TODO groups
|
|
||||||
// chat->addFlags(MTPDchat::Flag::f_admin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!chat->participants.empty()) {
|
|
||||||
auto h = App::historyLoaded(chat->id);
|
|
||||||
bool found = !h || !h->lastKeyboardFrom;
|
|
||||||
auto botStatus = -1;
|
|
||||||
for (auto i = chat->participants.begin(); i != chat->participants.end();) {
|
|
||||||
const auto [user, version] = *i;
|
|
||||||
if (version < pversion) {
|
|
||||||
i = chat->participants.erase(i);
|
|
||||||
} else {
|
|
||||||
if (user->botInfo) {
|
|
||||||
botStatus = 2;// (botStatus > 0/* || !user->botInfo->readsAllHistory*/) ? 2 : 1;
|
|
||||||
if (requestBotInfos && !user->botInfo->inited) {
|
|
||||||
Auth().api().requestFullPeer(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found && user->id == h->lastKeyboardFrom) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chat->botStatus = botStatus;
|
|
||||||
if (!found) {
|
|
||||||
h->clearLastKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
Notify::peerUpdatedDelayed(chat, Notify::PeerUpdate::Flag::MembersChanged | Notify::PeerUpdate::Flag::AdminsChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d) {
|
|
||||||
ChatData *chat = App::chat(d.vchat_id.v);
|
|
||||||
if (chat->version + 1 < d.vversion.v) {
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
Auth().api().requestPeer(chat);
|
|
||||||
} else if (chat->version <= d.vversion.v && chat->count >= 0) {
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
UserData *user = App::userLoaded(d.vuser_id.v);
|
|
||||||
if (user) {
|
|
||||||
if (chat->participants.empty() && chat->count) {
|
|
||||||
chat->count++;
|
|
||||||
chat->botStatus = 0;
|
|
||||||
} else if (chat->participants.find(user) == chat->participants.end()) {
|
|
||||||
chat->participants[user] = (chat->participants.empty() ? 1 : chat->participants.begin()->second);
|
|
||||||
if (d.vinviter_id.v == Auth().userId()) {
|
|
||||||
chat->invitedByMe.insert(user);
|
|
||||||
} else {
|
|
||||||
chat->invitedByMe.remove(user);
|
|
||||||
}
|
|
||||||
chat->count++;
|
|
||||||
if (user->botInfo) {
|
|
||||||
chat->botStatus = 2;// (chat->botStatus > 0/* || !user->botInfo->readsAllHistory*/) ? 2 : 1;
|
|
||||||
if (!user->botInfo->inited) {
|
|
||||||
Auth().api().requestFullPeer(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
chat->count++;
|
|
||||||
}
|
|
||||||
Notify::peerUpdatedDelayed(chat, Notify::PeerUpdate::Flag::MembersChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d) {
|
|
||||||
ChatData *chat = App::chat(d.vchat_id.v);
|
|
||||||
if (chat->version + 1 < d.vversion.v) {
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
Auth().api().requestPeer(chat);
|
|
||||||
} else if (chat->version <= d.vversion.v && chat->count > 0) {
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
const auto user = App::userLoaded(d.vuser_id.v);
|
|
||||||
if (user) {
|
|
||||||
if (chat->participants.empty()) {
|
|
||||||
if (chat->count > 0) {
|
|
||||||
chat->count--;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto i = chat->participants.find(user);
|
|
||||||
if (i != chat->participants.end()) {
|
|
||||||
chat->participants.erase(i);
|
|
||||||
chat->count--;
|
|
||||||
chat->invitedByMe.remove(user);
|
|
||||||
chat->admins.remove(user);
|
|
||||||
if (user->isSelf()) {
|
|
||||||
// #TODO groups
|
|
||||||
// chat->removeFlags(MTPDchat::Flag::f_admin);
|
|
||||||
}
|
|
||||||
|
|
||||||
History *h = App::historyLoaded(chat->id);
|
|
||||||
if (h && h->lastKeyboardFrom == user->id) {
|
|
||||||
h->clearLastKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chat->botStatus > 0 && user->botInfo) {
|
|
||||||
int32 botStatus = -1;
|
|
||||||
for (const auto [participant, v] : chat->participants) {
|
|
||||||
if (participant->botInfo) {
|
|
||||||
if (true || botStatus > 0/* || !participant->botInfo->readsAllHistory*/) {
|
|
||||||
botStatus = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
botStatus = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chat->botStatus = botStatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
chat->count--;
|
|
||||||
}
|
|
||||||
Notify::peerUpdatedDelayed(chat, Notify::PeerUpdate::Flag::MembersChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d) {
|
|
||||||
const auto chat = App::chat(d.vchat_id.v);
|
|
||||||
if (chat->version + 1 < d.vversion.v) {
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
Auth().api().requestPeer(chat);
|
|
||||||
} else if (chat->version <= d.vversion.v && chat->count > 0) {
|
|
||||||
chat->version = d.vversion.v;
|
|
||||||
const auto user = App::userLoaded(d.vuser_id.v);
|
|
||||||
if (user) {
|
|
||||||
if (mtpIsTrue(d.vis_admin)) {
|
|
||||||
if (user->isSelf()) {
|
|
||||||
// #TODO groups
|
|
||||||
// chat->addFlags(MTPDchat::Flag::f_admin);
|
|
||||||
}
|
|
||||||
if (chat->noParticipantInfo()) {
|
|
||||||
Auth().api().requestFullPeer(chat);
|
|
||||||
} else {
|
|
||||||
chat->admins.insert(user);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (user->isSelf()) {
|
|
||||||
// #TODO groups
|
|
||||||
//chat->removeFlags(MTPDchat::Flag::f_admin);
|
|
||||||
}
|
|
||||||
chat->admins.remove(user);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
}
|
|
||||||
Notify::peerUpdatedDelayed(chat, Notify::PeerUpdate::Flag::AdminsChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m) {
|
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m) {
|
||||||
auto peerId = peerFromMTP(m.vto_id);
|
auto peerId = peerFromMTP(m.vto_id);
|
||||||
if (m.has_from_id() && peerId == Auth().userPeerId()) {
|
if (m.has_from_id() && peerId == Auth().userPeerId()) {
|
||||||
|
|
|
@ -70,10 +70,6 @@ namespace App {
|
||||||
PeerData *feedChat(const MTPChat &chat);
|
PeerData *feedChat(const MTPChat &chat);
|
||||||
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
|
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
|
||||||
|
|
||||||
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos);
|
|
||||||
void feedParticipantAdd(const MTPDupdateChatParticipantAdd &d);
|
|
||||||
void feedParticipantDelete(const MTPDupdateChatParticipantDelete &d);
|
|
||||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d);
|
|
||||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
||||||
void updateEditedMessage(const MTPMessage &m);
|
void updateEditedMessage(const MTPMessage &m);
|
||||||
void addSavedGif(DocumentData *doc);
|
void addSavedGif(DocumentData *doc);
|
||||||
|
|
|
@ -1183,26 +1183,27 @@ RevokePublicLinkBox::Inner::Inner(QWidget *parent, Fn<void()> revokeCallback) :
|
||||||
|
|
||||||
request(MTPchannels_GetAdminedPublicChannels(
|
request(MTPchannels_GetAdminedPublicChannels(
|
||||||
)).done([=](const MTPmessages_Chats &result) {
|
)).done([=](const MTPmessages_Chats &result) {
|
||||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
const auto &chats = result.match([](const auto &data) {
|
||||||
for_const (auto &chat, chats->v) {
|
return data.vchats.v;
|
||||||
if (auto peer = App::feedChat(chat)) {
|
});
|
||||||
if (!peer->isChannel() || peer->userName().isEmpty()) {
|
for (const auto &chat : chats) {
|
||||||
continue;
|
if (const auto peer = App::feedChat(chat)) {
|
||||||
}
|
if (!peer->isChannel() || peer->userName().isEmpty()) {
|
||||||
|
continue;
|
||||||
auto row = ChatRow(peer);
|
|
||||||
row.peer = peer;
|
|
||||||
row.name.setText(
|
|
||||||
st::contactsNameStyle,
|
|
||||||
peer->name,
|
|
||||||
Ui::NameTextOptions());
|
|
||||||
row.status.setText(
|
|
||||||
st::defaultTextStyle,
|
|
||||||
Messenger::Instance().createInternalLink(
|
|
||||||
textcmdLink(1, peer->userName())),
|
|
||||||
Ui::DialogTextOptions());
|
|
||||||
_rows.push_back(std::move(row));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto row = ChatRow(peer);
|
||||||
|
row.peer = peer;
|
||||||
|
row.name.setText(
|
||||||
|
st::contactsNameStyle,
|
||||||
|
peer->name,
|
||||||
|
Ui::NameTextOptions());
|
||||||
|
row.status.setText(
|
||||||
|
st::defaultTextStyle,
|
||||||
|
Messenger::Instance().createInternalLink(
|
||||||
|
textcmdLink(1, peer->userName())),
|
||||||
|
Ui::DialogTextOptions());
|
||||||
|
_rows.push_back(std::move(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resize(width(), _rows.size() * _rowHeight);
|
resize(width(), _rows.size() * _rowHeight);
|
||||||
|
|
|
@ -30,12 +30,7 @@ base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (const auto chat = peer->asChat()) {
|
if (const auto chat = peer->asChat()) {
|
||||||
const auto participants = (
|
return chat->participants;
|
||||||
chat->participants
|
|
||||||
) | ranges::view::transform([](auto &&pair) -> not_null<UserData*> {
|
|
||||||
return pair.first;
|
|
||||||
});
|
|
||||||
return { participants.begin(), participants.end() };
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
if (channel->isMegagroup()) {
|
if (channel->isMegagroup()) {
|
||||||
const auto &participants = channel->mgInfo->lastParticipants;
|
const auto &participants = channel->mgInfo->lastParticipants;
|
||||||
|
@ -306,7 +301,7 @@ void AddSpecialBoxController::rebuildChatRows(not_null<ChatData*> chat) {
|
||||||
--count;
|
--count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto [user, v] : participants) {
|
for (const auto user : participants) {
|
||||||
if (auto row = createRow(user)) {
|
if (auto row = createRow(user)) {
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
|
@ -976,7 +971,7 @@ void AddSpecialBoxSearchController::addChatMembers(
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto [user, v] : chat->participants) {
|
for (const auto user : chat->participants) {
|
||||||
if (allWordsAreFound(user->nameWords())) {
|
if (allWordsAreFound(user->nameWords())) {
|
||||||
delegate()->peerListSearchAddRow(user);
|
delegate()->peerListSearchAddRow(user);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,9 @@ void RemoveAdmin(
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
channel->session().api().applyUpdates(result);
|
channel->session().api().applyUpdates(result);
|
||||||
channel->applyEditAdmin(user, oldRights, newRights);
|
channel->applyEditAdmin(user, oldRights, newRights);
|
||||||
if (const auto done = onDone) {
|
onDone();
|
||||||
done();
|
|
||||||
}
|
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
if (const auto fail = onFail) {
|
onFail();
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,13 +65,9 @@ void SaveChatAdmin(
|
||||||
MTP_bool(isAdmin)
|
MTP_bool(isAdmin)
|
||||||
)).done([=](const MTPBool &result) {
|
)).done([=](const MTPBool &result) {
|
||||||
chat->applyEditAdmin(user, isAdmin);
|
chat->applyEditAdmin(user, isAdmin);
|
||||||
if (const auto done = onDone) {
|
onDone();
|
||||||
done();
|
|
||||||
}
|
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
if (const auto fail = onFail) {
|
onFail();
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +85,7 @@ void SaveChannelAdmin(
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
channel->session().api().applyUpdates(result);
|
channel->session().api().applyUpdates(result);
|
||||||
channel->applyEditAdmin(user, oldRights, newRights);
|
channel->applyEditAdmin(user, oldRights, newRights);
|
||||||
if (const auto done = onDone) {
|
onDone();
|
||||||
done();
|
|
||||||
}
|
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) {
|
if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) {
|
||||||
Ui::show(
|
Ui::show(
|
||||||
|
@ -115,9 +105,7 @@ void SaveChannelAdmin(
|
||||||
: lng_error_admin_limit_channel)),
|
: lng_error_admin_limit_channel)),
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
if (const auto fail = onFail) {
|
onFail();
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,16 +121,11 @@ void SaveChannelRestriction(
|
||||||
user->inputUser,
|
user->inputUser,
|
||||||
newRights
|
newRights
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
const auto done = onDone;
|
|
||||||
channel->session().api().applyUpdates(result);
|
channel->session().api().applyUpdates(result);
|
||||||
channel->applyEditBanned(user, oldRights, newRights);
|
channel->applyEditBanned(user, oldRights, newRights);
|
||||||
if (const auto done = onDone) {
|
onDone();
|
||||||
done();
|
|
||||||
}
|
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
if (const auto fail = onFail) {
|
onFail();
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,12 +351,7 @@ void ParticipantsAdditionalData::fillFromChat(not_null<ChatData*> chat) {
|
||||||
if (chat->participants.empty()) {
|
if (chat->participants.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto keys = ranges::view::all(
|
_members = chat->participants;
|
||||||
chat->participants
|
|
||||||
) | ranges::view::transform([](auto &&pair) {
|
|
||||||
return pair.first;
|
|
||||||
});
|
|
||||||
_members = { keys.begin(), keys.end() };
|
|
||||||
_admins = chat->admins;
|
_admins = chat->admins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,7 +772,7 @@ void ParticipantsBoxController::addNewParticipants() {
|
||||||
auto already = std::vector<not_null<UserData*>>();
|
auto already = std::vector<not_null<UserData*>>();
|
||||||
already.reserve(count);
|
already.reserve(count);
|
||||||
for (auto i = 0; i != count; ++i) {
|
for (auto i = 0; i != count; ++i) {
|
||||||
already.push_back(
|
already.emplace_back(
|
||||||
delegate()->peerListRowAt(i)->peer()->asUser());
|
delegate()->peerListRowAt(i)->peer()->asUser());
|
||||||
}
|
}
|
||||||
AddParticipantsBoxController::Start(
|
AddParticipantsBoxController::Start(
|
||||||
|
@ -805,16 +783,18 @@ void ParticipantsBoxController::addNewParticipants() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticipantsBoxController::peerListSearchAddRow(not_null<PeerData*> peer) {
|
void ParticipantsBoxController::peerListSearchAddRow(
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
PeerListController::peerListSearchAddRow(peer);
|
PeerListController::peerListSearchAddRow(peer);
|
||||||
if (_role == Role::Restricted && delegate()->peerListFullRowsCount() > 0) {
|
if (_role == Role::Restricted
|
||||||
|
&& delegate()->peerListFullRowsCount() > 0) {
|
||||||
setDescriptionText(QString());
|
setDescriptionText(QString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ParticipantsBoxController::createSearchRow(
|
std::unique_ptr<PeerListRow> ParticipantsBoxController::createSearchRow(
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
if (auto user = peer->asUser()) {
|
if (const auto user = peer->asUser()) {
|
||||||
return createRow(user);
|
return createRow(user);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -822,13 +802,14 @@ std::unique_ptr<PeerListRow> ParticipantsBoxController::createSearchRow(
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ParticipantsBoxController::createRestoredRow(
|
std::unique_ptr<PeerListRow> ParticipantsBoxController::createRestoredRow(
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
if (auto user = peer->asUser()) {
|
if (const auto user = peer->asUser()) {
|
||||||
return createRow(user);
|
return createRow(user);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListState> ParticipantsBoxController::saveState() const {
|
auto ParticipantsBoxController::saveState() const
|
||||||
|
-> std::unique_ptr<PeerListState> {
|
||||||
Expects(_role == Role::Profile);
|
Expects(_role == Role::Profile);
|
||||||
|
|
||||||
auto result = PeerListController::saveState();
|
auto result = PeerListController::saveState();
|
||||||
|
@ -837,14 +818,19 @@ std::unique_ptr<PeerListState> ParticipantsBoxController::saveState() const {
|
||||||
my->offset = _offset;
|
my->offset = _offset;
|
||||||
my->allLoaded = _allLoaded;
|
my->allLoaded = _allLoaded;
|
||||||
my->wasLoading = (_loadRequestId != 0);
|
my->wasLoading = (_loadRequestId != 0);
|
||||||
if (auto search = searchController()) {
|
if (const auto search = searchController()) {
|
||||||
my->searchState = search->saveState();
|
my->searchState = search->saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_peer->isMegagroup()) {
|
const auto weak = result.get();
|
||||||
const auto channel = _peer->asChannel();
|
if (const auto chat = _peer->asChat()) {
|
||||||
|
Notify::PeerUpdateViewer(
|
||||||
auto weak = result.get();
|
chat,
|
||||||
|
Notify::PeerUpdate::Flag::MembersChanged
|
||||||
|
) | rpl::start_with_next([=](const Notify::PeerUpdate &) {
|
||||||
|
weak->controllerState = nullptr;
|
||||||
|
}, my->lifetime);
|
||||||
|
} else if (const auto channel = _peer->asMegagroup()) {
|
||||||
channel->owner().megagroupParticipantAdded(
|
channel->owner().megagroupParticipantAdded(
|
||||||
channel
|
channel
|
||||||
) | rpl::start_with_next([=](not_null<UserData*> user) {
|
) | rpl::start_with_next([=](not_null<UserData*> user) {
|
||||||
|
@ -855,7 +841,7 @@ std::unique_ptr<PeerListState> ParticipantsBoxController::saveState() const {
|
||||||
}
|
}
|
||||||
auto pos = ranges::find(weak->list, user);
|
auto pos = ranges::find(weak->list, user);
|
||||||
if (pos == weak->list.cend()) {
|
if (pos == weak->list.cend()) {
|
||||||
weak->list.push_back(user);
|
weak->list.emplace_back(user);
|
||||||
}
|
}
|
||||||
ranges::stable_partition(
|
ranges::stable_partition(
|
||||||
weak->list,
|
weak->list,
|
||||||
|
@ -884,15 +870,15 @@ void ParticipantsBoxController::restoreState(
|
||||||
auto typeErasedState = state
|
auto typeErasedState = state
|
||||||
? state->controllerState.get()
|
? state->controllerState.get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (auto my = dynamic_cast<SavedState*>(typeErasedState)) {
|
if (const auto my = dynamic_cast<SavedState*>(typeErasedState)) {
|
||||||
if (auto requestId = base::take(_loadRequestId)) {
|
if (const auto requestId = base::take(_loadRequestId)) {
|
||||||
request(requestId).cancel();
|
request(requestId).cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
_additional = std::move(my->additional);
|
_additional = std::move(my->additional);
|
||||||
_offset = my->offset;
|
_offset = my->offset;
|
||||||
_allLoaded = my->allLoaded;
|
_allLoaded = my->allLoaded;
|
||||||
if (auto search = searchController()) {
|
if (const auto search = searchController()) {
|
||||||
search->restoreState(std::move(my->searchState));
|
search->restoreState(std::move(my->searchState));
|
||||||
}
|
}
|
||||||
if (my->wasLoading) {
|
if (my->wasLoading) {
|
||||||
|
@ -989,13 +975,8 @@ void ParticipantsBoxController::rebuildChatRows(not_null<ChatData*> chat) {
|
||||||
|
|
||||||
void ParticipantsBoxController::rebuildChatParticipants(
|
void ParticipantsBoxController::rebuildChatParticipants(
|
||||||
not_null<ChatData*> chat) {
|
not_null<ChatData*> chat) {
|
||||||
if (chat->participants.empty()) {
|
if (chat->noParticipantInfo()) {
|
||||||
// We get such updates often
|
chat->updateFullForced();
|
||||||
// (when participants list was invalidated).
|
|
||||||
//while (delegate()->peerListFullRowsCount() > 0) {
|
|
||||||
// delegate()->peerListRemoveRow(
|
|
||||||
// delegate()->peerListRowAt(0));
|
|
||||||
//}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,7 +992,7 @@ void ParticipantsBoxController::rebuildChatParticipants(
|
||||||
--count;
|
--count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto [user, v] : participants) {
|
for (const auto user : participants) {
|
||||||
if (auto row = createRow(user)) {
|
if (auto row = createRow(user)) {
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
|
@ -1036,7 +1017,7 @@ void ParticipantsBoxController::rebuildChatAdmins(
|
||||||
|
|
||||||
auto list = ranges::view::all(chat->admins) | ranges::to_vector;
|
auto list = ranges::view::all(chat->admins) | ranges::to_vector;
|
||||||
if (const auto creator = chat->owner().userLoaded(chat->creator)) {
|
if (const auto creator = chat->owner().userLoaded(chat->creator)) {
|
||||||
list.push_back(creator);
|
list.emplace_back(creator);
|
||||||
}
|
}
|
||||||
ranges::sort(list, [](not_null<UserData*> a, not_null<UserData*> b) {
|
ranges::sort(list, [](not_null<UserData*> a, not_null<UserData*> b) {
|
||||||
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
|
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
|
||||||
|
|
|
@ -1175,11 +1175,11 @@ void ShareGameScoreByHash(const QString &hash) {
|
||||||
} else {
|
} else {
|
||||||
auto requestChannelIds = MTP_vector<MTPInputChannel>(1, MTP_inputChannel(MTP_int(channelId), MTP_long(channelAccessHash)));
|
auto requestChannelIds = MTP_vector<MTPInputChannel>(1, MTP_inputChannel(MTP_int(channelId), MTP_long(channelAccessHash)));
|
||||||
auto requestChannel = MTPchannels_GetChannels(requestChannelIds);
|
auto requestChannel = MTPchannels_GetChannels(requestChannelIds);
|
||||||
MTP::send(requestChannel, rpcDone([channelId, resolveMessageAndShareScore](const MTPmessages_Chats &result) {
|
MTP::send(requestChannel, rpcDone([=](const MTPmessages_Chats &result) {
|
||||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
result.match([](const auto &data) {
|
||||||
App::feedChats(*chats);
|
App::feedChats(data.vchats);
|
||||||
}
|
});
|
||||||
if (auto channel = App::channelLoaded(channelId)) {
|
if (const auto channel = App::channelLoaded(channelId)) {
|
||||||
resolveMessageAndShareScore(channel);
|
resolveMessageAndShareScore(channel);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -194,7 +194,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
||||||
if (_chat->noParticipantInfo()) {
|
if (_chat->noParticipantInfo()) {
|
||||||
Auth().api().requestFullPeer(_chat);
|
Auth().api().requestFullPeer(_chat);
|
||||||
} else if (!_chat->participants.empty()) {
|
} else if (!_chat->participants.empty()) {
|
||||||
for (const auto [user, v] : _chat->participants) {
|
for (const auto user : _chat->participants) {
|
||||||
if (user->isInaccessible()) continue;
|
if (user->isInaccessible()) continue;
|
||||||
if (!listAllSuggestions && filterNotPassedByName(user)) continue;
|
if (!listAllSuggestions && filterNotPassedByName(user)) continue;
|
||||||
if (indexOfInFirstN(mrows, user, recentInlineBots) >= 0) continue;
|
if (indexOfInFirstN(mrows, user, recentInlineBots) >= 0) continue;
|
||||||
|
@ -253,7 +253,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
||||||
if (_chat->noParticipantInfo()) {
|
if (_chat->noParticipantInfo()) {
|
||||||
Auth().api().requestFullPeer(_chat);
|
Auth().api().requestFullPeer(_chat);
|
||||||
} else if (!_chat->participants.empty()) {
|
} else if (!_chat->participants.empty()) {
|
||||||
for (const auto [user, version] : _chat->participants) {
|
for (const auto user : _chat->participants) {
|
||||||
if (!user->botInfo) continue;
|
if (!user->botInfo) continue;
|
||||||
if (!user->botInfo->inited) {
|
if (!user->botInfo->inited) {
|
||||||
Auth().api().requestFullPeer(user);
|
Auth().api().requestFullPeer(user);
|
||||||
|
|
|
@ -157,7 +157,7 @@ void Changelogs::addLocalLog(const QString &text) {
|
||||||
};
|
};
|
||||||
|
|
||||||
void Changelogs::addBetaLogs() {
|
void Changelogs::addBetaLogs() {
|
||||||
for (const auto[version, changes] : BetaLogs()) {
|
for (const auto [version, changes] : BetaLogs()) {
|
||||||
addBetaLog(version, changes);
|
addBetaLog(version, changes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_feed.h"
|
#include "data/data_feed.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -482,3 +483,28 @@ void ChannelData::setDefaultRestrictions(const MTPChatBannedRights &rights) {
|
||||||
_defaultRestrictions.set(rights.c_chatBannedRights().vflags.v);
|
_defaultRestrictions.set(rights.c_chatBannedRights().vflags.v);
|
||||||
Notify::peerUpdatedDelayed(this, UpdateFlag::RightsChanged);
|
Notify::peerUpdatedDelayed(this, UpdateFlag::RightsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ChannelData::applyUpdateVersion(int version) -> UpdateStatus {
|
||||||
|
if (_version > version) {
|
||||||
|
return UpdateStatus::TooOld;
|
||||||
|
} else if (_version + 1 < version) {
|
||||||
|
session().api().requestPeer(this);
|
||||||
|
return UpdateStatus::Skipped;
|
||||||
|
}
|
||||||
|
setVersion(version);
|
||||||
|
return UpdateStatus::Good;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
void ApplyChannelUpdate(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
const MTPDupdateChatDefaultBannedRights &update) {
|
||||||
|
if (channel->applyUpdateVersion(update.vversion.v)
|
||||||
|
!= ChannelData::UpdateStatus::Good) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
channel->setDefaultRestrictions(update.vdefault_banned_rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
|
@ -326,6 +326,19 @@ public:
|
||||||
return _feed;
|
return _feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class UpdateStatus {
|
||||||
|
Good,
|
||||||
|
TooOld,
|
||||||
|
Skipped,
|
||||||
|
};
|
||||||
|
int version() const {
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
void setVersion(int version) {
|
||||||
|
_version = version;
|
||||||
|
}
|
||||||
|
UpdateStatus applyUpdateVersion(int version);
|
||||||
|
|
||||||
// Still public data members.
|
// Still public data members.
|
||||||
uint64 access = 0;
|
uint64 access = 0;
|
||||||
|
|
||||||
|
@ -334,7 +347,6 @@ public:
|
||||||
QString username;
|
QString username;
|
||||||
|
|
||||||
int32 date = 0;
|
int32 date = 0;
|
||||||
int version = 0;
|
|
||||||
std::unique_ptr<MegagroupInfo> mgInfo;
|
std::unique_ptr<MegagroupInfo> mgInfo;
|
||||||
|
|
||||||
UserId inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel
|
UserId inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel
|
||||||
|
@ -354,6 +366,7 @@ private:
|
||||||
int _restrictedCount = 0;
|
int _restrictedCount = 0;
|
||||||
int _kickedCount = 0;
|
int _kickedCount = 0;
|
||||||
MsgId _availableMinId = 0;
|
MsgId _availableMinId = 0;
|
||||||
|
int _version = 0;
|
||||||
|
|
||||||
RestrictionFlags _defaultRestrictions;
|
RestrictionFlags _defaultRestrictions;
|
||||||
AdminRightFlags _adminRights;
|
AdminRightFlags _adminRights;
|
||||||
|
@ -368,3 +381,11 @@ private:
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
void ApplyChannelUpdate(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
const MTPDupdateChatDefaultBannedRights &update);
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
|
@ -7,6 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
|
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -113,10 +118,10 @@ void ChatData::applyEditAdmin(not_null<UserData*> user, bool isAdmin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatData::invalidateParticipants() {
|
void ChatData::invalidateParticipants() {
|
||||||
// #TODO groups
|
|
||||||
participants.clear();
|
participants.clear();
|
||||||
admins.clear();
|
admins.clear();
|
||||||
//removeFlags(MTPDchat::Flag::f_admin);
|
setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
|
||||||
|
//setDefaultRestrictions(MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
|
||||||
invitedByMe.clear();
|
invitedByMe.clear();
|
||||||
botStatus = 0;
|
botStatus = 0;
|
||||||
Notify::peerUpdatedDelayed(
|
Notify::peerUpdatedDelayed(
|
||||||
|
@ -150,3 +155,242 @@ void ChatData::setDefaultRestrictions(const MTPChatBannedRights &rights) {
|
||||||
_defaultRestrictions.set(rights.c_chatBannedRights().vflags.v);
|
_defaultRestrictions.set(rights.c_chatBannedRights().vflags.v);
|
||||||
Notify::peerUpdatedDelayed(this, UpdateFlag::RightsChanged);
|
Notify::peerUpdatedDelayed(this, UpdateFlag::RightsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatData::refreshBotStatus() {
|
||||||
|
if (participants.empty()) {
|
||||||
|
botStatus = 0;
|
||||||
|
} else {
|
||||||
|
const auto bot = ranges::find_if(participants, &UserData::isBot);
|
||||||
|
botStatus = (bot == end(participants)) ? -1 : 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ChatData::applyUpdateVersion(int version) -> UpdateStatus {
|
||||||
|
if (_version > version) {
|
||||||
|
return UpdateStatus::TooOld;
|
||||||
|
} else if (_version + 1 < version) {
|
||||||
|
invalidateParticipants();
|
||||||
|
session().api().requestPeer(this);
|
||||||
|
return UpdateStatus::Skipped;
|
||||||
|
}
|
||||||
|
setVersion(version);
|
||||||
|
return UpdateStatus::Good;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipants &update) {
|
||||||
|
ApplyChatParticipants(chat, update.vparticipants);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipantAdd &update) {
|
||||||
|
if (chat->applyUpdateVersion(update.vversion.v)
|
||||||
|
!= ChatData::UpdateStatus::Good) {
|
||||||
|
return;
|
||||||
|
} else if (chat->count < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto user = chat->owner().userLoaded(update.vuser_id.v);
|
||||||
|
if (!user
|
||||||
|
|| (!chat->participants.empty()
|
||||||
|
&& chat->participants.contains(user))) {
|
||||||
|
chat->invalidateParticipants();
|
||||||
|
++chat->count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (chat->participants.empty()) {
|
||||||
|
if (chat->count > 0) { // If the count is known.
|
||||||
|
++chat->count;
|
||||||
|
}
|
||||||
|
chat->botStatus = 0;
|
||||||
|
} else {
|
||||||
|
chat->participants.emplace(user);
|
||||||
|
if (update.vinviter_id.v == chat->session().userId()) {
|
||||||
|
chat->invitedByMe.insert(user);
|
||||||
|
} else {
|
||||||
|
chat->invitedByMe.remove(user);
|
||||||
|
}
|
||||||
|
++chat->count;
|
||||||
|
if (user->isBot()) {
|
||||||
|
chat->botStatus = 2;
|
||||||
|
if (!user->botInfo->inited) {
|
||||||
|
chat->session().api().requestFullPeer(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
chat,
|
||||||
|
Notify::PeerUpdate::Flag::MembersChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipantDelete &update) {
|
||||||
|
if (chat->applyUpdateVersion(update.vversion.v)
|
||||||
|
!= ChatData::UpdateStatus::Good) {
|
||||||
|
return;
|
||||||
|
} else if (chat->count <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto user = chat->owner().userLoaded(update.vuser_id.v);
|
||||||
|
if (!user
|
||||||
|
|| (!chat->participants.empty()
|
||||||
|
&& !chat->participants.contains(user))) {
|
||||||
|
chat->invalidateParticipants();
|
||||||
|
--chat->count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (chat->participants.empty()) {
|
||||||
|
if (chat->count > 0) {
|
||||||
|
chat->count--;
|
||||||
|
}
|
||||||
|
chat->botStatus = 0;
|
||||||
|
} else {
|
||||||
|
chat->participants.erase(user);
|
||||||
|
chat->count--;
|
||||||
|
chat->invitedByMe.remove(user);
|
||||||
|
chat->admins.remove(user);
|
||||||
|
if (user->isSelf()) {
|
||||||
|
chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
|
||||||
|
}
|
||||||
|
if (const auto history = chat->owner().historyLoaded(chat)) {
|
||||||
|
if (history->lastKeyboardFrom == user->id) {
|
||||||
|
history->clearLastKeyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chat->botStatus > 0 && user->botInfo) {
|
||||||
|
chat->refreshBotStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
chat,
|
||||||
|
Notify::PeerUpdate::Flag::MembersChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipantAdmin &update) {
|
||||||
|
if (chat->applyUpdateVersion(update.vversion.v)
|
||||||
|
!= ChatData::UpdateStatus::Good) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto user = chat->owner().userLoaded(update.vuser_id.v);
|
||||||
|
if (!user) {
|
||||||
|
chat->invalidateParticipants();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user->isSelf()) {
|
||||||
|
chat->setAdminRights(MTP_chatAdminRights(mtpIsTrue(update.vis_admin)
|
||||||
|
? MTP_flags(ChatData::DefaultAdminRights())
|
||||||
|
: MTP_flags(0)));
|
||||||
|
}
|
||||||
|
if (mtpIsTrue(update.vis_admin)) {
|
||||||
|
if (chat->noParticipantInfo()) {
|
||||||
|
chat->session().api().requestFullPeer(chat);
|
||||||
|
} else {
|
||||||
|
chat->admins.emplace(user);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chat->admins.erase(user);
|
||||||
|
}
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
chat,
|
||||||
|
Notify::PeerUpdate::Flag::AdminsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatDefaultBannedRights &update) {
|
||||||
|
if (chat->applyUpdateVersion(update.vversion.v)
|
||||||
|
!= ChatData::UpdateStatus::Good) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chat->setDefaultRestrictions(update.vdefault_banned_rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyChatParticipants(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPChatParticipants &participants) {
|
||||||
|
participants.match([&](const MTPDchatParticipantsForbidden &data) {
|
||||||
|
if (data.has_self_participant()) {
|
||||||
|
// data.vself_participant.
|
||||||
|
}
|
||||||
|
chat->count = -1;
|
||||||
|
chat->invalidateParticipants();
|
||||||
|
}, [&](const MTPDchatParticipants &data) {
|
||||||
|
const auto status = chat->applyUpdateVersion(data.vversion.v);
|
||||||
|
if (status == ChatData::UpdateStatus::TooOld) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Even if we skipped some updates, we got current participants
|
||||||
|
// and we've requested peer from API to have current rights.
|
||||||
|
chat->setVersion(data.vversion.v);
|
||||||
|
|
||||||
|
const auto &list = data.vparticipants.v;
|
||||||
|
chat->count = list.size();
|
||||||
|
chat->participants.clear();
|
||||||
|
chat->invitedByMe.clear();
|
||||||
|
chat->admins.clear();
|
||||||
|
chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
|
||||||
|
const auto selfUserId = chat->session().userId();
|
||||||
|
for (const auto &participant : list) {
|
||||||
|
const auto userId = participant.match([&](const auto &data) {
|
||||||
|
return data.vuser_id.v;
|
||||||
|
});
|
||||||
|
const auto user = chat->owner().userLoaded(userId);
|
||||||
|
if (!user) {
|
||||||
|
chat->invalidateParticipants();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
chat->participants.emplace(user);
|
||||||
|
|
||||||
|
const auto inviterId = participant.match([&](
|
||||||
|
const MTPDchatParticipantCreator &data) {
|
||||||
|
return 0;
|
||||||
|
}, [&](const auto &data) {
|
||||||
|
return data.vinviter_id.v;
|
||||||
|
});
|
||||||
|
if (inviterId == selfUserId) {
|
||||||
|
chat->invitedByMe.insert(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
participant.match([&](const MTPDchatParticipantCreator &data) {
|
||||||
|
chat->creator = userId;
|
||||||
|
}, [&](const MTPDchatParticipantAdmin &data) {
|
||||||
|
chat->admins.emplace(user);
|
||||||
|
if (user->isSelf()) {
|
||||||
|
chat->setAdminRights(MTP_chatAdminRights(
|
||||||
|
MTP_flags(ChatData::DefaultAdminRights())));
|
||||||
|
}
|
||||||
|
}, [](const MTPDchatParticipant &) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (chat->participants.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (const auto history = chat->owner().historyLoaded(chat)) {
|
||||||
|
if (history->lastKeyboardFrom) {
|
||||||
|
const auto i = ranges::find(
|
||||||
|
chat->participants,
|
||||||
|
history->lastKeyboardFrom,
|
||||||
|
&UserData::id);
|
||||||
|
if (i == end(chat->participants)) {
|
||||||
|
history->clearLastKeyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chat->refreshBotStatus();
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
chat,
|
||||||
|
Notify::PeerUpdate::Flag::MembersChanged
|
||||||
|
| Notify::PeerUpdate::Flag::AdminsChanged);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
|
@ -141,6 +141,20 @@ public:
|
||||||
QString inviteLink() const {
|
QString inviteLink() const {
|
||||||
return _inviteLink;
|
return _inviteLink;
|
||||||
}
|
}
|
||||||
|
void refreshBotStatus();
|
||||||
|
|
||||||
|
enum class UpdateStatus {
|
||||||
|
Good,
|
||||||
|
TooOld,
|
||||||
|
Skipped,
|
||||||
|
};
|
||||||
|
int version() const {
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
void setVersion(int version) {
|
||||||
|
_version = version;
|
||||||
|
}
|
||||||
|
UpdateStatus applyUpdateVersion(int version);
|
||||||
|
|
||||||
// Still public data members.
|
// Still public data members.
|
||||||
MTPint inputChat;
|
MTPint inputChat;
|
||||||
|
@ -149,10 +163,9 @@ public:
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
TimeId date = 0;
|
TimeId date = 0;
|
||||||
int version = 0;
|
|
||||||
UserId creator = 0;
|
UserId creator = 0;
|
||||||
|
|
||||||
base::flat_map<not_null<UserData*>, int> participants;
|
base::flat_set<not_null<UserData*>> participants;
|
||||||
base::flat_set<not_null<UserData*>> invitedByMe;
|
base::flat_set<not_null<UserData*>> invitedByMe;
|
||||||
base::flat_set<not_null<UserData*>> admins;
|
base::flat_set<not_null<UserData*>> admins;
|
||||||
std::deque<not_null<UserData*>> lastAuthors;
|
std::deque<not_null<UserData*>> lastAuthors;
|
||||||
|
@ -169,5 +182,30 @@ private:
|
||||||
|
|
||||||
RestrictionFlags _defaultRestrictions;
|
RestrictionFlags _defaultRestrictions;
|
||||||
AdminRightFlags _adminRights;
|
AdminRightFlags _adminRights;
|
||||||
|
int _version = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipants &update);
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipantAdd &update);
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipantDelete &update);
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatParticipantAdmin &update);
|
||||||
|
void ApplyChatUpdate(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPDupdateChatDefaultBannedRights &update);
|
||||||
|
|
||||||
|
void ApplyChatParticipants(
|
||||||
|
not_null<ChatData*> chat,
|
||||||
|
const MTPChatParticipants &participants);
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
|
@ -350,10 +350,9 @@ bool PeerData::canPinMessages() const {
|
||||||
if (const auto user = asUser()) {
|
if (const auto user = asUser()) {
|
||||||
return user->fullFlags() & MTPDuserFull::Flag::f_can_pin_message;
|
return user->fullFlags() & MTPDuserFull::Flag::f_can_pin_message;
|
||||||
} else if (const auto chat = asChat()) {
|
} else if (const auto chat = asChat()) {
|
||||||
// #TODO groups
|
|
||||||
return !chat->isDeactivated()
|
return !chat->isDeactivated()
|
||||||
/*&& ((chat->adminRights() & ChatAdminRight::f_pin_messages)
|
&& ((chat->adminRights() & ChatAdminRight::f_pin_messages)
|
||||||
|| chat->amCreator())*/;
|
|| chat->amCreator());
|
||||||
} else if (const auto channel = asChannel()) {
|
} else if (const auto channel = asChannel()) {
|
||||||
if (channel->isMegagroup()) {
|
if (channel->isMegagroup()) {
|
||||||
return (channel->adminRights() & ChatAdminRight::f_pin_messages)
|
return (channel->adminRights() & ChatAdminRight::f_pin_messages)
|
||||||
|
|
|
@ -430,9 +430,8 @@ not_null<PeerData*> Session::chat(const MTPChat &data) {
|
||||||
const auto chat = result->asChat();
|
const auto chat = result->asChat();
|
||||||
|
|
||||||
const auto canAddMembers = chat->canAddMembers();
|
const auto canAddMembers = chat->canAddMembers();
|
||||||
|
if (chat->version() < data.vversion.v) {
|
||||||
if (chat->version < data.vversion.v) {
|
chat->setVersion(data.vversion.v);
|
||||||
chat->version = data.vversion.v;
|
|
||||||
chat->invalidateParticipants();
|
chat->invalidateParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,8 +560,8 @@ not_null<PeerData*> Session::chat(const MTPChat &data) {
|
||||||
channel->inputChannel = MTP_inputChannel(data.vid, data.vaccess_hash);
|
channel->inputChannel = MTP_inputChannel(data.vid, data.vaccess_hash);
|
||||||
channel->access = data.vaccess_hash.v;
|
channel->access = data.vaccess_hash.v;
|
||||||
channel->date = data.vdate.v;
|
channel->date = data.vdate.v;
|
||||||
if (channel->version < data.vversion.v) {
|
if (channel->version() < data.vversion.v) {
|
||||||
channel->version = data.vversion.v;
|
channel->setVersion(data.vversion.v);
|
||||||
}
|
}
|
||||||
channel->setUnavailableReason(data.is_restricted()
|
channel->setUnavailableReason(data.is_restricted()
|
||||||
? ExtractUnavailableReason(qs(data.vrestriction_reason))
|
? ExtractUnavailableReason(qs(data.vrestriction_reason))
|
||||||
|
@ -657,6 +656,25 @@ PeerData *Session::processChats(const MTPVector<MTPChat> &data) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::applyMaximumChatVersions(const MTPVector<MTPChat> &data) {
|
||||||
|
for (const auto &chat : data.v) {
|
||||||
|
chat.match([&](const MTPDchat &data) {
|
||||||
|
if (const auto chat = chatLoaded(data.vid.v)) {
|
||||||
|
if (data.vversion.v < chat->version()) {
|
||||||
|
chat->setVersion(data.vversion.v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [&](const MTPDchannel &data) {
|
||||||
|
if (const auto channel = channelLoaded(data.vid.v)) {
|
||||||
|
if (data.vversion.v < channel->version()) {
|
||||||
|
channel->setVersion(data.vversion.v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [](const auto &) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PeerData *Session::peerByUsername(const QString &username) const {
|
PeerData *Session::peerByUsername(const QString &username) const {
|
||||||
const auto uname = username.trimmed();
|
const auto uname = username.trimmed();
|
||||||
for (const auto &[peerId, peer] : _peers) {
|
for (const auto &[peerId, peer] : _peers) {
|
||||||
|
@ -2372,7 +2390,7 @@ not_null<PollData*> Session::poll(const MTPDmessageMediaPoll &data) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::applyPollUpdate(const MTPDupdateMessagePoll &update) {
|
void Session::applyUpdate(const MTPDupdateMessagePoll &update) {
|
||||||
const auto updated = [&] {
|
const auto updated = [&] {
|
||||||
const auto i = _polls.find(update.vpoll_id.v);
|
const auto i = _polls.find(update.vpoll_id.v);
|
||||||
return (i == end(_polls))
|
return (i == end(_polls))
|
||||||
|
@ -2386,6 +2404,51 @@ void Session::applyPollUpdate(const MTPDupdateMessagePoll &update) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::applyUpdate(const MTPDupdateChatParticipants &update) {
|
||||||
|
const auto chatId = update.vparticipants.match([](const auto &update) {
|
||||||
|
return update.vchat_id.v;
|
||||||
|
});
|
||||||
|
if (const auto chat = chatLoaded(chatId)) {
|
||||||
|
ApplyChatUpdate(chat, update);
|
||||||
|
for (const auto user : chat->participants) {
|
||||||
|
if (user->botInfo && !user->botInfo->inited) {
|
||||||
|
_session->api().requestFullPeer(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::applyUpdate(const MTPDupdateChatParticipantAdd &update) {
|
||||||
|
if (const auto chat = chatLoaded(update.vchat_id.v)) {
|
||||||
|
ApplyChatUpdate(chat, update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::applyUpdate(const MTPDupdateChatParticipantDelete &update) {
|
||||||
|
if (const auto chat = chatLoaded(update.vchat_id.v)) {
|
||||||
|
ApplyChatUpdate(chat, update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::applyUpdate(const MTPDupdateChatParticipantAdmin &update) {
|
||||||
|
if (const auto chat = chatLoaded(update.vchat_id.v)) {
|
||||||
|
ApplyChatUpdate(chat, update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::applyUpdate(const MTPDupdateChatDefaultBannedRights &update) {
|
||||||
|
if (const auto peer = peerLoaded(peerFromMTP(update.vpeer))) {
|
||||||
|
if (const auto chat = peer->asChat()) {
|
||||||
|
ApplyChatUpdate(chat, update);
|
||||||
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
|
ApplyChannelUpdate(channel, update);
|
||||||
|
} else {
|
||||||
|
LOG(("API Error: "
|
||||||
|
"User received in updateChatDefaultBannedRights."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
not_null<LocationData*> Session::location(const LocationCoords &coords) {
|
not_null<LocationData*> Session::location(const LocationCoords &coords) {
|
||||||
auto i = _locations.find(coords);
|
auto i = _locations.find(coords);
|
||||||
if (i == _locations.cend()) {
|
if (i == _locations.cend()) {
|
||||||
|
|
|
@ -103,6 +103,8 @@ public:
|
||||||
UserData *processUsers(const MTPVector<MTPUser> &data);
|
UserData *processUsers(const MTPVector<MTPUser> &data);
|
||||||
PeerData *processChats(const MTPVector<MTPChat> &data);
|
PeerData *processChats(const MTPVector<MTPChat> &data);
|
||||||
|
|
||||||
|
void applyMaximumChatVersions(const MTPVector<MTPChat> &data);
|
||||||
|
|
||||||
void enumerateUsers(Fn<void(not_null<UserData*>)> action) const;
|
void enumerateUsers(Fn<void(not_null<UserData*>)> action) const;
|
||||||
void enumerateGroups(Fn<void(not_null<PeerData*>)> action) const;
|
void enumerateGroups(Fn<void(not_null<PeerData*>)> action) const;
|
||||||
void enumerateChannels(Fn<void(not_null<ChannelData*>)> action) const;
|
void enumerateChannels(Fn<void(not_null<ChannelData*>)> action) const;
|
||||||
|
@ -270,6 +272,13 @@ public:
|
||||||
MessageIdsList itemsToIds(const HistoryItemsList &items) const;
|
MessageIdsList itemsToIds(const HistoryItemsList &items) const;
|
||||||
MessageIdsList itemOrItsGroup(not_null<HistoryItem*> item) const;
|
MessageIdsList itemOrItsGroup(not_null<HistoryItem*> item) const;
|
||||||
|
|
||||||
|
void applyUpdate(const MTPDupdateMessagePoll &update);
|
||||||
|
void applyUpdate(const MTPDupdateChatParticipants &update);
|
||||||
|
void applyUpdate(const MTPDupdateChatParticipantAdd &update);
|
||||||
|
void applyUpdate(const MTPDupdateChatParticipantDelete &update);
|
||||||
|
void applyUpdate(const MTPDupdateChatParticipantAdmin &update);
|
||||||
|
void applyUpdate(const MTPDupdateChatDefaultBannedRights &update);
|
||||||
|
|
||||||
int pinnedDialogsCount() const;
|
int pinnedDialogsCount() const;
|
||||||
const std::deque<Dialogs::Key> &pinnedDialogsOrder() const;
|
const std::deque<Dialogs::Key> &pinnedDialogsOrder() const;
|
||||||
void setPinnedDialog(const Dialogs::Key &key, bool pinned);
|
void setPinnedDialog(const Dialogs::Key &key, bool pinned);
|
||||||
|
@ -403,7 +412,6 @@ public:
|
||||||
not_null<PollData*> poll(PollId id);
|
not_null<PollData*> poll(PollId id);
|
||||||
not_null<PollData*> poll(const MTPPoll &data);
|
not_null<PollData*> poll(const MTPPoll &data);
|
||||||
not_null<PollData*> poll(const MTPDmessageMediaPoll &data);
|
not_null<PollData*> poll(const MTPDmessageMediaPoll &data);
|
||||||
void applyPollUpdate(const MTPDupdateMessagePoll &update);
|
|
||||||
|
|
||||||
not_null<LocationData*> location(const LocationCoords &coords);
|
not_null<LocationData*> location(const LocationCoords &coords);
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,9 @@ public:
|
||||||
bool isBotInlineGeo() const {
|
bool isBotInlineGeo() const {
|
||||||
return flags() & MTPDuser::Flag::f_bot_inline_geo;
|
return flags() & MTPDuser::Flag::f_bot_inline_geo;
|
||||||
}
|
}
|
||||||
|
bool isBot() const {
|
||||||
|
return botInfo != nullptr;
|
||||||
|
}
|
||||||
bool isInaccessible() const {
|
bool isInaccessible() const {
|
||||||
constexpr auto inaccessible = 0
|
constexpr auto inaccessible = 0
|
||||||
| MTPDuser::Flag::f_deleted;
|
| MTPDuser::Flag::f_deleted;
|
||||||
|
|
|
@ -96,7 +96,7 @@ void ChatSearchFromController::rebuildRows() {
|
||||||
if (_chat->noParticipantInfo()) {
|
if (_chat->noParticipantInfo()) {
|
||||||
Auth().api().requestFullPeer(_chat);
|
Auth().api().requestFullPeer(_chat);
|
||||||
} else if (!_chat->participants.empty()) {
|
} else if (!_chat->participants.empty()) {
|
||||||
for (const auto [user, version] : _chat->participants) {
|
for (const auto user : _chat->participants) {
|
||||||
ordered.insertMulti(byOnline(user), user);
|
ordered.insertMulti(byOnline(user), user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -506,8 +506,9 @@ bool HistoryItem::canDeleteForEveryone(TimeId now) const {
|
||||||
}
|
}
|
||||||
if (!out()) {
|
if (!out()) {
|
||||||
if (const auto chat = peer->asChat()) {
|
if (const auto chat = peer->asChat()) {
|
||||||
// #TODO groups
|
if (!chat->amCreator()
|
||||||
if (!chat->amCreator()/* && (!chat->amAdmin() || !chat->adminsEnabled())*/) {
|
&& !(chat->adminRights()
|
||||||
|
& ChatAdminRight::f_delete_messages)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (peer->isUser()) {
|
} else if (peer->isUser()) {
|
||||||
|
|
|
@ -758,7 +758,7 @@ void TopBarWidget::updateOnlineDisplay() {
|
||||||
const auto self = Auth().user();
|
const auto self = Auth().user();
|
||||||
auto online = 0;
|
auto online = 0;
|
||||||
auto onlyMe = true;
|
auto onlyMe = true;
|
||||||
for (const auto [user, v] : chat->participants) {
|
for (const auto user : chat->participants) {
|
||||||
if (user->onlineTill > now) {
|
if (user->onlineTill > now) {
|
||||||
++online;
|
++online;
|
||||||
if (onlyMe && user != self) onlyMe = false;
|
if (onlyMe && user != self) onlyMe = false;
|
||||||
|
@ -826,7 +826,7 @@ void TopBarWidget::updateOnlineDisplayTimer() {
|
||||||
if (const auto user = _activeChat.peer()->asUser()) {
|
if (const auto user = _activeChat.peer()->asUser()) {
|
||||||
handleUser(user);
|
handleUser(user);
|
||||||
} else if (auto chat = _activeChat.peer()->asChat()) {
|
} else if (auto chat = _activeChat.peer()->asChat()) {
|
||||||
for (const auto [user, v] : chat->participants) {
|
for (const auto user : chat->participants) {
|
||||||
handleUser(user);
|
handleUser(user);
|
||||||
}
|
}
|
||||||
} else if (_activeChat.peer()->isChannel()) {
|
} else if (_activeChat.peer()->isChannel()) {
|
||||||
|
|
|
@ -97,21 +97,21 @@ void ListController::loadMoreRows() {
|
||||||
_preloadRequestId = 0;
|
_preloadRequestId = 0;
|
||||||
_preloadGroupId = 0;
|
_preloadGroupId = 0;
|
||||||
_allLoaded = true;
|
_allLoaded = true;
|
||||||
if (auto chats = Api::getChatsFromMessagesChats(result)) {
|
const auto &chats = result.match([](const auto &data) {
|
||||||
auto &list = chats->v;
|
return data.vchats.v;
|
||||||
if (!list.empty()) {
|
});
|
||||||
for_const (auto &chatData, list) {
|
if (!chats.empty()) {
|
||||||
if (auto chat = App::feedChat(chatData)) {
|
for (const auto &chatData : chats) {
|
||||||
if (!chat->migrateTo()) {
|
if (const auto chat = App::feedChat(chatData)) {
|
||||||
delegate()->peerListAppendRow(
|
if (!chat->migrateTo()) {
|
||||||
createRow(chat));
|
delegate()->peerListAppendRow(
|
||||||
}
|
createRow(chat));
|
||||||
_preloadGroupId = chat->bareId();
|
|
||||||
_allLoaded = false;
|
|
||||||
}
|
}
|
||||||
|
_preloadGroupId = chat->bareId();
|
||||||
|
_allLoaded = false;
|
||||||
}
|
}
|
||||||
delegate()->peerListRefreshRows();
|
|
||||||
}
|
}
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
auto fullCount = delegate()->peerListFullRowsCount();
|
auto fullCount = delegate()->peerListFullRowsCount();
|
||||||
if (fullCount > kCommonGroupsSearchAfter) {
|
if (fullCount > kCommonGroupsSearchAfter) {
|
||||||
|
|
|
@ -26,288 +26,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Info {
|
namespace Info {
|
||||||
namespace Profile {
|
namespace Profile {
|
||||||
namespace {
|
|
||||||
|
|
||||||
constexpr auto kSortByOnlineDelay = TimeMs(1000);
|
|
||||||
|
|
||||||
class ChatMembersController
|
|
||||||
: public PeerListController
|
|
||||||
, private base::Subscriber
|
|
||||||
, public base::has_weak_ptr {
|
|
||||||
public:
|
|
||||||
ChatMembersController(
|
|
||||||
not_null<Window::Navigation*> navigation,
|
|
||||||
not_null<ChatData*> chat);
|
|
||||||
|
|
||||||
void prepare() override;
|
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
|
||||||
void rowActionClicked(not_null<PeerListRow*> row) override;
|
|
||||||
base::unique_qptr<Ui::PopupMenu> rowContextMenu(
|
|
||||||
QWidget *parent,
|
|
||||||
not_null<PeerListRow*> row) override;
|
|
||||||
|
|
||||||
rpl::producer<int> onlineCountValue() const override {
|
|
||||||
return _onlineCount.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> createRestoredRow(
|
|
||||||
not_null<PeerData*> peer) override;
|
|
||||||
|
|
||||||
std::unique_ptr<PeerListState> saveState() const override;
|
|
||||||
void restoreState(std::unique_ptr<PeerListState> state) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using Rights = MemberListRow::Rights;
|
|
||||||
using Type = MemberListRow::Type;
|
|
||||||
struct SavedState : SavedStateBase {
|
|
||||||
rpl::lifetime lifetime;
|
|
||||||
};
|
|
||||||
void rebuildRows();
|
|
||||||
void rebuildRowTypes();
|
|
||||||
void refreshOnlineCount();
|
|
||||||
std::unique_ptr<PeerListRow> createRow(
|
|
||||||
not_null<UserData*> user);
|
|
||||||
void sortByOnline();
|
|
||||||
void sortByOnlineDelayed();
|
|
||||||
void removeMember(not_null<UserData*> user);
|
|
||||||
Type computeType(not_null<UserData*> user);
|
|
||||||
|
|
||||||
not_null<Window::Navigation*> _navigation;
|
|
||||||
not_null<ChatData*> _chat;
|
|
||||||
|
|
||||||
base::Timer _sortByOnlineTimer;
|
|
||||||
rpl::variable<int> _onlineCount = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
ChatMembersController::ChatMembersController(
|
|
||||||
not_null<Window::Navigation*> navigation,
|
|
||||||
not_null<ChatData*> chat)
|
|
||||||
: PeerListController()
|
|
||||||
, _navigation(navigation)
|
|
||||||
, _chat(chat) {
|
|
||||||
_sortByOnlineTimer.setCallback([this] { sortByOnline(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::prepare() {
|
|
||||||
setSearchNoResultsText(lang(lng_blocked_list_not_found));
|
|
||||||
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
|
|
||||||
delegate()->peerListSetTitle(langFactory(lng_channel_admins));
|
|
||||||
|
|
||||||
rebuildRows();
|
|
||||||
if (!delegate()->peerListFullRowsCount()) {
|
|
||||||
Auth().api().requestFullPeer(_chat);
|
|
||||||
}
|
|
||||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
|
||||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
|
|
||||||
UpdateFlag::MembersChanged
|
|
||||||
| UpdateFlag::UserOnlineChanged
|
|
||||||
| UpdateFlag::AdminsChanged,
|
|
||||||
[this](const Notify::PeerUpdate &update) {
|
|
||||||
if (update.peer == _chat) {
|
|
||||||
if (update.flags & UpdateFlag::MembersChanged) {
|
|
||||||
rebuildRows();
|
|
||||||
}
|
|
||||||
if (update.flags & UpdateFlag::AdminsChanged) {
|
|
||||||
rebuildRowTypes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (update.flags & UpdateFlag::UserOnlineChanged) {
|
|
||||||
if (auto row = delegate()->peerListFindRow(
|
|
||||||
update.peer->id)) {
|
|
||||||
row->refreshStatus();
|
|
||||||
sortByOnlineDelayed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::sortByOnlineDelayed() {
|
|
||||||
if (!_sortByOnlineTimer.isActive()) {
|
|
||||||
_sortByOnlineTimer.callOnce(kSortByOnlineDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::sortByOnline() {
|
|
||||||
auto now = unixtime();
|
|
||||||
delegate()->peerListSortRows([now](
|
|
||||||
const PeerListRow &a,
|
|
||||||
const PeerListRow &b) {
|
|
||||||
return Data::SortByOnlineValue(a.peer()->asUser(), now) >
|
|
||||||
Data::SortByOnlineValue(b.peer()->asUser(), now);
|
|
||||||
});
|
|
||||||
refreshOnlineCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<PeerListState> ChatMembersController::saveState() const {
|
|
||||||
auto result = PeerListController::saveState();
|
|
||||||
auto my = std::make_unique<SavedState>();
|
|
||||||
using Flag = Notify::PeerUpdate::Flag;
|
|
||||||
Notify::PeerUpdateViewer(
|
|
||||||
_chat,
|
|
||||||
Flag::MembersChanged
|
|
||||||
) | rpl::start_with_next([state = result.get()](auto update) {
|
|
||||||
state->controllerState = nullptr;
|
|
||||||
}, my->lifetime);
|
|
||||||
result->controllerState = std::move(my);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::restoreState(
|
|
||||||
std::unique_ptr<PeerListState> state) {
|
|
||||||
PeerListController::restoreState(std::move(state));
|
|
||||||
sortByOnline();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::rebuildRows() {
|
|
||||||
if (_chat->participants.empty()) {
|
|
||||||
// We get such updates often
|
|
||||||
// (when participants list was invalidated).
|
|
||||||
//while (delegate()->peerListFullRowsCount() > 0) {
|
|
||||||
// delegate()->peerListRemoveRow(
|
|
||||||
// delegate()->peerListRowAt(0));
|
|
||||||
//}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &participants = _chat->participants;
|
|
||||||
for (auto i = 0, count = delegate()->peerListFullRowsCount();
|
|
||||||
i != count;) {
|
|
||||||
auto row = delegate()->peerListRowAt(i);
|
|
||||||
auto user = row->peer()->asUser();
|
|
||||||
if (participants.contains(user)) {
|
|
||||||
++i;
|
|
||||||
} else {
|
|
||||||
delegate()->peerListRemoveRow(row);
|
|
||||||
--count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const auto [user, v] : participants) {
|
|
||||||
if (auto row = createRow(user)) {
|
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sortByOnline();
|
|
||||||
|
|
||||||
delegate()->peerListRefreshRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::rebuildRowTypes() {
|
|
||||||
auto count = delegate()->peerListFullRowsCount();
|
|
||||||
for (auto i = 0; i != count; ++i) {
|
|
||||||
auto row = static_cast<MemberListRow*>(
|
|
||||||
delegate()->peerListRowAt(i).get());
|
|
||||||
row->setType(computeType(row->user()));
|
|
||||||
}
|
|
||||||
delegate()->peerListRefreshRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::refreshOnlineCount() {
|
|
||||||
auto now = unixtime();
|
|
||||||
auto left = 0, right = delegate()->peerListFullRowsCount();
|
|
||||||
while (right > left) {
|
|
||||||
auto middle = (left + right) / 2;
|
|
||||||
auto row = delegate()->peerListRowAt(middle);
|
|
||||||
if (Data::OnlineTextActive(row->peer()->asUser(), now)) {
|
|
||||||
left = middle + 1;
|
|
||||||
} else {
|
|
||||||
right = middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_onlineCount = left;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ChatMembersController::createRestoredRow(
|
|
||||||
not_null<PeerData*> peer) {
|
|
||||||
if (auto user = peer->asUser()) {
|
|
||||||
return createRow(user);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> ChatMembersController::createRow(
|
|
||||||
not_null<UserData*> user) {
|
|
||||||
return std::make_unique<MemberListRow>(user, computeType(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ChatMembersController::computeType(
|
|
||||||
not_null<UserData*> user) -> Type {
|
|
||||||
auto isCreator = (peerFromUser(_chat->creator) == user->id);
|
|
||||||
// #TODO groups
|
|
||||||
auto isAdmin = false;/* _chat->adminsEnabled()
|
|
||||||
&& _chat->admins.contains(user);*/
|
|
||||||
auto canRemove = false;/* [&] {
|
|
||||||
if (user->isSelf()) {
|
|
||||||
return false;
|
|
||||||
} else if (_chat->amCreator()) {
|
|
||||||
return true;
|
|
||||||
} else if (isAdmin || isCreator) {
|
|
||||||
return false;
|
|
||||||
} else if (_chat->amAdmin()) {
|
|
||||||
return true;
|
|
||||||
} else if (_chat->invitedByMe.contains(user)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}();*/
|
|
||||||
|
|
||||||
auto result = Type();
|
|
||||||
result.rights = isCreator
|
|
||||||
? Rights::Creator
|
|
||||||
: isAdmin
|
|
||||||
? Rights::Admin
|
|
||||||
: Rights::Normal;
|
|
||||||
result.canRemove = canRemove;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::rowClicked(not_null<PeerListRow*> row) {
|
|
||||||
_navigation->showPeerInfo(row->peer());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::rowActionClicked(
|
|
||||||
not_null<PeerListRow*> row) {
|
|
||||||
removeMember(row->peer()->asUser());
|
|
||||||
}
|
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> ChatMembersController::rowContextMenu(
|
|
||||||
QWidget *parent,
|
|
||||||
not_null<PeerListRow*> row) {
|
|
||||||
auto my = static_cast<MemberListRow*>(row.get());
|
|
||||||
auto user = my->user();
|
|
||||||
auto canRemoveMember = my->canRemove();
|
|
||||||
|
|
||||||
auto result = base::make_unique_q<Ui::PopupMenu>(parent);
|
|
||||||
result->addAction(
|
|
||||||
lang(lng_context_view_profile),
|
|
||||||
[weak = base::make_weak(this), user] {
|
|
||||||
if (weak) {
|
|
||||||
weak->_navigation->showPeerInfo(user);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (canRemoveMember) {
|
|
||||||
result->addAction(
|
|
||||||
lang(lng_context_remove_from_group),
|
|
||||||
[weak = base::make_weak(this), user] {
|
|
||||||
if (weak) {
|
|
||||||
weak->removeMember(user);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatMembersController::removeMember(not_null<UserData*> user) {
|
|
||||||
auto text = lng_profile_sure_kick(lt_user, user->firstName);
|
|
||||||
Ui::show(Box<ConfirmBox>(text, lang(lng_box_remove), [user, chat = _chat] {
|
|
||||||
Ui::hideLayer();
|
|
||||||
Auth().api().kickParticipant(chat, user);
|
|
||||||
Ui::showPeerHistory(chat->id, ShowAtTheEndMsgId);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
MemberListRow::MemberListRow(
|
MemberListRow::MemberListRow(
|
||||||
not_null<UserData*> user,
|
not_null<UserData*> user,
|
||||||
|
@ -379,17 +97,10 @@ void MemberListRow::paintNameIcon(
|
||||||
std::unique_ptr<PeerListController> CreateMembersController(
|
std::unique_ptr<PeerListController> CreateMembersController(
|
||||||
not_null<Window::Navigation*> navigation,
|
not_null<Window::Navigation*> navigation,
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
if (const auto chat = peer->asChat()) {
|
return std::make_unique<ParticipantsBoxController>(
|
||||||
return std::make_unique<ChatMembersController>(
|
navigation,
|
||||||
navigation,
|
peer,
|
||||||
chat);
|
ParticipantsBoxController::Role::Profile);
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
return std::make_unique<ParticipantsBoxController>(
|
|
||||||
navigation,
|
|
||||||
channel,
|
|
||||||
ParticipantsBoxController::Role::Profile);
|
|
||||||
}
|
|
||||||
Unexpected("Peer type in CreateMembersController()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Profile
|
} // namespace Profile
|
||||||
|
|
|
@ -4182,7 +4182,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateMessagePoll: {
|
case mtpc_updateMessagePoll: {
|
||||||
Auth().data().applyPollUpdate(update.c_updateMessagePoll());
|
Auth().data().applyUpdate(update.c_updateMessagePoll());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateUserTyping: {
|
case mtpc_updateUserTyping: {
|
||||||
|
@ -4216,47 +4216,23 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateChatParticipants: {
|
case mtpc_updateChatParticipants: {
|
||||||
App::feedParticipants(update.c_updateChatParticipants().vparticipants, true);
|
Auth().data().applyUpdate(update.c_updateChatParticipants());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateChatParticipantAdd: {
|
case mtpc_updateChatParticipantAdd: {
|
||||||
App::feedParticipantAdd(update.c_updateChatParticipantAdd());
|
Auth().data().applyUpdate(update.c_updateChatParticipantAdd());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateChatParticipantDelete: {
|
case mtpc_updateChatParticipantDelete: {
|
||||||
App::feedParticipantDelete(update.c_updateChatParticipantDelete());
|
Auth().data().applyUpdate(update.c_updateChatParticipantDelete());
|
||||||
} break;
|
|
||||||
|
|
||||||
case mtpc_updateChatDefaultBannedRights: {
|
|
||||||
const auto &data = update.c_updateChatDefaultBannedRights();
|
|
||||||
const auto peerId = peerFromMTP(data.vpeer);
|
|
||||||
if (const auto peer = Auth().data().peerLoaded(peerId)) {
|
|
||||||
if (const auto chat = peer->asChat()) {
|
|
||||||
if (data.vversion.v == chat->version + 1) {
|
|
||||||
chat->setDefaultRestrictions(
|
|
||||||
data.vdefault_banned_rights);
|
|
||||||
} else {
|
|
||||||
chat->version = data.vversion.v;
|
|
||||||
chat->invalidateParticipants();
|
|
||||||
Auth().api().requestPeer(chat);
|
|
||||||
}
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
if (data.vversion.v == channel->version + 1) {
|
|
||||||
channel->setDefaultRestrictions(
|
|
||||||
data.vdefault_banned_rights);
|
|
||||||
} else {
|
|
||||||
channel->version = data.vversion.v;
|
|
||||||
Auth().api().requestPeer(channel);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG(("API Error: "
|
|
||||||
"User received in updateChatDefaultBannedRights."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateChatParticipantAdmin: {
|
case mtpc_updateChatParticipantAdmin: {
|
||||||
App::feedParticipantAdmin(update.c_updateChatParticipantAdmin());
|
Auth().data().applyUpdate(update.c_updateChatParticipantAdmin());
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mtpc_updateChatDefaultBannedRights: {
|
||||||
|
Auth().data().applyUpdate(update.c_updateChatDefaultBannedRights());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateUserStatus: {
|
case mtpc_updateUserStatus: {
|
||||||
|
|
|
@ -411,7 +411,9 @@ template <typename Flags>
|
||||||
class MTPflags {
|
class MTPflags {
|
||||||
public:
|
public:
|
||||||
Flags v = 0;
|
Flags v = 0;
|
||||||
static_assert(sizeof(Flags) == sizeof(int32), "MTPflags are allowed only wrapping int32 flag types!");
|
static_assert(
|
||||||
|
sizeof(Flags) == sizeof(int32),
|
||||||
|
"MTPflags are allowed only wrapping int32 flag types!");
|
||||||
|
|
||||||
MTPflags() = default;
|
MTPflags() = default;
|
||||||
MTPflags(internal::ZeroFlagsHelper helper) {
|
MTPflags(internal::ZeroFlagsHelper helper) {
|
||||||
|
|
|
@ -179,13 +179,13 @@ void GroupMembersWidget::updateItemStatusText(Item *item) {
|
||||||
|
|
||||||
void GroupMembersWidget::refreshMembers() {
|
void GroupMembersWidget::refreshMembers() {
|
||||||
_now = unixtime();
|
_now = unixtime();
|
||||||
if (auto chat = peer()->asChat()) {
|
if (const auto chat = peer()->asChat()) {
|
||||||
checkSelfAdmin(chat);
|
checkSelfAdmin(chat);
|
||||||
if (chat->noParticipantInfo()) {
|
if (chat->noParticipantInfo()) {
|
||||||
Auth().api().requestFullPeer(chat);
|
Auth().api().requestFullPeer(chat);
|
||||||
}
|
}
|
||||||
fillChatMembers(chat);
|
fillChatMembers(chat);
|
||||||
} else if (auto megagroup = peer()->asMegagroup()) {
|
} else if (const auto megagroup = peer()->asMegagroup()) {
|
||||||
auto &megagroupInfo = megagroup->mgInfo;
|
auto &megagroupInfo = megagroup->mgInfo;
|
||||||
if (megagroupInfo->lastParticipants.empty() || megagroup->lastParticipantsCountOutdated()) {
|
if (megagroupInfo->lastParticipants.empty() || megagroup->lastParticipantsCountOutdated()) {
|
||||||
Auth().api().requestLastParticipants(megagroup);
|
Auth().api().requestLastParticipants(megagroup);
|
||||||
|
@ -197,11 +197,12 @@ void GroupMembersWidget::refreshMembers() {
|
||||||
refreshVisibility();
|
refreshVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupMembersWidget::checkSelfAdmin(ChatData *chat) {
|
void GroupMembersWidget::checkSelfAdmin(not_null<ChatData*> chat) {
|
||||||
if (chat->participants.empty()) return;
|
if (chat->participants.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// #TODO groups
|
const auto self = chat->session().user();
|
||||||
const auto self = Auth().user();
|
|
||||||
//if (chat->amAdmin() && !chat->admins.contains(self)) {
|
//if (chat->amAdmin() && !chat->admins.contains(self)) {
|
||||||
// chat->admins.insert(self);
|
// chat->admins.insert(self);
|
||||||
//} else if (!chat->amAdmin() && chat->admins.contains(self)) {
|
//} else if (!chat->amAdmin() && chat->admins.contains(self)) {
|
||||||
|
@ -246,74 +247,95 @@ void GroupMembersWidget::updateOnlineCount() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupMembersWidget::Member *GroupMembersWidget::addUser(ChatData *chat, UserData *user) {
|
auto GroupMembersWidget::addUser(
|
||||||
auto member = computeMember(user);
|
not_null<ChatData*> chat,
|
||||||
|
not_null<UserData*> user)
|
||||||
|
-> not_null<Member*> {
|
||||||
|
const auto member = computeMember(user);
|
||||||
setItemFlags(member, chat);
|
setItemFlags(member, chat);
|
||||||
addItem(member);
|
addItem(member);
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupMembersWidget::fillChatMembers(ChatData *chat) {
|
void GroupMembersWidget::fillChatMembers(not_null<ChatData*> chat) {
|
||||||
if (chat->participants.empty()) return;
|
if (chat->participants.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
clearItems();
|
clearItems();
|
||||||
if (!chat->amIn()) return;
|
if (!chat->amIn()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_sortByOnline = true;
|
_sortByOnline = true;
|
||||||
|
|
||||||
reserveItemsForSize(chat->participants.size());
|
reserveItemsForSize(chat->participants.size());
|
||||||
addUser(chat, Auth().user())->onlineForSort
|
addUser(chat, chat->session().user())->onlineForSort
|
||||||
= std::numeric_limits<TimeId>::max();
|
= std::numeric_limits<TimeId>::max();
|
||||||
for (const auto &[user, v] : chat->participants) {
|
for (const auto user : chat->participants) {
|
||||||
if (!user->isSelf()) {
|
if (!user->isSelf()) {
|
||||||
addUser(chat, user);
|
addUser(chat, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupMembersWidget::setItemFlags(Item *item, ChatData *chat) {
|
void GroupMembersWidget::setItemFlags(
|
||||||
|
not_null<Item*> item,
|
||||||
|
not_null<ChatData*> chat) {
|
||||||
using AdminState = Item::AdminState;
|
using AdminState = Item::AdminState;
|
||||||
auto user = getMember(item)->user();
|
const auto user = getMember(item)->user();
|
||||||
auto isCreator = (peerFromUser(chat->creator) == item->peer->id);
|
const auto isCreator = (peerFromUser(chat->creator) == item->peer->id);
|
||||||
// #TODO groups
|
const auto isAdmin = chat->hasAdminRights();
|
||||||
auto isAdmin = false;// chat->adminsEnabled() && chat->admins.contains(user);
|
const auto adminState = isCreator
|
||||||
auto adminState = isCreator ? AdminState::Creator : isAdmin ? AdminState::Admin : AdminState::None;
|
? AdminState::Creator
|
||||||
|
: isAdmin
|
||||||
|
? AdminState::Admin
|
||||||
|
: AdminState::None;
|
||||||
item->adminState = adminState;
|
item->adminState = adminState;
|
||||||
if (item->peer->id == Auth().userPeerId()) {
|
if (item->peer->id == chat->session().userPeerId()) {
|
||||||
item->hasRemoveLink = false;
|
item->hasRemoveLink = false;
|
||||||
} else if (chat->amCreator() /*|| (chat->amAdmin() && (adminState == AdminState::None))*/) {
|
} else if (chat->amCreator()
|
||||||
|
|| ((chat->adminRights() & ChatAdminRight::f_ban_users)
|
||||||
|
&& (adminState == AdminState::None))) {
|
||||||
item->hasRemoveLink = true;
|
item->hasRemoveLink = true;
|
||||||
} else if (chat->invitedByMe.contains(user) && (adminState == AdminState::None)) {
|
} else if (chat->invitedByMe.contains(user)
|
||||||
|
&& (adminState == AdminState::None)) {
|
||||||
item->hasRemoveLink = true;
|
item->hasRemoveLink = true;
|
||||||
} else {
|
} else {
|
||||||
item->hasRemoveLink = false;
|
item->hasRemoveLink = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupMembersWidget::Member *GroupMembersWidget::addUser(ChannelData *megagroup, UserData *user) {
|
auto GroupMembersWidget::addUser(
|
||||||
auto member = computeMember(user);
|
not_null<ChannelData*> megagroup,
|
||||||
|
not_null<UserData*> user)
|
||||||
|
-> not_null<Member*> {
|
||||||
|
const auto member = computeMember(user);
|
||||||
setItemFlags(member, megagroup);
|
setItemFlags(member, megagroup);
|
||||||
addItem(member);
|
addItem(member);
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupMembersWidget::fillMegagroupMembers(ChannelData *megagroup) {
|
void GroupMembersWidget::fillMegagroupMembers(
|
||||||
Assert(megagroup->mgInfo != nullptr);
|
not_null<ChannelData*> megagroup) {
|
||||||
if (megagroup->mgInfo->lastParticipants.empty()) return;
|
Expects(megagroup->mgInfo != nullptr);
|
||||||
|
|
||||||
if (!megagroup->canViewMembers()) {
|
if (megagroup->mgInfo->lastParticipants.empty()) {
|
||||||
|
return;
|
||||||
|
} else if (!megagroup->canViewMembers()) {
|
||||||
clearItems();
|
clearItems();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sortByOnline = (megagroup->membersCount() > 0 && megagroup->membersCount() <= Global::ChatSizeMax());
|
_sortByOnline = (megagroup->membersCount() > 0)
|
||||||
|
&& (megagroup->membersCount() <= Global::ChatSizeMax());
|
||||||
|
|
||||||
auto &membersList = megagroup->mgInfo->lastParticipants;
|
auto &membersList = megagroup->mgInfo->lastParticipants;
|
||||||
if (_sortByOnline) {
|
if (_sortByOnline) {
|
||||||
clearItems();
|
clearItems();
|
||||||
reserveItemsForSize(membersList.size());
|
reserveItemsForSize(membersList.size());
|
||||||
if (megagroup->amIn()) {
|
if (megagroup->amIn()) {
|
||||||
addUser(megagroup, Auth().user())->onlineForSort
|
addUser(megagroup, megagroup->session().user())->onlineForSort
|
||||||
= std::numeric_limits<TimeId>::max();
|
= std::numeric_limits<TimeId>::max();
|
||||||
}
|
}
|
||||||
} else if (membersList.size() >= itemsCount()) {
|
} else if (membersList.size() >= itemsCount()) {
|
||||||
|
@ -325,14 +347,14 @@ void GroupMembersWidget::fillMegagroupMembers(ChannelData *megagroup) {
|
||||||
clearItems();
|
clearItems();
|
||||||
reserveItemsForSize(membersList.size());
|
reserveItemsForSize(membersList.size());
|
||||||
}
|
}
|
||||||
for_const (auto user, membersList) {
|
for (const auto user : membersList) {
|
||||||
if (!_sortByOnline || !user->isSelf()) {
|
if (!_sortByOnline || !user->isSelf()) {
|
||||||
addUser(megagroup, user);
|
addUser(megagroup, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupMembersWidget::addUsersToEnd(ChannelData *megagroup) {
|
bool GroupMembersWidget::addUsersToEnd(not_null<ChannelData*> megagroup) {
|
||||||
auto &membersList = megagroup->mgInfo->lastParticipants;
|
auto &membersList = megagroup->mgInfo->lastParticipants;
|
||||||
auto &itemsList = items();
|
auto &itemsList = items();
|
||||||
for (int i = 0, count = itemsList.size(); i < count; ++i) {
|
for (int i = 0, count = itemsList.size(); i < count; ++i) {
|
||||||
|
@ -347,7 +369,9 @@ bool GroupMembersWidget::addUsersToEnd(ChannelData *megagroup) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupMembersWidget::setItemFlags(Item *item, ChannelData *megagroup) {
|
void GroupMembersWidget::setItemFlags(
|
||||||
|
not_null<Item*> item,
|
||||||
|
not_null<ChannelData*> megagroup) {
|
||||||
using AdminState = Item::AdminState;
|
using AdminState = Item::AdminState;
|
||||||
auto amCreator = item->peer->isSelf() && megagroup->amCreator();
|
auto amCreator = item->peer->isSelf() && megagroup->amCreator();
|
||||||
auto amAdmin = item->peer->isSelf() && megagroup->hasAdminRights();
|
auto amAdmin = item->peer->isSelf() && megagroup->hasAdminRights();
|
||||||
|
@ -355,7 +379,11 @@ void GroupMembersWidget::setItemFlags(Item *item, ChannelData *megagroup) {
|
||||||
auto isAdmin = (adminIt != megagroup->mgInfo->lastAdmins.cend());
|
auto isAdmin = (adminIt != megagroup->mgInfo->lastAdmins.cend());
|
||||||
auto isCreator = megagroup->mgInfo->creator == item->peer;
|
auto isCreator = megagroup->mgInfo->creator == item->peer;
|
||||||
auto adminCanEdit = isAdmin && adminIt->second.canEdit;
|
auto adminCanEdit = isAdmin && adminIt->second.canEdit;
|
||||||
auto adminState = (amCreator || isCreator) ? AdminState::Creator : (amAdmin || isAdmin) ? AdminState::Admin : AdminState::None;
|
auto adminState = (amCreator || isCreator)
|
||||||
|
? AdminState::Creator
|
||||||
|
: (amAdmin || isAdmin)
|
||||||
|
? AdminState::Admin
|
||||||
|
: AdminState::None;
|
||||||
if (item->adminState != adminState) {
|
if (item->adminState != adminState) {
|
||||||
item->adminState = adminState;
|
item->adminState = adminState;
|
||||||
auto user = item->peer->asUser();
|
auto user = item->peer->asUser();
|
||||||
|
@ -375,7 +403,8 @@ void GroupMembersWidget::setItemFlags(Item *item, ChannelData *megagroup) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupMembersWidget::Member *GroupMembersWidget::computeMember(UserData *user) {
|
auto GroupMembersWidget::computeMember(not_null<UserData*> user)
|
||||||
|
-> not_null<Member*> {
|
||||||
auto it = _membersByUser.constFind(user);
|
auto it = _membersByUser.constFind(user);
|
||||||
if (it == _membersByUser.cend()) {
|
if (it == _membersByUser.cend()) {
|
||||||
auto member = new Member(user);
|
auto member = new Member(user);
|
||||||
|
|
|
@ -44,11 +44,11 @@ private:
|
||||||
|
|
||||||
void removePeer(PeerData *selectedPeer);
|
void removePeer(PeerData *selectedPeer);
|
||||||
void refreshMembers();
|
void refreshMembers();
|
||||||
void fillChatMembers(ChatData *chat);
|
void fillChatMembers(not_null<ChatData*> chat);
|
||||||
void fillMegagroupMembers(ChannelData *megagroup);
|
void fillMegagroupMembers(not_null<ChannelData*> megagroup);
|
||||||
void sortMembers();
|
void sortMembers();
|
||||||
void updateOnlineCount();
|
void updateOnlineCount();
|
||||||
void checkSelfAdmin(ChatData *chat);
|
void checkSelfAdmin(not_null<ChatData*> chat);
|
||||||
void preloadMore();
|
void preloadMore();
|
||||||
|
|
||||||
void refreshUserOnline(UserData *user);
|
void refreshUserOnline(UserData *user);
|
||||||
|
@ -66,12 +66,14 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateItemStatusText(Item *item);
|
void updateItemStatusText(Item *item);
|
||||||
Member *computeMember(UserData *user);
|
not_null<Member*> computeMember(not_null<UserData*> user);
|
||||||
Member *addUser(ChatData *chat, UserData *user);
|
not_null<Member*> addUser(not_null<ChatData*> chat, not_null<UserData*> user);
|
||||||
Member *addUser(ChannelData *megagroup, UserData *user);
|
not_null<Member*> addUser(not_null<ChannelData*> megagroup, not_null<UserData*> user);
|
||||||
void setItemFlags(Item *item, ChatData *chat);
|
void setItemFlags(not_null<Item*> item, not_null<ChatData*> chat);
|
||||||
void setItemFlags(Item *item, ChannelData *megagroup);
|
void setItemFlags(
|
||||||
bool addUsersToEnd(ChannelData *megagroup);
|
not_null<Item*> item,
|
||||||
|
not_null<ChannelData*> megagroup);
|
||||||
|
bool addUsersToEnd(not_null<ChannelData*> megagroup);
|
||||||
|
|
||||||
QMap<UserData*, Member*> _membersByUser;
|
QMap<UserData*, Member*> _membersByUser;
|
||||||
bool _sortByOnline = false;
|
bool _sortByOnline = false;
|
||||||
|
|
|
@ -126,7 +126,7 @@ void writePeer(QDataStream &stream, PeerData *peer) {
|
||||||
<< chat->name
|
<< chat->name
|
||||||
<< qint32(chat->count)
|
<< qint32(chat->count)
|
||||||
<< qint32(chat->date)
|
<< qint32(chat->date)
|
||||||
<< qint32(chat->version)
|
<< qint32(chat->version())
|
||||||
<< qint32(chat->creator)
|
<< qint32(chat->creator)
|
||||||
<< qint32(0)
|
<< qint32(0)
|
||||||
<< quint32(chat->flags())
|
<< quint32(chat->flags())
|
||||||
|
@ -136,7 +136,7 @@ void writePeer(QDataStream &stream, PeerData *peer) {
|
||||||
<< channel->name
|
<< channel->name
|
||||||
<< quint64(channel->access)
|
<< quint64(channel->access)
|
||||||
<< qint32(channel->date)
|
<< qint32(channel->date)
|
||||||
<< qint32(channel->version)
|
<< qint32(channel->version())
|
||||||
<< qint32(0)
|
<< qint32(0)
|
||||||
<< quint32(channel->flags())
|
<< quint32(channel->flags())
|
||||||
<< channel->inviteLink();
|
<< channel->inviteLink();
|
||||||
|
@ -226,7 +226,11 @@ PeerData *readPeer(int streamAppVersion, QDataStream &stream) {
|
||||||
chat->setName(name);
|
chat->setName(name);
|
||||||
chat->count = count;
|
chat->count = count;
|
||||||
chat->date = date;
|
chat->date = date;
|
||||||
chat->version = version;
|
|
||||||
|
// We don't save participants, admin status and banned rights.
|
||||||
|
// So we don't restore the version field, info is still unknown.
|
||||||
|
chat->setVersion(0);
|
||||||
|
|
||||||
chat->creator = creator;
|
chat->creator = creator;
|
||||||
chat->setFlags(MTPDchat::Flags::from_raw(flags));
|
chat->setFlags(MTPDchat::Flags::from_raw(flags));
|
||||||
chat->setInviteLink(inviteLink);
|
chat->setInviteLink(inviteLink);
|
||||||
|
@ -247,7 +251,11 @@ PeerData *readPeer(int streamAppVersion, QDataStream &stream) {
|
||||||
channel->setName(name, QString());
|
channel->setName(name, QString());
|
||||||
channel->access = access;
|
channel->access = access;
|
||||||
channel->date = date;
|
channel->date = date;
|
||||||
channel->version = version;
|
|
||||||
|
// We don't save participants, admin status and banned rights.
|
||||||
|
// So we don't restore the version field, info is still unknown.
|
||||||
|
channel->setVersion(0);
|
||||||
|
|
||||||
channel->setFlags(MTPDchannel::Flags::from_raw(flags));
|
channel->setFlags(MTPDchannel::Flags::from_raw(flags));
|
||||||
channel->setInviteLink(inviteLink);
|
channel->setInviteLink(inviteLink);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue