Move message ownership to History.

This commit is contained in:
John Preston 2020-02-20 12:45:25 +04:00
parent 6357529901
commit c8d2ac9583
13 changed files with 138 additions and 130 deletions

View file

@ -2424,7 +2424,8 @@ int ApiWrap::OnlineTillFromStatus(
void ApiWrap::clearHistory(not_null<PeerData*> peer, bool revoke) {
auto deleteTillId = MsgId(0);
if (const auto history = _session->data().historyLoaded(peer)) {
const auto history = _session->data().historyLoaded(peer);
if (history) {
while (history->lastMessageKnown()) {
const auto last = history->lastMessage();
if (!last) {
@ -2446,7 +2447,6 @@ void ApiWrap::clearHistory(not_null<PeerData*> peer, bool revoke) {
return;
}
deleteTillId = history->lastMessage()->id;
history->clear(History::ClearType::ClearHistory);
}
if (const auto channel = peer->asChannel()) {
if (const auto migrated = peer->migrateFrom()) {
@ -2461,6 +2461,9 @@ void ApiWrap::clearHistory(not_null<PeerData*> peer, bool revoke) {
} else {
deleteHistory(peer, true, revoke);
}
if (history) {
history->clear(History::ClearType::ClearHistory);
}
}
void ApiWrap::deleteConversation(not_null<PeerData*> peer, bool revoke) {

View file

@ -293,8 +293,7 @@ AdminLog::OwnedItem GenerateTextItem(
const auto clientFlags = MTPDmessage_ClientFlag::f_fake_history_item;
const auto replyTo = 0;
const auto viaBotId = 0;
const auto item = history->owner().makeMessage(
history,
const auto item = history->makeMessage(
++id,
flags,
clientFlags,

View file

@ -740,6 +740,9 @@ void ApplyChannelUpdate(
channel->session().api().applyNotifySettings(
MTP_inputNotifyPeer(channel->input),
update.vnotify_settings());
// For clearUpTill() call.
channel->owner().sendHistoryChangeNotifications();
}
void ApplyMegagroupAdmins(

View file

@ -1724,18 +1724,15 @@ auto Session::messagesListForInsert(ChannelId channelId)
: &_channelMessages[channelId];
}
HistoryItem *Session::registerMessage(std::unique_ptr<HistoryItem> item) {
Expects(item != nullptr);
const auto result = item.get();
const auto list = messagesListForInsert(result->channelId());
const auto i = list->find(result->id);
void Session::registerMessage(not_null<HistoryItem*> item) {
const auto list = messagesListForInsert(item->channelId());
const auto itemId = item->id;
const auto i = list->find(itemId);
if (i != list->end()) {
LOG(("App Error: Trying to re-registerMessage()."));
i->second->destroy();
}
list->emplace(result->id, std::move(item));
return result;
list->emplace(itemId, item);
}
void Session::processMessagesDeleted(
@ -1754,7 +1751,7 @@ void Session::processMessagesDeleted(
const auto i = list ? list->find(messageId.v) : Messages::iterator();
if (list && i != list->end()) {
const auto history = i->second->history();
destroyMessage(i->second.get());
i->second->destroy();
if (!history->chatListMessageKnown()) {
historiesToCheck.emplace(history);
}
@ -1780,32 +1777,12 @@ void Session::removeDependencyMessage(not_null<HistoryItem*> item) {
}
}
void Session::destroyMessage(not_null<HistoryItem*> item) {
Expects(item->isHistoryEntry() || !item->mainView());
void Session::unregisterMessage(not_null<HistoryItem*> item) {
const auto peerId = item->history()->peer->id;
if (item->isHistoryEntry()) {
// All this must be done for all items manually in History::clear()!
item->eraseFromUnreadMentions();
if (IsServerMsgId(item->id)) {
if (const auto types = item->sharedMediaTypes()) {
session().storage().remove(Storage::SharedMediaRemoveOne(
peerId,
types,
item->id));
}
} else {
session().api().cancelLocalItem(item);
}
item->history()->itemRemoved(item);
}
_itemRemoved.fire_copy(item);
groups().unregisterMessage(item);
removeDependencyMessage(item);
session().notifications().clearFromItem(item);
const auto list = messagesListForInsert(peerToChannel(peerId));
list->erase(item->id);
messagesListForInsert(peerToChannel(peerId))->erase(item->id);
}
MsgId Session::nextLocalMessageId() {

View file

@ -371,22 +371,8 @@ public:
const Dialogs::Key &key1,
const Dialogs::Key &key2);
template <typename ...Args>
not_null<HistoryMessage*> makeMessage(Args &&...args) {
return static_cast<HistoryMessage*>(
registerMessage(
std::make_unique<HistoryMessage>(
std::forward<Args>(args)...)));
}
template <typename ...Args>
not_null<HistoryService*> makeServiceMessage(Args &&...args) {
return static_cast<HistoryService*>(
registerMessage(
std::make_unique<HistoryService>(
std::forward<Args>(args)...)));
}
void destroyMessage(not_null<HistoryItem*> item);
void registerMessage(not_null<HistoryItem*> item);
void unregisterMessage(not_null<HistoryItem*> item);
// Returns true if item found and it is not detached.
bool checkEntitiesAndViewsUpdate(const MTPDmessage &data);
@ -698,7 +684,7 @@ public:
void clearLocalStorage();
private:
using Messages = std::unordered_map<MsgId, std::unique_ptr<HistoryItem>>;
using Messages = std::unordered_map<MsgId, not_null<HistoryItem*>>;
void suggestStartExport();
@ -719,7 +705,8 @@ private:
const Messages *messagesList(ChannelId channelId) const;
not_null<Messages*> messagesListForInsert(ChannelId channelId);
HistoryItem *registerMessage(std::unique_ptr<HistoryItem> item);
not_null<HistoryItem*> registerMessage(
std::unique_ptr<HistoryItem> item);
void changeMessageId(ChannelId channel, MsgId wasId, MsgId nowId);
void removeDependencyMessage(not_null<HistoryItem*> item);

View file

@ -392,10 +392,9 @@ void GenerateItems(
auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) {
auto message = HistoryService::PreparedText { text };
message.links.push_back(fromLink);
addPart(history->owner().makeServiceMessage(
history,
MTPDmessage_ClientFlag::f_admin_log_entry,
addPart(history->makeServiceMessage(
history->nextNonHistoryEntryId(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),
@ -433,8 +432,7 @@ void GenerateItems(
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto newDescription = PrepareText(newValue, QString());
auto body = history->owner().makeMessage(
history,
auto body = history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
@ -469,8 +467,7 @@ void GenerateItems(
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Core::App().createInternalLinkFull(newValue), QString());
auto body = history->owner().makeMessage(
history,
auto body = history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
@ -609,8 +606,7 @@ void GenerateItems(
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto bodyText = GenerateParticipantChangeText(channel, action.vparticipant());
addPart(history->owner().makeMessage(
history,
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
@ -628,8 +624,7 @@ void GenerateItems(
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant(), &action.vprev_participant());
addPart(history->owner().makeMessage(
history,
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
@ -653,8 +648,7 @@ void GenerateItems(
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto bodyText = GenerateParticipantChangeText(channel, action.vnew_participant(), &action.vprev_participant());
addPart(history->owner().makeMessage(
history,
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
@ -687,10 +681,9 @@ void GenerateItems(
auto message = HistoryService::PreparedText { text };
message.links.push_back(fromLink);
message.links.push_back(setLink);
addPart(history->owner().makeServiceMessage(
history,
MTPDmessage_ClientFlag::f_admin_log_entry,
addPart(history->makeServiceMessage(
history->nextNonHistoryEntryId(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),
@ -712,8 +705,7 @@ void GenerateItems(
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto bodyText = GenerateDefaultBannedRightsChangeText(channel, action.vnew_banned_rights(), action.vprev_banned_rights());
addPart(history->owner().makeMessage(
history,
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
@ -763,10 +755,9 @@ void GenerateItems(
auto message = HistoryService::PreparedText{ text };
message.links.push_back(fromLink);
message.links.push_back(chatLink);
addPart(history->owner().makeServiceMessage(
history,
MTPDmessage_ClientFlag::f_admin_log_entry,
addPart(history->makeServiceMessage(
history->nextNonHistoryEntryId(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),

View file

@ -637,6 +637,50 @@ HistoryItem *History::addNewMessage(
return addNewItem(item, unread);
}
not_null<HistoryItem*> History::insertItem(
std::unique_ptr<HistoryItem> item) {
Expects(item != nullptr);
const auto [i, ok] = _messages.insert(std::move(item));
const auto result = i->get();
owner().registerMessage(result);
Ensures(ok);
return result;
}
void History::destroyMessage(not_null<HistoryItem*> item) {
Expects(item->isHistoryEntry() || !item->mainView());
const auto peerId = peer->id;
if (item->isHistoryEntry()) {
// All this must be done for all items manually in History::clear()!
item->eraseFromUnreadMentions();
if (IsServerMsgId(item->id)) {
if (const auto types = item->sharedMediaTypes()) {
session().storage().remove(Storage::SharedMediaRemoveOne(
peerId,
types,
item->id));
}
} else {
session().api().cancelLocalItem(item);
}
itemRemoved(item);
}
owner().unregisterMessage(item);
session().notifications().clearFromItem(item);
auto hack = std::unique_ptr<HistoryItem>(item.get());
const auto i = _messages.find(hack);
hack.release();
Assert(i != end(_messages));
_messages.erase(i);
}
not_null<HistoryItem*> History::addNewItem(
not_null<HistoryItem*> item,
bool unread) {
@ -693,8 +737,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
const QString &postAuthor,
not_null<HistoryMessage*> forwardOriginal) {
return addNewItem(
owner().makeMessage(
this,
makeMessage(
id,
flags,
clientFlags,
@ -718,8 +761,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
const TextWithEntities &caption,
const MTPReplyMarkup &markup) {
return addNewItem(
owner().makeMessage(
this,
makeMessage(
id,
flags,
clientFlags,
@ -747,8 +789,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
const TextWithEntities &caption,
const MTPReplyMarkup &markup) {
return addNewItem(
owner().makeMessage(
this,
makeMessage(
id,
flags,
clientFlags,
@ -775,8 +816,7 @@ not_null<HistoryItem*> History::addNewLocalMessage(
not_null<GameData*> game,
const MTPReplyMarkup &markup) {
return addNewItem(
owner().makeMessage(
this,
makeMessage(
id,
flags,
clientFlags,
@ -3097,10 +3137,10 @@ void History::clear(ClearType type) {
removeJoinedMessage();
forgetScrollState();
if (type == ClearType::Unload) {
blocks.clear();
owner().notifyHistoryUnloaded(this);
lastKeyboardInited = false;
if (type == ClearType::Unload) {
_loadedAtTop = _loadedAtBottom = false;
} else {
// Leave the 'sending' messages in local messages.
@ -3145,7 +3185,6 @@ void History::clear(ClearType type) {
//}
}
}
owner().notifyHistoryChangeDelayed(this);
if (const auto chat = peer->asChat()) {
chat->lastAuthors.clear();
@ -3153,27 +3192,28 @@ void History::clear(ClearType type) {
} else if (const auto channel = peer->asMegagroup()) {
channel->mgInfo->markupSenders.clear();
}
owner().notifyHistoryChangeDelayed(this);
owner().sendHistoryChangeNotifications();
}
void History::clearUpTill(MsgId availableMinId) {
auto minId = minMsgId();
if (!minId || minId > availableMinId) {
return;
}
do {
const auto item = blocks.front()->messages.front()->data();
auto remove = std::vector<not_null<HistoryItem*>>();
remove.reserve(_messages.size());
for (const auto &item : _messages) {
const auto itemId = item->id;
if (IsServerMsgId(itemId) && itemId >= availableMinId) {
if (itemId == availableMinId) {
if (!IsServerMsgId(itemId)) {
continue;
} else if (itemId == availableMinId) {
item->applyEditionToHistoryCleared();
} else if (itemId < availableMinId) {
remove.push_back(item.get());
}
break;
}
for (const auto item : remove) {
item->destroy();
} while (!isEmpty());
}
requestChatListMessage();
owner().sendHistoryChangeNotifications();
}
void History::applyGroupAdminChanges(const base::flat_set<UserId> &changes) {

View file

@ -90,6 +90,25 @@ public:
void applyGroupAdminChanges(const base::flat_set<UserId> &changes);
template <typename ...Args>
not_null<HistoryMessage*> makeMessage(Args &&...args) {
return static_cast<HistoryMessage*>(
insertItem(
std::make_unique<HistoryMessage>(
this,
std::forward<Args>(args)...)).get());
}
template <typename ...Args>
not_null<HistoryService*> makeServiceMessage(Args &&...args) {
return static_cast<HistoryService*>(
insertItem(
std::make_unique<HistoryService>(
this,
std::forward<Args>(args)...)).get());
}
void destroyMessage(not_null<HistoryItem*> item);
HistoryItem *addNewMessage(
const MTPMessage &msg,
MTPDmessage_ClientFlags clientFlags,
@ -405,6 +424,7 @@ private:
void removeBlock(not_null<HistoryBlock*> block);
void clearSharedMedia();
not_null<HistoryItem*> insertItem(std::unique_ptr<HistoryItem> item);
not_null<HistoryItem*> addNewItem(
not_null<HistoryItem*> item,
bool unread);
@ -512,6 +532,7 @@ private:
std::optional<HistoryItem*> _lastMessage;
std::optional<HistoryItem*> _lastServerMessage;
base::flat_set<not_null<HistoryItem*>> _localMessages;
std::unordered_set<std::unique_ptr<HistoryItem>> _messages;
// This almost always is equal to _lastMessage. The only difference is
// for a group that migrated to a supergroup. Then _lastMessage can

View file

@ -75,8 +75,7 @@ not_null<HistoryItem*> CreateUnsupportedMessage(
EntityInText(EntityType::Italic, 0, text.text.size()));
flags &= ~MTPDmessage::Flag::f_post_author;
flags |= MTPDmessage::Flag::f_legacy;
return history->owner().makeMessage(
history,
return history->makeMessage(
msgId,
flags,
clientFlags,
@ -413,7 +412,7 @@ bool HistoryItem::isScheduled() const {
}
void HistoryItem::destroy() {
_history->owner().destroyMessage(this);
_history->destroyMessage(this);
}
void HistoryItem::refreshMainView() {
@ -929,37 +928,29 @@ not_null<HistoryItem*> HistoryItem::Create(
const auto text = HistoryService::PreparedText {
tr::lng_message_empty(tr::now)
};
return history->owner().makeServiceMessage(
history,
clientFlags,
return history->makeServiceMessage(
data.vid().v,
clientFlags,
data.vdate().v,
text,
data.vflags().v,
data.vfrom_id().value_or_empty());
} else if (checked == MediaCheckResult::HasTimeToLive) {
return history->owner().makeServiceMessage(
history,
data,
clientFlags);
return history->makeServiceMessage(data, clientFlags);
}
return history->owner().makeMessage(history, data, clientFlags);
return history->makeMessage(data, clientFlags);
}, [&](const MTPDmessageService &data) -> HistoryItem* {
if (data.vaction().type() == mtpc_messageActionPhoneCall) {
return history->owner().makeMessage(history, data, clientFlags);
return history->makeMessage(data, clientFlags);
}
return history->owner().makeServiceMessage(
history,
data,
clientFlags);
return history->makeServiceMessage(data, clientFlags);
}, [&](const MTPDmessageEmpty &data) -> HistoryItem* {
const auto text = HistoryService::PreparedText{
tr::lng_message_empty(tr::now)
};
return history->owner().makeServiceMessage(
history,
clientFlags,
return history->makeServiceMessage(
data.vid().v,
clientFlags,
TimeId(0),
text);
});

View file

@ -525,8 +525,8 @@ HistoryService::HistoryService(
HistoryService::HistoryService(
not_null<History*> history,
MTPDmessage_ClientFlags clientFlags,
MsgId id,
MTPDmessage_ClientFlags clientFlags,
TimeId date,
const PreparedText &message,
MTPDmessage::Flags flags,
@ -797,10 +797,9 @@ not_null<HistoryService*> GenerateJoinedMessage(
TimeId inviteDate,
not_null<UserData*> inviter,
MTPDmessage::Flags flags) {
return new HistoryService(
history,
MTPDmessage_ClientFlag::f_local_history_entry,
return history->makeServiceMessage(
history->owner().nextLocalMessageId(),
MTPDmessage_ClientFlag::f_local_history_entry,
inviteDate,
GenerateJoinedText(history, inviter),
flags);

View file

@ -68,8 +68,8 @@ public:
MTPDmessage_ClientFlags clientFlags);
HistoryService(
not_null<History*> history,
MTPDmessage_ClientFlags clientFlags,
MsgId id,
MTPDmessage_ClientFlags clientFlags,
TimeId date,
const PreparedText &message,
MTPDmessage::Flags flags = 0,

View file

@ -165,8 +165,7 @@ AdminLog::OwnedItem GenerateForwardedItem(
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>()
).match([&](const MTPDmessage &data) {
return history->owner().makeMessage(
history,
return history->makeMessage(
data,
MTPDmessage_ClientFlag::f_fake_history_item);
}, [](auto &&) -> not_null<HistoryMessage*> {

View file

@ -275,8 +275,7 @@ AdminLog::OwnedItem GenerateCommentItem(
const auto clientFlags = MTPDmessage_ClientFlag::f_fake_history_item;
const auto replyTo = 0;
const auto viaBotId = 0;
const auto item = history->owner().makeMessage(
history,
const auto item = history->makeMessage(
id,
flags,
clientFlags,
@ -322,8 +321,7 @@ AdminLog::OwnedItem GenerateContactItem(
MTP_long(0),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>());
const auto item = history->owner().makeMessage(
history,
const auto item = history->makeMessage(
message.c_message(),
MTPDmessage_ClientFlag::f_fake_history_item);
return AdminLog::OwnedItem(delegate, item);