Adjusted scroll position for highlighted items in media groups.

Related commit: 2b53df98cd.
This commit is contained in:
23rd
2026-03-29 23:02:54 +03:00
parent d5f4c5366c
commit 59bf5515c3
5 changed files with 69 additions and 3 deletions
@@ -1624,6 +1624,33 @@ int HistoryWidget::itemTopForHighlight(
result = itemTop + begin;
}
return result;
} else if (IsSubGroupSelection(highlight.range)) {
if (const auto media = view->media()) {
for (auto i = 0; i != 15; ++i) {
if (!IsGroupItemSelection(highlight.range, i)) {
continue;
}
const auto rect = media->groupItemRect(i);
if (rect.isEmpty()) {
break;
}
const auto inner = view->innerGeometry();
const auto single = st::messageTextStyle.font->height;
const auto begin = inner.y() + rect.y() - 2 * single;
const auto end = inner.y() + rect.y()
+ rect.height() + 2 * single;
auto result = itemTop;
if (end > visibleAreaHeight) {
result = std::max(
result,
itemTop + end - visibleAreaHeight);
}
if (itemTop + begin < result) {
result = itemTop + begin;
}
return result;
}
}
} else if (reactionCenter >= 0) {
const auto maxSize = st::reactionInlineImage;
@@ -798,6 +798,31 @@ std::optional<int> ListWidget::scrollTopForView(
result = top + begin;
}
return result;
} else if (IsSubGroupSelection(highlight.range)) {
if (const auto media = view->media()) {
for (auto i = 0; i != 15; ++i) {
if (!IsGroupItemSelection(highlight.range, i)) {
continue;
}
const auto rect = media->groupItemRect(i);
if (rect.isEmpty()) {
break;
}
const auto inner = view->innerGeometry();
const auto single = st::messageTextStyle.font->height;
const auto begin = inner.y() + rect.y() - 2 * single;
const auto end = inner.y() + rect.y()
+ rect.height() + 2 * single;
auto result = top;
if (end > available) {
result = std::max(result, top + end - available);
}
if (top + begin < result) {
result = top + begin;
}
return result;
}
}
}
return top;
}
@@ -966,10 +991,11 @@ bool ListWidget::showAtPositionNow(
}
if (position != Data::MaxMessagePosition
&& position != Data::UnreadMessagePosition) {
const auto hasHighlight = !params.highlight.empty();
const auto item = session().data().message(position.fullId);
const auto mayScrollToPart = !params.highlight.empty()
|| (item && item->groupId());
highlightMessage(position.fullId, params.highlight);
if (hasHighlight) {
// We may want to scroll to a different part of the message.
if (mayScrollToPart) {
scrollTop = scrollTopForPosition(position);
Assert(scrollTop.has_value());
}
@@ -141,6 +141,9 @@ public:
const PaintContext &context,
int top) const {
}
[[nodiscard]] virtual QRect groupItemRect(int index) const {
return {};
}
virtual void draw(Painter &p, const PaintContext &context) const = 0;
[[nodiscard]] virtual PointState pointState(QPoint point) const;
[[nodiscard]] virtual TextState textState(
@@ -301,6 +301,15 @@ QMargins GroupedMedia::groupedPadding() const {
(normal.bottom() - grouped.bottom()) + addToBottom);
}
QRect GroupedMedia::groupItemRect(int index) const {
if (index >= 0 && index < int(_parts.size())) {
return _parts[index].geometry.translated(
0,
groupedPadding().top());
}
return {};
}
Media *GroupedMedia::lookupSpoilerTagMedia() const {
if (_parts.empty()) {
return nullptr;
@@ -97,6 +97,7 @@ public:
bool customHighlight() const override {
return true;
}
QRect groupItemRect(int index) const override;
bool enforceBubbleWidth() const override;
void stopAnimation() override;