mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 15:47:11 +02:00
Support unread mentions / reactions in topics.
This commit is contained in:
parent
6a7f030ee7
commit
3999bca823
15 changed files with 229 additions and 175 deletions
|
@ -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
|
||||
|
|
|
@ -271,6 +271,7 @@ void Changes::sendNotifications() {
|
|||
_historyChanges.sendNotifications();
|
||||
_messageChanges.sendNotifications();
|
||||
_entryChanges.sendNotifications();
|
||||
_topicChanges.sendNotifications();
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -5769,7 +5769,7 @@ bool HistoryWidget::cornerButtonsIgnoreVisibility() {
|
|||
return _a_show.animating();
|
||||
}
|
||||
|
||||
bool HistoryWidget::cornerButtonsDownShown() {
|
||||
std::optional<bool> HistoryWidget::cornerButtonsDownShown() {
|
||||
if (!_list || _firstLoadRequest) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue