mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Improve layout of gift / auction webpage preview.
This commit is contained in:
@@ -1417,8 +1417,7 @@ void Element::overrideMedia(std::unique_ptr<Media> media) {
|
||||
Expects(!history()->owner().groups().find(data()));
|
||||
|
||||
_text = Ui::Text::String(st::msgMinWidth);
|
||||
_textWidth = -1;
|
||||
_textHeight = 0;
|
||||
invalidateTextSizeCache();
|
||||
|
||||
_media = std::move(media);
|
||||
if (!pendingResize()) {
|
||||
@@ -1603,8 +1602,8 @@ OnlyEmojiAndSpaces Element::isOnlyEmojiAndSpaces() const {
|
||||
}
|
||||
}
|
||||
|
||||
int Element::textHeightFor(int textWidth) {
|
||||
validateText();
|
||||
int Element::textHeightFor(int textWidth) const {
|
||||
const_cast<Element*>(this)->validateText();
|
||||
if (_textWidth != textWidth) {
|
||||
_textWidth = textWidth;
|
||||
_textHeight = _text.countHeight(textWidth);
|
||||
@@ -1873,20 +1872,17 @@ void Element::setTextWithLinks(
|
||||
if (const auto next = _text.nextFormattedDateUpdate()) {
|
||||
history()->session().data().registerFormattedDateUpdate(next, this);
|
||||
}
|
||||
_textWidth = -1;
|
||||
_textHeight = 0;
|
||||
invalidateTextSizeCache();
|
||||
}
|
||||
|
||||
void Element::validateTextSkipBlock(bool has, int width, int height) {
|
||||
validateText();
|
||||
if (!has) {
|
||||
if (_text.removeSkipBlock()) {
|
||||
_textWidth = -1;
|
||||
_textHeight = 0;
|
||||
invalidateTextSizeCache();
|
||||
}
|
||||
} else if (_text.updateSkipBlock(width, height)) {
|
||||
_textWidth = -1;
|
||||
_textHeight = 0;
|
||||
invalidateTextSizeCache();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2519,17 +2515,21 @@ void Element::itemTextUpdated() {
|
||||
_flags &= ~Flag::SummaryShown;
|
||||
clearSpecialOnlyEmoji();
|
||||
_text = Ui::Text::String(st::msgMinWidth);
|
||||
_textWidth = -1;
|
||||
_textHeight = 0;
|
||||
invalidateTextSizeCache();
|
||||
if (_media && !data()->media()) {
|
||||
refreshMedia(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Element::blockquoteExpandChanged() {
|
||||
invalidateTextSizeCache();
|
||||
history()->owner().requestViewResize(this);
|
||||
}
|
||||
|
||||
void Element::invalidateTextSizeCache() {
|
||||
_textWidth = -1;
|
||||
_textHeight = 0;
|
||||
history()->owner().requestViewResize(this);
|
||||
invalidateTextDependentCache();
|
||||
}
|
||||
|
||||
void Element::unloadHeavyPart() {
|
||||
|
||||
@@ -707,7 +707,7 @@ protected:
|
||||
virtual void refreshDataIdHook();
|
||||
|
||||
[[nodiscard]] const Ui::Text::String &text() const;
|
||||
[[nodiscard]] int textHeightFor(int textWidth);
|
||||
[[nodiscard]] int textHeightFor(int textWidth) const;
|
||||
void validateText();
|
||||
void validateTextSkipBlock(bool has, int width, int height);
|
||||
void validateInlineKeyboard(HistoryMessageReplyMarkup *markup);
|
||||
@@ -743,8 +743,11 @@ private:
|
||||
|
||||
virtual QSize performCountOptimalSize() = 0;
|
||||
virtual QSize performCountCurrentSize(int newWidth) = 0;
|
||||
virtual void invalidateTextDependentCache() {
|
||||
}
|
||||
|
||||
void refreshMedia(Element *replacing);
|
||||
void invalidateTextSizeCache();
|
||||
void setTextWithLinks(
|
||||
const TextWithEntities &text,
|
||||
const std::vector<ClickHandlerPtr> &links = {});
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace {
|
||||
|
||||
constexpr auto kSummarizeThreshold = 512;
|
||||
constexpr auto kPlayStatusLimit = 2;
|
||||
constexpr auto kMaxNiceToReadLines = 6;
|
||||
const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_";
|
||||
|
||||
struct SecondRightAction {
|
||||
@@ -673,6 +674,9 @@ QSize Message::performCountOptimalSize() {
|
||||
const auto botTop = item->isFakeAboutView()
|
||||
? Get<FakeBotAboutTop>()
|
||||
: nullptr;
|
||||
const auto bubble = drawBubble();
|
||||
auto withVisibleText = false;
|
||||
auto fullTextualWidth = 0;
|
||||
if (botTop) {
|
||||
botTop->init();
|
||||
}
|
||||
@@ -696,7 +700,7 @@ QSize Message::performCountOptimalSize() {
|
||||
}
|
||||
}
|
||||
|
||||
if (drawBubble()) {
|
||||
if (bubble) {
|
||||
const auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
const auto via = item->Get<HistoryMessageVia>();
|
||||
const auto entry = logEntryOriginal();
|
||||
@@ -718,8 +722,9 @@ QSize Message::performCountOptimalSize() {
|
||||
}
|
||||
|
||||
// Entry page is always a bubble bottom.
|
||||
const auto withVisibleText = hasVisibleText();
|
||||
const auto textualWidth = textualMaxWidth();
|
||||
withVisibleText = hasVisibleText();
|
||||
fullTextualWidth = textualMaxWidth();
|
||||
const auto textualWidth = bubbleTextualWidth();
|
||||
auto mediaOnBottom = (mediaDisplayed && media->isBubbleBottom()) || check || (entry/* && entry->isBubbleBottom()*/);
|
||||
auto mediaOnTop = (mediaDisplayed && media->isBubbleTop()) || (entry && entry->isBubbleTop());
|
||||
maxWidth = textualWidth;
|
||||
@@ -770,12 +775,6 @@ QSize Message::performCountOptimalSize() {
|
||||
const auto innerWidth = maxWidth
|
||||
- st::msgPadding.left()
|
||||
- st::msgPadding.right();
|
||||
if (withVisibleText) {
|
||||
if (maxWidth < textualWidth) {
|
||||
minHeight -= text().minHeight();
|
||||
minHeight += text().countHeight(innerWidth);
|
||||
}
|
||||
}
|
||||
if (reactionsInBubble) {
|
||||
minHeight -= _reactions->minHeight();
|
||||
minHeight
|
||||
@@ -869,6 +868,10 @@ QSize Message::performCountOptimalSize() {
|
||||
if (markup && markup->inlineKeyboard && hasVisibleText()) {
|
||||
accumulate_max(maxWidth, markup->inlineKeyboard->naturalWidth());
|
||||
}
|
||||
if (bubble && withVisibleText && maxWidth < fullTextualWidth) {
|
||||
minHeight -= text().minHeight();
|
||||
minHeight += textHeightFor(bubbleTextWidth(maxWidth));
|
||||
}
|
||||
return QSize(maxWidth, minHeight);
|
||||
}
|
||||
|
||||
@@ -4021,6 +4024,52 @@ int Message::monospaceMaxWidth() const {
|
||||
+ st::msgPadding.right();
|
||||
}
|
||||
|
||||
int Message::bubbleTextWidth(int bubbleWidth) const {
|
||||
return std::max(bubbleWidth, st::msgMinWidth)
|
||||
- st::msgPadding.left()
|
||||
- st::msgPadding.right();
|
||||
}
|
||||
|
||||
int Message::bubbleTextualWidth() const {
|
||||
const auto full = textualMaxWidth();
|
||||
const auto media = this->media();
|
||||
if (!hasVisibleText()
|
||||
|| !media
|
||||
|| !media->allowsNarrowBubble()) {
|
||||
return full;
|
||||
}
|
||||
const auto minimum = std::max(
|
||||
media->minBubbleWidthForNarrowBubble(),
|
||||
st::msgMinWidth);
|
||||
if (_bubbleTextualWidthMinimum != minimum) {
|
||||
_bubbleTextualWidthMinimum = minimum;
|
||||
if (minimum >= full) {
|
||||
_bubbleTextualWidthCache = minimum;
|
||||
} else {
|
||||
const auto lineHeight = text().style()->font->height;
|
||||
const auto fullTextHeight = textHeightFor(bubbleTextWidth(full));
|
||||
if (fullTextHeight > kMaxNiceToReadLines * lineHeight) {
|
||||
_bubbleTextualWidthCache = full;
|
||||
} else {
|
||||
auto left = minimum;
|
||||
auto right = full;
|
||||
while (left < right) {
|
||||
const auto middle = left + (right - left) / 2;
|
||||
const auto middleHeight = textHeightFor(
|
||||
bubbleTextWidth(middle));
|
||||
if (middleHeight <= kMaxNiceToReadLines * lineHeight) {
|
||||
right = middle;
|
||||
} else {
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
_bubbleTextualWidthCache = right;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _bubbleTextualWidthCache;
|
||||
}
|
||||
|
||||
int Message::viewButtonHeight() const {
|
||||
return _viewButton ? _viewButton->height() : 0;
|
||||
}
|
||||
@@ -4801,7 +4850,7 @@ QRect Message::countGeometry() const {
|
||||
accumulate_min(contentWidth, maxWidth());
|
||||
accumulate_min(contentWidth, int(_bubbleWidthLimit));
|
||||
if (mediaWidth < contentWidth) {
|
||||
const auto textualWidth = textualMaxWidth();
|
||||
const auto textualWidth = bubbleTextualWidth();
|
||||
if (mediaWidth < textualWidth
|
||||
&& (!media || !media->enforceBubbleWidth())) {
|
||||
accumulate_min(contentWidth, textualWidth);
|
||||
@@ -4930,10 +4979,10 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||
accumulate_min(contentWidth, maxWidth());
|
||||
_bubbleWidthLimit = std::max(st::msgMaxWidth, monospaceMaxWidth());
|
||||
accumulate_min(contentWidth, int(_bubbleWidthLimit));
|
||||
const auto textualWidth = bubbleTextualWidth();
|
||||
if (mediaDisplayed) {
|
||||
media->resizeGetHeight(contentWidth);
|
||||
if (media->width() < contentWidth) {
|
||||
const auto textualWidth = textualMaxWidth();
|
||||
if (media->width() < textualWidth
|
||||
&& !media->enforceBubbleWidth()) {
|
||||
accumulate_min(contentWidth, textualWidth);
|
||||
@@ -4942,12 +4991,17 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto textWidth = qMax(contentWidth - st::msgPadding.left() - st::msgPadding.right(), 1);
|
||||
const auto bottomInfoWidth = qMax(
|
||||
contentWidth - st::msgPadding.left() - st::msgPadding.right(),
|
||||
1);
|
||||
const auto textWidth = bubble
|
||||
? bubbleTextWidth(contentWidth)
|
||||
: bottomInfoWidth;
|
||||
const auto reactionsInBubble = _reactions && embedReactionsInBubble();
|
||||
const auto bottomInfoHeight = _bottomInfo.resizeGetHeight(
|
||||
std::min(
|
||||
_bottomInfo.optimalSize().width(),
|
||||
textWidth - 2 * st::msgDateDelta.x()));
|
||||
bottomInfoWidth - 2 * st::msgDateDelta.x()));
|
||||
|
||||
if (bubble) {
|
||||
auto reply = Get<Reply>();
|
||||
@@ -5094,6 +5148,11 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||
return newHeight;
|
||||
}
|
||||
|
||||
void Message::invalidateTextDependentCache() {
|
||||
_bubbleTextualWidthMinimum = -1;
|
||||
_bubbleTextualWidthCache = 0;
|
||||
}
|
||||
|
||||
bool Message::needInfoDisplay() const {
|
||||
const auto media = this->media();
|
||||
const auto mediaDisplayed = media ? media->isDisplayed() : false;
|
||||
|
||||
@@ -349,6 +349,8 @@ private:
|
||||
void refreshTopicButton();
|
||||
void refreshInfoSkipBlock(HistoryItem *textItem);
|
||||
[[nodiscard]] int monospaceMaxWidth() const;
|
||||
[[nodiscard]] int bubbleTextWidth(int bubbleWidth) const;
|
||||
[[nodiscard]] int bubbleTextualWidth() const;
|
||||
|
||||
void ensureSummarizeButton() const;
|
||||
void paintSummarize(
|
||||
@@ -368,6 +370,7 @@ private:
|
||||
[[nodiscard]] ClickHandlerPtr createGoToCommentsLink() const;
|
||||
[[nodiscard]] ClickHandlerPtr psaTooltipLink() const;
|
||||
void psaTooltipToggled(bool shown) const;
|
||||
void invalidateTextDependentCache() override;
|
||||
|
||||
void refreshRightBadge();
|
||||
[[nodiscard]] int rightBadgeWidth() const;
|
||||
@@ -387,6 +390,8 @@ private:
|
||||
mutable std::unique_ptr<FromNameStatus> _fromNameStatus;
|
||||
mutable std::unique_ptr<Ui::RoundCheckbox> _selectionRoundCheckbox;
|
||||
mutable int _fromNameVersion = 0;
|
||||
mutable int _bubbleTextualWidthMinimum : 16 = -1;
|
||||
mutable int _bubbleTextualWidthCache : 16 = 0;
|
||||
uint32 _bubbleWidthLimit : 27 = 0;
|
||||
uint32 _invertMedia : 1 = 0;
|
||||
uint32 _hideReply : 1 = 0;
|
||||
|
||||
@@ -330,6 +330,12 @@ public:
|
||||
[[nodiscard]] virtual bool enforceBubbleWidth() const {
|
||||
return false;
|
||||
}
|
||||
[[nodiscard]] virtual bool allowsNarrowBubble() const {
|
||||
return false;
|
||||
}
|
||||
[[nodiscard]] virtual int minBubbleWidthForNarrowBubble() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sometimes click on media in message is overloaded by the message:
|
||||
// (for example it can open a link or a game instead of opening media)
|
||||
|
||||
@@ -66,6 +66,7 @@ MediaGeneric::MediaGeneric(
|
||||
, _paintBg(_paintBgFactory ? _paintBgFactory() : nullptr)
|
||||
, _fullAreaLink(descriptor.fullAreaLink)
|
||||
, _maxWidthCap(descriptor.maxWidth)
|
||||
, _expandCurrentWidth(descriptor.expandCurrentWidth)
|
||||
, _service(descriptor.service)
|
||||
, _hideServiceText(descriptor.hideServiceText) {
|
||||
generate(this, [&](std::unique_ptr<Part> part) {
|
||||
@@ -97,7 +98,7 @@ QSize MediaGeneric::countOptimalSize() {
|
||||
}
|
||||
|
||||
QSize MediaGeneric::countCurrentSize(int newWidth) {
|
||||
if (newWidth > maxWidth()) {
|
||||
if (!_expandCurrentWidth && newWidth > maxWidth()) {
|
||||
newWidth = maxWidth();
|
||||
}
|
||||
auto top = 0;
|
||||
|
||||
@@ -61,6 +61,7 @@ struct MediaGenericDescriptor {
|
||||
int maxWidth = 0;
|
||||
MediaGenericPart::PaintBgFactory paintBgFactory;
|
||||
ClickHandlerPtr fullAreaLink;
|
||||
bool expandCurrentWidth = false;
|
||||
bool service = false;
|
||||
bool hideServiceText = false;
|
||||
};
|
||||
@@ -133,6 +134,7 @@ private:
|
||||
int _maxWidthCap = 0;
|
||||
int _marginTop = 0;
|
||||
int _marginBottom = 0;
|
||||
bool _expandCurrentWidth : 1 = false;
|
||||
bool _service : 1 = false;
|
||||
bool _hideServiceText : 1 = false;
|
||||
|
||||
|
||||
@@ -533,6 +533,7 @@ QSize WebPage::countOptimalSize() {
|
||||
.paintBgFactory = [=] {
|
||||
return UniqueGiftBg(_parent, _data->uniqueGift);
|
||||
},
|
||||
.expandCurrentWidth = true,
|
||||
});
|
||||
} else if (!_attach && _data->auction) {
|
||||
const auto &gift = _data->auction->auctionGift;
|
||||
@@ -556,6 +557,7 @@ QSize WebPage::countOptimalSize() {
|
||||
_data->auction->auctionGift->auctionStartDate,
|
||||
_data->auction->endDate);
|
||||
},
|
||||
.expandCurrentWidth = true,
|
||||
});
|
||||
} else if (!_attach && !_asArticle) {
|
||||
_attach = CreateAttach(
|
||||
@@ -1623,6 +1625,15 @@ bool WebPage::enforceBubbleWidth() const {
|
||||
&& (_data->document->isWallPaper() || _data->document->isTheme());
|
||||
}
|
||||
|
||||
bool WebPage::allowsNarrowBubble() const {
|
||||
return (_attach != nullptr)
|
||||
&& (_data->uniqueGift != nullptr || _data->auction != nullptr);
|
||||
}
|
||||
|
||||
int WebPage::minBubbleWidthForNarrowBubble() const {
|
||||
return allowsNarrowBubble() ? maxWidth() : 0;
|
||||
}
|
||||
|
||||
void WebPage::playAnimation(bool autoplay) {
|
||||
if (_attach) {
|
||||
if (autoplay) {
|
||||
|
||||
@@ -94,6 +94,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
bool enforceBubbleWidth() const override;
|
||||
bool allowsNarrowBubble() const override;
|
||||
int minBubbleWidthForNarrowBubble() const override;
|
||||
|
||||
Media *attach() const {
|
||||
return _attach.get();
|
||||
|
||||
Reference in New Issue
Block a user