mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-01 00:08:02 +00:00
Make link preview title clickable
This commit is contained in:
parent
f979df3dfe
commit
f1eddcd584
Telegram/SourceFiles/history/view/media
@ -73,6 +73,7 @@ WebPage::WebPage(
|
||||
not_null<WebPageData*> data)
|
||||
: Media(parent)
|
||||
, _data(data)
|
||||
, _siteName(st::msgMinWidth - st::webPageLeft)
|
||||
, _title(st::msgMinWidth - st::webPageLeft)
|
||||
, _description(st::msgMinWidth - st::webPageLeft) {
|
||||
history()->owner().registerWebPageView(_data, _parent);
|
||||
@ -88,9 +89,9 @@ QSize WebPage::countOptimalSize() {
|
||||
_openl = nullptr;
|
||||
_attach = nullptr;
|
||||
_collage = PrepareCollageMedia(_parent->data(), _data->collage);
|
||||
_siteName = Ui::Text::String(st::msgMinWidth - st::webPageLeft);
|
||||
_title = Ui::Text::String(st::msgMinWidth - st::webPageLeft);
|
||||
_description = Ui::Text::String(st::msgMinWidth - st::webPageLeft);
|
||||
_siteNameWidth = 0;
|
||||
}
|
||||
auto lineHeight = unitedLineHeight();
|
||||
|
||||
@ -196,17 +197,29 @@ QSize WebPage::countOptimalSize() {
|
||||
text,
|
||||
Ui::WebpageTextDescriptionOptions(_data->siteName));
|
||||
}
|
||||
if (!displayedSiteName().isEmpty()) {
|
||||
_siteNameLines = 1;
|
||||
_siteName.setRichText(
|
||||
st::webPageTitleStyle,
|
||||
textcmdLink(_data->url, displayedSiteName()),
|
||||
Ui::WebpageTextTitleOptions());
|
||||
}
|
||||
if (_title.isEmpty() && !title.isEmpty()) {
|
||||
if (textFloatsAroundInfo && _description.isEmpty()) {
|
||||
title += _parent->skipBlock();
|
||||
}
|
||||
_title.setText(
|
||||
st::webPageTitleStyle,
|
||||
title,
|
||||
Ui::WebpageTextTitleOptions());
|
||||
}
|
||||
if (!_siteNameWidth && !displayedSiteName().isEmpty()) {
|
||||
_siteNameWidth = st::webPageTitleFont->width(displayedSiteName());
|
||||
if (!_siteNameLines && !_data->url.isEmpty()) {
|
||||
_title.setRichText(
|
||||
st::webPageTitleStyle,
|
||||
textcmdLink(_data->url, title),
|
||||
Ui::WebpageTextTitleOptions());
|
||||
|
||||
} else {
|
||||
_title.setText(
|
||||
st::webPageTitleStyle,
|
||||
title,
|
||||
Ui::WebpageTextTitleOptions());
|
||||
}
|
||||
}
|
||||
|
||||
// init dimensions
|
||||
@ -215,7 +228,7 @@ QSize WebPage::countOptimalSize() {
|
||||
auto maxWidth = skipBlockWidth;
|
||||
auto minHeight = 0;
|
||||
|
||||
auto siteNameHeight = _siteNameWidth ? lineHeight : 0;
|
||||
auto siteNameHeight = _siteName.isEmpty() ? 0 : lineHeight;
|
||||
auto titleMinHeight = _title.isEmpty() ? 0 : lineHeight;
|
||||
auto descMaxLines = isLogEntryOriginal() ? kMaxOriginalEntryLines : (3 + (siteNameHeight ? 0 : 1) + (titleMinHeight ? 0 : 1));
|
||||
auto descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight);
|
||||
@ -225,11 +238,11 @@ QSize WebPage::countOptimalSize() {
|
||||
articlePhotoMaxWidth = st::webPagePhotoDelta + qMax(articleThumbWidth(_data->photo, articleMinHeight), lineHeight);
|
||||
}
|
||||
|
||||
if (_siteNameWidth) {
|
||||
if (!_siteName.isEmpty()) {
|
||||
if (_title.isEmpty() && _description.isEmpty() && textFloatsAroundInfo) {
|
||||
accumulate_max(maxWidth, _siteNameWidth + _parent->skipBlockWidth());
|
||||
accumulate_max(maxWidth, _siteName.maxWidth() + _parent->skipBlockWidth());
|
||||
} else {
|
||||
accumulate_max(maxWidth, _siteNameWidth + articlePhotoMaxWidth);
|
||||
accumulate_max(maxWidth, _siteName.maxWidth() + articlePhotoMaxWidth);
|
||||
}
|
||||
minHeight += lineHeight;
|
||||
}
|
||||
@ -242,7 +255,7 @@ QSize WebPage::countOptimalSize() {
|
||||
minHeight += descriptionMinHeight;
|
||||
}
|
||||
if (_attach) {
|
||||
auto attachAtTop = !_siteNameWidth && _title.isEmpty() && _description.isEmpty();
|
||||
auto attachAtTop = _siteName.isEmpty() && _title.isEmpty() && _description.isEmpty();
|
||||
if (!attachAtTop) minHeight += st::mediaInBubbleSkip;
|
||||
|
||||
_attach->initDimensions();
|
||||
@ -281,8 +294,7 @@ QSize WebPage::countCurrentSize(int newWidth) {
|
||||
|
||||
auto lineHeight = unitedLineHeight();
|
||||
auto linesMax = isLogEntryOriginal() ? kMaxOriginalEntryLines : 5;
|
||||
auto siteNameLines = _siteNameWidth ? 1 : 0;
|
||||
auto siteNameHeight = _siteNameWidth ? lineHeight : 0;
|
||||
auto siteNameHeight = _siteNameLines ? lineHeight : 0;
|
||||
if (asArticle()) {
|
||||
_pixh = linesMax * lineHeight;
|
||||
do {
|
||||
@ -303,12 +315,12 @@ QSize WebPage::countCurrentSize(int newWidth) {
|
||||
}
|
||||
|
||||
auto descriptionHeight = _description.countHeight(wleft);
|
||||
if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
|
||||
if (descriptionHeight < (linesMax - _siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
|
||||
// We have height for all the lines.
|
||||
_descriptionLines = -1;
|
||||
newHeight += descriptionHeight;
|
||||
} else {
|
||||
_descriptionLines = (linesMax - siteNameLines - _titleLines);
|
||||
_descriptionLines = (linesMax - _siteNameLines - _titleLines);
|
||||
newHeight += _descriptionLines * lineHeight;
|
||||
}
|
||||
|
||||
@ -337,18 +349,18 @@ QSize WebPage::countCurrentSize(int newWidth) {
|
||||
_descriptionLines = 0;
|
||||
} else {
|
||||
auto descriptionHeight = _description.countHeight(innerWidth);
|
||||
if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
|
||||
if (descriptionHeight < (linesMax - _siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
|
||||
// We have height for all the lines.
|
||||
_descriptionLines = -1;
|
||||
newHeight += descriptionHeight;
|
||||
} else {
|
||||
_descriptionLines = (linesMax - siteNameLines - _titleLines);
|
||||
_descriptionLines = (linesMax - _siteNameLines - _titleLines);
|
||||
newHeight += _descriptionLines * lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (_attach) {
|
||||
auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines;
|
||||
auto attachAtTop = !_siteNameLines && !_titleLines && !_descriptionLines;
|
||||
if (!attachAtTop) newHeight += st::mediaInBubbleSkip;
|
||||
|
||||
auto bubble = _attach->bubbleMargins();
|
||||
@ -368,14 +380,24 @@ QSize WebPage::countCurrentSize(int newWidth) {
|
||||
return { newWidth, newHeight };
|
||||
}
|
||||
|
||||
TextSelection WebPage::toTitleSelection(
|
||||
TextSelection selection) const {
|
||||
return UnshiftItemSelection(selection, _siteName);
|
||||
}
|
||||
|
||||
TextSelection WebPage::fromTitleSelection(
|
||||
TextSelection selection) const {
|
||||
return ShiftItemSelection(selection, _siteName);
|
||||
}
|
||||
|
||||
TextSelection WebPage::toDescriptionSelection(
|
||||
TextSelection selection) const {
|
||||
return UnshiftItemSelection(selection, _title);
|
||||
return UnshiftItemSelection(toTitleSelection(selection), _title);
|
||||
}
|
||||
|
||||
TextSelection WebPage::fromDescriptionSelection(
|
||||
TextSelection selection) const {
|
||||
return ShiftItemSelection(selection, _title);
|
||||
return ShiftItemSelection(fromTitleSelection(selection), _title);
|
||||
}
|
||||
|
||||
void WebPage::refreshParentId(not_null<HistoryItem*> realParent) {
|
||||
@ -441,10 +463,13 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
||||
}
|
||||
paintw -= pw + st::webPagePhotoDelta;
|
||||
}
|
||||
if (_siteNameWidth) {
|
||||
p.setFont(st::webPageTitleFont);
|
||||
if (_siteNameLines) {
|
||||
p.setPen(semibold);
|
||||
p.drawTextLeft(padding.left(), tshift, width(), (paintw >= _siteNameWidth) ? displayedSiteName() : st::webPageTitleFont->elided(displayedSiteName(), paintw));
|
||||
auto endskip = 0;
|
||||
if (_siteName.hasSkipBlock()) {
|
||||
endskip = _parent->skipBlockWidth();
|
||||
}
|
||||
_siteName.drawLeftElided(p, padding.left(), tshift, paintw, width(), _siteNameLines, style::al_left, 0, -1, endskip, false, selection);
|
||||
tshift += lineHeight;
|
||||
}
|
||||
if (_titleLines) {
|
||||
@ -453,7 +478,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
||||
if (_title.hasSkipBlock()) {
|
||||
endskip = _parent->skipBlockWidth();
|
||||
}
|
||||
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, selection);
|
||||
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, toTitleSelection(selection));
|
||||
tshift += _titleLines * lineHeight;
|
||||
}
|
||||
if (_descriptionLines) {
|
||||
@ -471,7 +496,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
|
||||
}
|
||||
}
|
||||
if (_attach) {
|
||||
auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines;
|
||||
auto attachAtTop = !_siteNameLines && !_titleLines && !_descriptionLines;
|
||||
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
|
||||
|
||||
auto attachLeft = padding.left() - bubble.left();
|
||||
@ -551,7 +576,18 @@ TextState WebPage::textState(QPoint point, StateRequest request) const {
|
||||
paintw -= pw + st::webPagePhotoDelta;
|
||||
}
|
||||
int symbolAdd = 0;
|
||||
if (_siteNameWidth) {
|
||||
if (_siteNameLines) {
|
||||
if (point.y() >= tshift && point.y() < tshift + lineHeight) {
|
||||
Ui::Text::StateRequestElided siteNameRequest = request.forText();
|
||||
siteNameRequest.lines = _siteNameLines;
|
||||
result = TextState(_parent, _siteName.getStateElidedLeft(
|
||||
point - QPoint(padding.left(), tshift),
|
||||
paintw,
|
||||
width(),
|
||||
siteNameRequest));
|
||||
} else if (point.y() >= tshift + lineHeight) {
|
||||
symbolAdd += _siteName.length();
|
||||
}
|
||||
tshift += lineHeight;
|
||||
}
|
||||
if (_titleLines) {
|
||||
@ -594,7 +630,7 @@ TextState WebPage::textState(QPoint point, StateRequest request) const {
|
||||
if (inThumb) {
|
||||
result.link = _openl;
|
||||
} else if (_attach) {
|
||||
auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines;
|
||||
auto attachAtTop = !_siteNameLines && !_titleLines && !_descriptionLines;
|
||||
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
|
||||
|
||||
if (QRect(padding.left(), tshift, paintw, height() - tshift - bshift).contains(point)) {
|
||||
@ -635,15 +671,26 @@ ClickHandlerPtr WebPage::replaceAttachLink(
|
||||
}
|
||||
|
||||
TextSelection WebPage::adjustSelection(TextSelection selection, TextSelectType type) const {
|
||||
if (!_descriptionLines || selection.to <= _title.length()) {
|
||||
return _title.adjustSelection(selection, type);
|
||||
if ((!_titleLines && !_descriptionLines) || selection.to <= _siteName.length()) {
|
||||
return _siteName.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
auto titleSelection = _title.adjustSelection(toTitleSelection(selection), type);
|
||||
if ((!_siteNameLines && !_descriptionLines) || (selection.from >= _siteName.length() && selection.to <= _description.length())) {
|
||||
return fromTitleSelection(titleSelection);
|
||||
}
|
||||
|
||||
auto titlesLength = _siteName.length() + _title.length();
|
||||
auto descriptionSelection = _description.adjustSelection(toDescriptionSelection(selection), type);
|
||||
if (selection.from >= _title.length()) {
|
||||
if ((!_siteNameLines && !_titleLines) || selection.from >= titlesLength) {
|
||||
return fromDescriptionSelection(descriptionSelection);
|
||||
}
|
||||
auto titleSelection = _title.adjustSelection(selection, type);
|
||||
return { titleSelection.from, fromDescriptionSelection(descriptionSelection).to };
|
||||
|
||||
auto siteNameSelection = _siteName.adjustSelection(selection, type);
|
||||
if (!_descriptionLines || selection.to <= titlesLength) {
|
||||
return { siteNameSelection.from, fromTitleSelection(titleSelection).to };
|
||||
}
|
||||
return { siteNameSelection.from, fromDescriptionSelection(descriptionSelection).to };
|
||||
}
|
||||
|
||||
void WebPage::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||
@ -681,16 +728,26 @@ bool WebPage::isDisplayed() const {
|
||||
}
|
||||
|
||||
TextForMimeData WebPage::selectedText(TextSelection selection) const {
|
||||
auto titleResult = _title.toTextForMimeData(selection);
|
||||
auto siteNameResult = _siteName.toTextForMimeData(selection);
|
||||
auto titleResult = _title.toTextForMimeData(
|
||||
toTitleSelection(selection));
|
||||
auto descriptionResult = _description.toTextForMimeData(
|
||||
toDescriptionSelection(selection));
|
||||
if (titleResult.empty()) {
|
||||
return descriptionResult;
|
||||
} else if (descriptionResult.empty()) {
|
||||
if (titleResult.empty() && descriptionResult.empty()) {
|
||||
return siteNameResult;
|
||||
} else if (siteNameResult.empty() && descriptionResult.empty()) {
|
||||
return titleResult;
|
||||
} else if (siteNameResult.empty() && titleResult.empty()) {
|
||||
return descriptionResult;
|
||||
} else if (siteNameResult.empty()) {
|
||||
return titleResult.append('\n').append(std::move(descriptionResult));
|
||||
} else if (titleResult.empty()) {
|
||||
return siteNameResult.append('\n').append(std::move(descriptionResult));
|
||||
} else if (descriptionResult.empty()) {
|
||||
return siteNameResult.append('\n').append(std::move(titleResult));
|
||||
}
|
||||
|
||||
return titleResult.append('\n').append(std::move(descriptionResult));
|
||||
return siteNameResult.append('\n').append(std::move(titleResult)).append('\n').append(std::move(descriptionResult));
|
||||
}
|
||||
|
||||
QMargins WebPage::inBubblePadding() const {
|
||||
|
@ -89,6 +89,8 @@ private:
|
||||
QSize countOptimalSize() override;
|
||||
QSize countCurrentSize(int newWidth) override;
|
||||
|
||||
TextSelection toTitleSelection(TextSelection selection) const;
|
||||
TextSelection fromTitleSelection(TextSelection selection) const;
|
||||
TextSelection toDescriptionSelection(TextSelection selection) const;
|
||||
TextSelection fromDescriptionSelection(TextSelection selection) const;
|
||||
QMargins inBubblePadding() const;
|
||||
@ -106,11 +108,11 @@ private:
|
||||
|
||||
bool _asArticle = false;
|
||||
int _dataVersion = -1;
|
||||
int _siteNameLines = 0;
|
||||
int _titleLines = 0;
|
||||
int _descriptionLines = 0;
|
||||
|
||||
Ui::Text::String _title, _description;
|
||||
int _siteNameWidth = 0;
|
||||
Ui::Text::String _siteName, _title, _description;
|
||||
|
||||
QString _duration;
|
||||
int _durationWidth = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user