mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Fix navigation in a message replies section.
This commit is contained in:
parent
1849f01b15
commit
c563df7d9d
5 changed files with 61 additions and 25 deletions
|
@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Data {
|
namespace Data {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kMessagesPerPage = 4; // #TODO replies
|
constexpr auto kMessagesPerPage = 16;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -94,8 +94,8 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
|
||||||
const auto around = viewer->around;
|
const auto around = viewer->around;
|
||||||
if (_list.empty()
|
if (_list.empty()
|
||||||
|| (!around && _skippedAfter != 0)
|
|| (!around && _skippedAfter != 0)
|
||||||
|| (around > 0 && around < _list.back())
|
|| (around > _list.front() && _skippedAfter != 0)
|
||||||
|| (around > _list.front())) {
|
|| (around > 0 && around < _list.back() && _skippedBefore != 0)) {
|
||||||
loadAround(around);
|
loadAround(around);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -207,6 +207,13 @@ void RepliesList::loadAround(MsgId id) {
|
||||||
_list.clear();
|
_list.clear();
|
||||||
if (processMessagesIsEmpty(result)) {
|
if (processMessagesIsEmpty(result)) {
|
||||||
_fullCount = _skippedBefore = _skippedAfter = 0;
|
_fullCount = _skippedBefore = _skippedAfter = 0;
|
||||||
|
} else if (id > 0) {
|
||||||
|
Assert(!_list.empty());
|
||||||
|
if (_list.front() <= id) {
|
||||||
|
_skippedAfter = 0;
|
||||||
|
} else if (_list.back() >= id) {
|
||||||
|
_skippedBefore = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
_beforeId = 0;
|
_beforeId = 0;
|
||||||
|
@ -312,7 +319,8 @@ void RepliesList::loadAfter() {
|
||||||
bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
|
bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
|
||||||
const auto guard = gsl::finally([&] { _partLoaded.fire({}); });
|
const auto guard = gsl::finally([&] { _partLoaded.fire({}); });
|
||||||
|
|
||||||
_fullCount = result.match([&](const MTPDmessages_messagesNotModified &) {
|
const auto fullCount = result.match([&](
|
||||||
|
const MTPDmessages_messagesNotModified &) {
|
||||||
LOG(("API Error: received messages.messagesNotModified! "
|
LOG(("API Error: received messages.messagesNotModified! "
|
||||||
"(HistoryWidget::messagesReceived)"));
|
"(HistoryWidget::messagesReceived)"));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -346,7 +354,8 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto id = IdFromMessage(list.front());
|
const auto id = IdFromMessage(list.front());
|
||||||
const auto toFront = !_list.empty() && (id > _list.front());
|
const auto wasSize = int(_list.size());
|
||||||
|
const auto toFront = (wasSize > 0) && (id > _list.front());
|
||||||
const auto clientFlags = MTPDmessage_ClientFlags();
|
const auto clientFlags = MTPDmessage_ClientFlags();
|
||||||
const auto type = NewMessageType::Existing;
|
const auto type = NewMessageType::Existing;
|
||||||
auto refreshed = std::vector<MsgId>();
|
auto refreshed = std::vector<MsgId>();
|
||||||
|
@ -368,11 +377,31 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
|
||||||
refreshed.insert(refreshed.end(), _list.begin(), _list.end());
|
refreshed.insert(refreshed.end(), _list.begin(), _list.end());
|
||||||
_list = std::move(refreshed);
|
_list = std::move(refreshed);
|
||||||
}
|
}
|
||||||
if (_fullCount.current() && _skippedBefore && !_skippedAfter) {
|
|
||||||
_skippedAfter = *_fullCount.current() - *_skippedBefore - _list.size();
|
const auto nowSize = int(_list.size());
|
||||||
} else if (_fullCount.current() && _skippedAfter && !_skippedBefore) {
|
auto &decrementFrom = toFront ? _skippedAfter : _skippedBefore;
|
||||||
_skippedBefore = *_fullCount.current() - *_skippedAfter - _list.size();
|
if (decrementFrom.has_value()) {
|
||||||
|
*decrementFrom = std::max(
|
||||||
|
*decrementFrom - (nowSize - wasSize),
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto checkedCount = std::max(fullCount, nowSize);
|
||||||
|
if (_skippedBefore && _skippedAfter) {
|
||||||
|
auto &correct = toFront ? _skippedBefore : _skippedAfter;
|
||||||
|
*correct = std::max(
|
||||||
|
checkedCount - *decrementFrom - nowSize,
|
||||||
|
0);
|
||||||
|
*decrementFrom = *_fullCount.current() - *correct - nowSize;
|
||||||
|
Assert(*decrementFrom >= 0);
|
||||||
|
} else if (_skippedBefore) {
|
||||||
|
*_skippedBefore = std::min(*_skippedBefore, checkedCount - nowSize);
|
||||||
|
_skippedAfter = checkedCount - *_skippedBefore - nowSize;
|
||||||
|
} else if (_skippedAfter) {
|
||||||
|
*_skippedAfter = std::min(*_skippedAfter, checkedCount - nowSize);
|
||||||
|
_skippedBefore = checkedCount - *_skippedAfter - nowSize;
|
||||||
|
}
|
||||||
|
_fullCount = checkedCount;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -455,6 +455,15 @@ void ListWidget::highlightMessage(FullMsgId itemId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::showAroundPosition(
|
||||||
|
Data::MessagePosition position,
|
||||||
|
Fn<bool()> overrideInitialScroll) {
|
||||||
|
_aroundPosition = position;
|
||||||
|
_aroundIndex = -1;
|
||||||
|
_overrideInitialScroll = std::move(overrideInitialScroll);
|
||||||
|
refreshViewer();
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::updateHighlightedMessage() {
|
void ListWidget::updateHighlightedMessage() {
|
||||||
if (const auto item = session().data().message(_highlightedMessageId)) {
|
if (const auto item = session().data().message(_highlightedMessageId)) {
|
||||||
if (const auto view = viewForItem(item)) {
|
if (const auto view = viewForItem(item)) {
|
||||||
|
@ -486,7 +495,9 @@ void ListWidget::saveScrollState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::restoreScrollState() {
|
void ListWidget::restoreScrollState() {
|
||||||
if (_items.empty()) {
|
if (_items.empty()
|
||||||
|
|| (_overrideInitialScroll
|
||||||
|
&& base::take(_overrideInitialScroll)())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!_scrollTopState.item) {
|
if (!_scrollTopState.item) {
|
||||||
|
|
|
@ -164,6 +164,9 @@ public:
|
||||||
bool isAbovePosition(Data::MessagePosition position) const;
|
bool isAbovePosition(Data::MessagePosition position) const;
|
||||||
bool isBelowPosition(Data::MessagePosition position) const;
|
bool isBelowPosition(Data::MessagePosition position) const;
|
||||||
void highlightMessage(FullMsgId itemId);
|
void highlightMessage(FullMsgId itemId);
|
||||||
|
void showAroundPosition(
|
||||||
|
Data::MessagePosition position,
|
||||||
|
Fn<bool()> overrideInitialScroll);
|
||||||
|
|
||||||
TextForMimeData getSelectedText() const;
|
TextForMimeData getSelectedText() const;
|
||||||
MessageIdsList getSelectedItems() const;
|
MessageIdsList getSelectedItems() const;
|
||||||
|
@ -472,6 +475,7 @@ private:
|
||||||
int _visibleTopFromItem = 0;
|
int _visibleTopFromItem = 0;
|
||||||
ScrollTopState _scrollTopState;
|
ScrollTopState _scrollTopState;
|
||||||
Ui::Animations::Simple _scrollToAnimation;
|
Ui::Animations::Simple _scrollToAnimation;
|
||||||
|
Fn<bool()> _overrideInitialScroll;
|
||||||
|
|
||||||
bool _scrollDateShown = false;
|
bool _scrollDateShown = false;
|
||||||
Ui::Animations::Simple _scrollDateOpacity;
|
Ui::Animations::Simple _scrollDateOpacity;
|
||||||
|
|
|
@ -780,19 +780,10 @@ void RepliesWidget::scrollDownClicked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesWidget::showAtPosition(Data::MessagePosition position) {
|
void RepliesWidget::showAtPosition(Data::MessagePosition position) {
|
||||||
if (showAtPositionNow(position)) {
|
if (!showAtPositionNow(position)) {
|
||||||
if (const auto highlight = base::take(_highlightMessageId)) {
|
_inner->showAroundPosition(position, [=] {
|
||||||
_inner->highlightMessage(highlight);
|
return showAtPositionNow(position);
|
||||||
}
|
});
|
||||||
} else {
|
|
||||||
_nextAnimatedScrollPosition = position;
|
|
||||||
_nextAnimatedScrollDelta = _inner->isBelowPosition(position)
|
|
||||||
? -_scroll->height()
|
|
||||||
: _inner->isAbovePosition(position)
|
|
||||||
? _scroll->height()
|
|
||||||
: 0;
|
|
||||||
auto memento = HistoryView::ListMemento(position);
|
|
||||||
_inner->restoreState(&memento);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,6 +801,9 @@ bool RepliesWidget::showAtPositionNow(Data::MessagePosition position) {
|
||||||
(std::abs(fullDelta) > limit
|
(std::abs(fullDelta) > limit
|
||||||
? HistoryView::ListWidget::AnimatedScroll::Part
|
? HistoryView::ListWidget::AnimatedScroll::Part
|
||||||
: HistoryView::ListWidget::AnimatedScroll::Full));
|
: HistoryView::ListWidget::AnimatedScroll::Full));
|
||||||
|
if (const auto highlight = base::take(_highlightMessageId)) {
|
||||||
|
_inner->highlightMessage(highlight);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -213,8 +213,6 @@ private:
|
||||||
bool _skipScrollEvent = false;
|
bool _skipScrollEvent = false;
|
||||||
|
|
||||||
FullMsgId _highlightMessageId;
|
FullMsgId _highlightMessageId;
|
||||||
std::optional<Data::MessagePosition> _nextAnimatedScrollPosition;
|
|
||||||
int _nextAnimatedScrollDelta = 0;
|
|
||||||
|
|
||||||
Ui::Animations::Simple _scrollDownShown;
|
Ui::Animations::Simple _scrollDownShown;
|
||||||
bool _scrollDownIsShown = false;
|
bool _scrollDownIsShown = false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue