Support unread mentions / reactions in topics.

This commit is contained in:
John Preston 2022-10-10 16:46:13 +04:00
parent 6a7f030ee7
commit 3999bca823
15 changed files with 229 additions and 175 deletions

View file

@ -128,12 +128,12 @@ void UnreadThings::requestMentions(
MTP_int(maxId),
MTP_int(minId)
)).done([=](const MTPmessages_Messages &result) {
_mentionsRequests.remove(history);
history->unreadMentions().addSlice(result, loaded);
_mentionsRequests.remove(entry);
entry->unreadMentions().addSlice(result, loaded);
}).fail([=] {
_mentionsRequests.remove(history);
_mentionsRequests.remove(entry);
}).send();
_mentionsRequests.emplace(history, requestId);
_mentionsRequests.emplace(entry, requestId);
}
void UnreadThings::requestReactions(
@ -162,12 +162,12 @@ void UnreadThings::requestReactions(
MTP_int(maxId),
MTP_int(minId)
)).done([=](const MTPmessages_Messages &result) {
_reactionsRequests.remove(history);
history->unreadReactions().addSlice(result, loaded);
_reactionsRequests.remove(entry);
entry->unreadReactions().addSlice(result, loaded);
}).fail([=] {
_reactionsRequests.remove(history);
_reactionsRequests.remove(entry);
}).send();
_reactionsRequests.emplace(history, requestId);
_reactionsRequests.emplace(entry, requestId);
}
} // namespace UnreadThings

View file

@ -271,6 +271,7 @@ void Changes::sendNotifications() {
_historyChanges.sendNotifications();
_messageChanges.sendNotifications();
_entryChanges.sendNotifications();
_topicChanges.sendNotifications();
}
} // namespace Data

View file

@ -914,7 +914,6 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
width(),
std::min(st::msgMaxWidth / 2, width() / 2));
const auto now = crl::now();
const auto historyDisplayedEmpty = _history->isDisplayedEmpty()
&& (!_migrated || _migrated->isDisplayedEmpty());
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
@ -1015,7 +1014,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
_widget->enqueueMessageHighlight(view);
}
}
session().data().reactions().poll(item, now);
session().data().reactions().poll(item, context.now);
if (item->hasExtendedMediaPreview()) {
session().api().views().pollExtendedMedia(item);
}

View file

@ -5769,7 +5769,7 @@ bool HistoryWidget::cornerButtonsIgnoreVisibility() {
return _a_show.animating();
}
bool HistoryWidget::cornerButtonsDownShown() {
std::optional<bool> HistoryWidget::cornerButtonsDownShown() {
if (!_list || _firstLoadRequest) {
return false;
}

View file

@ -328,7 +328,7 @@ private:
Dialogs::Entry *cornerButtonsEntry() override;
FullMsgId cornerButtonsCurrentId() override;
bool cornerButtonsIgnoreVisibility() override;
bool cornerButtonsDownShown() override;
std::optional<bool> cornerButtonsDownShown() override;
bool cornerButtonsUnreadMayBeShown() override;
void checkSuggestToGigagroup();

View file

@ -251,8 +251,9 @@ void CornerButtons::updateUnreadThingsVisibility() {
}
void CornerButtons::updateJumpDownVisibility(std::optional<int> counter) {
const auto shown = _delegate->cornerButtonsDownShown();
updateVisibility(CornerButtonType::Down, shown);
if (const auto shown = _delegate->cornerButtonsDownShown()) {
updateVisibility(CornerButtonType::Down, *shown);
}
if (counter) {
down.widget->setUnreadCount(*counter);
}

View file

@ -53,7 +53,7 @@ public:
[[nodiscard]] virtual Dialogs::Entry *cornerButtonsEntry() = 0;
[[nodiscard]] virtual FullMsgId cornerButtonsCurrentId() = 0;
[[nodiscard]] virtual bool cornerButtonsIgnoreVisibility() = 0;
[[nodiscard]] virtual bool cornerButtonsDownShown() = 0;
[[nodiscard]] virtual std::optional<bool> cornerButtonsDownShown() = 0;
[[nodiscard]] virtual bool cornerButtonsUnreadMayBeShown() = 0;
};

View file

@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/core_settings.h"
#include "apiwrap.h"
#include "api/api_who_reacted.h"
#include "api/api_views.h"
#include "layout/layout_selection.h"
#include "window/section_widget.h"
#include "window/window_adaptive.h"
@ -54,6 +55,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/premium_preview_box.h"
#include "boxes/peers/edit_participant_box.h"
#include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "data/data_changes.h"
#include "data/data_folder.h"
#include "data/data_media_types.h"
#include "data/data_document.h"
@ -350,6 +353,13 @@ ListWidget::ListWidget(
itemRemoved(item);
}, lifetime());
using MessageUpdateFlag = Data::MessageUpdate::Flag;
session().changes().realtimeMessageUpdates(
MessageUpdateFlag::NewUnreadReaction
) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
maybeMarkReactionsRead(update.item);
}, lifetime());
session().data().itemVisibilityQueries(
) | rpl::start_with_next([=](
const Data::Session::ItemVisibilityQuery &query) {
@ -787,7 +797,6 @@ void ListWidget::visibleTopBottomUpdated(
void ListWidget::applyUpdatedScrollState() {
checkMoveToOtherViewer();
_delegate->listVisibleItemsChanged(collectVisibleItems());
}
void ListWidget::updateVisibleTopItem() {
@ -1764,7 +1773,15 @@ void ListWidget::paintEvent(QPaintEvent *e) {
return;
}
auto readTill = (HistoryItem*)nullptr;
auto readContents = base::flat_set<not_null<HistoryItem*>>();
const auto guard = gsl::finally([&] {
if (readTill) {
_delegate->listMarkReadTill(readTill);
}
if (!readContents.empty()) {
_delegate->listMarkContentsRead(readContents);
}
_userpicsCache.clear();
});
@ -1787,23 +1804,61 @@ void ListWidget::paintEvent(QPaintEvent *e) {
if (from != end(_items)) {
_reactionsManager->startEffectsCollection();
const auto session = &controller()->session();
auto top = itemTop(from->get());
auto context = preparePaintContext(clip).translated(0, -top);
p.translate(0, top);
const auto &sendingAnimation = _controller->sendingAnimation();
for (auto i = from; i != to; ++i) {
const auto view = *i;
if (!sendingAnimation.hasAnimatedMessage(view->data())) {
const auto item = view->data();
const auto height = view->height();
if (!sendingAnimation.hasAnimatedMessage(item)) {
context.reactionInfo
= _reactionsManager->currentReactionPaintInfo();
context.outbg = view->hasOutLayout();
context.selection = itemRenderSelection(view);
view->draw(p, context);
}
const auto isSponsored = item->isSponsored();
const auto isUnread = _delegate->listElementShownUnread(view)
&& item->isRegular();
const auto withReaction = 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);
if (markShown) {
if (isSponsored) {
session->data().sponsoredMessages().view(
item->fullId());
} else if (isUnread) {
readTill = item;
}
if (item->hasViews()) {
session->api().views().scheduleIncrement(item);
}
if (withReaction) {
readContents.insert(item);
} else if (item->isUnreadMention()
&& !item->isUnreadMedia()) {
readContents.insert(item);
_highlighter.enqueue(view);
}
}
session->data().reactions().poll(item, context.now);
if (item->hasExtendedMediaPreview()) {
session->api().views().pollExtendedMedia(item);
}
_reactionsManager->recordCurrentReactionEffect(
view->data()->fullId(),
item->fullId(),
QPoint(0, top));
const auto height = view->height();
top += height;
context.translate(0, -height);
p.translate(0, height);
@ -1847,7 +1902,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
auto &v = _sponsoredUserpics[itemId.msg];
if (!info->customUserpic.isCurrentView(v)) {
v = info->customUserpic.createView();
info->customUserpic.load(&session(), itemId);
info->customUserpic.load(session, itemId);
}
}
}
@ -1909,6 +1964,21 @@ void ListWidget::paintEvent(QPaintEvent *e) {
}
}
void ListWidget::maybeMarkReactionsRead(not_null<HistoryItem*> item) {
const auto view = viewForItem(item);
if (!view) {
return;
}
const auto top = itemTop(view);
const auto reactionCenter
= view->reactionButtonParameters({}, {}).center.y();
if (top + reactionCenter < _visibleTop
|| top + view->height() > _visibleBottom) {
return;
}
_delegate->listMarkContentsRead({ item });
}
bool ListWidget::eventHook(QEvent *e) {
if (e->type() == QEvent::TouchBegin
|| e->type() == QEvent::TouchUpdate

View file

@ -100,7 +100,9 @@ public:
not_null<HistoryItem*> first,
not_null<HistoryItem*> second) = 0;
virtual void listSelectionChanged(SelectedItems &&items) = 0;
virtual void listVisibleItemsChanged(HistoryItemsList &&items) = 0;
virtual void listMarkReadTill(not_null<HistoryItem*> item) = 0;
virtual void listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) = 0;
virtual MessagesBarData listMessagesBar(
const std::vector<not_null<Element*>> &elements) = 0;
virtual void listContentRefreshed() = 0;
@ -529,6 +531,7 @@ private:
void scrollToAnimationCallback(FullMsgId attachToId, int relativeTo);
void startItemRevealAnimations();
void revealItemsCallback();
void maybeMarkReactionsRead(not_null<HistoryItem*> item);
void startMessageSendingAnimation(not_null<HistoryItem*> item);
void showPremiumStickerTooltip(

View file

@ -636,7 +636,11 @@ void PinnedWidget::listSelectionChanged(SelectedItems &&items) {
_topBar->showSelected(state);
}
void PinnedWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
void PinnedWidget::listMarkReadTill(not_null<HistoryItem*> item) {
}
void PinnedWidget::listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) {
}
MessagesBarData PinnedWidget::listMessagesBar(

View file

@ -90,7 +90,9 @@ public:
not_null<HistoryItem*> first,
not_null<HistoryItem*> second) override;
void listSelectionChanged(SelectedItems &&items) override;
void listVisibleItemsChanged(HistoryItemsList &&items) override;
void listMarkReadTill(not_null<HistoryItem*> item) override;
void listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) override;
MessagesBarData listMessagesBar(
const std::vector<not_null<Element*>> &elements) override;
void listContentRefreshed() override;

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_schedule_box.h"
#include "history/view/history_view_pinned_bar.h"
#include "history/view/history_view_sticker_toast.h"
#include "history/view/history_view_cursor_state.h"
#include "history/history.h"
#include "history/history_drag_area.h"
#include "history/history_item_components.h"
@ -212,9 +213,10 @@ RepliesWidget::RepliesWidget(
this,
controller->chatStyle()->value(lifetime(), st::historyScroll),
false))
, _scrollDown(
, _cornerButtons(
_scroll.get(),
controller->chatStyle()->value(lifetime(), st::historyToDown))
controller->chatStyle(),
static_cast<HistoryView::CornerButtonsDelegate*>(this))
, _readRequestTimer([=] { sendReadTillRequest(); }) {
controller->chatStyle()->paletteChanged(
) | rpl::start_with_next([=] {
@ -335,8 +337,8 @@ RepliesWidget::RepliesWidget(
controller->showBackFromStack();
}
}
while (update.item == _replyReturn) {
calculateNextReplyReturn();
while (update.item == _cornerButtons.replyReturn()) {
_cornerButtons.calculateNextReplyReturn();
}
}, lifetime());
@ -347,7 +349,6 @@ RepliesWidget::RepliesWidget(
_inner->update();
}, lifetime());
setupScrollDownButton();
setupComposeControls();
orderWidgets();
}
@ -469,14 +470,34 @@ void RepliesWidget::setupTopicViewer() {
_inner->update();
}
}, lifetime());
if (_topic) {
subscribeToTopic();
}
}
void RepliesWidget::subscribeToTopic() {
using TopicUpdateFlag = Data::TopicUpdate::Flag;
session().changes().topicUpdates(
_topic,
(TopicUpdateFlag::UnreadMentions
| TopicUpdateFlag::UnreadReactions)
) | rpl::start_with_next([=](const Data::TopicUpdate &update) {
_cornerButtons.updateUnreadThingsVisibility();
}, _topicLifetime);
}
void RepliesWidget::setTopic(Data::ForumTopic *topic) {
if (_topic != topic) {
_topic = topic;
refreshReplies();
refreshTopBarActiveChat();
if (_topic && _rootView) {
if (_topic == topic) {
return;
}
_topicLifetime.destroy();
_topic = topic;
refreshReplies();
refreshTopBarActiveChat();
if (_topic) {
subscribeToTopic();
if (_rootView) {
_rootView = nullptr;
_rootViewHeight = 0;
updateControlsGeometry();
@ -684,7 +705,8 @@ void RepliesWidget::setupComposeControls() {
_composeControls->lockShowStarts(
) | rpl::start_with_next([=] {
updateScrollDownVisibility();
_cornerButtons.updateJumpDownVisibility();
_cornerButtons.updateUnreadThingsVisibility();
}, lifetime());
_composeControls->viewportEvents(
@ -919,48 +941,21 @@ std::optional<QString> RepliesWidget::writeRestriction() const {
void RepliesWidget::pushReplyReturn(not_null<HistoryItem*> item) {
if (item->history() == _history && item->inThread(_rootId)) {
_replyReturns.push_back(item->id);
} else {
return;
}
_replyReturn = item;
updateScrollDownVisibility();
}
void RepliesWidget::restoreReplyReturns(const std::vector<MsgId> &list) {
_replyReturns = list;
computeCurrentReplyReturn();
if (!_replyReturn) {
calculateNextReplyReturn();
}
}
void RepliesWidget::computeCurrentReplyReturn() {
_replyReturn = _replyReturns.empty()
? nullptr
: _history->owner().message(_history->peer, _replyReturns.back());
}
void RepliesWidget::calculateNextReplyReturn() {
_replyReturn = nullptr;
while (!_replyReturns.empty() && !_replyReturn) {
_replyReturns.pop_back();
computeCurrentReplyReturn();
}
if (!_replyReturn) {
updateScrollDownVisibility();
_cornerButtons.pushReplyReturn(item);
}
}
void RepliesWidget::checkReplyReturns() {
const auto currentTop = _scroll->scrollTop();
for (; _replyReturn != nullptr; calculateNextReplyReturn()) {
const auto position = _replyReturn->position();
while (const auto replyReturn = _cornerButtons.replyReturn()) {
const auto position = replyReturn->position();
const auto scrollTop = _inner->scrollTopForPosition(position);
const auto scrolledBelow = scrollTop
const auto below = scrollTop
? (currentTop >= std::min(*scrollTop, _scroll->scrollTopMax()))
: _inner->isBelowPosition(position);
if (!scrolledBelow) {
if (below) {
_cornerButtons.calculateNextReplyReturn();
} else {
break;
}
}
@ -1057,6 +1052,10 @@ void RepliesWidget::send(Api::SendOptions options) {
return;
}
if (!options.scheduled) {
_cornerButtons.clearReplyReturns();
}
const auto webPageId = _composeControls->webPageId();
auto message = ApiWrap::MessageToSend(prepareSendAction(options));
@ -1355,24 +1354,9 @@ MsgId RepliesWidget::replyToId() const {
: _rootId;
}
void RepliesWidget::setupScrollDownButton() {
_scrollDown->setClickedCallback([=] {
scrollDownClicked();
});
base::install_event_filter(_scrollDown, [=](not_null<QEvent*> event) {
if (event->type() != QEvent::Wheel) {
return base::EventFilterResult::Continue;
}
return _scroll->viewportEvent(event)
? base::EventFilterResult::Cancel
: base::EventFilterResult::Continue;
});
updateScrollDownVisibility();
}
void RepliesWidget::refreshUnreadCountBadge(std::optional<int> count) {
if (count.has_value()) {
_scrollDown->setUnreadCount(*count);
_cornerButtons.updateJumpDownVisibility(count);
} else if (!_readRequestTimer.isActive() && !_readRequestId) {
reloadUnreadCountIfNeeded();
}
@ -1389,14 +1373,39 @@ void RepliesWidget::reloadUnreadCountIfNeeded() {
}
}
void RepliesWidget::scrollDownClicked() {
if (base::IsCtrlPressed()) {
showAtEnd();
} else if (_replyReturn) {
showAtPosition(_replyReturn->position());
} else {
showAtEnd();
void RepliesWidget::cornerButtonsShowAtPosition(
Data::MessagePosition position) {
showAtPosition(position);
}
Dialogs::Entry *RepliesWidget::cornerButtonsEntry() {
return _topic;
}
FullMsgId RepliesWidget::cornerButtonsCurrentId() {
return _lastShownAt;
}
bool RepliesWidget::cornerButtonsIgnoreVisibility() {
return animatingShow();
}
std::optional<bool> RepliesWidget::cornerButtonsDownShown() {
if (_composeControls->isLockPresent()) {
return false;
}
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
if (top < _scroll->scrollTopMax() || _cornerButtons.replyReturn()) {
return true;
} else if (_inner->loadedAtBottomKnown()) {
return !_inner->loadedAtBottom();
}
return std::nullopt;
}
bool RepliesWidget::cornerButtonsUnreadMayBeShown() {
return _inner->loadedAtBottomKnown()
&& !_composeControls->isLockPresent();
}
void RepliesWidget::showAtStart() {
@ -1435,9 +1444,7 @@ bool RepliesWidget::showAtPositionNow(
: nullptr;
const auto use = item ? item->position() : position;
if (const auto scrollTop = _inner->scrollTopForPosition(use)) {
while (_replyReturn && use.fullId.msg == _replyReturn->id) {
calculateNextReplyReturn();
}
_cornerButtons.skipReplyReturn(use.fullId);
const auto currentScrollTop = _scroll->scrollTop();
const auto wanted = std::clamp(
*scrollTop,
@ -1452,6 +1459,7 @@ bool RepliesWidget::showAtPositionNow(
? AnimatedScroll::Part
: AnimatedScroll::Full;
_inner->scrollTo(wanted, use, scrollDelta, type);
_lastShownAt = use.fullId;
if (use != Data::MaxMessagePosition
&& use != Data::UnreadMessagePosition) {
_inner->highlightMessage(use.fullId);
@ -1464,57 +1472,6 @@ bool RepliesWidget::showAtPositionNow(
return false;
}
void RepliesWidget::updateScrollDownVisibility() {
if (animatingShow()) {
return;
}
const auto scrollDownIsVisible = [&]() -> std::optional<bool> {
if (_composeControls->isLockPresent()) {
return false;
}
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
if (top < _scroll->scrollTopMax() || _replyReturn) {
return true;
} else if (_inner->loadedAtBottomKnown()) {
return !_inner->loadedAtBottom();
}
return std::nullopt;
};
const auto scrollDownIsShown = scrollDownIsVisible();
if (!scrollDownIsShown) {
return;
}
if (_scrollDownIsShown != *scrollDownIsShown) {
_scrollDownIsShown = *scrollDownIsShown;
_scrollDownShown.start(
[=] { updateScrollDownPosition(); },
_scrollDownIsShown ? 0. : 1.,
_scrollDownIsShown ? 1. : 0.,
st::historyToDownDuration);
}
}
void RepliesWidget::updateScrollDownPosition() {
// _scrollDown is a child widget of _scroll, not me.
auto top = anim::interpolate(
0,
_scrollDown->height() + st::historyToDownPosition.y(),
_scrollDownShown.value(_scrollDownIsShown ? 1. : 0.));
_scrollDown->moveToRight(
st::historyToDownPosition.x(),
_scroll->height() - top);
auto shouldBeHidden = !_scrollDownIsShown && !_scrollDownShown.animating();
if (shouldBeHidden != _scrollDown->isHidden()) {
_scrollDown->setVisible(!shouldBeHidden);
}
}
void RepliesWidget::scrollDownAnimationFinish() {
_scrollDownShown.stop();
updateScrollDownPosition();
}
void RepliesWidget::updateAdaptiveLayout() {
_topBarShadow->moveToLeft(
controller()->adaptive().isOneColumn() ? 0 : st::lineWidth,
@ -1662,7 +1619,8 @@ bool RepliesWidget::showMessage(
if (!originMessage) {
return false;
}
const auto originItem = (!originMessage || _replyReturn == originMessage)
const auto originItem = (!originMessage
|| _cornerButtons.replyReturn() == originMessage)
? nullptr
: originMessage;
showAtPosition(message->position(), originItem);
@ -1685,7 +1643,7 @@ void RepliesWidget::replyToMessage(FullMsgId itemId) {
void RepliesWidget::saveState(not_null<RepliesMemento*> memento) {
memento->setReplies(_replies);
memento->setReplyReturns(_replyReturns);
memento->setReplyReturns(_cornerButtons.replyReturns());
_inner->saveState(memento->list());
}
@ -1740,7 +1698,7 @@ void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
} else if (!_replies) {
refreshReplies();
}
restoreReplyReturns(memento->replyReturns());
_cornerButtons.setReplyReturns(memento->replyReturns());
_inner->restoreState(memento->list());
if (const auto highlight = memento->getHighlightId()) {
const auto position = Data::MessagePosition{
@ -1811,7 +1769,7 @@ void RepliesWidget::updateControlsGeometry() {
_composeControls->move(0, bottom - controlsHeight);
_composeControls->setAutocompleteBoundingRect(_scroll->geometry());
updateScrollDownPosition();
_cornerButtons.updatePositions();
}
void RepliesWidget::paintEvent(QPaintEvent *e) {
@ -1842,7 +1800,8 @@ void RepliesWidget::updateInnerVisibleArea() {
const auto scrollTop = _scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
updatePinnedVisibility();
updateScrollDownVisibility();
_cornerButtons.updateJumpDownVisibility();
_cornerButtons.updateUnreadThingsVisibility();
}
void RepliesWidget::updatePinnedVisibility() {
@ -2024,11 +1983,16 @@ void RepliesWidget::readTill(not_null<HistoryItem*> item) {
}
}
void RepliesWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
const auto reversed = ranges::views::reverse(items);
const auto good = ranges::find_if(reversed, &HistoryItem::isRegular);
if (good != end(reversed)) {
readTill(*good);
void RepliesWidget::listMarkReadTill(not_null<HistoryItem*> item) {
if (true/*doWeReadServerHistory()*/) { // #TODO forum active
readTill(item);
}
}
void RepliesWidget::listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) {
if (true/*doWeReadMentions()*/) { // #TODO forum active
session().api().markContentsRead(items);
}
}

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/section_widget.h"
#include "window/section_memento.h"
#include "history/view/history_view_corner_buttons.h"
#include "history/view/history_view_list_widget.h"
#include "data/data_messages.h"
#include "base/timer.h"
@ -67,7 +68,8 @@ class StickerToast;
class RepliesWidget final
: public Window::SectionWidget
, private ListDelegate {
, private ListDelegate
, private CornerButtonsDelegate {
public:
RepliesWidget(
QWidget *parent,
@ -128,7 +130,9 @@ public:
not_null<HistoryItem*> first,
not_null<HistoryItem*> second) override;
void listSelectionChanged(SelectedItems &&items) override;
void listVisibleItemsChanged(HistoryItemsList &&items) override;
void listMarkReadTill(not_null<HistoryItem*> item) override;
void listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) override;
MessagesBarData listMessagesBar(
const std::vector<not_null<Element*>> &elements) override;
void listContentRefreshed() override;
@ -147,6 +151,15 @@ public:
->rpl::producer<Data::AllowedReactions> override;
void listShowPremiumToast(not_null<DocumentData*> document) override;
// CornerButtonsDelegate delegate.
void cornerButtonsShowAtPosition(
Data::MessagePosition position) override;
Dialogs::Entry *cornerButtonsEntry() override;
FullMsgId cornerButtonsCurrentId() override;
bool cornerButtonsIgnoreVisibility() override;
std::optional<bool> cornerButtonsDownShown() override;
bool cornerButtonsUnreadMayBeShown() override;
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
@ -181,16 +194,13 @@ private:
void setupRoot();
void setupRootView();
void setupTopicViewer();
void subscribeToTopic();
void setTopic(Data::ForumTopic *topic);
void setupDragArea();
void sendReadTillRequest();
void readTill(not_null<HistoryItem*> item);
void setupScrollDownButton();
void scrollDownClicked();
void scrollDownAnimationFinish();
void updateScrollDownVisibility();
void updateScrollDownPosition();
void updatePinnedVisibility();
void confirmDeleteSelected();
@ -216,9 +226,6 @@ private:
void orderWidgets();
void pushReplyReturn(not_null<HistoryItem*> item);
void computeCurrentReplyReturn();
void calculateNextReplyReturn();
void restoreReplyReturns(const std::vector<MsgId> &list);
void checkReplyReturns();
void recountChatWidth();
void replyToMessage(FullMsgId itemId);
@ -295,12 +302,9 @@ private:
std::unique_ptr<Ui::ScrollArea> _scroll;
std::unique_ptr<HistoryView::StickerToast> _stickerToast;
std::vector<MsgId> _replyReturns;
HistoryItem *_replyReturn = nullptr;
Ui::Animations::Simple _scrollDownShown;
bool _scrollDownIsShown = false;
object_ptr<Ui::HistoryDownButton> _scrollDown;
FullMsgId _lastShownAt;
HistoryView::CornerButtons _cornerButtons;
rpl::lifetime _topicLifetime;
bool _choosingAttach = false;
@ -351,10 +355,10 @@ public:
return _replies;
}
void setReplyReturns(const std::vector<MsgId> &list) {
void setReplyReturns(const QVector<FullMsgId> &list) {
_replyReturns = list;
}
const std::vector<MsgId> &replyReturns() const {
const QVector<FullMsgId> &replyReturns() const {
return _replyReturns;
}
@ -373,7 +377,7 @@ private:
const MsgId _highlightId = 0;
ListMemento _list;
std::shared_ptr<Data::RepliesList> _replies;
std::vector<MsgId> _replyReturns;
QVector<FullMsgId> _replyReturns;
rpl::lifetime _lifetime;

View file

@ -1258,7 +1258,11 @@ void ScheduledWidget::listSelectionChanged(SelectedItems &&items) {
_topBar->showSelected(state);
}
void ScheduledWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
void ScheduledWidget::listMarkReadTill(not_null<HistoryItem*> item) {
}
void ScheduledWidget::listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) {
}
MessagesBarData ScheduledWidget::listMessagesBar(

View file

@ -112,7 +112,9 @@ public:
not_null<HistoryItem*> first,
not_null<HistoryItem*> second) override;
void listSelectionChanged(SelectedItems &&items) override;
void listVisibleItemsChanged(HistoryItemsList &&items) override;
void listMarkReadTill(not_null<HistoryItem*> item) override;
void listMarkContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) override;
MessagesBarData listMessagesBar(
const std::vector<not_null<Element*>> &elements) override;
void listContentRefreshed() override;