mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Fix long message parts highlighting in topics.
This commit is contained in:
parent
99a7a13218
commit
2b53df98cd
4 changed files with 86 additions and 52 deletions
|
@ -1433,41 +1433,12 @@ int HistoryWidget::itemTopForHighlight(
|
||||||
const auto heightLeft = (visibleAreaHeight - viewHeight);
|
const auto heightLeft = (visibleAreaHeight - viewHeight);
|
||||||
if (heightLeft >= 0) {
|
if (heightLeft >= 0) {
|
||||||
return std::max(itemTop - (heightLeft / 2), 0);
|
return std::max(itemTop - (heightLeft / 2), 0);
|
||||||
} else if (const auto sel = itemHighlight(item).range; !sel.empty()) {
|
} else if (const auto sel = itemHighlight(item).range
|
||||||
auto request = HistoryView::StateRequest();
|
; !sel.empty() && !IsSubGroupSelection(sel)) {
|
||||||
request.flags = Ui::Text::StateRequest::Flag::LookupSymbol;
|
|
||||||
const auto single = st::messageTextStyle.font->height;
|
const auto single = st::messageTextStyle.font->height;
|
||||||
const auto findy = [&](int symbol, int yfrom = 0) {
|
const auto begin = HistoryView::FindViewY(view, sel.from) - single;
|
||||||
const auto fory = [&](int y) {
|
const auto end = HistoryView::FindViewY(view, sel.to, begin + single)
|
||||||
return view->textState(QPoint(0, y), request).symbol;
|
+ 2 * single;
|
||||||
};
|
|
||||||
auto ytill = view->height() - 1;
|
|
||||||
auto symbolfrom = fory(yfrom);
|
|
||||||
auto symboltill = fory(ytill);
|
|
||||||
if ((yfrom >= ytill) || (symbolfrom >= symbol)) {
|
|
||||||
return yfrom;
|
|
||||||
} else if (symboltill <= symbol) {
|
|
||||||
return ytill;
|
|
||||||
}
|
|
||||||
while (ytill - yfrom >= 2 * single) {
|
|
||||||
const auto middle = (yfrom + ytill) / 2;
|
|
||||||
const auto found = fory(middle);
|
|
||||||
if (found == symbol
|
|
||||||
|| symbolfrom > found
|
|
||||||
|| symboltill < found) {
|
|
||||||
return middle;
|
|
||||||
} else if (found < symbol) {
|
|
||||||
yfrom = middle;
|
|
||||||
symbolfrom = found;
|
|
||||||
} else {
|
|
||||||
ytill = middle;
|
|
||||||
symboltill = found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (yfrom + ytill) / 2;
|
|
||||||
};
|
|
||||||
const auto begin = findy(sel.from) - single;
|
|
||||||
const auto end = findy(sel.to, begin + single) + 2 * single;
|
|
||||||
auto result = itemTop;
|
auto result = itemTop;
|
||||||
if (end > visibleAreaHeight) {
|
if (end > visibleAreaHeight) {
|
||||||
result = std::max(result, itemTop + end - visibleAreaHeight);
|
result = std::max(result, itemTop + end - visibleAreaHeight);
|
||||||
|
|
|
@ -2015,4 +2015,37 @@ void Element::ClearGlobal() {
|
||||||
MousedElement = nullptr;
|
MousedElement = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FindViewY(not_null<Element*> view, uint16 symbol, int yfrom) {
|
||||||
|
auto request = HistoryView::StateRequest();
|
||||||
|
request.flags = Ui::Text::StateRequest::Flag::LookupSymbol;
|
||||||
|
const auto single = st::messageTextStyle.font->height;
|
||||||
|
const auto fory = [&](int y) {
|
||||||
|
return view->textState(QPoint(0, y), request).symbol;
|
||||||
|
};
|
||||||
|
auto ytill = view->height() - 1;
|
||||||
|
auto symbolfrom = fory(yfrom);
|
||||||
|
auto symboltill = fory(ytill);
|
||||||
|
if ((yfrom >= ytill) || (symbolfrom >= symbol)) {
|
||||||
|
return yfrom;
|
||||||
|
} else if (symboltill <= symbol) {
|
||||||
|
return ytill;
|
||||||
|
}
|
||||||
|
while (ytill - yfrom >= 2 * single) {
|
||||||
|
const auto middle = (yfrom + ytill) / 2;
|
||||||
|
const auto found = fory(middle);
|
||||||
|
if (found == symbol
|
||||||
|
|| symbolfrom > found
|
||||||
|
|| symboltill < found) {
|
||||||
|
return middle;
|
||||||
|
} else if (found < symbol) {
|
||||||
|
yfrom = middle;
|
||||||
|
symbolfrom = found;
|
||||||
|
} else {
|
||||||
|
ytill = middle;
|
||||||
|
symboltill = found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (yfrom + ytill) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -668,4 +668,9 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] int FindViewY(
|
||||||
|
not_null<Element*> view,
|
||||||
|
uint16 symbol,
|
||||||
|
int yfrom = 0);
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -711,7 +711,25 @@ std::optional<int> ListWidget::scrollTopForView(
|
||||||
const auto top = view->y();
|
const auto top = view->y();
|
||||||
const auto height = view->height();
|
const auto height = view->height();
|
||||||
const auto available = _visibleBottom - _visibleTop;
|
const auto available = _visibleBottom - _visibleTop;
|
||||||
return top - std::max((available - height) / 2, 0);
|
const auto heightLeft = (available - height);
|
||||||
|
if (heightLeft >= 0) {
|
||||||
|
return std::max(top - (heightLeft / 2), 0);
|
||||||
|
} else if (const auto sel = _highlighter.state(view->data()).range
|
||||||
|
; !sel.empty() && !IsSubGroupSelection(sel)) {
|
||||||
|
const auto single = st::messageTextStyle.font->height;
|
||||||
|
const auto begin = HistoryView::FindViewY(view, sel.from) - single;
|
||||||
|
const auto end = HistoryView::FindViewY(view, sel.to, begin + single)
|
||||||
|
+ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::scrollTo(
|
void ListWidget::scrollTo(
|
||||||
|
@ -873,24 +891,31 @@ bool ListWidget::showAtPositionNow(
|
||||||
Data::MessagePosition position,
|
Data::MessagePosition position,
|
||||||
const Window::SectionShow ¶ms,
|
const Window::SectionShow ¶ms,
|
||||||
Fn<void(bool found)> done) {
|
Fn<void(bool found)> done) {
|
||||||
if (const auto scrollTop = scrollTopForPosition(position)) {
|
auto scrollTop = scrollTopForPosition(position);
|
||||||
computeScrollTo(*scrollTop, position, params.animated);
|
if (!scrollTop.has_value()) {
|
||||||
if (position != Data::MaxMessagePosition
|
return false;
|
||||||
&& position != Data::UnreadMessagePosition) {
|
|
||||||
highlightMessage(
|
|
||||||
position.fullId,
|
|
||||||
params.highlightPart,
|
|
||||||
params.highlightPartOffsetHint);
|
|
||||||
}
|
|
||||||
if (done) {
|
|
||||||
const auto found = !position.fullId.peer
|
|
||||||
|| !IsServerMsgId(position.fullId.msg)
|
|
||||||
|| viewForItem(position.fullId);
|
|
||||||
done(found);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
if (position != Data::MaxMessagePosition
|
||||||
|
&& position != Data::UnreadMessagePosition) {
|
||||||
|
const auto hasHighlight = !params.highlightPart.empty();
|
||||||
|
highlightMessage(
|
||||||
|
position.fullId,
|
||||||
|
params.highlightPart,
|
||||||
|
params.highlightPartOffsetHint);
|
||||||
|
if (hasHighlight) {
|
||||||
|
// We may want to scroll to a different part of the message.
|
||||||
|
scrollTop = scrollTopForPosition(position);
|
||||||
|
Assert(scrollTop.has_value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
computeScrollTo(*scrollTop, position, params.animated);
|
||||||
|
if (done) {
|
||||||
|
const auto found = !position.fullId.peer
|
||||||
|
|| !IsServerMsgId(position.fullId.msg)
|
||||||
|
|| viewForItem(position.fullId);
|
||||||
|
done(found);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::computeScrollTo(
|
void ListWidget::computeScrollTo(
|
||||||
|
|
Loading…
Add table
Reference in a new issue