Fix crash in pinned topic deletion.

This commit is contained in:
John Preston 2022-12-07 10:43:02 +04:00
parent d01969ff1e
commit 02e2fb1258
14 changed files with 66 additions and 40 deletions

View File

@ -76,6 +76,11 @@ rpl::producer<UpdateType> Changes::Manager<DataType, UpdateType>::flagsValue(
) | rpl::then(updates(data, flags));
}
template <typename DataType, typename UpdateType>
void Changes::Manager<DataType, UpdateType>::drop(not_null<DataType*> data) {
_updates.remove(data);
}
template <typename DataType, typename UpdateType>
void Changes::Manager<DataType, UpdateType>::sendNotifications() {
for (const auto &[data, flags] : base::take(_updates)) {
@ -166,8 +171,11 @@ rpl::producer<HistoryUpdate> Changes::realtimeHistoryUpdates(
void Changes::topicUpdated(
not_null<ForumTopic*> topic,
TopicUpdate::Flags flags) {
_topicChanges.updated(topic, flags);
scheduleNotifications();
const auto drop = (flags & TopicUpdate::Flag::Destroyed);
_topicChanges.updated(topic, flags, drop);
if (!drop) {
scheduleNotifications();
}
}
rpl::producer<TopicUpdate> Changes::topicUpdates(
@ -192,6 +200,10 @@ rpl::producer<TopicUpdate> Changes::realtimeTopicUpdates(
return _topicChanges.realtimeUpdates(flag);
}
void Changes::topicRemoved(not_null<ForumTopic*> topic) {
_topicChanges.drop(topic);
}
void Changes::messageUpdated(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags) {
@ -227,8 +239,11 @@ rpl::producer<MessageUpdate> Changes::realtimeMessageUpdates(
void Changes::entryUpdated(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags) {
_entryChanges.updated(entry, flags);
scheduleNotifications();
const auto drop = (flags & EntryUpdate::Flag::Destroyed);
_entryChanges.updated(entry, flags, drop);
if (!drop) {
scheduleNotifications();
}
}
rpl::producer<EntryUpdate> Changes::entryUpdates(
@ -253,6 +268,10 @@ rpl::producer<EntryUpdate> Changes::realtimeEntryUpdates(
return _entryChanges.realtimeUpdates(flag);
}
void Changes::entryRemoved(not_null<Dialogs::Entry*> entry) {
_entryChanges.drop(entry);
}
void Changes::scheduleNotifications() {
if (!_notify) {
_notify = true;

View File

@ -153,8 +153,9 @@ struct TopicUpdate {
CloudDraft = (1U << 8),
Closed = (1U << 9),
Creator = (1U << 10),
Destroyed = (1U << 11),
LastUsedBit = (1U << 10),
LastUsedBit = (1U << 11),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }
@ -198,8 +199,9 @@ struct EntryUpdate {
ForwardDraft = (1U << 2),
LocalDraftSet = (1U << 3),
Height = (1U << 4),
Destroyed = (1U << 5),
LastUsedBit = (1U << 4),
LastUsedBit = (1U << 5),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }
@ -261,6 +263,7 @@ public:
TopicUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<TopicUpdate> realtimeTopicUpdates(
TopicUpdate::Flag flag) const;
void topicRemoved(not_null<ForumTopic*> topic);
void messageUpdated(
not_null<HistoryItem*> item,
@ -289,6 +292,7 @@ public:
EntryUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<EntryUpdate> realtimeEntryUpdates(
EntryUpdate::Flag flag) const;
void entryRemoved(not_null<Dialogs::Entry*> entry);
void sendNotifications();
@ -313,6 +317,8 @@ private:
[[nodiscard]] rpl::producer<UpdateType> realtimeUpdates(
Flag flag) const;
void drop(not_null<DataType*> data);
void sendNotifications();
private:

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "data/data_session.h"
#include "data/data_forum_icons.h"
#include "data/data_forum_topic.h"
@ -68,12 +69,16 @@ Forum::~Forum() {
if (_requestId) {
session().api().request(_requestId).cancel();
}
auto &storage = session().storage();
auto &changes = session().changes();
const auto peerId = _history->peer->id;
for (const auto &[rootId, topic] : _topics) {
session().storage().unload(Storage::SharedMediaUnloadThread(
peerId,
rootId));
storage.unload(Storage::SharedMediaUnloadThread(peerId, rootId));
_history->setForwardDraft(rootId, {});
const auto raw = topic.get();
changes.topicRemoved(raw);
changes.entryRemoved(raw);
}
}
@ -181,6 +186,12 @@ void Forum::applyTopicDeleted(MsgId rootId) {
}
_topicDestroyed.fire(raw);
session().changes().topicUpdated(
raw,
Data::TopicUpdate::Flag::Destroyed);
session().changes().entryUpdated(
raw,
Data::EntryUpdate::Flag::Destroyed);
_topics.erase(i);
_history->destroyMessagesByTopic(rootId);

View File

@ -333,7 +333,7 @@ not_null<Row*> Entry::addToChatList(
void Entry::removeFromChatList(
FilterId filterId,
not_null<MainList*> list) {
if (!asTopic() && isPinnedDialog(filterId)) {
if (isPinnedDialog(filterId)) {
owner().setChatPinned(this, filterId, false);
}

View File

@ -1223,13 +1223,11 @@ void Element::drawRightAction(
int outerWidth) const {
}
ClickHandlerPtr Element::rightActionLink() const {
ClickHandlerPtr Element::rightActionLink(
std::optional<QPoint> pressPoint) const {
return ClickHandlerPtr();
}
void Element::applyRightActionLastPoint(QPoint p) const {
}
TimeId Element::displayedEditDate() const {
return TimeId(0);
}

View File

@ -403,8 +403,8 @@ public:
int left,
int top,
int outerWidth) const;
[[nodiscard]] virtual ClickHandlerPtr rightActionLink() const;
virtual void applyRightActionLastPoint(QPoint p) const;
[[nodiscard]] virtual ClickHandlerPtr rightActionLink(
std::optional<QPoint> pressPoint) const;
[[nodiscard]] virtual TimeId displayedEditDate() const;
[[nodiscard]] virtual bool hasVisibleText() const;
[[nodiscard]] virtual HistoryMessageReply *displayedReply() const;

View File

@ -1963,10 +1963,9 @@ TextState Message::textState(
size->width(),
size->height()
).contains(point)) {
result.link = rightActionLink();
result.link = rightActionLink(point
- QPoint(fastShareLeft, fastShareTop));
}
applyRightActionLastPoint(point
- QPoint(fastShareLeft, fastShareTop));
}
} else if (media && media->isDisplayed()) {
result = media->textState(point - g.topLeft(), request);
@ -2715,7 +2714,7 @@ auto Message::verticalRepaintRange() const -> VerticalRepaintRange {
void Message::refreshDataIdHook() {
if (_rightAction && base::take(_rightAction->link)) {
_rightAction->link = rightActionLink();
_rightAction->link = rightActionLink(_rightAction->lastPoint);
}
if (base::take(_fastReplyLink)) {
_fastReplyLink = fastReplyLink();
@ -2989,11 +2988,6 @@ std::optional<QSize> Message::rightActionSize() const {
: std::optional<QSize>();
}
void Message::applyRightActionLastPoint(QPoint p) const {
ensureRightAction();
_rightAction->lastPoint = std::move(p);
}
bool Message::displayFastShare() const {
const auto item = message();
const auto peer = item->history()->peer;
@ -3100,11 +3094,15 @@ void Message::drawRightAction(
}
}
ClickHandlerPtr Message::rightActionLink() const {
ClickHandlerPtr Message::rightActionLink(
std::optional<QPoint> pressPoint) const {
ensureRightAction();
if (!_rightAction->link) {
_rightAction->link = prepareRightActionLink();
}
if (pressPoint) {
_rightAction->lastPoint = *pressPoint;
}
return _rightAction->link;
}

View File

@ -130,14 +130,14 @@ public:
bool displayFastReply() const override;
bool displayRightActionComments() const;
std::optional<QSize> rightActionSize() const override;
void applyRightActionLastPoint(QPoint p) const override;
void drawRightAction(
Painter &p,
const PaintContext &context,
int left,
int top,
int outerWidth) const override;
[[nodiscard]] ClickHandlerPtr rightActionLink() const override;
[[nodiscard]] ClickHandlerPtr rightActionLink(
std::optional<QPoint> pressPoint) const override;
[[nodiscard]] TimeId displayedEditDate() const override;
[[nodiscard]] HistoryMessageReply *displayedReply() const override;
[[nodiscard]] bool toggleSelectionByHandlerClick(

View File

@ -393,8 +393,7 @@ TextState ExtendedPreview::textState(QPoint point, StateRequest request) const {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop));
}
}

View File

@ -1032,8 +1032,7 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
+ st::msgDateImgPadding.y();
}
if (QRect(QPoint(fastShareLeft, fastShareTop), *size).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop));
}
}

View File

@ -334,8 +334,7 @@ TextState Location::textState(QPoint point, StateRequest request) const {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop));
}
}

View File

@ -461,8 +461,7 @@ TextState GroupedMedia::textState(QPoint point, StateRequest request) const {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop));
}
}

View File

@ -485,8 +485,7 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
fullRight,
*rightActionSize);
if (QRect(position.x(), position.y(), rightActionSize->width(), rightActionSize->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point - position);
result.link = _parent->rightActionLink(point - position);
return result;
}
}

View File

@ -563,8 +563,7 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height());
if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) {
result.link = _parent->rightActionLink();
_parent->applyRightActionLastPoint(point
result.link = _parent->rightActionLink(point
- QPoint(fastShareLeft, fastShareTop));
}
}