mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Improve reactions position and colors.
This commit is contained in:
parent
38c296b69f
commit
4228557722
17 changed files with 195 additions and 55 deletions
|
@ -746,7 +746,7 @@ bool HistoryItem::suggestDeleteAllReport() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryItem::canReact() const {
|
bool HistoryItem::canReact() const {
|
||||||
return isRegular();
|
return isRegular() && !isService();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::addReaction(const QString &reaction) {
|
void HistoryItem::addReaction(const QString &reaction) {
|
||||||
|
|
|
@ -359,15 +359,23 @@ QSize Message::performCountOptimalSize() {
|
||||||
}
|
}
|
||||||
minHeight = hasVisibleText() ? item->_text.minHeight() : 0;
|
minHeight = hasVisibleText() ? item->_text.minHeight() : 0;
|
||||||
if (reactionsInBubble) {
|
if (reactionsInBubble) {
|
||||||
accumulate_max(maxWidth, std::min(
|
const auto reactionsMaxWidth = st::msgPadding.left()
|
||||||
st::msgMaxWidth,
|
+ _reactions->maxWidth()
|
||||||
(st::msgPadding.left()
|
+ st::msgPadding.right();
|
||||||
+ _reactions->maxWidth()
|
accumulate_max(
|
||||||
+ st::msgPadding.right())));
|
maxWidth,
|
||||||
|
std::min(st::msgMaxWidth, reactionsMaxWidth));
|
||||||
if (!mediaDisplayed) {
|
if (!mediaDisplayed) {
|
||||||
minHeight += st::mediaInBubbleSkip;
|
minHeight += st::mediaInBubbleSkip;
|
||||||
}
|
}
|
||||||
minHeight += _reactions->minHeight();
|
if (maxWidth >= reactionsMaxWidth) {
|
||||||
|
minHeight += _reactions->minHeight();
|
||||||
|
} else {
|
||||||
|
const auto widthForReactions = maxWidth
|
||||||
|
- st::msgPadding.left()
|
||||||
|
- st::msgPadding.right();
|
||||||
|
minHeight += _reactions->resizeGetHeight(widthForReactions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!mediaOnBottom) {
|
if (!mediaOnBottom) {
|
||||||
minHeight += st::msgPadding.bottom();
|
minHeight += st::msgPadding.bottom();
|
||||||
|
@ -457,13 +465,6 @@ QSize Message::performCountOptimalSize() {
|
||||||
maxWidth = st::msgMinWidth;
|
maxWidth = st::msgMinWidth;
|
||||||
minHeight = 0;
|
minHeight = 0;
|
||||||
}
|
}
|
||||||
if (_reactions && !reactionsInBubble) {
|
|
||||||
// if we have a text bubble we can resize it to fit the keyboard
|
|
||||||
// but if we have only media we don't do that
|
|
||||||
if (hasVisibleText()) {
|
|
||||||
accumulate_max(maxWidth, _reactions->maxWidth());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (const auto markup = item->inlineReplyMarkup()) {
|
if (const auto markup = item->inlineReplyMarkup()) {
|
||||||
if (!markup->inlineKeyboard) {
|
if (!markup->inlineKeyboard) {
|
||||||
markup->inlineKeyboard = std::make_unique<ReplyKeyboard>(
|
markup->inlineKeyboard = std::make_unique<ReplyKeyboard>(
|
||||||
|
@ -601,8 +602,11 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
||||||
|
|
||||||
if (_reactions && !reactionsInBubble) {
|
if (_reactions && !reactionsInBubble) {
|
||||||
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
|
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
|
||||||
|
const auto reactionsLeft = (!bubble && mediaDisplayed)
|
||||||
|
? media->contentRectForReactionButton().x()
|
||||||
|
: 0;
|
||||||
g.setHeight(g.height() - reactionsHeight);
|
g.setHeight(g.height() - reactionsHeight);
|
||||||
const auto reactionsPosition = QPoint(g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
||||||
p.translate(reactionsPosition);
|
p.translate(reactionsPosition);
|
||||||
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
|
_reactions->paint(p, context, g.width(), context.clip.translated(-reactionsPosition));
|
||||||
p.translate(-reactionsPosition);
|
p.translate(-reactionsPosition);
|
||||||
|
@ -1250,7 +1254,9 @@ TextState Message::textState(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto bubble = drawBubble();
|
||||||
const auto reactionsInBubble = _reactions && embedReactionsInBubble();
|
const auto reactionsInBubble = _reactions && embedReactionsInBubble();
|
||||||
|
const auto mediaDisplayed = media && media->isDisplayed();
|
||||||
auto keyboard = item->inlineReplyKeyboard();
|
auto keyboard = item->inlineReplyKeyboard();
|
||||||
auto keyboardHeight = 0;
|
auto keyboardHeight = 0;
|
||||||
if (keyboard) {
|
if (keyboard) {
|
||||||
|
@ -1260,17 +1266,19 @@ TextState Message::textState(
|
||||||
|
|
||||||
if (_reactions && !reactionsInBubble) {
|
if (_reactions && !reactionsInBubble) {
|
||||||
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
|
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
|
||||||
|
const auto reactionsLeft = (!bubble && mediaDisplayed)
|
||||||
|
? media->contentRectForReactionButton().x()
|
||||||
|
: 0;
|
||||||
g.setHeight(g.height() - reactionsHeight);
|
g.setHeight(g.height() - reactionsHeight);
|
||||||
const auto reactionsPosition = QPoint(g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
const auto reactionsPosition = QPoint(reactionsLeft + g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
|
||||||
if (_reactions->getState(point - reactionsPosition, &result)) {
|
if (_reactions->getState(point - reactionsPosition, &result)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawBubble()) {
|
if (bubble) {
|
||||||
const auto inBubble = g.contains(point);
|
const auto inBubble = g.contains(point);
|
||||||
auto entry = logEntryOriginal();
|
auto entry = logEntryOriginal();
|
||||||
auto mediaDisplayed = media && media->isDisplayed();
|
|
||||||
|
|
||||||
// Entry page is always a bubble bottom.
|
// Entry page is always a bubble bottom.
|
||||||
auto mediaOnBottom = (mediaDisplayed && media->isBubbleBottom()) || (entry/* && entry->isBubbleBottom()*/);
|
auto mediaOnBottom = (mediaDisplayed && media->isBubbleBottom()) || (entry/* && entry->isBubbleBottom()*/);
|
||||||
|
@ -1807,17 +1815,39 @@ TextSelection Message::adjustSelection(
|
||||||
Reactions::ButtonParameters Message::reactionButtonParameters(
|
Reactions::ButtonParameters Message::reactionButtonParameters(
|
||||||
QPoint position,
|
QPoint position,
|
||||||
const TextState &reactionState) const {
|
const TextState &reactionState) const {
|
||||||
auto result = Reactions::ButtonParameters{ .context = data()->fullId() };
|
using namespace Reactions;
|
||||||
const auto outbg = result.outbg = hasOutLayout();
|
auto result = ButtonParameters{ .context = data()->fullId() };
|
||||||
|
const auto outbg = hasOutLayout();
|
||||||
|
result.style = (!_comments && !embedReactionsInBubble())
|
||||||
|
? ButtonStyle::Service
|
||||||
|
: outbg
|
||||||
|
? ButtonStyle::Outgoing
|
||||||
|
: ButtonStyle::Incoming;
|
||||||
const auto geometry = countGeometry();
|
const auto geometry = countGeometry();
|
||||||
result.pointer = position;
|
result.pointer = position;
|
||||||
const auto onTheLeft = (outbg && !delegate()->elementIsChatWide());
|
const auto onTheLeft = (outbg && !delegate()->elementIsChatWide());
|
||||||
const auto leftAdd = onTheLeft ? 0 : geometry.width();
|
const auto leftAdd = onTheLeft ? 0 : geometry.width();
|
||||||
result.center = geometry.topLeft() + (onTheLeft
|
|
||||||
? (QPoint(0, geometry.height()) + QPoint(
|
const auto keyboard = data()->inlineReplyKeyboard();
|
||||||
|
const auto keyboardHeight = keyboard
|
||||||
|
? (st::msgBotKbButton.margin + keyboard->naturalHeight())
|
||||||
|
: 0;
|
||||||
|
const auto reactionsHeight = (_reactions && !embedReactionsInBubble())
|
||||||
|
? (st::mediaInBubbleSkip + _reactions->height())
|
||||||
|
: 0;
|
||||||
|
const auto innerHeight = geometry.height()
|
||||||
|
- keyboardHeight
|
||||||
|
- reactionsHeight;
|
||||||
|
const auto contentRect = (result.style == ButtonStyle::Service
|
||||||
|
&& !drawBubble())
|
||||||
|
? media()->contentRectForReactionButton().translated(
|
||||||
|
geometry.topLeft())
|
||||||
|
: geometry;
|
||||||
|
result.center = contentRect.topLeft() + (onTheLeft
|
||||||
|
? (QPoint(0, innerHeight) + QPoint(
|
||||||
-st::reactionCornerCenter.x(),
|
-st::reactionCornerCenter.x(),
|
||||||
st::reactionCornerCenter.y()))
|
st::reactionCornerCenter.y()))
|
||||||
: (QPoint(geometry.width(), geometry.height())
|
: (QPoint(contentRect.width(), innerHeight)
|
||||||
+ st::reactionCornerCenter));
|
+ st::reactionCornerCenter));
|
||||||
if (reactionState.itemId != result.context) {
|
if (reactionState.itemId != result.context) {
|
||||||
const auto top = marginTop();
|
const auto top = marginTop();
|
||||||
|
@ -2739,7 +2769,11 @@ int Message::resizeContentGetHeight(int newWidth) {
|
||||||
newHeight = 0;
|
newHeight = 0;
|
||||||
}
|
}
|
||||||
if (_reactions && !reactionsInBubble) {
|
if (_reactions && !reactionsInBubble) {
|
||||||
newHeight += st::mediaInBubbleSkip + _reactions->resizeGetHeight(contentWidth);
|
const auto reactionsWidth = (!bubble && mediaDisplayed)
|
||||||
|
? media->contentRectForReactionButton().width()
|
||||||
|
: contentWidth;
|
||||||
|
newHeight += st::mediaInBubbleSkip
|
||||||
|
+ _reactions->resizeGetHeight(reactionsWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto keyboard = item->inlineReplyKeyboard()) {
|
if (const auto keyboard = item->inlineReplyKeyboard()) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ constexpr auto kActivateDuration = crl::time(150);
|
||||||
constexpr auto kExpandDuration = crl::time(150);
|
constexpr auto kExpandDuration = crl::time(150);
|
||||||
constexpr auto kInCacheIndex = 0;
|
constexpr auto kInCacheIndex = 0;
|
||||||
constexpr auto kOutCacheIndex = 1;
|
constexpr auto kOutCacheIndex = 1;
|
||||||
|
constexpr auto kServiceCacheIndex = 2;
|
||||||
constexpr auto kShadowCacheIndex = 0;
|
constexpr auto kShadowCacheIndex = 0;
|
||||||
constexpr auto kEmojiCacheIndex = 1;
|
constexpr auto kEmojiCacheIndex = 1;
|
||||||
constexpr auto kMaskCacheIndex = 2;
|
constexpr auto kMaskCacheIndex = 2;
|
||||||
|
@ -86,8 +87,8 @@ Button::Button(
|
||||||
|
|
||||||
Button::~Button() = default;
|
Button::~Button() = default;
|
||||||
|
|
||||||
bool Button::outbg() const {
|
ButtonStyle Button::style() const {
|
||||||
return _outbg;
|
return _style;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Button::isHidden() const {
|
bool Button::isHidden() const {
|
||||||
|
@ -150,8 +151,8 @@ void Button::applyParameters(
|
||||||
? State::Active
|
? State::Active
|
||||||
: State::Shown;
|
: State::Shown;
|
||||||
applyState(state, update);
|
applyState(state, update);
|
||||||
if (_outbg != parameters.outbg) {
|
if (_style != parameters.style) {
|
||||||
_outbg = parameters.outbg;
|
_style = parameters.style;
|
||||||
if (update) {
|
if (update) {
|
||||||
update(_geometry);
|
update(_geometry);
|
||||||
}
|
}
|
||||||
|
@ -264,12 +265,12 @@ Manager::Manager(
|
||||||
QRect({}, _outer).center() - _innerActive.center());
|
QRect({}, _outer).center() - _innerActive.center());
|
||||||
|
|
||||||
const auto ratio = style::DevicePixelRatio();
|
const auto ratio = style::DevicePixelRatio();
|
||||||
_cacheInOut = QImage(
|
_cacheInOutService = QImage(
|
||||||
_outer.width() * 2 * ratio,
|
_outer.width() * 3 * ratio,
|
||||||
_outer.height() * kFramesCount * ratio,
|
_outer.height() * kFramesCount * ratio,
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
_cacheInOut.setDevicePixelRatio(ratio);
|
_cacheInOutService.setDevicePixelRatio(ratio);
|
||||||
_cacheInOut.fill(Qt::transparent);
|
_cacheInOutService.fill(Qt::transparent);
|
||||||
_cacheParts = QImage(
|
_cacheParts = QImage(
|
||||||
_outer.width() * kCacheColumsCount * ratio,
|
_outer.width() * kCacheColumsCount * ratio,
|
||||||
_outer.height() * kFramesCount * ratio,
|
_outer.height() * kFramesCount * ratio,
|
||||||
|
@ -529,8 +530,8 @@ void Manager::paintButton(
|
||||||
const auto geometry = button->geometry();
|
const auto geometry = button->geometry();
|
||||||
const auto position = geometry.topLeft();
|
const auto position = geometry.topLeft();
|
||||||
const auto size = geometry.size();
|
const auto size = geometry.size();
|
||||||
const auto outbg = button->outbg();
|
const auto style = button->style();
|
||||||
const auto patterned = outbg
|
const auto patterned = (style == ButtonStyle::Outgoing)
|
||||||
&& context.bubblesPattern
|
&& context.bubblesPattern
|
||||||
&& !context.viewport.isEmpty()
|
&& !context.viewport.isEmpty()
|
||||||
&& !context.bubblesPattern->pixmap.size().isEmpty();
|
&& !context.bubblesPattern->pixmap.size().isEmpty();
|
||||||
|
@ -547,15 +548,19 @@ void Manager::paintButton(
|
||||||
_cacheForPattern,
|
_cacheForPattern,
|
||||||
QRect(QPoint(), geometry.size() * style::DevicePixelRatio()));
|
QRect(QPoint(), geometry.size() * style::DevicePixelRatio()));
|
||||||
} else {
|
} else {
|
||||||
const auto &stm = context.st->messageStyle(outbg, false);
|
const auto background = (style == ButtonStyle::Service)
|
||||||
const auto background = stm.msgBg->c;
|
? context.st->msgServiceFg()->c
|
||||||
|
: context.st->messageStyle(
|
||||||
|
(style == ButtonStyle::Outgoing),
|
||||||
|
false
|
||||||
|
).msgBg->c;
|
||||||
const auto source = validateFrame(
|
const auto source = validateFrame(
|
||||||
outbg,
|
style,
|
||||||
frameIndex,
|
frameIndex,
|
||||||
scale,
|
scale,
|
||||||
stm.msgBg->c,
|
background,
|
||||||
shadow);
|
shadow);
|
||||||
paintLongImage(p, geometry, _cacheInOut, source);
|
paintLongImage(p, geometry, _cacheInOutService, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto mainEmojiPosition = position + (button->expandUp()
|
const auto mainEmojiPosition = position + (button->expandUp()
|
||||||
|
@ -746,20 +751,32 @@ QRect Manager::validateEmoji(int frameIndex, float64 scale) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect Manager::validateFrame(
|
QRect Manager::validateFrame(
|
||||||
bool outbg,
|
ButtonStyle style,
|
||||||
int frameIndex,
|
int frameIndex,
|
||||||
float64 scale,
|
float64 scale,
|
||||||
const QColor &background,
|
const QColor &background,
|
||||||
const QColor &shadow) {
|
const QColor &shadow) {
|
||||||
applyPatternedShadow(shadow);
|
applyPatternedShadow(shadow);
|
||||||
auto &valid = outbg ? _validOut : _validIn;
|
auto &valid = (style == ButtonStyle::Service)
|
||||||
auto &color = outbg ? _backgroundOut : _backgroundIn;
|
? _validService
|
||||||
|
: (style == ButtonStyle::Outgoing)
|
||||||
|
? _validOut
|
||||||
|
: _validIn;
|
||||||
|
auto &color = (style == ButtonStyle::Service)
|
||||||
|
? _backgroundService
|
||||||
|
: (style == ButtonStyle::Outgoing)
|
||||||
|
? _backgroundOut
|
||||||
|
: _backgroundIn;
|
||||||
if (color != background) {
|
if (color != background) {
|
||||||
color = background;
|
color = background;
|
||||||
ranges::fill(valid, false);
|
ranges::fill(valid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto columnIndex = outbg ? kOutCacheIndex : kInCacheIndex;
|
const auto columnIndex = (style == ButtonStyle::Service)
|
||||||
|
? kServiceCacheIndex
|
||||||
|
: (style == ButtonStyle::Outgoing)
|
||||||
|
? kOutCacheIndex
|
||||||
|
: kInCacheIndex;
|
||||||
const auto result = cacheRect(frameIndex, columnIndex);
|
const auto result = cacheRect(frameIndex, columnIndex);
|
||||||
if (valid[frameIndex]) {
|
if (valid[frameIndex]) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -767,7 +784,7 @@ QRect Manager::validateFrame(
|
||||||
|
|
||||||
const auto shadowSource = validateShadow(frameIndex, scale, shadow);
|
const auto shadowSource = validateShadow(frameIndex, scale, shadow);
|
||||||
const auto position = result.topLeft() / style::DevicePixelRatio();
|
const auto position = result.topLeft() / style::DevicePixelRatio();
|
||||||
auto p = QPainter(&_cacheInOut);
|
auto p = QPainter(&_cacheInOutService);
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
p.drawImage(position, _cacheParts, shadowSource);
|
p.drawImage(position, _cacheParts, shadowSource);
|
||||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||||
|
|
|
@ -27,7 +27,9 @@ struct TextState;
|
||||||
namespace HistoryView::Reactions {
|
namespace HistoryView::Reactions {
|
||||||
|
|
||||||
enum class ButtonStyle {
|
enum class ButtonStyle {
|
||||||
Bubble,
|
Incoming,
|
||||||
|
Outgoing,
|
||||||
|
Service,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ExpandDirection {
|
enum class ExpandDirection {
|
||||||
|
@ -46,11 +48,10 @@ struct ButtonParameters {
|
||||||
FullMsgId context;
|
FullMsgId context;
|
||||||
QPoint center;
|
QPoint center;
|
||||||
QPoint pointer;
|
QPoint pointer;
|
||||||
ButtonStyle style = ButtonStyle::Bubble;
|
ButtonStyle style = ButtonStyle::Incoming;
|
||||||
int reactionsCount = 1;
|
int reactionsCount = 1;
|
||||||
int visibleTop = 0;
|
int visibleTop = 0;
|
||||||
int visibleBottom = 0;
|
int visibleBottom = 0;
|
||||||
bool outbg = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ButtonState {
|
enum class ButtonState {
|
||||||
|
@ -70,7 +71,7 @@ public:
|
||||||
using State = ButtonState;
|
using State = ButtonState;
|
||||||
void applyState(State state);
|
void applyState(State state);
|
||||||
|
|
||||||
[[nodiscard]] bool outbg() const;
|
[[nodiscard]] ButtonStyle style() const;
|
||||||
[[nodiscard]] bool expandUp() const;
|
[[nodiscard]] bool expandUp() const;
|
||||||
[[nodiscard]] bool isHidden() const;
|
[[nodiscard]] bool isHidden() const;
|
||||||
[[nodiscard]] QRect geometry() const;
|
[[nodiscard]] QRect geometry() const;
|
||||||
|
@ -101,7 +102,7 @@ private:
|
||||||
int _finalHeight = 0;
|
int _finalHeight = 0;
|
||||||
int _scroll = 0;
|
int _scroll = 0;
|
||||||
ExpandDirection _expandDirection = ExpandDirection::Up;
|
ExpandDirection _expandDirection = ExpandDirection::Up;
|
||||||
bool _outbg = false;
|
ButtonStyle _style = ButtonStyle::Incoming;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,7 +172,7 @@ private:
|
||||||
const QColor &shadow);
|
const QColor &shadow);
|
||||||
QRect validateEmoji(int frameIndex, float64 scale);
|
QRect validateEmoji(int frameIndex, float64 scale);
|
||||||
QRect validateFrame(
|
QRect validateFrame(
|
||||||
bool outbg,
|
ButtonStyle style,
|
||||||
int frameIndex,
|
int frameIndex,
|
||||||
float64 scale,
|
float64 scale,
|
||||||
const QColor &background,
|
const QColor &background,
|
||||||
|
@ -198,17 +199,19 @@ private:
|
||||||
QSize _outer;
|
QSize _outer;
|
||||||
QRectF _inner;
|
QRectF _inner;
|
||||||
QRect _innerActive;
|
QRect _innerActive;
|
||||||
QImage _cacheInOut;
|
QImage _cacheInOutService;
|
||||||
QImage _cacheParts;
|
QImage _cacheParts;
|
||||||
QImage _cacheForPattern;
|
QImage _cacheForPattern;
|
||||||
QImage _shadowBuffer;
|
QImage _shadowBuffer;
|
||||||
std::array<bool, kFramesCount> _validIn = { { false } };
|
std::array<bool, kFramesCount> _validIn = { { false } };
|
||||||
std::array<bool, kFramesCount> _validOut = { { false } };
|
std::array<bool, kFramesCount> _validOut = { { false } };
|
||||||
|
std::array<bool, kFramesCount> _validService = { { false } };
|
||||||
std::array<bool, kFramesCount> _validShadow = { { false } };
|
std::array<bool, kFramesCount> _validShadow = { { false } };
|
||||||
std::array<bool, kFramesCount> _validEmoji = { { false } };
|
std::array<bool, kFramesCount> _validEmoji = { { false } };
|
||||||
std::array<bool, kFramesCount> _validMask = { { false } };
|
std::array<bool, kFramesCount> _validMask = { { false } };
|
||||||
QColor _backgroundIn;
|
QColor _backgroundIn;
|
||||||
QColor _backgroundOut;
|
QColor _backgroundOut;
|
||||||
|
QColor _backgroundService;
|
||||||
QColor _shadow;
|
QColor _shadow;
|
||||||
|
|
||||||
std::shared_ptr<Data::DocumentMedia> _mainReactionMedia;
|
std::shared_ptr<Data::DocumentMedia> _mainReactionMedia;
|
||||||
|
|
|
@ -22,6 +22,11 @@ namespace {
|
||||||
constexpr auto kInNonChosenOpacity = 0.12;
|
constexpr auto kInNonChosenOpacity = 0.12;
|
||||||
constexpr auto kOutNonChosenOpacity = 0.18;
|
constexpr auto kOutNonChosenOpacity = 0.18;
|
||||||
|
|
||||||
|
[[nodiscard]] QColor AdaptChosenServiceFg(QColor serviceBg) {
|
||||||
|
serviceBg.setAlpha(std::max(serviceBg.alpha(), 192));
|
||||||
|
return serviceBg;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
InlineList::InlineList(
|
InlineList::InlineList(
|
||||||
|
@ -146,6 +151,14 @@ QSize InlineList::countCurrentSize(int newWidth) {
|
||||||
return { newWidth, height + add };
|
return { newWidth, height + add };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int InlineList::placeAndResizeGetHeight(QRect available) {
|
||||||
|
const auto result = resizeGetHeight(available.width());
|
||||||
|
for (auto &button : _buttons) {
|
||||||
|
button.geometry.translate(available.x(), 0);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void InlineList::paint(
|
void InlineList::paint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
|
@ -173,9 +186,7 @@ void InlineList::paint(
|
||||||
}
|
}
|
||||||
p.setBrush(stm->msgFileBg);
|
p.setBrush(stm->msgFileBg);
|
||||||
} else {
|
} else {
|
||||||
p.setBrush(chosen
|
p.setBrush(chosen ? st->msgServiceFg() : st->msgServiceBg());
|
||||||
? st->msgServiceBgSelected()
|
|
||||||
: st->msgServiceBg());
|
|
||||||
}
|
}
|
||||||
const auto radius = geometry.height() / 2.;
|
const auto radius = geometry.height() / 2.;
|
||||||
p.drawRoundedRect(geometry, radius, radius);
|
p.drawRoundedRect(geometry, radius, radius);
|
||||||
|
@ -192,7 +203,9 @@ void InlineList::paint(
|
||||||
p.drawImage(inner.topLeft(), button.image);
|
p.drawImage(inner.topLeft(), button.image);
|
||||||
}
|
}
|
||||||
p.setPen(!inbubble
|
p.setPen(!inbubble
|
||||||
? st->msgServiceFg()
|
? (chosen
|
||||||
|
? QPen(AdaptChosenServiceFg(st->msgServiceBg()->c))
|
||||||
|
: st->msgServiceFg())
|
||||||
: !chosen
|
: !chosen
|
||||||
? stm->msgServiceFg
|
? stm->msgServiceFg
|
||||||
: context.outbg
|
: context.outbg
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
|
|
||||||
void update(Data &&data, int availableWidth);
|
void update(Data &&data, int availableWidth);
|
||||||
QSize countCurrentSize(int newWidth) override;
|
QSize countCurrentSize(int newWidth) override;
|
||||||
|
[[nodiscard]] int placeAndResizeGetHeight(QRect available);
|
||||||
|
|
||||||
void updateSkipBlock(int width, int height);
|
void updateSkipBlock(int width, int height);
|
||||||
void removeSkipBlock();
|
void removeSkipBlock();
|
||||||
|
|
|
@ -1170,6 +1170,27 @@ bool Gif::needsBubble() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect Gif::contentRectForReactionButton() const {
|
||||||
|
if (isSeparateRoundVideo()) {
|
||||||
|
return QRect(0, 0, width(), height());
|
||||||
|
}
|
||||||
|
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
||||||
|
auto usex = 0, usew = paintw;
|
||||||
|
const auto outbg = _parent->hasOutLayout();
|
||||||
|
const auto item = _parent->data();
|
||||||
|
const auto via = item->Get<HistoryMessageVia>();
|
||||||
|
const auto reply = _parent->displayedReply();
|
||||||
|
const auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||||
|
if (via || reply || forwarded) {
|
||||||
|
usew = maxWidth() - additionalWidth(via, reply, forwarded);
|
||||||
|
if (outbg) {
|
||||||
|
usex = width() - usew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rtl()) usex = width() - usex - usew;
|
||||||
|
return style::rtlrect(usex + paintx, painty, usew, painth, width());
|
||||||
|
}
|
||||||
|
|
||||||
int Gif::additionalWidth() const {
|
int Gif::additionalWidth() const {
|
||||||
const auto item = _parent->data();
|
const auto item = _parent->data();
|
||||||
return additionalWidth(
|
return additionalWidth(
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
bool customInfoLayout() const override {
|
bool customInfoLayout() const override {
|
||||||
return _caption.isEmpty();
|
return _caption.isEmpty();
|
||||||
}
|
}
|
||||||
|
QRect contentRectForReactionButton() const override;
|
||||||
QString additionalInfoString() const override;
|
QString additionalInfoString() const override;
|
||||||
|
|
||||||
bool skipBubbleTail() const override {
|
bool skipBubbleTail() const override {
|
||||||
|
|
|
@ -345,6 +345,10 @@ bool Location::needsBubble() const {
|
||||||
|| _parent->displayFromName();
|
|| _parent->displayFromName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect Location::contentRectForReactionButton() const {
|
||||||
|
return QRect(0, 0, width(), height());
|
||||||
|
}
|
||||||
|
|
||||||
int Location::fullWidth() const {
|
int Location::fullWidth() const {
|
||||||
return st::locationSize.width();
|
return st::locationSize.width();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
bool customInfoLayout() const override {
|
bool customInfoLayout() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
QRect contentRectForReactionButton() const override;
|
||||||
|
|
||||||
bool skipBubbleTail() const override {
|
bool skipBubbleTail() const override {
|
||||||
return isRoundedInBubbleBottom();
|
return isRoundedInBubbleBottom();
|
||||||
|
|
|
@ -205,6 +205,9 @@ public:
|
||||||
}
|
}
|
||||||
[[nodiscard]] virtual bool needsBubble() const = 0;
|
[[nodiscard]] virtual bool needsBubble() const = 0;
|
||||||
[[nodiscard]] virtual bool customInfoLayout() const = 0;
|
[[nodiscard]] virtual bool customInfoLayout() const = 0;
|
||||||
|
[[nodiscard]] virtual QRect contentRectForReactionButton() const {
|
||||||
|
Unexpected("Media::contentRectForReactionButton");
|
||||||
|
}
|
||||||
[[nodiscard]] virtual QMargins bubbleMargins() const {
|
[[nodiscard]] virtual QMargins bubbleMargins() const {
|
||||||
return QMargins();
|
return QMargins();
|
||||||
}
|
}
|
||||||
|
|
|
@ -730,6 +730,10 @@ bool GroupedMedia::needsBubble() const {
|
||||||
return _needBubble;
|
return _needBubble;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect GroupedMedia::contentRectForReactionButton() const {
|
||||||
|
return QRect(0, 0, width(), height());
|
||||||
|
}
|
||||||
|
|
||||||
bool GroupedMedia::computeNeedBubble() const {
|
bool GroupedMedia::computeNeedBubble() const {
|
||||||
if (!_caption.isEmpty() || _mode == Mode::Column) {
|
if (!_caption.isEmpty() || _mode == Mode::Column) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -84,6 +84,7 @@ public:
|
||||||
bool customInfoLayout() const override {
|
bool customInfoLayout() const override {
|
||||||
return _caption.isEmpty() && (_mode != Mode::Column);
|
return _caption.isEmpty() && (_mode != Mode::Column);
|
||||||
}
|
}
|
||||||
|
QRect contentRectForReactionButton() const override;
|
||||||
bool allowsFastShare() const override {
|
bool allowsFastShare() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -401,6 +401,37 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect UnwrappedMedia::contentRectForReactionButton() const {
|
||||||
|
const auto inWebPage = (_parent->media() != this);
|
||||||
|
if (inWebPage) {
|
||||||
|
return QRect(0, 0, width(), height());
|
||||||
|
}
|
||||||
|
const auto rightAligned = _parent->hasOutLayout()
|
||||||
|
&& !_parent->delegate()->elementIsChatWide();
|
||||||
|
const auto item = _parent->data();
|
||||||
|
const auto via = item->Get<HistoryMessageVia>();
|
||||||
|
const auto reply = _parent->displayedReply();
|
||||||
|
const auto forwarded = getDisplayedForwardedInfo();
|
||||||
|
auto usex = 0;
|
||||||
|
auto usew = maxWidth();
|
||||||
|
if (!inWebPage) {
|
||||||
|
usew -= additionalWidth(via, reply, forwarded);
|
||||||
|
if (rightAligned) {
|
||||||
|
usex = width() - usew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rtl()) {
|
||||||
|
usex = width() - usex - usew;
|
||||||
|
}
|
||||||
|
const auto usey = rightAligned ? 0 : (height() - _contentSize.height());
|
||||||
|
const auto useh = rightAligned
|
||||||
|
? std::max(
|
||||||
|
_contentSize.height(),
|
||||||
|
height() - st::msgDateImgPadding.y() * 2 - st::msgDateFont->height)
|
||||||
|
: _contentSize.height();
|
||||||
|
return QRect(usex, usey, usew, useh);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Lottie::SinglePlayer> UnwrappedMedia::stickerTakeLottie(
|
std::unique_ptr<Lottie::SinglePlayer> UnwrappedMedia::stickerTakeLottie(
|
||||||
not_null<DocumentData*> data,
|
not_null<DocumentData*> data,
|
||||||
const Lottie::ColorReplacements *replacements) {
|
const Lottie::ColorReplacements *replacements) {
|
||||||
|
|
|
@ -81,6 +81,7 @@ public:
|
||||||
bool customInfoLayout() const override {
|
bool customInfoLayout() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
QRect contentRectForReactionButton() const override;
|
||||||
void stickerClearLoopPlayed() override {
|
void stickerClearLoopPlayed() override {
|
||||||
_content->stickerClearLoopPlayed();
|
_content->stickerClearLoopPlayed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -831,6 +831,10 @@ bool Photo::needsBubble() const {
|
||||||
|| _parent->displayFromName());
|
|| _parent->displayFromName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect Photo::contentRectForReactionButton() const {
|
||||||
|
return QRect(0, 0, width(), height());
|
||||||
|
}
|
||||||
|
|
||||||
bool Photo::isReadyForOpen() const {
|
bool Photo::isReadyForOpen() const {
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
return _dataMedia->loaded();
|
return _dataMedia->loaded();
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
bool customInfoLayout() const override {
|
bool customInfoLayout() const override {
|
||||||
return _caption.isEmpty();
|
return _caption.isEmpty();
|
||||||
}
|
}
|
||||||
|
QRect contentRectForReactionButton() const override;
|
||||||
bool skipBubbleTail() const override {
|
bool skipBubbleTail() const override {
|
||||||
return isRoundedInBubbleBottom() && _caption.isEmpty();
|
return isRoundedInBubbleBottom() && _caption.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue