mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 22:54:01 +02:00
Support media covers for bot descriptions.
For that replace custom handling of _botAbout by a fake message.
This commit is contained in:
parent
59c66d1f49
commit
221b0d19c7
10 changed files with 325 additions and 205 deletions
|
@ -293,6 +293,9 @@ enum class MessageFlag : uint64 {
|
||||||
|
|
||||||
OnlyEmojiAndSpaces = (1ULL << 34),
|
OnlyEmojiAndSpaces = (1ULL << 34),
|
||||||
OnlyEmojiAndSpacesSet = (1ULL << 35),
|
OnlyEmojiAndSpacesSet = (1ULL << 35),
|
||||||
|
|
||||||
|
// Fake message with bot cover and information.
|
||||||
|
FakeBotAbout = (1ULL << 36),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
||||||
using MessageFlags = base::flags<MessageFlag>;
|
using MessageFlags = base::flags<MessageFlag>;
|
||||||
|
|
|
@ -32,8 +32,7 @@ using UpdateFlag = Data::PeerUpdate::Flag;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
BotInfo::BotInfo() : text(st::msgMinWidth) {
|
BotInfo::BotInfo() = default;
|
||||||
}
|
|
||||||
|
|
||||||
UserData::UserData(not_null<Data::Session*> owner, PeerId id)
|
UserData::UserData(not_null<Data::Session*> owner, PeerId id)
|
||||||
: PeerData(owner, id)
|
: PeerData(owner, id)
|
||||||
|
@ -188,10 +187,30 @@ void UserData::setBotInfo(const MTPBotInfo &info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString desc = qs(d.vdescription().value_or_empty());
|
const auto description = qs(d.vdescription().value_or_empty());
|
||||||
if (botInfo->description != desc) {
|
if (botInfo->description != description) {
|
||||||
botInfo->description = desc;
|
botInfo->description = description;
|
||||||
botInfo->text = Ui::Text::String(st::msgMinWidth);
|
++botInfo->descriptionVersion;
|
||||||
|
}
|
||||||
|
if (const auto photo = d.vdescription_photo()) {
|
||||||
|
const auto parsed = owner().processPhoto(*photo);
|
||||||
|
if (botInfo->photo != parsed) {
|
||||||
|
botInfo->photo = parsed;
|
||||||
|
++botInfo->descriptionVersion;
|
||||||
|
}
|
||||||
|
} else if (botInfo->photo) {
|
||||||
|
botInfo->photo = nullptr;
|
||||||
|
++botInfo->descriptionVersion;
|
||||||
|
}
|
||||||
|
if (const auto document = d.vdescription_document()) {
|
||||||
|
const auto parsed = owner().processDocument(*document);
|
||||||
|
if (botInfo->document != parsed) {
|
||||||
|
botInfo->document = parsed;
|
||||||
|
++botInfo->descriptionVersion;
|
||||||
|
}
|
||||||
|
} else if (botInfo->document) {
|
||||||
|
botInfo->document = nullptr;
|
||||||
|
++botInfo->descriptionVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto commands = d.vcommands()
|
auto commands = d.vcommands()
|
||||||
|
|
|
@ -24,9 +24,13 @@ struct BotInfo {
|
||||||
bool cantJoinGroups = false;
|
bool cantJoinGroups = false;
|
||||||
bool supportsAttachMenu = false;
|
bool supportsAttachMenu = false;
|
||||||
int version = 0;
|
int version = 0;
|
||||||
QString description, inlinePlaceholder;
|
int descriptionVersion = 0;
|
||||||
|
QString description;
|
||||||
|
QString inlinePlaceholder;
|
||||||
std::vector<Data::BotCommand> commands;
|
std::vector<Data::BotCommand> commands;
|
||||||
Ui::Text::String text;
|
|
||||||
|
PhotoData *photo = nullptr;
|
||||||
|
DocumentData *document = nullptr;
|
||||||
|
|
||||||
QString botMenuButtonText;
|
QString botMenuButtonText;
|
||||||
QString botMenuButtonUrl;
|
QString botMenuButtonUrl;
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/crash_reports.h"
|
#include "core/crash_reports.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
|
#include "history/admin_log/history_admin_log_item.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history_item_helpers.h"
|
#include "history/history_item_helpers.h"
|
||||||
#include "history/view/media/history_view_media.h"
|
#include "history/view/media/history_view_media.h"
|
||||||
|
@ -326,41 +327,100 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class HistoryInner::BotAbout : public ClickHandlerHost {
|
class HistoryInner::BotAbout final : public ClickHandlerHost {
|
||||||
public:
|
public:
|
||||||
BotAbout(not_null<HistoryInner*> parent, not_null<BotInfo*> info);
|
BotAbout(
|
||||||
|
not_null<History*> history,
|
||||||
|
not_null<HistoryView::ElementDelegate*> delegate);
|
||||||
|
|
||||||
// ClickHandlerHost interface
|
[[nodiscard]] not_null<History*> history() const;
|
||||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
[[nodiscard]] HistoryView::Element *view() const;
|
||||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
|
[[nodiscard]] HistoryItem *item() const;
|
||||||
|
|
||||||
not_null<BotInfo*> info;
|
bool refresh();
|
||||||
int width = 0;
|
|
||||||
|
int top = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
QRect rect;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
not_null<HistoryInner*> _parent;
|
const not_null<History*> _history;
|
||||||
|
const not_null<HistoryView::ElementDelegate*> _delegate;
|
||||||
|
AdminLog::OwnedItem _item;
|
||||||
|
int _version = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HistoryInner::BotAbout::BotAbout(
|
HistoryInner::BotAbout::BotAbout(
|
||||||
not_null<HistoryInner*> parent,
|
not_null<History*> history,
|
||||||
not_null<BotInfo*> info)
|
not_null<HistoryView::ElementDelegate*> delegate)
|
||||||
: info(info)
|
: _history(history)
|
||||||
, _parent(parent) {
|
, _delegate(delegate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::BotAbout::clickHandlerActiveChanged(
|
not_null<History*> HistoryInner::BotAbout::history() const {
|
||||||
const ClickHandlerPtr &p,
|
return _history;
|
||||||
bool active) {
|
|
||||||
_parent->update(rect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::BotAbout::clickHandlerPressedChanged(
|
HistoryView::Element *HistoryInner::BotAbout::view() const {
|
||||||
const ClickHandlerPtr &p,
|
return _item.get();
|
||||||
bool pressed) {
|
}
|
||||||
_parent->update(rect);
|
|
||||||
|
HistoryItem *HistoryInner::BotAbout::item() const {
|
||||||
|
if (const auto element = view()) {
|
||||||
|
return element->data();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistoryInner::BotAbout::refresh() {
|
||||||
|
const auto bot = _history->peer->asUser();
|
||||||
|
const auto info = bot ? bot->botInfo.get() : nullptr;
|
||||||
|
if (!info) {
|
||||||
|
if (_item) {
|
||||||
|
_item = {};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_version = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto version = info->descriptionVersion;
|
||||||
|
if (_version == version) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_version = version;
|
||||||
|
|
||||||
|
const auto flags = MessageFlag::FakeBotAbout
|
||||||
|
| MessageFlag::FakeHistoryItem
|
||||||
|
| MessageFlag::Local;
|
||||||
|
const auto postAuthor = QString();
|
||||||
|
const auto date = TimeId(0);
|
||||||
|
const auto replyTo = MsgId(0);
|
||||||
|
const auto viaBotId = UserId(0);
|
||||||
|
const auto groupedId = uint64(0);
|
||||||
|
const auto textWithEntities = TextUtilities::ParseEntities(
|
||||||
|
info->description,
|
||||||
|
Ui::ItemTextBotNoMonoOptions().flags);
|
||||||
|
const auto make = [&](auto &&a, auto &&b, auto &&...other) {
|
||||||
|
return _history->makeMessage(
|
||||||
|
_history->nextNonHistoryEntryId(),
|
||||||
|
flags,
|
||||||
|
replyTo,
|
||||||
|
viaBotId,
|
||||||
|
date,
|
||||||
|
bot->id,
|
||||||
|
postAuthor,
|
||||||
|
std::forward<decltype(a)>(a),
|
||||||
|
std::forward<decltype(b)>(b),
|
||||||
|
HistoryMessageMarkupData(),
|
||||||
|
std::forward<decltype(other)>(other)...);
|
||||||
|
};
|
||||||
|
const auto item = info->document
|
||||||
|
? make(info->document, textWithEntities)
|
||||||
|
: info->photo
|
||||||
|
? make(info->photo, textWithEntities)
|
||||||
|
: make(textWithEntities, MTP_messageMediaEmpty(), groupedId);
|
||||||
|
_item = AdminLog::OwnedItem(_delegate, item);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryInner::HistoryInner(
|
HistoryInner::HistoryInner(
|
||||||
|
@ -971,41 +1031,10 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
const auto historyDisplayedEmpty = _history->isDisplayedEmpty()
|
const auto historyDisplayedEmpty = _history->isDisplayedEmpty()
|
||||||
&& (!_migrated || _migrated->isDisplayedEmpty());
|
&& (!_migrated || _migrated->isDisplayedEmpty());
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
|
if (const auto view = _botAbout ? _botAbout->view() : nullptr) {
|
||||||
const auto st = context.st;
|
if (clip.y() < _botAbout->top + _botAbout->height
|
||||||
const auto stm = &st->messageStyle(false, false);
|
&& clip.y() + clip.height() > _botAbout->top) {
|
||||||
if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) {
|
view->draw(p, context);
|
||||||
p.setTextPalette(stm->textPalette);
|
|
||||||
using Corner = Ui::BubbleCornerRounding;
|
|
||||||
const auto rounding = Ui::BubbleRounding{
|
|
||||||
Corner::Large,
|
|
||||||
Corner::Large,
|
|
||||||
Corner::Large,
|
|
||||||
Corner::Large,
|
|
||||||
};
|
|
||||||
Ui::PaintBubble(p, Ui::SimpleBubble{
|
|
||||||
.st = st,
|
|
||||||
.geometry = _botAbout->rect,
|
|
||||||
.pattern = context.bubblesPattern,
|
|
||||||
.patternViewport = context.viewport,
|
|
||||||
.outerWidth = width(),
|
|
||||||
.selected = false,
|
|
||||||
.outbg = false,
|
|
||||||
.rounding = rounding,
|
|
||||||
});
|
|
||||||
|
|
||||||
auto top = _botAbout->rect.top() + st::msgPadding.top();
|
|
||||||
if (!_history->peer->isRepliesChat()) {
|
|
||||||
p.setFont(st::msgNameFont);
|
|
||||||
p.setPen(st->dialogsNameFg());
|
|
||||||
p.drawText(_botAbout->rect.left() + st::msgPadding.left(), top + st::msgNameFont->ascent, tr::lng_bot_description(tr::now));
|
|
||||||
top += +st::msgNameFont->height + st::botDescSkip;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setPen(stm->historyTextFg);
|
|
||||||
_botAbout->info->text.draw(p, _botAbout->rect.left() + st::msgPadding.left(), top, _botAbout->width);
|
|
||||||
|
|
||||||
p.restoreTextPalette();
|
|
||||||
}
|
}
|
||||||
} else if (historyDisplayedEmpty) {
|
} else if (historyDisplayedEmpty) {
|
||||||
paintEmpty(p, context.st, width(), height());
|
paintEmpty(p, context.st, width(), height());
|
||||||
|
@ -2939,9 +2968,11 @@ void HistoryInner::recountHistoryGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto visibleHeight = _scroll->height();
|
const auto visibleHeight = _scroll->height();
|
||||||
int oldHistoryPaddingTop = qMax(visibleHeight - historyHeight() - st::historyPaddingBottom, 0);
|
auto oldHistoryPaddingTop = qMax(
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty()) {
|
visibleHeight - historyHeight() - st::historyPaddingBottom,
|
||||||
accumulate_max(oldHistoryPaddingTop, st::msgMargin.top() + st::msgMargin.bottom() + st::msgPadding.top() + st::msgPadding.bottom() + st::msgNameFont->height + st::botDescSkip + _botAbout->height);
|
0);
|
||||||
|
if (_botAbout) {
|
||||||
|
accumulate_max(oldHistoryPaddingTop, _botAbout->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
_history->resizeToWidth(_contentWidth);
|
_history->resizeToWidth(_contentWidth);
|
||||||
|
@ -2968,39 +2999,20 @@ void HistoryInner::recountHistoryGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBotInfo(false);
|
updateBotInfo(false);
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty()) {
|
if (const auto view = _botAbout ? _botAbout->view() : nullptr) {
|
||||||
int32 tw = _scroll->width() - st::msgMargin.left() - st::msgMargin.right();
|
_botAbout->height = view->resizeGetHeight(_contentWidth);
|
||||||
if (tw > st::msgMaxWidth) tw = st::msgMaxWidth;
|
_botAbout->top = qMin(
|
||||||
tw -= st::msgPadding.left() + st::msgPadding.right();
|
_historyPaddingTop - _botAbout->height,
|
||||||
const auto descriptionWidth = _history->peer->isRepliesChat()
|
qMax(0, (_scroll->height() - _botAbout->height) / 2));
|
||||||
? 0
|
|
||||||
: st::msgNameFont->width(tr::lng_bot_description(tr::now));
|
|
||||||
int32 mw = qMax(_botAbout->info->text.maxWidth(), descriptionWidth);
|
|
||||||
if (tw > mw) tw = mw;
|
|
||||||
|
|
||||||
_botAbout->width = tw;
|
|
||||||
_botAbout->height = _botAbout->info->text.countHeight(_botAbout->width);
|
|
||||||
|
|
||||||
const auto descriptionHeight = _history->peer->isRepliesChat()
|
|
||||||
? 0
|
|
||||||
: (st::msgNameFont->height + st::botDescSkip);
|
|
||||||
int32 descH = st::msgMargin.top() + st::msgPadding.top() + descriptionHeight + _botAbout->height + st::msgPadding.bottom() + st::msgMargin.bottom();
|
|
||||||
int32 descMaxWidth = _scroll->width();
|
|
||||||
if (_isChatWide) {
|
|
||||||
descMaxWidth = qMin(descMaxWidth, int32(st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left()));
|
|
||||||
}
|
|
||||||
int32 descAtX = (descMaxWidth - _botAbout->width) / 2 - st::msgPadding.left();
|
|
||||||
int32 descAtY = qMin(_historyPaddingTop - descH, qMax(0, (_scroll->height() - descH) / 2)) + st::msgMargin.top();
|
|
||||||
|
|
||||||
_botAbout->rect = QRect(descAtX, descAtY, _botAbout->width + st::msgPadding.left() + st::msgPadding.right(), descH - st::msgMargin.top() - st::msgMargin.bottom());
|
|
||||||
} else if (_botAbout) {
|
} else if (_botAbout) {
|
||||||
_botAbout->width = _botAbout->height = 0;
|
_botAbout->top = _botAbout->height = 0;
|
||||||
_botAbout->rect = QRect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int newHistoryPaddingTop = qMax(visibleHeight - historyHeight() - st::historyPaddingBottom, 0);
|
auto newHistoryPaddingTop = qMax(
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty()) {
|
visibleHeight - historyHeight() - st::historyPaddingBottom,
|
||||||
accumulate_max(newHistoryPaddingTop, st::msgMargin.top() + st::msgMargin.bottom() + st::msgPadding.top() + st::msgPadding.bottom() + st::msgNameFont->height + st::botDescSkip + _botAbout->height);
|
0);
|
||||||
|
if (_botAbout) {
|
||||||
|
accumulate_max(newHistoryPaddingTop, _botAbout->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto historyPaddingTopDelta = (newHistoryPaddingTop - oldHistoryPaddingTop);
|
auto historyPaddingTopDelta = (newHistoryPaddingTop - oldHistoryPaddingTop);
|
||||||
|
@ -3014,48 +3026,15 @@ void HistoryInner::recountHistoryGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::updateBotInfo(bool recount) {
|
void HistoryInner::updateBotInfo(bool recount) {
|
||||||
int newh = 0;
|
if (!_botAbout) {
|
||||||
if (_botAbout && !_botAbout->info->description.isEmpty()) {
|
return;
|
||||||
if (_botAbout->info->text.isEmpty()) {
|
} else if (_botAbout->refresh() && recount && _contentWidth > 0) {
|
||||||
_botAbout->info->text.setText(
|
const auto view = _botAbout->view();
|
||||||
st::messageTextStyle,
|
const auto now = view ? view->resizeGetHeight(_contentWidth) : 0;
|
||||||
_botAbout->info->description,
|
if (_botAbout->height != now) {
|
||||||
Ui::ItemTextBotNoMonoOptions());
|
_botAbout->height = now;
|
||||||
if (recount) {
|
|
||||||
int32 tw = _scroll->width() - st::msgMargin.left() - st::msgMargin.right();
|
|
||||||
if (tw > st::msgMaxWidth) tw = st::msgMaxWidth;
|
|
||||||
tw -= st::msgPadding.left() + st::msgPadding.right();
|
|
||||||
const auto descriptionWidth = _history->peer->isRepliesChat()
|
|
||||||
? 0
|
|
||||||
: st::msgNameFont->width(tr::lng_bot_description(tr::now));
|
|
||||||
int32 mw = qMax(_botAbout->info->text.maxWidth(), descriptionWidth);
|
|
||||||
if (tw > mw) tw = mw;
|
|
||||||
|
|
||||||
_botAbout->width = tw;
|
|
||||||
newh = _botAbout->info->text.countHeight(_botAbout->width);
|
|
||||||
}
|
|
||||||
} else if (recount) {
|
|
||||||
newh = _botAbout->height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (recount && _botAbout) {
|
|
||||||
if (_botAbout->height != newh) {
|
|
||||||
_botAbout->height = newh;
|
|
||||||
updateSize();
|
updateSize();
|
||||||
}
|
}
|
||||||
if (_botAbout->height > 0) {
|
|
||||||
const auto descriptionHeight = _history->peer->isRepliesChat()
|
|
||||||
? 0
|
|
||||||
: (st::msgNameFont->height + st::botDescSkip);
|
|
||||||
int32 descH = st::msgMargin.top() + st::msgPadding.top() + descriptionHeight + _botAbout->height + st::msgPadding.bottom() + st::msgMargin.bottom();
|
|
||||||
int32 descAtX = (_scroll->width() - _botAbout->width) / 2 - st::msgPadding.left();
|
|
||||||
int32 descAtY = qMin(_historyPaddingTop - descH, (_scroll->height() - descH) / 2) + st::msgMargin.top();
|
|
||||||
|
|
||||||
_botAbout->rect = QRect(descAtX, descAtY, _botAbout->width + st::msgPadding.left() + st::msgPadding.right(), descH - st::msgMargin.top() - st::msgMargin.bottom());
|
|
||||||
} else {
|
|
||||||
_botAbout->width = 0;
|
|
||||||
_botAbout->rect = QRect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3200,24 +3179,15 @@ void HistoryInner::changeItemsRevealHeight(int revealHeight) {
|
||||||
void HistoryInner::updateSize() {
|
void HistoryInner::updateSize() {
|
||||||
const auto visibleHeight = _scroll->height();
|
const auto visibleHeight = _scroll->height();
|
||||||
const auto itemsHeight = historyHeight() - _revealHeight;
|
const auto itemsHeight = historyHeight() - _revealHeight;
|
||||||
int newHistoryPaddingTop = qMax(visibleHeight - itemsHeight - st::historyPaddingBottom, 0);
|
auto newHistoryPaddingTop = qMax(visibleHeight - itemsHeight - st::historyPaddingBottom, 0);
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty()) {
|
if (_botAbout) {
|
||||||
accumulate_max(newHistoryPaddingTop, st::msgMargin.top() + st::msgMargin.bottom() + st::msgPadding.top() + st::msgPadding.bottom() + st::msgNameFont->height + st::botDescSkip + _botAbout->height);
|
accumulate_max(newHistoryPaddingTop, _botAbout->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_botAbout && _botAbout->height > 0) {
|
if (_botAbout && _botAbout->height > 0) {
|
||||||
const auto descriptionHeight = _history->peer->isRepliesChat()
|
_botAbout->top = qMin(
|
||||||
? 0
|
newHistoryPaddingTop - _botAbout->height,
|
||||||
: (st::msgNameFont->height + st::botDescSkip);
|
qMax(0, (_scroll->height() - _botAbout->height) / 2));
|
||||||
int32 descH = st::msgMargin.top() + st::msgPadding.top() + descriptionHeight + _botAbout->height + st::msgPadding.bottom() + st::msgMargin.bottom();
|
|
||||||
int32 descMaxWidth = _scroll->width();
|
|
||||||
if (_isChatWide) {
|
|
||||||
descMaxWidth = qMin(descMaxWidth, int32(st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left()));
|
|
||||||
}
|
|
||||||
int32 descAtX = (descMaxWidth - _botAbout->width) / 2 - st::msgPadding.left();
|
|
||||||
int32 descAtY = qMin(newHistoryPaddingTop - descH, qMax(0, (_scroll->height() - descH) / 2)) + st::msgMargin.top();
|
|
||||||
|
|
||||||
_botAbout->rect = QRect(descAtX, descAtY, _botAbout->width + st::msgPadding.left() + st::msgPadding.right(), descH - st::msgMargin.top() - st::msgMargin.bottom());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_historyPaddingTop != newHistoryPaddingTop) {
|
if (_historyPaddingTop != newHistoryPaddingTop) {
|
||||||
|
@ -3261,6 +3231,7 @@ void HistoryInner::leaveEventHook(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryInner::~HistoryInner() {
|
HistoryInner::~HistoryInner() {
|
||||||
|
_botAbout = nullptr;
|
||||||
for (const auto &item : _animatedStickersPlayed) {
|
for (const auto &item : _animatedStickersPlayed) {
|
||||||
if (const auto view = item->mainView()) {
|
if (const auto view = item->mainView()) {
|
||||||
if (const auto media = view->media()) {
|
if (const auto media = view->media()) {
|
||||||
|
@ -3632,12 +3603,15 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
dragState = reactionState;
|
dragState = reactionState;
|
||||||
lnkhost = reactionView;
|
lnkhost = reactionView;
|
||||||
} else if (point.y() < _historyPaddingTop) {
|
} else if (point.y() < _historyPaddingTop) {
|
||||||
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
|
if (const auto view = _botAbout ? _botAbout->view() : nullptr) {
|
||||||
dragState = TextState(nullptr, _botAbout->info->text.getState(
|
StateRequest request;
|
||||||
point - _botAbout->rect.topLeft() - QPoint(st::msgPadding.left(), st::msgPadding.top() + st::botDescSkip + st::msgNameFont->height),
|
if (base::IsAltPressed()) {
|
||||||
_botAbout->width));
|
request.flags &= ~Ui::Text::StateRequest::Flag::LookupLink;
|
||||||
|
}
|
||||||
|
const auto relative = point - QPoint(0, _botAbout->top);
|
||||||
|
dragState = view->textState(relative, request);
|
||||||
_dragStateItem = session().data().message(dragState.itemId);
|
_dragStateItem = session().data().message(dragState.itemId);
|
||||||
lnkhost = _botAbout.get();
|
lnkhost = view;
|
||||||
}
|
}
|
||||||
} else if (item) {
|
} else if (item) {
|
||||||
if (item != _mouseActionItem || (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
if (item != _mouseActionItem || (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
|
@ -3947,16 +3921,22 @@ void HistoryInner::setCanHaveFromUserpicsSponsored(bool value) {
|
||||||
int HistoryInner::itemTop(const HistoryItem *item) const {
|
int HistoryInner::itemTop(const HistoryItem *item) const {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return -2;
|
return -2;
|
||||||
|
} else if (_botAbout && item == _botAbout->item()) {
|
||||||
|
return _botAbout->top;
|
||||||
}
|
}
|
||||||
return itemTop(item->mainView());
|
return itemTop(item->mainView());
|
||||||
}
|
}
|
||||||
|
|
||||||
int HistoryInner::itemTop(const Element *view) const {
|
int HistoryInner::itemTop(const Element *view) const {
|
||||||
if (!view || view->data()->mainView() != view) {
|
if (!view) {
|
||||||
|
return -1;
|
||||||
|
} else if (_botAbout && view == _botAbout->view()) {
|
||||||
|
return _botAbout->top;
|
||||||
|
} else if (view->data()->mainView() != view) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto top = (view->history() == _history)
|
const auto top = (view->history() == _history)
|
||||||
? historyTop()
|
? historyTop()
|
||||||
: (view->history() == _migrated
|
: (view->history() == _migrated
|
||||||
? migratedTop()
|
? migratedTop()
|
||||||
|
@ -3990,21 +3970,17 @@ auto HistoryInner::findViewForPinnedTracking(int top) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::notifyIsBotChanged() {
|
void HistoryInner::notifyIsBotChanged() {
|
||||||
const auto newinfo = _peer->isUser()
|
if (const auto user = _peer->asUser()) {
|
||||||
? _peer->asUser()->botInfo.get()
|
if (const auto info = user->botInfo.get()) {
|
||||||
: nullptr;
|
if (!_botAbout) {
|
||||||
if ((!newinfo && !_botAbout)
|
_botAbout = std::make_unique<BotAbout>(
|
||||||
|| (newinfo && _botAbout && _botAbout->info == newinfo)) {
|
_history,
|
||||||
return;
|
_history->delegateMixin()->delegate());
|
||||||
}
|
}
|
||||||
|
if (!info->inited) {
|
||||||
if (newinfo) {
|
session().api().requestFullPeer(_peer);
|
||||||
_botAbout = std::make_unique<BotAbout>(this, newinfo);
|
}
|
||||||
if (newinfo && !newinfo->inited) {
|
|
||||||
session().api().requestFullPeer(_peer);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_botAbout = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -306,6 +306,9 @@ public:
|
||||||
[[nodiscard]] bool isLocal() const {
|
[[nodiscard]] bool isLocal() const {
|
||||||
return _flags & MessageFlag::Local;
|
return _flags & MessageFlag::Local;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] bool isFakeBotAbout() const {
|
||||||
|
return _flags & MessageFlag::FakeBotAbout;
|
||||||
|
}
|
||||||
[[nodiscard]] bool isRegular() const;
|
[[nodiscard]] bool isRegular() const;
|
||||||
[[nodiscard]] bool isUploading() const;
|
[[nodiscard]] bool isUploading() const;
|
||||||
void sendFailed();
|
void sendFailed();
|
||||||
|
|
|
@ -354,6 +354,20 @@ void DateBadge::paint(
|
||||||
ServiceMessagePainter::PaintDate(p, st, text, width, y, w, chatWide);
|
ServiceMessagePainter::PaintDate(p, st, text, width, y, w, chatWide);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FakeBotAboutTop::init() {
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
text.setText(
|
||||||
|
st::msgNameStyle,
|
||||||
|
tr::lng_bot_description(tr::now),
|
||||||
|
Ui::NameTextOptions());
|
||||||
|
maxWidth = st::msgPadding.left()
|
||||||
|
+ text.maxWidth()
|
||||||
|
+ st::msgPadding.right();
|
||||||
|
height = st::msgNameStyle.font->height + st::botDescSkip;
|
||||||
|
}
|
||||||
|
|
||||||
Element::Element(
|
Element::Element(
|
||||||
not_null<ElementDelegate*> delegate,
|
not_null<ElementDelegate*> delegate,
|
||||||
not_null<HistoryItem*> data,
|
not_null<HistoryItem*> data,
|
||||||
|
@ -376,6 +390,9 @@ Element::Element(
|
||||||
if (_context == Context::History) {
|
if (_context == Context::History) {
|
||||||
history()->setHasPendingResizedItems();
|
history()->setHasPendingResizedItems();
|
||||||
}
|
}
|
||||||
|
if (data->isFakeBotAbout() && !data->history()->peer->isRepliesChat()) {
|
||||||
|
AddComponents(FakeBotAboutTop::Bit());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<ElementDelegate*> Element::delegate() const {
|
not_null<ElementDelegate*> Element::delegate() const {
|
||||||
|
|
|
@ -230,6 +230,14 @@ struct DateBadge : public RuntimeComponent<DateBadge, Element> {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FakeBotAboutTop : public RuntimeComponent<FakeBotAboutTop, Element> {
|
||||||
|
void init();
|
||||||
|
|
||||||
|
Ui::Text::String text;
|
||||||
|
int maxWidth = 0;
|
||||||
|
int height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct TopicButton {
|
struct TopicButton {
|
||||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||||
ClickHandlerPtr link;
|
ClickHandlerPtr link;
|
||||||
|
|
|
@ -530,6 +530,12 @@ QSize Message::performCountOptimalSize() {
|
||||||
refreshInfoSkipBlock();
|
refreshInfoSkipBlock();
|
||||||
|
|
||||||
const auto media = this->media();
|
const auto media = this->media();
|
||||||
|
const auto botTop = item->isFakeBotAbout()
|
||||||
|
? Get<FakeBotAboutTop>()
|
||||||
|
: nullptr;
|
||||||
|
if (botTop) {
|
||||||
|
botTop->init();
|
||||||
|
}
|
||||||
|
|
||||||
auto maxWidth = 0;
|
auto maxWidth = 0;
|
||||||
auto minHeight = 0;
|
auto minHeight = 0;
|
||||||
|
@ -560,13 +566,14 @@ QSize Message::performCountOptimalSize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry page is always a bubble bottom.
|
// Entry page is always a bubble bottom.
|
||||||
|
const auto withVisibleText = hasVisibleText();
|
||||||
auto mediaOnBottom = (mediaDisplayed && media->isBubbleBottom()) || (entry/* && entry->isBubbleBottom()*/);
|
auto mediaOnBottom = (mediaDisplayed && media->isBubbleBottom()) || (entry/* && entry->isBubbleBottom()*/);
|
||||||
auto mediaOnTop = (mediaDisplayed && media->isBubbleTop()) || (entry && entry->isBubbleTop());
|
auto mediaOnTop = (mediaDisplayed && media->isBubbleTop()) || (entry && entry->isBubbleTop());
|
||||||
maxWidth = plainMaxWidth();
|
maxWidth = plainMaxWidth();
|
||||||
if (context() == Context::Replies && item->isDiscussionPost()) {
|
if (context() == Context::Replies && item->isDiscussionPost()) {
|
||||||
maxWidth = std::max(maxWidth, st::msgMaxWidth);
|
maxWidth = std::max(maxWidth, st::msgMaxWidth);
|
||||||
}
|
}
|
||||||
minHeight = hasVisibleText() ? text().minHeight() : 0;
|
minHeight = withVisibleText ? text().minHeight() : 0;
|
||||||
if (reactionsInBubble) {
|
if (reactionsInBubble) {
|
||||||
const auto reactionsMaxWidth = st::msgPadding.left()
|
const auto reactionsMaxWidth = st::msgPadding.left()
|
||||||
+ _reactions->maxWidth()
|
+ _reactions->maxWidth()
|
||||||
|
@ -604,9 +611,14 @@ QSize Message::performCountOptimalSize() {
|
||||||
const auto innerWidth = maxWidth
|
const auto innerWidth = maxWidth
|
||||||
- st::msgPadding.left()
|
- st::msgPadding.left()
|
||||||
- st::msgPadding.right();
|
- st::msgPadding.right();
|
||||||
if (hasVisibleText() && maxWidth < plainMaxWidth()) {
|
if (withVisibleText) {
|
||||||
minHeight -= text().minHeight();
|
if (botTop) {
|
||||||
minHeight += text().countHeight(innerWidth);
|
minHeight += botTop->height;
|
||||||
|
}
|
||||||
|
if (maxWidth < plainMaxWidth()) {
|
||||||
|
minHeight -= text().minHeight();
|
||||||
|
minHeight += text().countHeight(innerWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (reactionsInBubble) {
|
if (reactionsInBubble) {
|
||||||
minHeight -= _reactions->minHeight();
|
minHeight -= _reactions->minHeight();
|
||||||
|
@ -678,6 +690,10 @@ QSize Message::performCountOptimalSize() {
|
||||||
accumulate_max(maxWidth, entry->maxWidth());
|
accumulate_max(maxWidth, entry->maxWidth());
|
||||||
minHeight += entry->minHeight();
|
minHeight += entry->minHeight();
|
||||||
}
|
}
|
||||||
|
if (withVisibleText && botTop) {
|
||||||
|
accumulate_max(maxWidth, botTop->maxWidth);
|
||||||
|
minHeight += botTop->height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
accumulate_max(maxWidth, minWidthForMedia());
|
accumulate_max(maxWidth, minWidthForMedia());
|
||||||
} else if (media) {
|
} else if (media) {
|
||||||
|
@ -1467,6 +1483,15 @@ void Message::paintText(
|
||||||
p.setPen(stm->historyTextFg);
|
p.setPen(stm->historyTextFg);
|
||||||
p.setFont(st::msgFont);
|
p.setFont(st::msgFont);
|
||||||
prepareCustomEmojiPaint(p, context, text());
|
prepareCustomEmojiPaint(p, context, text());
|
||||||
|
if (const auto botTop = Get<FakeBotAboutTop>()) {
|
||||||
|
botTop->text.drawLeftElided(
|
||||||
|
p,
|
||||||
|
trect.x(),
|
||||||
|
trect.y(),
|
||||||
|
trect.width(),
|
||||||
|
width());
|
||||||
|
trect.setY(trect.y() + botTop->height);
|
||||||
|
}
|
||||||
text().draw(p, {
|
text().draw(p, {
|
||||||
.position = trect.topLeft(),
|
.position = trect.topLeft(),
|
||||||
.availableWidth = trect.width(),
|
.availableWidth = trect.width(),
|
||||||
|
@ -2281,6 +2306,8 @@ bool Message::getStateText(
|
||||||
StateRequest request) const {
|
StateRequest request) const {
|
||||||
if (!hasVisibleText()) {
|
if (!hasVisibleText()) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (const auto botTop = Get<FakeBotAboutTop>()) {
|
||||||
|
trect.setY(trect.y() + botTop->height);
|
||||||
}
|
}
|
||||||
const auto item = data();
|
const auto item = data();
|
||||||
if (base::in_range(point.y(), trect.y(), trect.y() + trect.height())) {
|
if (base::in_range(point.y(), trect.y(), trect.y() + trect.height())) {
|
||||||
|
@ -2886,7 +2913,7 @@ bool Message::drawBubble() const {
|
||||||
const auto item = data();
|
const auto item = data();
|
||||||
if (isHidden()) {
|
if (isHidden()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (logEntryOriginal()) {
|
} else if (logEntryOriginal() || item->isFakeBotAbout()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const auto media = this->media();
|
const auto media = this->media();
|
||||||
|
@ -3376,8 +3403,9 @@ QRect Message::innerGeometry() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect Message::countGeometry() const {
|
QRect Message::countGeometry() const {
|
||||||
const auto commentsRoot = (context() == Context::Replies)
|
const auto item = data();
|
||||||
&& data()->isDiscussionPost();
|
const auto centeredView = item->isFakeBotAbout()
|
||||||
|
|| (context() == Context::Replies && item->isDiscussionPost());
|
||||||
const auto media = this->media();
|
const auto media = this->media();
|
||||||
const auto mediaWidth = (media && media->isDisplayed())
|
const auto mediaWidth = (media && media->isDisplayed())
|
||||||
? media->width()
|
? media->width()
|
||||||
|
@ -3385,7 +3413,7 @@ QRect Message::countGeometry() const {
|
||||||
const auto outbg = hasOutLayout();
|
const auto outbg = hasOutLayout();
|
||||||
const auto availableWidth = width()
|
const auto availableWidth = width()
|
||||||
- st::msgMargin.left()
|
- st::msgMargin.left()
|
||||||
- (commentsRoot ? st::msgMargin.left() : st::msgMargin.right());
|
- (centeredView ? st::msgMargin.left() : st::msgMargin.right());
|
||||||
auto contentLeft = (outbg && !delegate()->elementIsChatWide())
|
auto contentLeft = (outbg && !delegate()->elementIsChatWide())
|
||||||
? st::msgMargin.right()
|
? st::msgMargin.right()
|
||||||
: st::msgMargin.left();
|
: st::msgMargin.left();
|
||||||
|
@ -3412,10 +3440,10 @@ QRect Message::countGeometry() const {
|
||||||
if (contentWidth < availableWidth && !delegate()->elementIsChatWide()) {
|
if (contentWidth < availableWidth && !delegate()->elementIsChatWide()) {
|
||||||
if (outbg) {
|
if (outbg) {
|
||||||
contentLeft += availableWidth - contentWidth;
|
contentLeft += availableWidth - contentWidth;
|
||||||
} else if (commentsRoot) {
|
} else if (centeredView) {
|
||||||
contentLeft += (availableWidth - contentWidth) / 2;
|
contentLeft += (availableWidth - contentWidth) / 2;
|
||||||
}
|
}
|
||||||
} else if (contentWidth < availableWidth && commentsRoot) {
|
} else if (contentWidth < availableWidth && centeredView) {
|
||||||
contentLeft += std::max(
|
contentLeft += std::max(
|
||||||
((st::msgMaxWidth + 2 * st::msgPhotoSkip) - contentWidth) / 2,
|
((st::msgMaxWidth + 2 * st::msgPhotoSkip) - contentWidth) / 2,
|
||||||
0);
|
0);
|
||||||
|
@ -3433,11 +3461,13 @@ Ui::BubbleRounding Message::countMessageRounding() const {
|
||||||
const auto smallTop = isBubbleAttachedToPrevious();
|
const auto smallTop = isBubbleAttachedToPrevious();
|
||||||
const auto smallBottom = isBubbleAttachedToNext();
|
const auto smallBottom = isBubbleAttachedToNext();
|
||||||
const auto media = smallBottom ? nullptr : this->media();
|
const auto media = smallBottom ? nullptr : this->media();
|
||||||
const auto keyboard = data()->inlineReplyKeyboard();
|
const auto item = data();
|
||||||
|
const auto keyboard = item->inlineReplyKeyboard();
|
||||||
const auto skipTail = smallBottom
|
const auto skipTail = smallBottom
|
||||||
|| (media && media->skipBubbleTail())
|
|| (media && media->skipBubbleTail())
|
||||||
|| (keyboard != nullptr)
|
|| (keyboard != nullptr)
|
||||||
|| (context() == Context::Replies && data()->isDiscussionPost());
|
|| item->isFakeBotAbout()
|
||||||
|
|| (context() == Context::Replies && item->isDiscussionPost());
|
||||||
const auto right = !delegate()->elementIsChatWide() && hasOutLayout();
|
const auto right = !delegate()->elementIsChatWide() && hasOutLayout();
|
||||||
using Corner = Ui::BubbleCornerRounding;
|
using Corner = Ui::BubbleCornerRounding;
|
||||||
return Ui::BubbleRounding{
|
return Ui::BubbleRounding{
|
||||||
|
@ -3480,16 +3510,19 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||||
auto newHeight = minHeight();
|
auto newHeight = minHeight();
|
||||||
|
|
||||||
const auto item = data();
|
const auto item = data();
|
||||||
|
const auto botTop = item->isFakeBotAbout()
|
||||||
|
? Get<FakeBotAboutTop>()
|
||||||
|
: nullptr;
|
||||||
const auto media = this->media();
|
const auto media = this->media();
|
||||||
const auto mediaDisplayed = media ? media->isDisplayed() : false;
|
const auto mediaDisplayed = media ? media->isDisplayed() : false;
|
||||||
const auto bubble = drawBubble();
|
const auto bubble = drawBubble();
|
||||||
|
|
||||||
// This code duplicates countGeometry() but also resizes media.
|
// This code duplicates countGeometry() but also resizes media.
|
||||||
const auto commentsRoot = (context() == Context::Replies)
|
const auto centeredView = item->isFakeBotAbout()
|
||||||
&& data()->isDiscussionPost();
|
|| (context() == Context::Replies && item->isDiscussionPost());
|
||||||
auto contentWidth = newWidth
|
auto contentWidth = newWidth
|
||||||
- st::msgMargin.left()
|
- st::msgMargin.left()
|
||||||
- (commentsRoot ? st::msgMargin.left() : st::msgMargin.right());
|
- (centeredView ? st::msgMargin.left() : st::msgMargin.right());
|
||||||
if (hasFromPhoto()) {
|
if (hasFromPhoto()) {
|
||||||
if (const auto size = rightActionSize()) {
|
if (const auto size = rightActionSize()) {
|
||||||
contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize);
|
contentWidth -= size->width() + (st::msgPhotoSkip - st::historyFastShareSize);
|
||||||
|
@ -3540,7 +3573,14 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||||
entry->resizeGetHeight(contentWidth);
|
entry->resizeGetHeight(contentWidth);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newHeight = hasVisibleText() ? textHeightFor(textWidth) : 0;
|
const auto withVisibleText = hasVisibleText();
|
||||||
|
newHeight = 0;
|
||||||
|
if (withVisibleText) {
|
||||||
|
if (botTop) {
|
||||||
|
newHeight += botTop->height;
|
||||||
|
}
|
||||||
|
newHeight += textHeightFor(textWidth);
|
||||||
|
}
|
||||||
if (!mediaOnBottom && (!_viewButton || !reactionsInBubble)) {
|
if (!mediaOnBottom && (!_viewButton || !reactionsInBubble)) {
|
||||||
newHeight += st::msgPadding.bottom();
|
newHeight += st::msgPadding.bottom();
|
||||||
if (mediaDisplayed) {
|
if (mediaDisplayed) {
|
||||||
|
|
|
@ -199,6 +199,10 @@ QSize Gif::countOptimalSize() {
|
||||||
minHeight = adjustHeightForLessCrop(
|
minHeight = adjustHeightForLessCrop(
|
||||||
scaled,
|
scaled,
|
||||||
{ maxWidth, minHeight });
|
{ maxWidth, minHeight });
|
||||||
|
if (const auto botTop = _parent->Get<FakeBotAboutTop>()) {
|
||||||
|
accumulate_max(maxWidth, botTop->maxWidth);
|
||||||
|
minHeight += botTop->height;
|
||||||
|
}
|
||||||
minHeight += st::mediaCaptionSkip + _caption.minHeight();
|
minHeight += st::mediaCaptionSkip + _caption.minHeight();
|
||||||
if (isBubbleBottom()) {
|
if (isBubbleBottom()) {
|
||||||
minHeight += st::msgPadding.bottom();
|
minHeight += st::msgPadding.bottom();
|
||||||
|
@ -236,11 +240,14 @@ QSize Gif::countCurrentSize(int newWidth) {
|
||||||
if (_parent->hasBubble()) {
|
if (_parent->hasBubble()) {
|
||||||
accumulate_max(newWidth, _parent->minWidthForMedia());
|
accumulate_max(newWidth, _parent->minWidthForMedia());
|
||||||
if (!_caption.isEmpty()) {
|
if (!_caption.isEmpty()) {
|
||||||
const auto maxWithCaption = qMin(
|
auto captionMaxWidth = st::msgPadding.left()
|
||||||
st::msgMaxWidth,
|
+ _caption.maxWidth()
|
||||||
(st::msgPadding.left()
|
+ st::msgPadding.right();
|
||||||
+ _caption.maxWidth()
|
const auto botTop = _parent->Get<FakeBotAboutTop>();
|
||||||
+ st::msgPadding.right()));
|
if (botTop) {
|
||||||
|
accumulate_max(captionMaxWidth, botTop->maxWidth);
|
||||||
|
}
|
||||||
|
const auto maxWithCaption = qMin(st::msgMaxWidth, captionMaxWidth);
|
||||||
newWidth = qMin(qMax(newWidth, maxWithCaption), thumbMaxWidth);
|
newWidth = qMin(qMax(newWidth, maxWithCaption), thumbMaxWidth);
|
||||||
newHeight = adjustHeightForLessCrop(
|
newHeight = adjustHeightForLessCrop(
|
||||||
scaled,
|
scaled,
|
||||||
|
@ -248,6 +255,9 @@ QSize Gif::countCurrentSize(int newWidth) {
|
||||||
const auto captionw = newWidth
|
const auto captionw = newWidth
|
||||||
- st::msgPadding.left()
|
- st::msgPadding.left()
|
||||||
- st::msgPadding.right();
|
- st::msgPadding.right();
|
||||||
|
if (botTop) {
|
||||||
|
newHeight += botTop->height;
|
||||||
|
}
|
||||||
newHeight += st::mediaCaptionSkip + _caption.countHeight(captionw);
|
newHeight += st::mediaCaptionSkip + _caption.countHeight(captionw);
|
||||||
if (isBubbleBottom()) {
|
if (isBubbleBottom()) {
|
||||||
newHeight += st::msgPadding.bottom();
|
newHeight += st::msgPadding.bottom();
|
||||||
|
@ -349,12 +359,16 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
const auto outbg = context.outbg;
|
const auto outbg = context.outbg;
|
||||||
const auto inWebPage = (_parent->media() != this);
|
const auto inWebPage = (_parent->media() != this);
|
||||||
const auto isRound = _data->isVideoMessage();
|
const auto isRound = _data->isVideoMessage();
|
||||||
|
const auto botTop = _parent->Get<FakeBotAboutTop>();
|
||||||
|
|
||||||
const auto rounding = inWebPage
|
const auto rounding = inWebPage
|
||||||
? std::optional<Ui::BubbleRounding>()
|
? std::optional<Ui::BubbleRounding>()
|
||||||
: adjustedBubbleRoundingWithCaption(_caption);
|
: adjustedBubbleRoundingWithCaption(_caption);
|
||||||
if (bubble) {
|
if (bubble) {
|
||||||
if (!_caption.isEmpty()) {
|
if (!_caption.isEmpty()) {
|
||||||
|
if (botTop) {
|
||||||
|
painth -= botTop->height;
|
||||||
|
}
|
||||||
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
||||||
if (isBubbleBottom()) {
|
if (isBubbleBottom()) {
|
||||||
painth -= st::msgPadding.bottom();
|
painth -= st::msgPadding.bottom();
|
||||||
|
@ -674,10 +688,18 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (!unwrapped && !_caption.isEmpty()) {
|
if (!unwrapped && !_caption.isEmpty()) {
|
||||||
p.setPen(stm->historyTextFg);
|
p.setPen(stm->historyTextFg);
|
||||||
_parent->prepareCustomEmojiPaint(p, context, _caption);
|
_parent->prepareCustomEmojiPaint(p, context, _caption);
|
||||||
_caption.draw(p, {
|
auto top = painty + painth + st::mediaCaptionSkip;
|
||||||
.position = QPoint(
|
if (botTop) {
|
||||||
|
botTop->text.drawLeftElided(
|
||||||
|
p,
|
||||||
st::msgPadding.left(),
|
st::msgPadding.left(),
|
||||||
painty + painth + st::mediaCaptionSkip),
|
top,
|
||||||
|
captionw,
|
||||||
|
_parent->width());
|
||||||
|
top += botTop->height;
|
||||||
|
}
|
||||||
|
_caption.draw(p, {
|
||||||
|
.position = QPoint(st::msgPadding.left(), top),
|
||||||
.availableWidth = captionw,
|
.availableWidth = captionw,
|
||||||
.palette = &stm->textPalette,
|
.palette = &stm->textPalette,
|
||||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||||
|
@ -956,6 +978,9 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
|
||||||
request.forText()));
|
request.forText()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (const auto botTop = _parent->Get<FakeBotAboutTop>()) {
|
||||||
|
painth -= botTop->height;
|
||||||
|
}
|
||||||
painth -= st::mediaCaptionSkip;
|
painth -= st::mediaCaptionSkip;
|
||||||
}
|
}
|
||||||
const auto outbg = _parent->hasOutLayout();
|
const auto outbg = _parent->hasOutLayout();
|
||||||
|
|
|
@ -187,6 +187,10 @@ QSize Photo::countOptimalSize() {
|
||||||
minHeight = adjustHeightForLessCrop(
|
minHeight = adjustHeightForLessCrop(
|
||||||
dimensions,
|
dimensions,
|
||||||
{ maxWidth, minHeight });
|
{ maxWidth, minHeight });
|
||||||
|
if (const auto botTop = _parent->Get<FakeBotAboutTop>()) {
|
||||||
|
accumulate_max(maxWidth, botTop->maxWidth);
|
||||||
|
minHeight += botTop->height;
|
||||||
|
}
|
||||||
minHeight += st::mediaCaptionSkip + _caption.minHeight();
|
minHeight += st::mediaCaptionSkip + _caption.minHeight();
|
||||||
if (isBubbleBottom()) {
|
if (isBubbleBottom()) {
|
||||||
minHeight += st::msgPadding.bottom();
|
minHeight += st::msgPadding.bottom();
|
||||||
|
@ -214,11 +218,14 @@ QSize Photo::countCurrentSize(int newWidth) {
|
||||||
newWidth = qMax(pix.width(), minWidth);
|
newWidth = qMax(pix.width(), minWidth);
|
||||||
auto newHeight = qMax(pix.height(), st::minPhotoSize);
|
auto newHeight = qMax(pix.height(), st::minPhotoSize);
|
||||||
if (_parent->hasBubble() && !_caption.isEmpty()) {
|
if (_parent->hasBubble() && !_caption.isEmpty()) {
|
||||||
const auto maxWithCaption = qMin(
|
auto captionMaxWidth = st::msgPadding.left()
|
||||||
st::msgMaxWidth,
|
+ _caption.maxWidth()
|
||||||
(st::msgPadding.left()
|
+ st::msgPadding.right();
|
||||||
+ _caption.maxWidth()
|
const auto botTop = _parent->Get<FakeBotAboutTop>();
|
||||||
+ st::msgPadding.right()));
|
if (botTop) {
|
||||||
|
accumulate_max(captionMaxWidth, botTop->maxWidth);
|
||||||
|
}
|
||||||
|
const auto maxWithCaption = qMin(st::msgMaxWidth, captionMaxWidth);
|
||||||
newWidth = qMin(qMax(newWidth, maxWithCaption), thumbMaxWidth);
|
newWidth = qMin(qMax(newWidth, maxWithCaption), thumbMaxWidth);
|
||||||
newHeight = adjustHeightForLessCrop(
|
newHeight = adjustHeightForLessCrop(
|
||||||
dimensions,
|
dimensions,
|
||||||
|
@ -226,6 +233,9 @@ QSize Photo::countCurrentSize(int newWidth) {
|
||||||
const auto captionw = newWidth
|
const auto captionw = newWidth
|
||||||
- st::msgPadding.left()
|
- st::msgPadding.left()
|
||||||
- st::msgPadding.right();
|
- st::msgPadding.right();
|
||||||
|
if (botTop) {
|
||||||
|
newHeight += botTop->height;
|
||||||
|
}
|
||||||
newHeight += st::mediaCaptionSkip + _caption.countHeight(captionw);
|
newHeight += st::mediaCaptionSkip + _caption.countHeight(captionw);
|
||||||
if (isBubbleBottom()) {
|
if (isBubbleBottom()) {
|
||||||
newHeight += st::msgPadding.bottom();
|
newHeight += st::msgPadding.bottom();
|
||||||
|
@ -268,6 +278,7 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto radial = isRadialAnimation();
|
const auto radial = isRadialAnimation();
|
||||||
|
const auto botTop = _parent->Get<FakeBotAboutTop>();
|
||||||
|
|
||||||
auto rthumb = style::rtlrect(paintx, painty, paintw, painth, width());
|
auto rthumb = style::rtlrect(paintx, painty, paintw, painth, width());
|
||||||
if (_serviceWidth > 0) {
|
if (_serviceWidth > 0) {
|
||||||
|
@ -279,6 +290,9 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (bubble) {
|
if (bubble) {
|
||||||
if (!_caption.isEmpty()) {
|
if (!_caption.isEmpty()) {
|
||||||
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
||||||
|
if (botTop) {
|
||||||
|
painth -= botTop->height;
|
||||||
|
}
|
||||||
if (isBubbleBottom()) {
|
if (isBubbleBottom()) {
|
||||||
painth -= st::msgPadding.bottom();
|
painth -= st::msgPadding.bottom();
|
||||||
}
|
}
|
||||||
|
@ -348,10 +362,18 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
|
||||||
if (!_caption.isEmpty()) {
|
if (!_caption.isEmpty()) {
|
||||||
p.setPen(stm->historyTextFg);
|
p.setPen(stm->historyTextFg);
|
||||||
_parent->prepareCustomEmojiPaint(p, context, _caption);
|
_parent->prepareCustomEmojiPaint(p, context, _caption);
|
||||||
_caption.draw(p, {
|
auto top = painty + painth + st::mediaCaptionSkip;
|
||||||
.position = QPoint(
|
if (botTop) {
|
||||||
|
botTop->text.drawLeftElided(
|
||||||
|
p,
|
||||||
st::msgPadding.left(),
|
st::msgPadding.left(),
|
||||||
painty + painth + st::mediaCaptionSkip),
|
top,
|
||||||
|
captionw,
|
||||||
|
_parent->width());
|
||||||
|
top += botTop->height;
|
||||||
|
}
|
||||||
|
_caption.draw(p, {
|
||||||
|
.position = QPoint(st::msgPadding.left(), top),
|
||||||
.availableWidth = captionw,
|
.availableWidth = captionw,
|
||||||
.palette = &stm->textPalette,
|
.palette = &stm->textPalette,
|
||||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||||
|
@ -592,6 +614,9 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
|
||||||
request.forText()));
|
request.forText()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (const auto botTop = _parent->Get<FakeBotAboutTop>()) {
|
||||||
|
painth -= botTop->height;
|
||||||
|
}
|
||||||
painth -= st::mediaCaptionSkip;
|
painth -= st::mediaCaptionSkip;
|
||||||
}
|
}
|
||||||
if (QRect(paintx, painty, paintw, painth).contains(point)) {
|
if (QRect(paintx, painty, paintw, painth).contains(point)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue