mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Expand reaction selection panel.
This commit is contained in:
parent
bd42c23999
commit
c9a98ae723
4 changed files with 161 additions and 22 deletions
|
@ -633,7 +633,11 @@ void Manager::paintButton(
|
|||
if (expanded) {
|
||||
q->fillRect(QRect(QPoint(), size), context.st->windowBg());
|
||||
} else {
|
||||
const auto frame = _cachedRound.validateFrame(frameIndex, scale);
|
||||
const auto radius = _inner.height() / 2.;
|
||||
const auto frame = _cachedRound.validateFrame(
|
||||
frameIndex,
|
||||
scale,
|
||||
radius);
|
||||
p.drawImage(position, *frame.image, frame.rect);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ QMargins Selector::extentsForShadow() const {
|
|||
}
|
||||
|
||||
int Selector::extendTopForCategories() const {
|
||||
return st::emojiFooterHeight;
|
||||
return _reactions.customAllowed ? st::emojiFooterHeight : 0;
|
||||
}
|
||||
|
||||
int Selector::desiredHeight() const {
|
||||
|
@ -76,6 +76,10 @@ int Selector::desiredHeight() const {
|
|||
: (_skipy + _recentRows * _size + _skipBottom);
|
||||
}
|
||||
|
||||
void Selector::setSpecialExpandTopSkip(int skip) {
|
||||
_specialExpandTopSkip = skip;
|
||||
}
|
||||
|
||||
void Selector::initGeometry(int innerTop) {
|
||||
const auto extents = extentsForShadow();
|
||||
const auto parent = parentWidget()->rect();
|
||||
|
@ -84,10 +88,14 @@ void Selector::initGeometry(int innerTop) {
|
|||
const auto width = innerWidth + extents.left() + extents.right();
|
||||
const auto height = innerHeight + extents.top() + extents.bottom();
|
||||
const auto left = style::RightToLeft() ? 0 : (parent.width() - width);
|
||||
const auto top = innerTop - extents.top();
|
||||
_collapsedTopSkip = extendTopForCategories() + _specialExpandTopSkip;
|
||||
const auto top = innerTop - extents.top() - _collapsedTopSkip;
|
||||
const auto add = st::reactStripBubble.height() - extents.bottom();
|
||||
_outer = QRect(0, 0, width, height);
|
||||
setGeometry(_outer.marginsAdded({ 0, 0, 0, add }).translated(left, top));
|
||||
_outer = QRect(0, _collapsedTopSkip, width, height);
|
||||
_outerWithBubble = _outer.marginsAdded({ 0, 0, 0, add });
|
||||
setGeometry(_outerWithBubble.marginsAdded(
|
||||
{ 0, _collapsedTopSkip, 0, 0 }
|
||||
).translated(left, top));
|
||||
_inner = _outer.marginsRemoved(extents);
|
||||
}
|
||||
|
||||
|
@ -120,8 +128,8 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
p.setOpacity(_appearOpacity);
|
||||
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
if (_paintBuffer.size() != size() * factor) {
|
||||
_paintBuffer = _cachedRound.PrepareImage(size());
|
||||
if (_paintBuffer.size() != _outerWithBubble.size() * factor) {
|
||||
_paintBuffer = _cachedRound.PrepareImage(_outerWithBubble.size());
|
||||
}
|
||||
_paintBuffer.fill(st::defaultPopupMenu.menu.itemBg->c);
|
||||
auto q = QPainter(&_paintBuffer);
|
||||
|
@ -133,16 +141,18 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
const auto fullWidth = _inner.x() + appearedWidth + extents.right();
|
||||
const auto size = QSize(fullWidth, _outer.height());
|
||||
|
||||
q.translate(_inner.topLeft() - QPoint(0, _collapsedTopSkip));
|
||||
_strip.paint(
|
||||
q,
|
||||
{ _inner.x() + _skipx, _inner.y() + _skipy },
|
||||
{ _skipx, _skipy },
|
||||
{ _size, 0 },
|
||||
{ _inner.x(), _inner.y(), appearedWidth, _inner.height() },
|
||||
{ 0, 0, appearedWidth, _inner.height() },
|
||||
1.,
|
||||
false);
|
||||
|
||||
_cachedRound.setBackgroundColor(st::defaultPopupMenu.menu.itemBg->c);
|
||||
_cachedRound.setShadowColor(st::shadowFg->c);
|
||||
q.translate(QPoint(0, _collapsedTopSkip) - _inner.topLeft());
|
||||
const auto radius = st::reactStripHeight / 2;
|
||||
_cachedRound.overlayExpandedBorder(q, size, _appearProgress, radius, 1.);
|
||||
q.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
@ -154,38 +164,114 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
q.end();
|
||||
|
||||
p.drawImage(
|
||||
QPoint(),
|
||||
_outer.topLeft(),
|
||||
_paintBuffer,
|
||||
QRect(QPoint(), QSize(fullWidth, height()) * factor));
|
||||
}
|
||||
|
||||
void Selector::paintBackgroundToBuffer() {
|
||||
if (_paintBuffer.size() != size() * style::DevicePixelRatio()) {
|
||||
_paintBuffer = _cachedRound.PrepareImage(size());
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
if (_paintBuffer.size() != _outerWithBubble.size() * factor) {
|
||||
_paintBuffer = _cachedRound.PrepareImage(_outerWithBubble.size());
|
||||
}
|
||||
_paintBuffer.fill(Qt::transparent);
|
||||
|
||||
auto p = QPainter(&_paintBuffer);
|
||||
_cachedRound.FillWithImage(p, _outer, _cachedRound.validateFrame(0, 1.));
|
||||
const auto radius = _inner.height() / 2.;
|
||||
const auto frame = _cachedRound.validateFrame(0, 1., radius);
|
||||
const auto outer = _outer.translated(0, -_collapsedTopSkip);
|
||||
_cachedRound.FillWithImage(p, outer, frame);
|
||||
paintBubble(p, _inner.width());
|
||||
}
|
||||
|
||||
void Selector::paintHorizontal(QPainter &p) {
|
||||
void Selector::paintCollapsed(QPainter &p) {
|
||||
if (_paintBuffer.isNull()) {
|
||||
paintBackgroundToBuffer();
|
||||
}
|
||||
p.drawImage(0, 0, _paintBuffer);
|
||||
|
||||
const auto extents = extentsForShadow();
|
||||
p.drawImage(_outer.topLeft(), _paintBuffer);
|
||||
_strip.paint(
|
||||
p,
|
||||
{ _inner.x() + _skipx, _inner.y() + _skipy },
|
||||
_inner.topLeft() + QPoint(_skipx, _skipy),
|
||||
{ _size, 0 },
|
||||
_inner,
|
||||
1.,
|
||||
false);
|
||||
}
|
||||
|
||||
void Selector::paintExpanding(QPainter &p, float64 progress) {
|
||||
paintExpandingBg(p, progress);
|
||||
paintStripWithoutExpand(p);
|
||||
paintFadingExpandIcon(p, progress);
|
||||
}
|
||||
|
||||
void Selector::paintExpandingBg(QPainter &p, float64 progress) {
|
||||
constexpr auto kFramesCount = Ui::RoundAreaWithShadow::kFramesCount;
|
||||
const auto frame = int(base::SafeRound(progress * (kFramesCount - 1)));
|
||||
const auto radiusStart = st::reactStripHeight / 2.;
|
||||
const auto radiusEnd = st::roundRadiusSmall;
|
||||
const auto radius = radiusStart + progress * (radiusEnd - radiusStart);
|
||||
const auto extents = extentsForShadow();
|
||||
const auto expanding = anim::easeOutCirc(1., progress);
|
||||
const auto expandUp = anim::interpolate(0, _collapsedTopSkip, expanding);
|
||||
const auto expandDown = anim::interpolate(
|
||||
0,
|
||||
(height() - _outer.y() - _outer.height()),
|
||||
expanding);
|
||||
const auto outer = _outer.marginsAdded({ 0, expandUp, 0, expandDown });
|
||||
const auto pattern = _cachedRound.validateFrame(frame, 1., radius);
|
||||
const auto fill = _cachedRound.FillWithImage(p, outer, pattern);
|
||||
if (!fill.isEmpty()) {
|
||||
p.fillRect(fill, st::defaultPopupMenu.menu.itemBg);
|
||||
}
|
||||
}
|
||||
|
||||
void Selector::paintStripWithoutExpand(QPainter &p) {
|
||||
_strip.paint(
|
||||
p,
|
||||
_inner.topLeft() + QPoint(_skipx, _skipy),
|
||||
{ _size, 0 },
|
||||
_inner.marginsRemoved({ 0, 0, _skipx + _size, 0 }),
|
||||
1.,
|
||||
false);
|
||||
}
|
||||
|
||||
void Selector::paintFadingExpandIcon(QPainter &p, float64 progress) {
|
||||
if (progress >= 1.) {
|
||||
return;
|
||||
}
|
||||
p.setOpacity(1. - progress);
|
||||
const auto sub = anim::interpolate(0, _size / 3, progress);
|
||||
const auto expandIconPosition = _inner.topLeft()
|
||||
+ QPoint(_inner.width() - _size - _skipx, _skipy);
|
||||
const auto expandIconRect = QRect(
|
||||
expandIconPosition,
|
||||
QSize(_size, _size)
|
||||
).marginsRemoved({ sub, sub, sub, sub });
|
||||
p.drawImage(expandIconRect, _expandIconCache);
|
||||
}
|
||||
|
||||
void Selector::paintExpanded(QPainter &p) {
|
||||
paintExpandedBg(p);
|
||||
paintStripWithoutExpand(p);
|
||||
}
|
||||
|
||||
void Selector::paintExpandedBg(QPainter &p) {
|
||||
if (!_expandedBgReady) {
|
||||
_expandedBgReady = true;
|
||||
auto q = QPainter(&_paintBuffer);
|
||||
q.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
const auto pattern = _cachedRound.validateFrame(
|
||||
kFramesCount - 1,
|
||||
1.,
|
||||
st::roundRadiusSmall);
|
||||
const auto fill = _cachedRound.FillWithImage(q, rect(), pattern);
|
||||
if (!fill.isEmpty()) {
|
||||
q.fillRect(fill, st::defaultPopupMenu.menu.itemBg);
|
||||
}
|
||||
}
|
||||
p.drawImage(0, 0, _paintBuffer);
|
||||
}
|
||||
|
||||
void Selector::paintBubble(QPainter &p, int innerWidth) {
|
||||
const auto &bubble = st::reactStripBubble;
|
||||
const auto bubbleRight = std::min(
|
||||
|
@ -194,7 +280,7 @@ void Selector::paintBubble(QPainter &p, int innerWidth) {
|
|||
bubble.paint(
|
||||
p,
|
||||
_inner.x() + innerWidth - bubbleRight - bubble.width(),
|
||||
_inner.y() + _inner.height(),
|
||||
_inner.y() + _inner.height() - _collapsedTopSkip,
|
||||
width());
|
||||
}
|
||||
|
||||
|
@ -202,8 +288,12 @@ void Selector::paintEvent(QPaintEvent *e) {
|
|||
auto p = QPainter(this);
|
||||
if (_appearing) {
|
||||
paintAppearing(p);
|
||||
} else if (!_expanded) {
|
||||
paintCollapsed(p);
|
||||
} else if (const auto progress = _expanding.value(1.); progress < 1.) {
|
||||
paintExpanding(p, progress);
|
||||
} else {
|
||||
paintHorizontal(p);
|
||||
paintExpanded(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,6 +342,7 @@ void Selector::mouseReleaseEvent(QMouseEvent *e) {
|
|||
if (selected == Strip::AddedButton::Premium) {
|
||||
_premiumPromoChosen.fire({});
|
||||
} else if (selected == Strip::AddedButton::Expand) {
|
||||
expand();
|
||||
} else {
|
||||
const auto id = std::get_if<Data::ReactionId>(&selected);
|
||||
if (id && !id->empty()) {
|
||||
|
@ -260,6 +351,33 @@ void Selector::mouseReleaseEvent(QMouseEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void Selector::expand() {
|
||||
const auto parent = parentWidget()->geometry();
|
||||
const auto additionalBottom = parent.height() - y() - height();
|
||||
const auto additional = _specialExpandTopSkip + additionalBottom;
|
||||
if (additionalBottom < 0 || additional <= 0) {
|
||||
return;
|
||||
}
|
||||
if (additionalBottom > 0) {
|
||||
resize(width(), height() + additionalBottom);
|
||||
raise();
|
||||
}
|
||||
_expandIconCache = _cachedRound.PrepareImage({ _size, _size });
|
||||
_expandIconCache.fill(Qt::transparent);
|
||||
auto q = QPainter(&_expandIconCache);
|
||||
const auto count = _strip.count();
|
||||
_strip.paint(
|
||||
q,
|
||||
QPoint(-(count - 1) * _size, 0),
|
||||
{ _size, 0 },
|
||||
QRect(-(count - 1) * _size, 0, count * _size, _size),
|
||||
1.,
|
||||
false);
|
||||
_paintBuffer = _cachedRound.PrepareImage(size());
|
||||
_expanded = true;
|
||||
_expanding.start([=] { update(); }, 0., 1., st::slideDuration);
|
||||
}
|
||||
|
||||
bool AdjustMenuGeometryForSelector(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
QPoint desiredPosition,
|
||||
|
@ -317,6 +435,7 @@ bool AdjustMenuGeometryForSelector(
|
|||
extents.right(),
|
||||
0
|
||||
));
|
||||
selector->setSpecialExpandTopSkip(additionalPaddingBottom);
|
||||
return menu->prepareGeometryFor(desiredPosition);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
[[nodiscard]] QMargins extentsForShadow() const;
|
||||
[[nodiscard]] int extendTopForCategories() const;
|
||||
[[nodiscard]] int desiredHeight() const;
|
||||
void setSpecialExpandTopSkip(int skip);
|
||||
void initGeometry(int innerTop);
|
||||
|
||||
[[nodiscard]] rpl::producer<ChosenReaction> chosen() const {
|
||||
|
@ -68,13 +69,21 @@ private:
|
|||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
void paintAppearing(QPainter &p);
|
||||
void paintHorizontal(QPainter &p);
|
||||
void paintCollapsed(QPainter &p);
|
||||
void paintExpanding(QPainter &p, float64 progress);
|
||||
void paintExpandingBg(QPainter &p, float64 progress);
|
||||
void paintStripWithoutExpand(QPainter &p);
|
||||
void paintFadingExpandIcon(QPainter &p, float64 progress);
|
||||
void paintExpanded(QPainter &p);
|
||||
void paintExpandedBg(QPainter &p);
|
||||
void paintBubble(QPainter &p, int innerWidth);
|
||||
void paintBackgroundToBuffer();
|
||||
|
||||
[[nodiscard]] int lookupSelectedIndex(QPoint position) const;
|
||||
void setSelected(int index);
|
||||
|
||||
void expand();
|
||||
|
||||
const Data::PossibleItemReactions _reactions;
|
||||
Ui::RoundAreaWithShadow _cachedRound;
|
||||
Strip _strip;
|
||||
|
@ -83,11 +92,16 @@ private:
|
|||
rpl::event_stream<> _premiumPromoChosen;
|
||||
|
||||
QImage _paintBuffer;
|
||||
Ui::Animations::Simple _expanding;
|
||||
float64 _appearProgress = 0.;
|
||||
float64 _appearOpacity = 0.;
|
||||
QRect _inner;
|
||||
QRect _outer;
|
||||
QRect _outerWithBubble;
|
||||
QImage _expandIconCache;
|
||||
QMargins _padding;
|
||||
int _specialExpandTopSkip = 0;
|
||||
int _collapsedTopSkip = 0;
|
||||
int _size = 0;
|
||||
int _recentRows = 0;
|
||||
int _columns = 0;
|
||||
|
@ -97,6 +111,8 @@ private:
|
|||
int _pressed = -1;
|
||||
bool _appearing = false;
|
||||
bool _toggling = false;
|
||||
bool _expanded = false;
|
||||
bool _expandedBgReady = false;
|
||||
bool _small = false;
|
||||
bool _over = false;
|
||||
bool _low = false;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit eed9293c80eefd7b6d5398b4a65bf7822a1364fc
|
||||
Subproject commit a1ec2c9ade2b050bd307ecf669a2ae5019d70df4
|
Loading…
Add table
Reference in a new issue