Fix opening Replies section on unread bar.

This commit is contained in:
John Preston 2020-10-02 19:26:04 +03:00
parent 8d70a62ee8
commit 4b6d74dd9b
7 changed files with 45 additions and 10 deletions

View file

@ -479,9 +479,15 @@ void MessagesSliceBuilder::requestMessagesCount() {
MessagesSlice MessagesSliceBuilder::snapshot() const { MessagesSlice MessagesSliceBuilder::snapshot() const {
auto result = MessagesSlice(); auto result = MessagesSlice();
result.ids.reserve(_ids.size()); result.ids.reserve(_ids.size());
auto nearestToAround = std::optional<FullMsgId>();
for (const auto &position : _ids) { for (const auto &position : _ids) {
result.ids.push_back(position.fullId); result.ids.push_back(position.fullId);
if (!nearestToAround && position >= _key) {
nearestToAround = position.fullId;
}
} }
result.nearestToAround = nearestToAround.value_or(
_ids.empty() ? FullMsgId() : _ids.back().fullId);
result.skippedBefore = _skippedBefore; result.skippedBefore = _skippedBefore;
result.skippedAfter = _skippedAfter; result.skippedAfter = _skippedAfter;
result.fullCount = _fullCount; result.fullCount = _fullCount;

View file

@ -93,10 +93,10 @@ constexpr auto UnreadMessagePosition = MessagePosition(
struct MessagesSlice { struct MessagesSlice {
std::vector<FullMsgId> ids; std::vector<FullMsgId> ids;
FullMsgId nearestToAround;
std::optional<int> skippedBefore; std::optional<int> skippedBefore;
std::optional<int> skippedAfter; std::optional<int> skippedAfter;
std::optional<int> fullCount; std::optional<int> fullCount;
}; };
struct MessagesQuery { struct MessagesQuery {
@ -112,7 +112,6 @@ struct MessagesQuery {
MessagePosition aroundId; MessagePosition aroundId;
int limitBefore = 0; int limitBefore = 0;
int limitAfter = 0; int limitAfter = 0;
}; };
struct MessagesResult { struct MessagesResult {

View file

@ -227,6 +227,7 @@ void RepliesList::injectRootDivider(
bool RepliesList::buildFromData(not_null<Viewer*> viewer) { bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
if (_list.empty() && _skippedBefore == 0 && _skippedAfter == 0) { if (_list.empty() && _skippedBefore == 0 && _skippedAfter == 0) {
viewer->slice.ids.clear(); viewer->slice.ids.clear();
viewer->slice.nearestToAround = FullMsgId();
viewer->slice.fullCount viewer->slice.fullCount
= viewer->slice.skippedBefore = viewer->slice.skippedBefore
= viewer->slice.skippedAfter = viewer->slice.skippedAfter
@ -268,10 +269,20 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
const auto channelId = _history->channelId(); const auto channelId = _history->channelId();
slice->ids.clear(); slice->ids.clear();
auto nearestToAround = std::optional<MsgId>();
slice->ids.reserve(useAfter + useBefore); slice->ids.reserve(useAfter + useBefore);
for (auto j = i - useAfter, e = i + useBefore; j != e; ++j) { for (auto j = i - useAfter, e = i + useBefore; j != e; ++j) {
if (!nearestToAround && *j < around) {
nearestToAround = (j == i - useAfter)
? *j
: *(j - 1);
}
slice->ids.emplace_back(channelId, *j); slice->ids.emplace_back(channelId, *j);
} }
slice->nearestToAround = FullMsgId(
channelId,
nearestToAround.value_or(
slice->ids.empty() ? 0 : slice->ids.back().msg));
slice->fullCount = _fullCount.current(); slice->fullCount = _fullCount.current();
injectRootMessageAndReverse(slice); injectRootMessageAndReverse(slice);

View file

@ -336,12 +336,16 @@ void ListWidget::refreshRows() {
_items.clear(); _items.clear();
_items.reserve(_slice.ids.size()); _items.reserve(_slice.ids.size());
auto nearestIndex = -1;
for (const auto &fullId : _slice.ids) { for (const auto &fullId : _slice.ids) {
if (const auto item = session().data().message(fullId)) { if (const auto item = session().data().message(fullId)) {
if (_slice.nearestToAround == fullId) {
nearestIndex = int(_items.size());
}
_items.push_back(enforceViewForItem(item)); _items.push_back(enforceViewForItem(item));
} }
} }
updateAroundPositionFromRows(); updateAroundPositionFromNearest(nearestIndex);
updateItemsGeometry(); updateItemsGeometry();
checkUnreadBarCreation(); checkUnreadBarCreation();
@ -573,8 +577,7 @@ not_null<Element*> ListWidget::enforceViewForItem(
return i->second.get(); return i->second.get();
} }
void ListWidget::updateAroundPositionFromRows() { void ListWidget::updateAroundPositionFromNearest(int nearestIndex) {
const auto nearestIndex = findNearestItem(_aroundPosition);
if (nearestIndex < 0) { if (nearestIndex < 0) {
_aroundIndex = -1; _aroundIndex = -1;
return; return;

View file

@ -305,7 +305,7 @@ private:
using CursorState = HistoryView::CursorState; using CursorState = HistoryView::CursorState;
void refreshViewer(); void refreshViewer();
void updateAroundPositionFromRows(); void updateAroundPositionFromNearest(int nearestIndex);
void refreshRows(); void refreshRows();
ScrollTopState countScrollState() const; ScrollTopState countScrollState() const;
void saveScrollState(); void saveScrollState();

View file

@ -1519,7 +1519,7 @@ void RepliesWidget::updateControlsGeometry() {
const auto bottom = height(); const auto bottom = height();
const auto controlsHeight = _composeControls->heightCurrent(); const auto controlsHeight = _composeControls->heightCurrent();
const auto scrollY = _topBar->height() + _rootView->height(); const auto scrollY = _topBar->height() + _rootViewHeight;
const auto scrollHeight = bottom - scrollY - controlsHeight; const auto scrollHeight = bottom - scrollY - controlsHeight;
const auto scrollSize = QSize(contentWidth, scrollHeight); const auto scrollSize = QSize(contentWidth, scrollHeight);
if (_scroll->size() != scrollSize) { if (_scroll->size() != scrollSize) {
@ -1585,13 +1585,28 @@ void RepliesWidget::updatePinnedVisibility() {
return _root; return _root;
}(); }();
const auto view = _inner->viewByPosition(item->position()); const auto view = _inner->viewByPosition(item->position());
setPinnedVisibility(!view const auto visible = !view
|| (view->y() + view->height() <= _scroll->scrollTop())); || (view->y() + view->height() <= _scroll->scrollTop());
setPinnedVisibility(visible);
} }
void RepliesWidget::setPinnedVisibility(bool shown) { void RepliesWidget::setPinnedVisibility(bool shown) {
if (!animating()) { if (!animating()) {
_rootView->toggle(shown, anim::type::normal); if (!_rootViewInited) {
const auto height = shown ? st::historyReplyHeight : 0;
if (const auto delta = height - _rootViewHeight) {
_rootViewHeight = height;
if (_scroll->scrollTop() == _scroll->scrollTopMax()) {
setGeometryWithTopMoved(geometry(), delta);
} else {
updateControlsGeometry();
}
}
_rootView->toggle(shown, anim::type::instant);
_rootViewInited = true;
} else {
_rootView->toggle(shown, anim::type::normal);
}
} }
} }

View file

@ -255,6 +255,7 @@ private:
object_ptr<Ui::SlideWrap<Ui::RpWidget>> _rootView; object_ptr<Ui::SlideWrap<Ui::RpWidget>> _rootView;
int _rootViewHeight = 0; int _rootViewHeight = 0;
object_ptr<Ui::PlainShadow> _rootShadow; object_ptr<Ui::PlainShadow> _rootShadow;
bool _rootViewInited = false;
std::unique_ptr<Ui::ScrollArea> _scroll; std::unique_ptr<Ui::ScrollArea> _scroll;