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)
, peer(owner->peer(peerId))
, cloudDraftTextCache(st::dialogsTextWidthMin)
, _delegateMixin(HistoryInner::DelegateMixin())
, _mute(owner->notifyIsMuted(peer))
, _chatListNameSortKey(owner->nameSortKey(peer->name))
, _sendActionPainter(this) {
@ -1244,8 +1245,7 @@ void History::addItemToBlock(not_null<HistoryItem*> item) {
auto block = prepareBlockForAddingItem();
block->messages.push_back(item->createView(
HistoryInner::ElementDelegate()));
block->messages.push_back(item->createView(_delegateMixin->delegate()));
const auto view = block->messages.back().get();
view->attachToBlock(block, block->messages.size() - 1);
@ -2011,8 +2011,7 @@ not_null<HistoryItem*> History::addNewInTheMiddle(
const auto it = block->messages.insert(
block->messages.begin() + itemIndex,
item->createView(
HistoryInner::ElementDelegate()));
item->createView(_delegateMixin->delegate()));
(*it)->attachToBlock(block.get(), itemIndex);
if (itemIndex + 1 < block->messages.size()) {
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();
auto refreshed = item->createView(
HistoryInner::ElementDelegate(),
_history->delegateMixin()->delegate(),
view);
auto blockIndex = indexInHistory();

View File

@ -25,6 +25,7 @@ class HistoryItem;
class HistoryMessage;
class HistoryService;
struct HistoryMessageMarkupData;
class HistoryMainElementDelegateMixin;
namespace Main {
class Session;
@ -84,6 +85,11 @@ public:
History &operator=(const History &) = delete;
~History();
[[nodiscard]] auto delegateMixin() const
-> not_null<HistoryMainElementDelegateMixin*> {
return _delegateMixin.get();
}
not_null<History*> migrateToOrMe() const;
History *migrateFrom() const;
MsgRange rangeForDifferenceRequest() const;
@ -585,6 +591,8 @@ private:
void setFolderPointer(Data::Folder *folder);
const std::unique_ptr<HistoryMainElementDelegateMixin> _delegateMixin;
Flags _flags = 0;
bool _mute = false;
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
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 {
public:
@ -170,6 +311,7 @@ HistoryInner::HistoryInner(
, _controller(controller)
, _peer(history->peer)
, _history(history)
, _elementDelegate(_history->delegateMixin()->delegate())
, _emojiInteractions(std::make_unique<HistoryView::EmojiInteractions>(
&controller->session()))
, _migrated(history->migrateFrom())
@ -185,7 +327,10 @@ HistoryInner::HistoryInner(
, _touchScrollTimer([=] { onTouchScrollTimer(); })
, _scrollDateCheck([this] { scrollDateCheck(); })
, _scrollDateHideTimer([this] { scrollDateHideByTimer(); }) {
Instance = this;
_history->delegateMixin()->setCurrent(this);
if (_migrated) {
_migrated->delegateMixin()->setCurrent(this);
}
Window::ChatThemeValueFromPeer(
controller,
@ -1531,16 +1676,24 @@ void HistoryInner::mouseActionFinish(
const auto pressedItemId = pressedItemView
? pressedItemView->data()->fullId()
: FullMsgId();
const auto weak = base::make_weak(_controller.get());
const auto history = pressedItemView->data()->history();
const auto delegate = history->delegateMixin()->delegate();
ActivateClickHandler(window(), activated, {
button,
QVariant::fromValue(ClickHandlerContext{
.itemId = pressedItemId,
.elementDelegate = [weak = Ui::MakeWeak(this)] {
return weak
? HistoryInner::ElementDelegate().get()
: nullptr;
.elementDelegate = [=]() -> HistoryView::ElementDelegate* {
if (const auto strong = weak.get()) {
auto &data = strong->session().data();
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;
@ -2551,7 +2704,13 @@ void HistoryInner::visibleAreaUpdated(int top, int bottom) {
const auto pages = kUnloadHeavyPartsPages;
const auto from = _visibleAreaTop - 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();
_emojiInteractions->visibleAreaUpdated(
@ -2701,8 +2860,9 @@ HistoryInner::~HistoryInner() {
}
}
}
if (Instance == this) {
Instance = nullptr;
_history->delegateMixin()->setCurrent(nullptr);
if (_migrated) {
_migrated->delegateMixin()->setCurrent(nullptr);
}
delete _menu;
_mouseAction = MouseAction::None;
@ -3737,139 +3897,7 @@ void HistoryInner::onParentGeometryChanged() {
}
}
not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
class Result final : public HistoryView::ElementDelegate {
public:
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;
auto HistoryInner::DelegateMixin()
-> std::unique_ptr<HistoryMainElementDelegateMixin> {
return std::make_unique<HistoryMainElementDelegate>();
}

View File

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

View File

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