mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 22:27:20 +02:00
Attach main views to correct HistoryInner-s.
This commit is contained in:
parent
18e6e2da9e
commit
cb8f86bc8d
5 changed files with 221 additions and 163 deletions
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue