mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-17 22:57:11 +02:00
Allow HistoryView::ListWidget without SessionController.
This commit is contained in:
parent
e5132e3fe8
commit
ef2aa05197
14 changed files with 312 additions and 125 deletions
|
@ -90,6 +90,95 @@ constexpr auto kClearUserpicsAfter = 50;
|
|||
|
||||
} // namespace
|
||||
|
||||
const crl::time ListWidget::kItemRevealDuration = crl::time(150);
|
||||
|
||||
WindowListDelegate::WindowListDelegate(
|
||||
not_null<Window::SessionController*> window)
|
||||
: _window(window) {
|
||||
}
|
||||
|
||||
not_null<Window::SessionController*> WindowListDelegate::listWindow() {
|
||||
return _window;
|
||||
}
|
||||
|
||||
not_null<const Ui::ChatStyle*> WindowListDelegate::listChatStyle() {
|
||||
return _window->chatStyle();
|
||||
}
|
||||
|
||||
rpl::producer<bool> WindowListDelegate::listChatWideValue() {
|
||||
return _window->adaptive().chatWideValue();
|
||||
}
|
||||
|
||||
auto WindowListDelegate::listMakeReactionsManager(
|
||||
QWidget *wheelEventsTarget,
|
||||
Fn<void(QRect)> update)
|
||||
-> std::unique_ptr<Reactions::Manager> {
|
||||
return std::make_unique<Reactions::Manager>(
|
||||
wheelEventsTarget,
|
||||
std::move(update),
|
||||
_window->cachedReactionIconFactory().createMethod());
|
||||
}
|
||||
|
||||
void WindowListDelegate::listVisibleAreaUpdated() {
|
||||
_window->floatPlayerAreaUpdated();
|
||||
}
|
||||
|
||||
std::shared_ptr<Ui::Show> WindowListDelegate::listUiShow() {
|
||||
return _window->uiShow();
|
||||
}
|
||||
|
||||
void WindowListDelegate::listShowPollResults(
|
||||
not_null<PollData*> poll,
|
||||
FullMsgId context) {
|
||||
_window->showPollResults(poll, context);
|
||||
}
|
||||
|
||||
void WindowListDelegate::listCancelUploadLayer(not_null<HistoryItem*> item) {
|
||||
_window->cancelUploadLayer(item);
|
||||
}
|
||||
|
||||
bool WindowListDelegate::listAnimationsPaused() {
|
||||
return _window->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
||||
}
|
||||
|
||||
auto WindowListDelegate::listSendingAnimation()
|
||||
-> Ui::MessageSendingAnimationController * {
|
||||
return &_window->sendingAnimation();
|
||||
}
|
||||
|
||||
Ui::ChatPaintContext WindowListDelegate::listPreparePaintContext(
|
||||
Ui::ChatPaintContextArgs &&args) {
|
||||
return _window->preparePaintContext(std::move(args));
|
||||
}
|
||||
|
||||
bool WindowListDelegate::listMarkingContentRead() {
|
||||
return _window->widget()->markingAsRead();
|
||||
}
|
||||
|
||||
bool WindowListDelegate::listIgnorePaintEvent(QWidget *w, QPaintEvent *e) {
|
||||
return _window->contentOverlapped(w, e);
|
||||
}
|
||||
|
||||
bool WindowListDelegate::listShowReactPremiumError(
|
||||
not_null<HistoryItem*> item,
|
||||
const Data::ReactionId &id) {
|
||||
return Window::ShowReactPremiumError(_window, item, id);
|
||||
}
|
||||
|
||||
void WindowListDelegate::listWindowSetInnerFocus() {
|
||||
_window->widget()->setInnerFocus();
|
||||
}
|
||||
|
||||
bool WindowListDelegate::listAllowsDragForward() {
|
||||
return _window->adaptive().isOneColumn();
|
||||
}
|
||||
|
||||
void WindowListDelegate::listLaunchDrag(
|
||||
std::unique_ptr<QMimeData> data,
|
||||
Fn<void()> finished) {
|
||||
_window->widget()->launchDrag(std::move(data), std::move(finished));
|
||||
}
|
||||
|
||||
ListWidget::MouseState::MouseState() : pointState(PointState::Outside) {
|
||||
}
|
||||
|
||||
|
@ -104,8 +193,6 @@ ListWidget::MouseState::MouseState(
|
|||
, pointState(pointState) {
|
||||
}
|
||||
|
||||
const crl::time ListWidget::kItemRevealDuration = crl::time(150);
|
||||
|
||||
template <ListWidget::EnumItemsDirection direction, typename Method>
|
||||
void ListWidget::enumerateItems(Method method) {
|
||||
constexpr auto TopToBottom = (direction == EnumItemsDirection::TopToBottom);
|
||||
|
@ -283,31 +370,29 @@ void ListWidget::enumerateDates(Method method) {
|
|||
|
||||
ListWidget::ListWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<ListDelegate*> delegate)
|
||||
: RpWidget(parent)
|
||||
, _delegate(delegate)
|
||||
, _controller(controller)
|
||||
, _session(session)
|
||||
, _emojiInteractions(std::make_unique<EmojiInteractions>(
|
||||
&controller->session(),
|
||||
session,
|
||||
[=](not_null<const Element*> view) { return itemTop(view); }))
|
||||
, _context(_delegate->listContext())
|
||||
, _itemAverageHeight(itemMinimalHeight())
|
||||
, _pathGradient(
|
||||
MakePathShiftGradient(
|
||||
controller->chatStyle(),
|
||||
_delegate->listChatStyle(),
|
||||
[=] { update(); }))
|
||||
, _reactionsManager(
|
||||
std::make_unique<Reactions::Manager>(
|
||||
this,
|
||||
[=](QRect updated) { update(updated); },
|
||||
controller->cachedReactionIconFactory().createMethod()))
|
||||
, _reactionsManager(_delegate->listMakeReactionsManager(
|
||||
this,
|
||||
[=](QRect updated) { update(updated); }))
|
||||
, _translateTracker(MaybeTranslateTracker(_delegate->listTranslateHistory()))
|
||||
, _scrollDateCheck([this] { scrollDateCheck(); })
|
||||
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
|
||||
, _selectEnabled(_delegate->listAllowsMultiSelect())
|
||||
, _highlighter(
|
||||
&session().data(),
|
||||
&_session->data(),
|
||||
[=](const HistoryItem *item) { return viewForItem(item); },
|
||||
[=](const Element *view) { repaintItem(view); })
|
||||
, _touchSelectTimer([=] { onTouchSelect(); })
|
||||
|
@ -315,25 +400,25 @@ ListWidget::ListWidget(
|
|||
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
setMouseTracking(true);
|
||||
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
||||
session().data().viewRepaintRequest(
|
||||
_session->data().viewRepaintRequest(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
if (view->delegate() == this) {
|
||||
repaintItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
session().data().viewResizeRequest(
|
||||
_session->data().viewResizeRequest(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
if (view->delegate() == this) {
|
||||
resizeItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
session().data().itemViewRefreshRequest(
|
||||
_session->data().itemViewRefreshRequest(
|
||||
) | rpl::start_with_next([this](auto item) {
|
||||
if (const auto view = viewForItem(item)) {
|
||||
refreshItem(view);
|
||||
}
|
||||
}, lifetime());
|
||||
session().data().viewLayoutChanged(
|
||||
_session->data().viewLayoutChanged(
|
||||
) | rpl::start_with_next([this](auto view) {
|
||||
if (view->delegate() == this) {
|
||||
if (view->isUnderCursor()) {
|
||||
|
@ -341,37 +426,37 @@ ListWidget::ListWidget(
|
|||
}
|
||||
}
|
||||
}, lifetime());
|
||||
session().data().itemDataChanges(
|
||||
_session->data().itemDataChanges(
|
||||
) | rpl::start_with_next([=](not_null<HistoryItem*> item) {
|
||||
if (const auto view = viewForItem(item)) {
|
||||
view->itemDataChanged();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
session().downloaderTaskFinished(
|
||||
_session->downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
|
||||
session().data().peerDecorationsUpdated(
|
||||
_session->data().peerDecorationsUpdated(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
|
||||
session().data().itemRemoved(
|
||||
_session->data().itemRemoved(
|
||||
) | rpl::start_with_next([=](not_null<const HistoryItem*> item) {
|
||||
itemRemoved(item);
|
||||
}, lifetime());
|
||||
|
||||
using MessageUpdateFlag = Data::MessageUpdate::Flag;
|
||||
session().changes().realtimeMessageUpdates(
|
||||
_session->changes().realtimeMessageUpdates(
|
||||
MessageUpdateFlag::NewUnreadReaction
|
||||
) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
|
||||
maybeMarkReactionsRead(update.item);
|
||||
}, lifetime());
|
||||
|
||||
if (const auto history = _delegate->listTranslateHistory()) {
|
||||
session().changes().historyUpdates(
|
||||
_session->changes().historyUpdates(
|
||||
history,
|
||||
Data::HistoryUpdate::Flag::TranslatedTo
|
||||
) | rpl::start_with_next([=] {
|
||||
|
@ -379,7 +464,7 @@ ListWidget::ListWidget(
|
|||
}, lifetime());
|
||||
}
|
||||
|
||||
session().data().itemVisibilityQueries(
|
||||
_session->data().itemVisibilityQueries(
|
||||
) | rpl::start_with_next([=](
|
||||
const Data::Session::ItemVisibilityQuery &query) {
|
||||
if (const auto view = viewForItem(query.item)) {
|
||||
|
@ -392,25 +477,27 @@ ListWidget::ListWidget(
|
|||
}
|
||||
}, lifetime());
|
||||
|
||||
_reactionsManager->chosen(
|
||||
) | rpl::start_with_next([=](ChosenReaction reaction) {
|
||||
_reactionsManager->updateButton({});
|
||||
reactionChosen(reaction);
|
||||
}, lifetime());
|
||||
|
||||
Reactions::SetupManagerList(
|
||||
_reactionsManager.get(),
|
||||
_reactionsItem.value());
|
||||
|
||||
Core::App().settings().cornerReactionValue(
|
||||
) | rpl::start_with_next([=](bool value) {
|
||||
_useCornerReaction = value;
|
||||
if (!value) {
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->chosen(
|
||||
) | rpl::start_with_next([=](ChosenReaction reaction) {
|
||||
_reactionsManager->updateButton({});
|
||||
}
|
||||
}, lifetime());
|
||||
reactionChosen(reaction);
|
||||
}, lifetime());
|
||||
|
||||
controller->adaptive().chatWideValue(
|
||||
Reactions::SetupManagerList(
|
||||
_reactionsManager.get(),
|
||||
_reactionsItem.value());
|
||||
|
||||
Core::App().settings().cornerReactionValue(
|
||||
) | rpl::start_with_next([=](bool value) {
|
||||
_useCornerReaction = value;
|
||||
if (!value) {
|
||||
_reactionsManager->updateButton({});
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
_delegate->listChatWideValue(
|
||||
) | rpl::start_with_next([=](bool wide) {
|
||||
_isChatWide = wide;
|
||||
}, lifetime());
|
||||
|
@ -427,11 +514,11 @@ ListWidget::ListWidget(
|
|||
}
|
||||
|
||||
Main::Session &ListWidget::session() const {
|
||||
return _controller->session();
|
||||
return *_session;
|
||||
}
|
||||
|
||||
not_null<Window::SessionController*> ListWidget::controller() const {
|
||||
return _controller;
|
||||
return _delegate->listWindow();
|
||||
}
|
||||
|
||||
not_null<ListDelegate*> ListWidget::delegate() const {
|
||||
|
@ -1006,7 +1093,7 @@ void ListWidget::visibleTopBottomUpdated(
|
|||
} else {
|
||||
scrollDateHideByTimer();
|
||||
}
|
||||
_controller->floatPlayerAreaUpdated();
|
||||
_delegate->listVisibleAreaUpdated();
|
||||
session().data().itemVisibilitiesUpdated();
|
||||
_applyUpdatedScrollState.call();
|
||||
|
||||
|
@ -1439,7 +1526,7 @@ bool ListWidget::showCopyRestriction(HistoryItem *item) {
|
|||
if (type == CopyRestrictionType::None) {
|
||||
return false;
|
||||
}
|
||||
_controller->showToast((type == CopyRestrictionType::Channel)
|
||||
_delegate->listUiShow()->showToast((type == CopyRestrictionType::Channel)
|
||||
? tr::lng_error_nocopy_channel(tr::now)
|
||||
: tr::lng_error_nocopy_group(tr::now));
|
||||
return true;
|
||||
|
@ -1450,7 +1537,7 @@ bool ListWidget::showCopyMediaRestriction(not_null<HistoryItem*> item) {
|
|||
if (type == CopyRestrictionType::None) {
|
||||
return false;
|
||||
}
|
||||
_controller->showToast((type == CopyRestrictionType::Channel)
|
||||
_delegate->listUiShow()->showToast((type == CopyRestrictionType::Channel)
|
||||
? tr::lng_error_nocopy_channel(tr::now)
|
||||
: tr::lng_error_nocopy_group(tr::now));
|
||||
return true;
|
||||
|
@ -1676,7 +1763,7 @@ void ListWidget::elementStartStickerLoop(not_null<const Element*> view) {
|
|||
void ListWidget::elementShowPollResults(
|
||||
not_null<PollData*> poll,
|
||||
FullMsgId context) {
|
||||
_controller->showPollResults(poll, context);
|
||||
_delegate->listShowPollResults(poll, context);
|
||||
}
|
||||
|
||||
void ListWidget::elementOpenPhoto(
|
||||
|
@ -1694,7 +1781,7 @@ void ListWidget::elementOpenDocument(
|
|||
|
||||
void ListWidget::elementCancelUpload(const FullMsgId &context) {
|
||||
if (const auto item = session().data().message(context)) {
|
||||
_controller->cancelUploadLayer(item);
|
||||
_delegate->listCancelUploadLayer(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1706,7 +1793,7 @@ void ListWidget::elementShowTooltip(
|
|||
}
|
||||
|
||||
bool ListWidget::elementAnimationsPaused() {
|
||||
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
||||
return _delegate->listAnimationsPaused();
|
||||
}
|
||||
|
||||
bool ListWidget::elementHideReply(not_null<const Element*> view) {
|
||||
|
@ -1838,8 +1925,8 @@ void ListWidget::startItemRevealAnimations() {
|
|||
|
||||
void ListWidget::startMessageSendingAnimation(
|
||||
not_null<HistoryItem*> item) {
|
||||
auto &sendingAnimation = controller()->sendingAnimation();
|
||||
if (!sendingAnimation.checkExpectedType(item)) {
|
||||
const auto sendingAnimation = _delegate->listSendingAnimation();
|
||||
if (!sendingAnimation || !sendingAnimation->checkExpectedType(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1855,7 +1942,7 @@ void ListWidget::startMessageSendingAnimation(
|
|||
return mapToGlobal(QPoint(0, itemTop(view) - additional));
|
||||
});
|
||||
|
||||
sendingAnimation.startAnimation({
|
||||
sendingAnimation->startAnimation({
|
||||
.globalEndTopLeft = std::move(globalEndTopLeft),
|
||||
.view = [=] { return viewForItem(item); },
|
||||
.paintContext = [=] { return preparePaintContext({}); },
|
||||
|
@ -2010,7 +2097,7 @@ TextSelection ListWidget::itemRenderSelection(
|
|||
|
||||
Ui::ChatPaintContext ListWidget::preparePaintContext(
|
||||
const QRect &clip) const {
|
||||
return controller()->preparePaintContext({
|
||||
return _delegate->listPreparePaintContext({
|
||||
.theme = _delegate->listChatTheme(),
|
||||
.clip = clip,
|
||||
.visibleAreaPositionGlobal = mapToGlobal(QPoint(0, _visibleTop)),
|
||||
|
@ -2022,7 +2109,7 @@ Ui::ChatPaintContext ListWidget::preparePaintContext(
|
|||
bool ListWidget::markingContentsRead() const {
|
||||
return _showFinished
|
||||
&& !_refreshingViewer
|
||||
&& controller()->widget()->markingAsRead();
|
||||
&& _delegate->listMarkingContentRead();
|
||||
}
|
||||
|
||||
bool ListWidget::markingMessagesRead() const {
|
||||
|
@ -2053,12 +2140,9 @@ void ListWidget::checkActivation() {
|
|||
}
|
||||
|
||||
void ListWidget::paintEvent(QPaintEvent *e) {
|
||||
if ((_context != Context::ShortcutMessages)
|
||||
&& _controller->contentOverlapped(this, e)) {
|
||||
if (_delegate->listIgnorePaintEvent(this, e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_translateTracker) {
|
||||
} else if (_translateTracker) {
|
||||
_translateTracker->startBunch();
|
||||
}
|
||||
auto readTill = (HistoryItem*)nullptr;
|
||||
|
@ -2100,20 +2184,25 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
_delegate->listPaintEmpty(p, context);
|
||||
return;
|
||||
}
|
||||
_reactionsManager->startEffectsCollection();
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->startEffectsCollection();
|
||||
}
|
||||
|
||||
const auto session = &controller()->session();
|
||||
const auto session = &this->session();
|
||||
auto top = itemTop(from->get());
|
||||
context = context.translated(0, -top);
|
||||
p.translate(0, top);
|
||||
const auto &sendingAnimation = _controller->sendingAnimation();
|
||||
const auto sendingAnimation = _delegate->listSendingAnimation();
|
||||
for (auto i = from; i != to; ++i) {
|
||||
const auto view = *i;
|
||||
const auto item = view->data();
|
||||
const auto height = view->height();
|
||||
if (!sendingAnimation.hasAnimatedMessage(item)) {
|
||||
context.reactionInfo
|
||||
= _reactionsManager->currentReactionPaintInfo();
|
||||
if (!sendingAnimation
|
||||
|| !sendingAnimation->hasAnimatedMessage(item)) {
|
||||
if (_reactionsManager) {
|
||||
context.reactionInfo
|
||||
= _reactionsManager->currentReactionPaintInfo();
|
||||
}
|
||||
context.outbg = view->hasOutLayout();
|
||||
context.selection = itemRenderSelection(view);
|
||||
context.highlight = _highlighter.state(item);
|
||||
|
@ -2125,17 +2214,19 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
const auto isSponsored = item->isSponsored();
|
||||
const auto isUnread = _delegate->listElementShownUnread(view)
|
||||
&& item->isRegular();
|
||||
const auto withReaction = item->hasUnreadReaction();
|
||||
const auto withReaction = context.reactionInfo
|
||||
&& item->hasUnreadReaction();
|
||||
const auto yShown = [&](int y) {
|
||||
return (_visibleBottom >= y && _visibleTop <= y);
|
||||
};
|
||||
const auto markShown = isSponsored
|
||||
? view->markSponsoredViewed(_visibleBottom - top)
|
||||
: withReaction
|
||||
? yShown(top + context.reactionInfo->position.y())
|
||||
: isUnread
|
||||
? yShown(top + height)
|
||||
: yShown(top + height / 2);
|
||||
const auto markShown = (_context != Context::ChatPreview)
|
||||
&& (isSponsored
|
||||
? view->markSponsoredViewed(_visibleBottom - top)
|
||||
: withReaction
|
||||
? yShown(top + context.reactionInfo->position.y())
|
||||
: isUnread
|
||||
? yShown(top + height)
|
||||
: yShown(top + height / 2));
|
||||
if (markShown) {
|
||||
if (isSponsored) {
|
||||
session->sponsoredMessages().view(item->fullId());
|
||||
|
@ -2157,9 +2248,11 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
if (item->hasExtendedMediaPreview()) {
|
||||
session->api().views().pollExtendedMedia(item);
|
||||
}
|
||||
_reactionsManager->recordCurrentReactionEffect(
|
||||
item->fullId(),
|
||||
QPoint(0, top));
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->recordCurrentReactionEffect(
|
||||
item->fullId(),
|
||||
QPoint(0, top));
|
||||
}
|
||||
top += height;
|
||||
context.translate(0, -height);
|
||||
p.translate(0, height);
|
||||
|
@ -2170,7 +2263,9 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
paintUserpics(p, context, clip);
|
||||
paintDates(p, context, clip);
|
||||
|
||||
_reactionsManager->paint(p, context);
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->paint(p, context);
|
||||
}
|
||||
_emojiInteractions->paint(p);
|
||||
}
|
||||
|
||||
|
@ -2181,7 +2276,7 @@ void ListWidget::paintUserpics(
|
|||
if (_context == Context::ShortcutMessages) {
|
||||
return;
|
||||
}
|
||||
const auto session = &controller()->session();
|
||||
const auto session = &this->session();
|
||||
enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
|
||||
// stop the enumeration if the userpic is below the painted rect
|
||||
if (userpicTop >= clip.top() + clip.height()) {
|
||||
|
@ -2530,7 +2625,7 @@ void ListWidget::toggleFavoriteReaction(not_null<Element*> view) const {
|
|||
Data::LookupPossibleReactions(item).recent,
|
||||
favorite,
|
||||
&Data::Reaction::id)
|
||||
|| Window::ShowReactPremiumError(_controller, item, favorite)) {
|
||||
|| _delegate->listShowReactPremiumError(item, favorite)) {
|
||||
return;
|
||||
} else if (!ranges::contains(item->chosenReactions(), favorite)) {
|
||||
if (const auto top = itemTop(view); top >= 0) {
|
||||
|
@ -2599,6 +2694,7 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (link
|
||||
&& !link->property(
|
||||
kSendReactionEmojiProperty).value<Data::ReactionId>().empty()
|
||||
&& _reactionsManager
|
||||
&& _reactionsManager->showContextMenu(
|
||||
this,
|
||||
e,
|
||||
|
@ -2624,13 +2720,13 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
this,
|
||||
overItem,
|
||||
clickedReaction,
|
||||
_controller,
|
||||
controller(),
|
||||
_whoReactedMenuLifetime);
|
||||
e->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
auto request = ContextMenuRequest(_controller);
|
||||
auto request = ContextMenuRequest(controller());
|
||||
|
||||
request.link = link;
|
||||
request.view = _overElement;
|
||||
|
@ -2666,12 +2762,12 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
const auto attached = reactItem
|
||||
? AttachSelectorToMenu(
|
||||
_menu.get(),
|
||||
_controller,
|
||||
controller(),
|
||||
desiredPosition,
|
||||
reactItem,
|
||||
[=](ChosenReaction reaction) { reactionChosen(reaction); },
|
||||
ItemReactionsAbout(reactItem),
|
||||
_controller->cachedReactionIconFactory().createMethod())
|
||||
controller()->cachedReactionIconFactory().createMethod())
|
||||
: AttachSelectorResult::Skipped;
|
||||
if (attached == AttachSelectorResult::Failed) {
|
||||
_menu = nullptr;
|
||||
|
@ -2688,10 +2784,7 @@ void ListWidget::reactionChosen(ChosenReaction reaction) {
|
|||
const auto item = session().data().message(reaction.context);
|
||||
if (!item) {
|
||||
return;
|
||||
} else if (Window::ShowReactPremiumError(
|
||||
_controller,
|
||||
item,
|
||||
reaction.id)) {
|
||||
} else if (_delegate->listShowReactPremiumError(item, reaction.id)) {
|
||||
if (_menu) {
|
||||
_menu->hideMenu();
|
||||
}
|
||||
|
@ -2945,7 +3038,9 @@ void ListWidget::enterEventHook(QEnterEvent *e) {
|
|||
}
|
||||
|
||||
void ListWidget::leaveEventHook(QEvent *e) {
|
||||
_reactionsManager->updateButton({ .cursorLeft = true });
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->updateButton({ .cursorLeft = true });
|
||||
}
|
||||
if (const auto view = _overElement) {
|
||||
if (_overState.pointState != PointState::Outside) {
|
||||
repaintItem(view);
|
||||
|
@ -3160,9 +3255,9 @@ void ListWidget::mouseActionStart(
|
|||
const auto pressElement = _overElement;
|
||||
|
||||
_mouseAction = MouseAction::None;
|
||||
_pressWasInactive = Ui::WasInactivePress(_controller->widget());
|
||||
_pressWasInactive = Ui::WasInactivePress(window());
|
||||
if (_pressWasInactive) {
|
||||
Ui::MarkInactivePress(_controller->widget(), false);
|
||||
Ui::MarkInactivePress(window(), false);
|
||||
}
|
||||
|
||||
if (ClickHandler::getPressed()) {
|
||||
|
@ -3334,7 +3429,7 @@ void ListWidget::mouseActionFinish(
|
|||
} else if (_selectedTextItem && !_pressWasInactive) {
|
||||
if (_selectedTextRange.from == _selectedTextRange.to) {
|
||||
clearTextSelection();
|
||||
_controller->widget()->setInnerFocus();
|
||||
_delegate->listWindowSetInnerFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3362,7 +3457,7 @@ ClickHandlerContext ListWidget::prepareClickHandlerContext(FullMsgId id) {
|
|||
? (ElementDelegate*)weak
|
||||
: nullptr;
|
||||
},
|
||||
.sessionWindow = base::make_weak(_controller),
|
||||
.sessionWindow = base::make_weak(controller()),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3372,7 +3467,9 @@ void ListWidget::mouseActionUpdate() {
|
|||
std::clamp(mousePosition.x(), 0, width()),
|
||||
std::clamp(mousePosition.y(), _visibleTop, _visibleBottom));
|
||||
|
||||
const auto reactionState = _reactionsManager->buttonTextState(point);
|
||||
const auto reactionState = _reactionsManager
|
||||
? _reactionsManager->buttonTextState(point)
|
||||
: TextState();
|
||||
const auto reactionItem = session().data().message(reactionState.itemId);
|
||||
const auto reactionView = viewForItem(reactionItem);
|
||||
const auto view = reactionView
|
||||
|
@ -3392,12 +3489,14 @@ void ListWidget::mouseActionUpdate() {
|
|||
_overElement = view;
|
||||
repaintItem(_overElement);
|
||||
}
|
||||
_reactionsManager->updateButton(view
|
||||
? reactionButtonParameters(
|
||||
view,
|
||||
itemPoint,
|
||||
reactionState)
|
||||
: Reactions::ButtonParameters());
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->updateButton(view
|
||||
? reactionButtonParameters(
|
||||
view,
|
||||
itemPoint,
|
||||
reactionState)
|
||||
: Reactions::ButtonParameters());
|
||||
}
|
||||
if (viewChanged && view) {
|
||||
_reactionsItem = item;
|
||||
}
|
||||
|
@ -3624,7 +3723,7 @@ std::unique_ptr<QMimeData> ListWidget::prepareDrag() {
|
|||
if (!urls.isEmpty()) {
|
||||
mimeData->setUrls(urls);
|
||||
}
|
||||
if (uponSelected && !_controller->adaptive().isOneColumn()) {
|
||||
if (uponSelected && !_delegate->listAllowsDragForward()) {
|
||||
const auto canForwardAll = [&] {
|
||||
for (const auto &[itemId, data] : _selected) {
|
||||
if (!data.canForward) {
|
||||
|
@ -3689,8 +3788,10 @@ std::unique_ptr<QMimeData> ListWidget::prepareDrag() {
|
|||
void ListWidget::performDrag() {
|
||||
if (auto mimeData = prepareDrag()) {
|
||||
// This call enters event loop and can destroy any QObject.
|
||||
_reactionsManager->updateButton({});
|
||||
_controller->widget()->launchDrag(
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->updateButton({});
|
||||
}
|
||||
_delegate->listLaunchDrag(
|
||||
std::move(mimeData),
|
||||
crl::guard(this, [=] { mouseActionUpdate(QCursor::pos()); }));
|
||||
}
|
||||
|
@ -3708,7 +3809,10 @@ void ListWidget::repaintItem(const Element *view) {
|
|||
const auto range = view->verticalRepaintRange();
|
||||
update(0, top + range.top, width(), range.height);
|
||||
const auto id = view->data()->fullId();
|
||||
if (const auto area = _reactionsManager->lookupEffectArea(id)) {
|
||||
const auto area = _reactionsManager
|
||||
? _reactionsManager->lookupEffectArea(id)
|
||||
: std::nullopt;
|
||||
if (area) {
|
||||
update(*area);
|
||||
}
|
||||
}
|
||||
|
@ -3866,7 +3970,9 @@ void ListWidget::itemRemoved(not_null<const HistoryItem*> item) {
|
|||
viewReplaced(view, nullptr);
|
||||
_views.erase(i);
|
||||
|
||||
_reactionsManager->remove(item->fullId());
|
||||
if (_reactionsManager) {
|
||||
_reactionsManager->remove(item->fullId());
|
||||
}
|
||||
updateItemsGeometry();
|
||||
}
|
||||
|
||||
|
@ -3992,7 +4098,7 @@ void ConfirmDeleteSelectedItems(not_null<ListWidget*> widget) {
|
|||
}
|
||||
}
|
||||
auto box = Box<DeleteMessagesBox>(
|
||||
&widget->controller()->session(),
|
||||
&widget->session(),
|
||||
widget->getSelectedIds());
|
||||
box->setDeleteConfirmedCallback(crl::guard(widget, [=] {
|
||||
widget->cancelSelection();
|
||||
|
|
|
@ -25,11 +25,14 @@ class Session;
|
|||
} // namespace Main
|
||||
|
||||
namespace Ui {
|
||||
class Show;
|
||||
class PopupMenu;
|
||||
class ChatTheme;
|
||||
struct ChatPaintContext;
|
||||
struct ChatPaintContextArgs;
|
||||
enum class TouchScrollState;
|
||||
struct PeerUserpicView;
|
||||
class MessageSendingAnimationController;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
@ -40,6 +43,7 @@ namespace Data {
|
|||
struct Group;
|
||||
struct Reaction;
|
||||
struct AllowedReactions;
|
||||
struct ReactionId;
|
||||
} // namespace Data
|
||||
|
||||
namespace HistoryView::Reactions {
|
||||
|
@ -154,6 +158,71 @@ public:
|
|||
virtual History *listTranslateHistory() = 0;
|
||||
virtual void listAddTranslatedItems(
|
||||
not_null<TranslateTracker*> tracker) = 0;
|
||||
|
||||
// Methods that use Window::SessionController by default.
|
||||
virtual not_null<Window::SessionController*> listWindow() = 0;
|
||||
virtual not_null<const Ui::ChatStyle*> listChatStyle() = 0;
|
||||
virtual rpl::producer<bool> listChatWideValue() = 0;
|
||||
virtual std::unique_ptr<Reactions::Manager> listMakeReactionsManager(
|
||||
QWidget *wheelEventsTarget,
|
||||
Fn<void(QRect)> update) = 0;
|
||||
virtual void listVisibleAreaUpdated() = 0;
|
||||
virtual std::shared_ptr<Ui::Show> listUiShow() = 0;
|
||||
virtual void listShowPollResults(
|
||||
not_null<PollData*> poll,
|
||||
FullMsgId context) = 0;
|
||||
virtual void listCancelUploadLayer(not_null<HistoryItem*> item) = 0;
|
||||
virtual bool listAnimationsPaused() = 0;
|
||||
virtual auto listSendingAnimation()
|
||||
-> Ui::MessageSendingAnimationController* = 0;
|
||||
virtual Ui::ChatPaintContext listPreparePaintContext(
|
||||
Ui::ChatPaintContextArgs &&args) = 0;
|
||||
virtual bool listMarkingContentRead() = 0;
|
||||
virtual bool listIgnorePaintEvent(QWidget *w, QPaintEvent *e) = 0;
|
||||
virtual bool listShowReactPremiumError(
|
||||
not_null<HistoryItem*> item,
|
||||
const Data::ReactionId &id) = 0;
|
||||
virtual void listWindowSetInnerFocus() = 0;
|
||||
virtual bool listAllowsDragForward() = 0;
|
||||
virtual void listLaunchDrag(
|
||||
std::unique_ptr<QMimeData> data,
|
||||
Fn<void()> finished) = 0;
|
||||
};
|
||||
|
||||
class WindowListDelegate : public ListDelegate {
|
||||
public:
|
||||
explicit WindowListDelegate(not_null<Window::SessionController*> window);
|
||||
|
||||
not_null<Window::SessionController*> listWindow() override;
|
||||
not_null<const Ui::ChatStyle*> listChatStyle() override;
|
||||
rpl::producer<bool> listChatWideValue() override;
|
||||
std::unique_ptr<Reactions::Manager> listMakeReactionsManager(
|
||||
QWidget *wheelEventsTarget,
|
||||
Fn<void(QRect)> update) override;
|
||||
void listVisibleAreaUpdated() override;
|
||||
std::shared_ptr<Ui::Show> listUiShow() override;
|
||||
void listShowPollResults(
|
||||
not_null<PollData*> poll,
|
||||
FullMsgId context) override;
|
||||
void listCancelUploadLayer(not_null<HistoryItem*> item) override;
|
||||
bool listAnimationsPaused() override;
|
||||
Ui::MessageSendingAnimationController *listSendingAnimation() override;
|
||||
Ui::ChatPaintContext listPreparePaintContext(
|
||||
Ui::ChatPaintContextArgs &&args) override;
|
||||
bool listMarkingContentRead() override;
|
||||
bool listIgnorePaintEvent(QWidget *w, QPaintEvent *e) override;
|
||||
bool listShowReactPremiumError(
|
||||
not_null<HistoryItem*> item,
|
||||
const Data::ReactionId &id) override;
|
||||
void listWindowSetInnerFocus() override;
|
||||
bool listAllowsDragForward() override;
|
||||
void listLaunchDrag(
|
||||
std::unique_ptr<QMimeData> data,
|
||||
Fn<void()> finished) override;
|
||||
|
||||
private:
|
||||
const not_null<Window::SessionController*> _window;
|
||||
|
||||
};
|
||||
|
||||
struct SelectionData {
|
||||
|
@ -211,7 +280,7 @@ class ListWidget final
|
|||
public:
|
||||
ListWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<ListDelegate*> delegate);
|
||||
|
||||
static const crl::time kItemRevealDuration;
|
||||
|
@ -648,7 +717,7 @@ private:
|
|||
static constexpr auto kMinimalIdsLimit = 24;
|
||||
|
||||
const not_null<ListDelegate*> _delegate;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<Main::Session*> _session;
|
||||
const std::unique_ptr<EmojiInteractions> _emojiInteractions;
|
||||
const Context _context;
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ PinnedWidget::PinnedWidget(
|
|||
not_null<Window::SessionController*> controller,
|
||||
not_null<Data::Thread*> thread)
|
||||
: Window::SectionWidget(parent, controller, thread->peer())
|
||||
, WindowListDelegate(controller)
|
||||
, _thread(thread->migrateToOrMe())
|
||||
, _history(thread->owningHistory())
|
||||
, _migratedPeer(thread->asHistory()
|
||||
|
@ -161,7 +162,7 @@ PinnedWidget::PinnedWidget(
|
|||
|
||||
_inner = _scroll->setOwnedWidget(object_ptr<ListWidget>(
|
||||
this,
|
||||
controller,
|
||||
&controller->session(),
|
||||
static_cast<ListDelegate*>(this)));
|
||||
_scroll->move(0, _topBar->height());
|
||||
_scroll->show();
|
||||
|
|
|
@ -36,7 +36,7 @@ class TranslateBar;
|
|||
|
||||
class PinnedWidget final
|
||||
: public Window::SectionWidget
|
||||
, private ListDelegate
|
||||
, private WindowListDelegate
|
||||
, private CornerButtonsDelegate {
|
||||
public:
|
||||
PinnedWidget(
|
||||
|
|
|
@ -205,6 +205,7 @@ RepliesWidget::RepliesWidget(
|
|||
not_null<History*> history,
|
||||
MsgId rootId)
|
||||
: Window::SectionWidget(parent, controller, history->peer)
|
||||
, WindowListDelegate(controller)
|
||||
, _history(history)
|
||||
, _rootId(rootId)
|
||||
, _root(lookupRoot())
|
||||
|
@ -299,7 +300,7 @@ RepliesWidget::RepliesWidget(
|
|||
|
||||
_inner = _scroll->setOwnedWidget(object_ptr<ListWidget>(
|
||||
this,
|
||||
controller,
|
||||
&controller->session(),
|
||||
static_cast<ListDelegate*>(this)));
|
||||
_scroll->move(0, _topBar->height());
|
||||
_scroll->show();
|
||||
|
|
|
@ -71,7 +71,7 @@ class TranslateBar;
|
|||
|
||||
class RepliesWidget final
|
||||
: public Window::SectionWidget
|
||||
, private ListDelegate
|
||||
, private WindowListDelegate
|
||||
, private CornerButtonsDelegate {
|
||||
public:
|
||||
RepliesWidget(
|
||||
|
|
|
@ -97,6 +97,7 @@ ScheduledWidget::ScheduledWidget(
|
|||
not_null<History*> history,
|
||||
const Data::ForumTopic *forumTopic)
|
||||
: Window::SectionWidget(parent, controller, history->peer)
|
||||
, WindowListDelegate(controller)
|
||||
, _history(history)
|
||||
, _forumTopic(forumTopic)
|
||||
, _scroll(
|
||||
|
@ -167,7 +168,7 @@ ScheduledWidget::ScheduledWidget(
|
|||
|
||||
_inner = _scroll->setOwnedWidget(object_ptr<ListWidget>(
|
||||
this,
|
||||
controller,
|
||||
&controller->session(),
|
||||
static_cast<ListDelegate*>(this)));
|
||||
_scroll->move(0, _topBar->height());
|
||||
_scroll->show();
|
||||
|
|
|
@ -52,7 +52,7 @@ class StickerToast;
|
|||
|
||||
class ScheduledWidget final
|
||||
: public Window::SectionWidget
|
||||
, private ListDelegate
|
||||
, private WindowListDelegate
|
||||
, private CornerButtonsDelegate {
|
||||
public:
|
||||
ScheduledWidget(
|
||||
|
|
|
@ -67,6 +67,7 @@ SublistWidget::SublistWidget(
|
|||
not_null<Window::SessionController*> controller,
|
||||
not_null<Data::SavedSublist*> sublist)
|
||||
: Window::SectionWidget(parent, controller, sublist->peer())
|
||||
, WindowListDelegate(controller)
|
||||
, _sublist(sublist)
|
||||
, _history(sublist->owner().history(sublist->session().user()))
|
||||
, _topBar(this, controller)
|
||||
|
@ -133,7 +134,7 @@ SublistWidget::SublistWidget(
|
|||
|
||||
_inner = _scroll->setOwnedWidget(object_ptr<ListWidget>(
|
||||
this,
|
||||
controller,
|
||||
&controller->session(),
|
||||
static_cast<ListDelegate*>(this)));
|
||||
_scroll->move(0, _topBar->height());
|
||||
_scroll->show();
|
||||
|
|
|
@ -37,7 +37,7 @@ class ComposeSearch;
|
|||
|
||||
class SublistWidget final
|
||||
: public Window::SectionWidget
|
||||
, private ListDelegate
|
||||
, private WindowListDelegate
|
||||
, private CornerButtonsDelegate {
|
||||
public:
|
||||
SublistWidget(
|
||||
|
|
|
@ -72,7 +72,7 @@ using namespace HistoryView;
|
|||
|
||||
class ShortcutMessages
|
||||
: public AbstractSection
|
||||
, private ListDelegate
|
||||
, private WindowListDelegate
|
||||
, private CornerButtonsDelegate {
|
||||
public:
|
||||
ShortcutMessages(
|
||||
|
@ -164,6 +164,7 @@ private:
|
|||
History *listTranslateHistory() override;
|
||||
void listAddTranslatedItems(
|
||||
not_null<TranslateTracker*> tracker) override;
|
||||
bool listIgnorePaintEvent(QWidget *w, QPaintEvent *e) override;
|
||||
|
||||
// CornerButtonsDelegate delegate.
|
||||
void cornerButtonsShowAtPosition(
|
||||
|
@ -330,6 +331,7 @@ ShortcutMessages::ShortcutMessages(
|
|||
rpl::producer<Container> containerValue,
|
||||
BusinessShortcutId shortcutId)
|
||||
: AbstractSection(parent)
|
||||
, WindowListDelegate(controller)
|
||||
, _controller(controller)
|
||||
, _session(&controller->session())
|
||||
, _scroll(scroll)
|
||||
|
@ -370,7 +372,7 @@ ShortcutMessages::ShortcutMessages(
|
|||
|
||||
_inner = Ui::CreateChild<ListWidget>(
|
||||
this,
|
||||
controller,
|
||||
&controller->session(),
|
||||
static_cast<ListDelegate*>(this));
|
||||
_inner->overrideIsChatWide(false);
|
||||
|
||||
|
@ -1053,6 +1055,10 @@ void ShortcutMessages::listAddTranslatedItems(
|
|||
not_null<TranslateTracker*> tracker) {
|
||||
}
|
||||
|
||||
bool ShortcutMessages::listIgnorePaintEvent(QWidget *w, QPaintEvent *e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShortcutMessages::cornerButtonsShowAtPosition(
|
||||
Data::MessagePosition position) {
|
||||
showAtPosition(position);
|
||||
|
|
|
@ -223,6 +223,14 @@ struct ChatPaintContext {
|
|||
|
||||
};
|
||||
|
||||
struct ChatPaintContextArgs {
|
||||
not_null<ChatTheme*> theme;
|
||||
QRect clip;
|
||||
QPoint visibleAreaPositionGlobal;
|
||||
int visibleAreaTop = 0;
|
||||
int visibleAreaWidth = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] int HistoryServiceMsgRadius();
|
||||
[[nodiscard]] int HistoryServiceMsgInvertedRadius();
|
||||
[[nodiscard]] int HistoryServiceMsgInvertedShrink();
|
||||
|
|
|
@ -2951,7 +2951,7 @@ void SessionController::openPeerStories(
|
|||
}
|
||||
|
||||
HistoryView::PaintContext SessionController::preparePaintContext(
|
||||
PaintContextArgs &&args) {
|
||||
Ui::ChatPaintContextArgs &&args) {
|
||||
const auto visibleAreaTopLocal = content()->mapFromGlobal(
|
||||
args.visibleAreaPositionGlobal).y();
|
||||
const auto viewport = QRect(
|
||||
|
|
|
@ -64,6 +64,7 @@ struct ChatThemeBackground;
|
|||
struct ChatThemeBackgroundData;
|
||||
class MessageSendingAnimationController;
|
||||
struct BoostCounters;
|
||||
struct ChatPaintContextArgs;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Data {
|
||||
|
@ -586,15 +587,8 @@ public:
|
|||
PeerId peerId,
|
||||
std::optional<Data::StorySourcesList> list = std::nullopt);
|
||||
|
||||
struct PaintContextArgs {
|
||||
not_null<Ui::ChatTheme*> theme;
|
||||
QRect clip;
|
||||
QPoint visibleAreaPositionGlobal;
|
||||
int visibleAreaTop = 0;
|
||||
int visibleAreaWidth = 0;
|
||||
};
|
||||
[[nodiscard]] Ui::ChatPaintContext preparePaintContext(
|
||||
PaintContextArgs &&args);
|
||||
Ui::ChatPaintContextArgs &&args);
|
||||
[[nodiscard]] not_null<const Ui::ChatStyle*> chatStyle() const {
|
||||
return _chatStyle.get();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue