Attach main views to correct HistoryInner-s.

This commit is contained in:
John Preston 2022-01-05 00:11:29 +03:00
parent 18e6e2da9e
commit cb8f86bc8d
5 changed files with 221 additions and 163 deletions

View file

@ -68,6 +68,7 @@ History::History(not_null<Data::Session*> owner, PeerId peerId)
: Entry(owner, Type::History) : Entry(owner, Type::History)
, peer(owner->peer(peerId)) , peer(owner->peer(peerId))
, cloudDraftTextCache(st::dialogsTextWidthMin) , cloudDraftTextCache(st::dialogsTextWidthMin)
, _delegateMixin(HistoryInner::DelegateMixin())
, _mute(owner->notifyIsMuted(peer)) , _mute(owner->notifyIsMuted(peer))
, _chatListNameSortKey(owner->nameSortKey(peer->name)) , _chatListNameSortKey(owner->nameSortKey(peer->name))
, _sendActionPainter(this) { , _sendActionPainter(this) {
@ -1244,8 +1245,7 @@ void History::addItemToBlock(not_null<HistoryItem*> item) {
auto block = prepareBlockForAddingItem(); auto block = prepareBlockForAddingItem();
block->messages.push_back(item->createView( block->messages.push_back(item->createView(_delegateMixin->delegate()));
HistoryInner::ElementDelegate()));
const auto view = block->messages.back().get(); const auto view = block->messages.back().get();
view->attachToBlock(block, block->messages.size() - 1); view->attachToBlock(block, block->messages.size() - 1);
@ -2011,8 +2011,7 @@ not_null<HistoryItem*> History::addNewInTheMiddle(
const auto it = block->messages.insert( const auto it = block->messages.insert(
block->messages.begin() + itemIndex, block->messages.begin() + itemIndex,
item->createView( item->createView(_delegateMixin->delegate()));
HistoryInner::ElementDelegate()));
(*it)->attachToBlock(block.get(), itemIndex); (*it)->attachToBlock(block.get(), itemIndex);
if (itemIndex + 1 < block->messages.size()) { if (itemIndex + 1 < block->messages.size()) {
for (auto i = itemIndex + 1, l = int(block->messages.size()); i != l; ++i) { for (auto i = itemIndex + 1, l = int(block->messages.size()); i != l; ++i) {
@ -3287,7 +3286,7 @@ void HistoryBlock::refreshView(not_null<Element*> view) {
const auto item = view->data(); const auto item = view->data();
auto refreshed = item->createView( auto refreshed = item->createView(
HistoryInner::ElementDelegate(), _history->delegateMixin()->delegate(),
view); view);
auto blockIndex = indexInHistory(); auto blockIndex = indexInHistory();

View file

@ -25,6 +25,7 @@ class HistoryItem;
class HistoryMessage; class HistoryMessage;
class HistoryService; class HistoryService;
struct HistoryMessageMarkupData; struct HistoryMessageMarkupData;
class HistoryMainElementDelegateMixin;
namespace Main { namespace Main {
class Session; class Session;
@ -84,6 +85,11 @@ public:
History &operator=(const History &) = delete; History &operator=(const History &) = delete;
~History(); ~History();
[[nodiscard]] auto delegateMixin() const
-> not_null<HistoryMainElementDelegateMixin*> {
return _delegateMixin.get();
}
not_null<History*> migrateToOrMe() const; not_null<History*> migrateToOrMe() const;
History *migrateFrom() const; History *migrateFrom() const;
MsgRange rangeForDifferenceRequest() const; MsgRange rangeForDifferenceRequest() const;
@ -585,6 +591,8 @@ private:
void setFolderPointer(Data::Folder *folder); void setFolderPointer(Data::Folder *folder);
const std::unique_ptr<HistoryMainElementDelegateMixin> _delegateMixin;
Flags _flags = 0; Flags _flags = 0;
bool _mute = false; bool _mute = false;
int _width = 0; int _width = 0;

View file

@ -120,7 +120,148 @@ int BinarySearchBlocksOrItems(const T &list, int edge) {
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
HistoryInner *HistoryInner::Instance = nullptr; HistoryMainElementDelegateMixin::HistoryMainElementDelegateMixin() = default;
HistoryMainElementDelegateMixin::~HistoryMainElementDelegateMixin()
= default;
class HistoryMainElementDelegate final
: public HistoryView::ElementDelegate
, public HistoryMainElementDelegateMixin {
public:
using Element = HistoryView::Element;
HistoryView::Context elementContext() override {
return HistoryView::Context::History;
}
std::unique_ptr<Element> elementCreate(
not_null<HistoryMessage*> message,
Element *replacing = nullptr) override {
return std::make_unique<HistoryView::Message>(
this,
message,
replacing);
}
std::unique_ptr<HistoryView::Element> elementCreate(
not_null<HistoryService*> message,
Element *replacing = nullptr) override {
return std::make_unique<HistoryView::Service>(
this,
message,
replacing);
}
bool elementUnderCursor(
not_null<const Element*> view) override {
return (App::mousedItem() == view);
}
crl::time elementHighlightTime(
not_null<const HistoryItem*> item) override {
return _widget ? _widget->elementHighlightTime(item) : 0;
}
bool elementInSelectionMode() override {
return _widget ? _widget->inSelectionMode() : false;
}
bool elementIntersectsRange(
not_null<const Element*> view,
int from,
int till) override {
return _widget
? _widget->elementIntersectsRange(view, from, till)
: false;
}
void elementStartStickerLoop(
not_null<const Element*> view) override {
if (_widget) {
_widget->elementStartStickerLoop(view);
}
}
void elementShowPollResults(
not_null<PollData*> poll,
FullMsgId context) override {
if (_widget) {
_widget->elementShowPollResults(poll, context);
}
}
void elementOpenPhoto(
not_null<PhotoData*> photo,
FullMsgId context) override {
if (_widget) {
_widget->elementOpenPhoto(photo, context);
}
}
void elementOpenDocument(
not_null<DocumentData*> document,
FullMsgId context,
bool showInMediaView = false) override {
if (_widget) {
_widget->elementOpenDocument(
document,
context,
showInMediaView);
}
}
void elementCancelUpload(const FullMsgId &context) override {
if (_widget) {
_widget->elementCancelUpload(context);
}
}
void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override {
if (_widget) {
_widget->elementShowTooltip(text, hiddenCallback);
}
}
bool elementIsGifPaused() override {
return _widget ? _widget->elementIsGifPaused() : false;
}
bool elementHideReply(not_null<const Element*> view) override {
return false;
}
bool elementShownUnread(not_null<const Element*> view) override {
return view->data()->unread();
}
void elementSendBotCommand(
const QString &command,
const FullMsgId &context) override {
if (_widget) {
_widget->elementSendBotCommand(command, context);
}
}
void elementHandleViaClick(not_null<UserData*> bot) override {
if (_widget) {
_widget->elementHandleViaClick(bot);
}
}
bool elementIsChatWide() override {
return _widget ? _widget->elementIsChatWide() : false;
}
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override {
Expects(_widget != nullptr);
return _widget->elementPathShiftGradient();
}
void elementReplyTo(const FullMsgId &to) override {
if (_widget) {
_widget->elementReplyTo(to);
}
}
void elementStartInteraction(not_null<const Element*> view) override {
if (_widget) {
_widget->elementStartInteraction(view);
}
}
void elementShowSpoilerAnimation() override {
if (_widget) {
_widget->elementShowSpoilerAnimation();
}
}
not_null<HistoryView::ElementDelegate*> delegate() override {
return this;
}
};
class HistoryInner::BotAbout : public ClickHandlerHost { class HistoryInner::BotAbout : public ClickHandlerHost {
public: public:
@ -170,6 +311,7 @@ HistoryInner::HistoryInner(
, _controller(controller) , _controller(controller)
, _peer(history->peer) , _peer(history->peer)
, _history(history) , _history(history)
, _elementDelegate(_history->delegateMixin()->delegate())
, _emojiInteractions(std::make_unique<HistoryView::EmojiInteractions>( , _emojiInteractions(std::make_unique<HistoryView::EmojiInteractions>(
&controller->session())) &controller->session()))
, _migrated(history->migrateFrom()) , _migrated(history->migrateFrom())
@ -185,7 +327,10 @@ HistoryInner::HistoryInner(
, _touchScrollTimer([=] { onTouchScrollTimer(); }) , _touchScrollTimer([=] { onTouchScrollTimer(); })
, _scrollDateCheck([this] { scrollDateCheck(); }) , _scrollDateCheck([this] { scrollDateCheck(); })
, _scrollDateHideTimer([this] { scrollDateHideByTimer(); }) { , _scrollDateHideTimer([this] { scrollDateHideByTimer(); }) {
Instance = this; _history->delegateMixin()->setCurrent(this);
if (_migrated) {
_migrated->delegateMixin()->setCurrent(this);
}
Window::ChatThemeValueFromPeer( Window::ChatThemeValueFromPeer(
controller, controller,
@ -1531,16 +1676,24 @@ void HistoryInner::mouseActionFinish(
const auto pressedItemId = pressedItemView const auto pressedItemId = pressedItemView
? pressedItemView->data()->fullId() ? pressedItemView->data()->fullId()
: FullMsgId(); : FullMsgId();
const auto weak = base::make_weak(_controller.get());
const auto history = pressedItemView->data()->history();
const auto delegate = history->delegateMixin()->delegate();
ActivateClickHandler(window(), activated, { ActivateClickHandler(window(), activated, {
button, button,
QVariant::fromValue(ClickHandlerContext{ QVariant::fromValue(ClickHandlerContext{
.itemId = pressedItemId, .itemId = pressedItemId,
.elementDelegate = [weak = Ui::MakeWeak(this)] { .elementDelegate = [=]() -> HistoryView::ElementDelegate* {
return weak if (const auto strong = weak.get()) {
? HistoryInner::ElementDelegate().get() auto &data = strong->session().data();
: nullptr; if (const auto item = data.message(pressedItemId)) {
const auto history = item->history();
return history->delegateMixin()->delegate();
}
}
return nullptr;
}, },
.sessionWindow = base::make_weak(_controller.get()), .sessionWindow = weak,
}) })
}); });
return; return;
@ -2551,7 +2704,13 @@ void HistoryInner::visibleAreaUpdated(int top, int bottom) {
const auto pages = kUnloadHeavyPartsPages; const auto pages = kUnloadHeavyPartsPages;
const auto from = _visibleAreaTop - pages * visibleAreaHeight; const auto from = _visibleAreaTop - pages * visibleAreaHeight;
const auto till = _visibleAreaBottom + pages * visibleAreaHeight; const auto till = _visibleAreaBottom + pages * visibleAreaHeight;
session().data().unloadHeavyViewParts(ElementDelegate(), from, till); session().data().unloadHeavyViewParts(_elementDelegate, from, till);
if (_migratedElementDelegate) {
session().data().unloadHeavyViewParts(
_migratedElementDelegate,
from,
till);
}
checkHistoryActivation(); checkHistoryActivation();
_emojiInteractions->visibleAreaUpdated( _emojiInteractions->visibleAreaUpdated(
@ -2701,8 +2860,9 @@ HistoryInner::~HistoryInner() {
} }
} }
} }
if (Instance == this) { _history->delegateMixin()->setCurrent(nullptr);
Instance = nullptr; if (_migrated) {
_migrated->delegateMixin()->setCurrent(nullptr);
} }
delete _menu; delete _menu;
_mouseAction = MouseAction::None; _mouseAction = MouseAction::None;
@ -3737,139 +3897,7 @@ void HistoryInner::onParentGeometryChanged() {
} }
} }
not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() { auto HistoryInner::DelegateMixin()
class Result final : public HistoryView::ElementDelegate { -> std::unique_ptr<HistoryMainElementDelegateMixin> {
public: return std::make_unique<HistoryMainElementDelegate>();
HistoryView::Context elementContext() override {
return HistoryView::Context::History;
}
std::unique_ptr<HistoryView::Element> elementCreate(
not_null<HistoryMessage*> message,
Element *replacing = nullptr) override {
return std::make_unique<HistoryView::Message>(
this,
message,
replacing);
}
std::unique_ptr<HistoryView::Element> elementCreate(
not_null<HistoryService*> message,
Element *replacing = nullptr) override {
return std::make_unique<HistoryView::Service>(
this,
message,
replacing);
}
bool elementUnderCursor(
not_null<const Element*> view) override {
return (App::mousedItem() == view);
}
crl::time elementHighlightTime(
not_null<const HistoryItem*> item) override {
return Instance ? Instance->elementHighlightTime(item) : 0;
}
bool elementInSelectionMode() override {
return Instance ? Instance->inSelectionMode() : false;
}
bool elementIntersectsRange(
not_null<const Element*> view,
int from,
int till) override {
return Instance
? Instance->elementIntersectsRange(view, from, till)
: false;
}
void elementStartStickerLoop(
not_null<const Element*> view) override {
if (Instance) {
Instance->elementStartStickerLoop(view);
}
}
void elementShowPollResults(
not_null<PollData*> poll,
FullMsgId context) override {
if (Instance) {
Instance->elementShowPollResults(poll, context);
}
}
void elementOpenPhoto(
not_null<PhotoData*> photo,
FullMsgId context) override {
if (Instance) {
Instance->elementOpenPhoto(photo, context);
}
}
void elementOpenDocument(
not_null<DocumentData*> document,
FullMsgId context,
bool showInMediaView = false) override {
if (Instance) {
Instance->elementOpenDocument(
document,
context,
showInMediaView);
}
}
void elementCancelUpload(const FullMsgId &context) override {
if (Instance) {
Instance->elementCancelUpload(context);
}
}
void elementShowTooltip(
const TextWithEntities &text,
Fn<void()> hiddenCallback) override {
if (Instance) {
Instance->elementShowTooltip(text, hiddenCallback);
}
}
bool elementIsGifPaused() override {
return Instance ? Instance->elementIsGifPaused() : false;
}
bool elementHideReply(not_null<const Element*> view) override {
return false;
}
bool elementShownUnread(not_null<const Element*> view) override {
return view->data()->unread();
}
void elementSendBotCommand(
const QString &command,
const FullMsgId &context) override {
if (Instance) {
Instance->elementSendBotCommand(command, context);
}
}
void elementHandleViaClick(not_null<UserData*> bot) override {
if (Instance) {
Instance->elementHandleViaClick(bot);
}
}
bool elementIsChatWide() override {
return Instance
? Instance->elementIsChatWide()
: false;
}
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override {
Expects(Instance != nullptr);
return Instance->elementPathShiftGradient();
}
void elementReplyTo(const FullMsgId &to) override {
if (Instance) {
Instance->elementReplyTo(to);
}
}
void elementStartInteraction(not_null<const Element*> view) override {
if (Instance) {
Instance->elementStartInteraction(view);
}
}
void elementShowSpoilerAnimation() override {
if (Instance) {
Instance->elementShowSpoilerAnimation();
}
}
};
static Result result;
return &result;
} }

View file

@ -47,6 +47,26 @@ enum class ReportReason;
class PathShiftGradient; class PathShiftGradient;
} // namespace Ui } // namespace Ui
class HistoryInner;
class HistoryMainElementDelegate;
class HistoryMainElementDelegateMixin {
public:
void setCurrent(HistoryInner *widget) {
_widget = widget;
}
virtual not_null<HistoryView::ElementDelegate*> delegate() = 0;
virtual ~HistoryMainElementDelegateMixin();
private:
friend class HistoryMainElementDelegate;
HistoryMainElementDelegateMixin();
HistoryInner *_widget = nullptr;
};
class HistoryWidget; class HistoryWidget;
class HistoryInner class HistoryInner
: public Ui::RpWidget : public Ui::RpWidget
@ -160,8 +180,8 @@ public:
void onParentGeometryChanged(); void onParentGeometryChanged();
// HistoryView::ElementDelegate interface. [[nodiscard]] static auto DelegateMixin()
static not_null<HistoryView::ElementDelegate*> ElementDelegate(); -> std::unique_ptr<HistoryMainElementDelegateMixin>;
protected: protected:
bool focusNextPrevChild(bool next) override; bool focusNextPrevChild(bool next) override;
@ -364,17 +384,17 @@ private:
// Does any of the shown histories has this flag set. // Does any of the shown histories has this flag set.
bool hasPendingResizedItems() const; bool hasPendingResizedItems() const;
static HistoryInner *Instance;
const not_null<HistoryWidget*> _widget; const not_null<HistoryWidget*> _widget;
const not_null<Ui::ScrollArea*> _scroll; const not_null<Ui::ScrollArea*> _scroll;
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
const not_null<PeerData*> _peer; const not_null<PeerData*> _peer;
const not_null<History*> _history; const not_null<History*> _history;
const not_null<HistoryView::ElementDelegate*> _elementDelegate;
const std::unique_ptr<HistoryView::EmojiInteractions> _emojiInteractions; const std::unique_ptr<HistoryView::EmojiInteractions> _emojiInteractions;
std::shared_ptr<Ui::ChatTheme> _theme; std::shared_ptr<Ui::ChatTheme> _theme;
History *_migrated = nullptr; History *_migrated = nullptr;
HistoryView::ElementDelegate *_migratedElementDelegate = nullptr;
int _contentWidth = 0; int _contentWidth = 0;
int _historyPaddingTop = 0; int _historyPaddingTop = 0;
int _revealHeight = 0; int _revealHeight = 0;

View file

@ -2056,9 +2056,6 @@ void HistoryWidget::showHistory(
_historyInited = false; _historyInited = false;
_contactStatus = nullptr; _contactStatus = nullptr;
// Unload lottie animations.
session().data().unloadHeavyViewParts(HistoryInner::ElementDelegate());
if (peerId) { if (peerId) {
_peer = session().data().peer(peerId); _peer = session().data().peer(peerId);
_canSendMessages = _peer->canWrite(); _canSendMessages = _peer->canWrite();
@ -2240,13 +2237,19 @@ void HistoryWidget::setHistory(History *history) {
if (_history == history) { if (_history == history) {
return; return;
} }
// Unload lottie animations.
const auto unloadHeavyViewParts = [](History *history) {
if (history) {
history->owner().unloadHeavyViewParts(
history->delegateMixin()->delegate());
history->forceFullResize();
}
};
unloadHeavyViewParts(_history);
unloadHeavyViewParts(_migrated);
unregisterDraftSources(); unregisterDraftSources();
if (_history) {
_history->forceFullResize();
}
if (_migrated) {
_migrated->forceFullResize();
}
_history = history; _history = history;
_migrated = _history ? _history->migrateFrom() : nullptr; _migrated = _history ? _history->migrateFrom() : nullptr;
registerDraftSource(); registerDraftSource();