2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-09-01 23:25:15 +00:00

Better chats list entries management.

Make unread counts and last message base::optional<>.
Remove ChannelHistory.
This commit is contained in:
John Preston
2018-01-31 20:10:29 +03:00
parent edcaccba1f
commit a7f67c4bc9
22 changed files with 1329 additions and 1146 deletions

View File

@@ -887,21 +887,27 @@ void MainWidget::deleteLayer(FullMsgId itemId) {
void MainWidget::cancelUploadLayer(not_null<HistoryItem*> item) {
const auto itemId = item->fullId();
Auth().uploader().pause(itemId);
Ui::show(Box<ConfirmBox>(lang(lng_selected_cancel_sure_this), lang(lng_selected_upload_stop), lang(lng_continue), base::lambda_guarded(this, [=] {
const auto stopUpload = [=] {
Ui::hideLayer();
if (const auto item = App::histItemById(itemId)) {
const auto history = item->history();
const auto wasLast = (history->lastMsg == item);
item->destroy();
if (wasLast && !history->lastMsg) {
checkPeerHistory(history->peer);
if (!history->lastMessageKnown()) {
Auth().api().requestDialogEntry(history);
}
Auth().data().sendHistoryChangeNotifications();
}
Auth().uploader().unpause();
}), base::lambda_guarded(this, [] {
};
const auto continueUpload = [=] {
Auth().uploader().unpause();
})));
};
Ui::show(Box<ConfirmBox>(
lang(lng_selected_cancel_sure_this),
lang(lng_selected_upload_stop),
lang(lng_continue),
stopUpload,
continueUpload));
}
void MainWidget::deletePhotoLayer(PhotoData *photo) {
@@ -1041,12 +1047,11 @@ void MainWidget::deleteConversation(
if (const auto history = App::historyLoaded(peer->id)) {
Auth().data().setPinnedDialog(history, false);
removeDialog(history);
if (peer->isMegagroup() && peer->asChannel()->mgInfo->migrateFromPtr) {
if (auto migrated = App::historyLoaded(peer->asChannel()->mgInfo->migrateFromPtr->id)) {
if (migrated->lastMsg) { // return initial dialog
migrated->setLastMessage(migrated->lastMsg);
} else {
checkPeerHistory(migrated->peer);
if (const auto channel = peer->asMegagroup()) {
channel->addFlags(MTPDchannel::Flag::f_left);
if (const auto from = channel->mgInfo->migrateFromPtr) {
if (const auto migrated = App::historyLoaded(from)) {
migrated->updateChatListExistence();
}
}
}
@@ -1059,7 +1064,12 @@ void MainWidget::deleteConversation(
}
if (deleteHistory) {
DeleteHistoryRequest request = { peer, false };
MTP::send(MTPmessages_DeleteHistory(MTP_flags(0), peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, request));
MTP::send(
MTPmessages_DeleteHistory(
MTP_flags(0),
peer->input,
MTP_int(0)),
rpcDone(&MainWidget::deleteHistoryPart, request));
}
}
@@ -1068,47 +1078,6 @@ void MainWidget::deleteAndExit(ChatData *chat) {
MTP::send(MTPmessages_DeleteChatUser(chat->inputChat, App::self()->inputUser), rpcDone(&MainWidget::deleteHistoryAfterLeave, peer), rpcFail(&MainWidget::leaveChatFailed, peer));
}
void MainWidget::deleteAllFromUser(ChannelData *channel, UserData *from) {
Assert(channel != nullptr && from != nullptr);
QVector<MsgId> toDestroy;
if (auto history = App::historyLoaded(channel->id)) {
for (const auto &block : history->blocks) {
for (const auto &message : block->messages) {
const auto item = message->data();
if (item->from() == from && item->canDelete()) {
toDestroy.push_back(item->id);
}
}
}
for_const (auto &msgId, toDestroy) {
if (auto item = App::histItemById(peerToChannel(channel->id), msgId)) {
item->destroy();
}
}
}
MTP::send(
MTPchannels_DeleteUserHistory(
channel->inputChannel,
from->inputUser),
rpcDone(&MainWidget::deleteAllFromUserPart, { channel, from }));
Auth().data().sendHistoryChangeNotifications();
}
void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTPmessages_AffectedHistory &result) {
auto &d = result.c_messages_affectedHistory();
params.channel->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
auto offset = d.voffset.v;
if (offset > 0) {
MTP::send(MTPchannels_DeleteUserHistory(params.channel->inputChannel, params.from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, params));
} else if (auto h = App::historyLoaded(params.channel)) {
if (!h->lastMsg) {
checkPeerHistory(params.channel);
}
}
}
void MainWidget::addParticipants(
not_null<PeerData*> chatOrChannel,
const std::vector<not_null<UserData*>> &users) {
@@ -1194,99 +1163,6 @@ bool MainWidget::addParticipantsFail(
return false;
}
void MainWidget::checkPeerHistory(PeerData *peer) {
auto offsetId = 0;
auto offsetDate = 0;
auto addOffset = 0;
auto limit = 1;
auto maxId = 0;
auto minId = 0;
auto historyHash = 0;
MTP::send(
MTPmessages_GetHistory(
peer->input,
MTP_int(offsetId),
MTP_int(offsetDate),
MTP_int(addOffset),
MTP_int(limit),
MTP_int(maxId),
MTP_int(minId),
MTP_int(historyHash)),
rpcDone(&MainWidget::checkedHistory, peer));
}
void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &result) {
const QVector<MTPMessage> *v = 0;
switch (result.type()) {
case mtpc_messages_messages: {
auto &d(result.c_messages_messages());
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
v = &d.vmessages.v;
} break;
case mtpc_messages_messagesSlice: {
auto &d(result.c_messages_messagesSlice());
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
v = &d.vmessages.v;
} break;
case mtpc_messages_channelMessages: {
auto &d(result.c_messages_channelMessages());
if (peer && peer->isChannel()) {
peer->asChannel()->ptsReceived(d.vpts.v);
} else {
LOG(("API Error: received messages.channelMessages when no channel was passed! (MainWidget::checkedHistory)"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
v = &d.vmessages.v;
} break;
case mtpc_messages_messagesNotModified: {
LOG(("API Error: received messages.messagesNotModified! (MainWidget::checkedHistory)"));
} break;
}
if (!v || v->isEmpty()) {
if (peer->isChat() && !peer->asChat()->haveLeft()) {
if (const auto history = App::historyLoaded(peer->id)) {
Local::addSavedPeer(peer, history->chatsListDate());
}
} else if (const auto channel = peer->asChannel()) {
if (channel->inviter > 0 && channel->amIn()) {
if (const auto from = App::userLoaded(channel->inviter)) {
const auto history = App::history(peer->id);
history->clear(true);
history->addNewerSlice(QVector<MTPMessage>());
history->asChannelHistory()->insertJoinedMessage(true);
}
}
} else if (const auto history = App::historyLoaded(peer->id)) {
deleteConversation(history->peer, false);
}
} else {
const auto history = App::history(peer->id);
if (!history->lastMsg) {
history->addNewMessage((*v)[0], NewMessageLast);
}
if (!history->chatsListDate().isNull() && history->loadedAtBottom()) {
if (const auto channel = peer->asChannel()) {
if (channel->inviter > 0
&& history->chatsListDate() <= channel->inviteDate
&& channel->amIn()) {
if (const auto from = App::userLoaded(channel->inviter)) {
history->asChannelHistory()->insertJoinedMessage(true);
}
}
}
}
history->updateChatListExistence();
}
Auth().data().sendHistoryChangeNotifications();
}
bool MainWidget::sendMessageFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
@@ -1562,9 +1438,9 @@ void MainWidget::messagesAffected(
ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
}
if (auto h = App::historyLoaded(peer ? peer->id : 0)) {
if (!h->lastMsg) {
checkPeerHistory(peer);
if (const auto history = App::historyLoaded(peer)) {
if (!history->lastMessageKnown()) {
Auth().api().requestDialogEntry(history);
}
}
}
@@ -3473,7 +3349,9 @@ void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
}
}
void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) {
void MainWidget::gotChannelDifference(
ChannelData *channel,
const MTPupdates_ChannelDifference &diff) {
_channelFailDifferenceTimeout.remove(channel);
int32 timeout = 0;
@@ -3491,28 +3369,28 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
auto h = App::historyLoaded(channel->id);
if (h) {
h->setNotLoadedAtBottom();
auto history = App::historyLoaded(channel->id);
if (history) {
history->setNotLoadedAtBottom();
}
App::feedMsgs(d.vmessages, NewMessageLast);
if (h) {
if (auto item = App::histItemById(peerToChannel(channel->id), d.vtop_message.v)) {
h->setLastMessage(item);
}
if (d.vunread_count.v >= h->unreadCount()) {
h->setUnreadCount(d.vunread_count.v);
h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
}
h->setUnreadMentionsCount(d.vunread_mentions_count.v);
if (history) {
history->applyDialogFields(
d.vunread_count.v,
d.vread_inbox_max_id.v,
d.vread_outbox_max_id.v);
history->applyDialogTopMessage(d.vtop_message.v);
history->setUnreadMentionsCount(d.vunread_mentions_count.v);
if (_history->peer() == channel) {
_history->updateHistoryDownVisibility();
_history->preloadHistoryIfNeeded();
}
h->asChannelHistory()->getRangeDifference();
Auth().api().requestChannelRangeDifference(history);
}
if (d.has_timeout()) timeout = d.vtimeout.v;
if (d.has_timeout()) {
timeout = d.vtimeout.v;
}
isFinal = d.is_final();
channel->ptsInit(d.vpts.v);
} break;
@@ -3520,39 +3398,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
case mtpc_updates_channelDifference: {
auto &d = diff.c_updates_channelDifference();
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
_handlingChannelDifference = true;
feedMessageIds(d.vother_updates);
// feed messages and groups, copy from App::feedMsgs
auto h = App::history(channel->id);
auto &vmsgs = d.vnew_messages.v;
auto indices = base::flat_map<uint64, int>();
for (auto i = 0, l = vmsgs.size(); i != l; ++i) {
const auto &msg = vmsgs[i];
if (msg.type() == mtpc_message) {
const auto &data = msg.c_message();
if (App::checkEntitiesAndViewsUpdate(data)) { // new message, index my forwarded messages to links _overview, already in blocks
LOG(("Skipping message, because it is already in blocks!"));
continue;
}
}
const auto msgId = idFromMessage(msg);
indices.emplace((uint64(uint32(msgId)) << 32) | uint64(i), i);
}
for (const auto [position, index] : indices) {
const auto &msg = vmsgs[index];
if (channel->id != peerFromMessage(msg)) {
LOG(("API Error: message with invalid peer returned in channelDifference, channelId: %1, peer: %2").arg(peerToChannel(channel->id)).arg(peerFromMessage(msg)));
continue; // wtf
}
h->addNewMessage(msg, NewMessageUnread);
}
feedUpdateVector(d.vother_updates, true);
_handlingChannelDifference = false;
feedChannelDifference(d);
if (d.has_timeout()) timeout = d.vtimeout.v;
isFinal = d.is_final();
@@ -3570,55 +3416,16 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
}
}
void MainWidget::gotRangeDifference(
ChannelData *channel,
const MTPupdates_ChannelDifference &diff) {
int32 nextRequestPts = 0;
bool isFinal = true;
switch (diff.type()) {
case mtpc_updates_channelDifferenceEmpty: {
auto &d = diff.c_updates_channelDifferenceEmpty();
nextRequestPts = d.vpts.v;
isFinal = d.is_final();
} break;
void MainWidget::feedChannelDifference(
const MTPDupdates_channelDifference &data) {
App::feedUsers(data.vusers);
App::feedChats(data.vchats);
case mtpc_updates_channelDifferenceTooLong: {
auto &d = diff.c_updates_channelDifferenceTooLong();
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
nextRequestPts = d.vpts.v;
isFinal = d.is_final();
} break;
case mtpc_updates_channelDifference: {
auto &d = diff.c_updates_channelDifference();
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
_handlingChannelDifference = true;
feedMessageIds(d.vother_updates);
App::feedMsgs(d.vnew_messages, NewMessageUnread);
feedUpdateVector(d.vother_updates, true);
_handlingChannelDifference = false;
nextRequestPts = d.vpts.v;
isFinal = d.is_final();
} break;
}
if (!isFinal) {
if (const auto history = App::historyLoaded(channel->id)) {
MTP_LOG(0, ("getChannelDifference { "
"good - after not final channelDifference was received, "
"validating history part }%1"
).arg(cTestMode() ? " TESTMODE" : ""));
history->asChannelHistory()->getRangeDifferenceNext(
nextRequestPts);
}
}
_handlingChannelDifference = true;
feedMessageIds(data.vother_updates);
App::feedMsgs(data.vnew_messages, NewMessageUnread);
feedUpdateVector(data.vother_updates, true);
_handlingChannelDifference = false;
}
bool MainWidget::failChannelDifference(ChannelData *channel, const RPCError &error) {
@@ -3985,12 +3792,12 @@ void MainWidget::onSelfParticipantUpdated(ChannelData *channel) {
history = App::history(channel);
}
if (history->isEmpty()) {
checkPeerHistory(channel);
Auth().api().requestDialogEntry(history);
} else {
history->asChannelHistory()->checkJoinedMessage(true);
history->checkJoinedMessage(true);
}
} else if (history) {
history->asChannelHistory()->checkJoinedMessage();
history->checkJoinedMessage();
}
Auth().data().sendHistoryChangeNotifications();
}
@@ -4768,10 +4575,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
const auto existing = App::histItemById(channel, newId);
if (existing && !local->mainView()) {
const auto history = local->history();
const auto wasLast = (history->lastMsg == local);
local->destroy();
if (wasLast && !history->lastMsg) {
checkPeerHistory(history->peer);
if (!history->lastMessageKnown()) {
Auth().api().requestDialogEntry(history);
}
} else {
if (existing) {
@@ -5211,7 +5017,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateChannel: {
auto &d = update.c_updateChannel();
if (auto channel = App::channelLoaded(d.vchannel_id.v)) {
if (const auto channel = App::channelLoaded(d.vchannel_id.v)) {
channel->inviter = 0;
if (!channel->amIn()) {
if (const auto history = App::historyLoaded(channel->id)) {