mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 07:33:52 +02:00
Improve multi-pinned message bar.
This commit is contained in:
parent
a614ccad97
commit
aefef948cd
8 changed files with 226 additions and 45 deletions
|
@ -543,7 +543,7 @@ void PeerData::addPinnedSlice(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ensurePinnedMessagesCreated();
|
ensurePinnedMessagesCreated();
|
||||||
_pinnedMessages->add(std::move(ids), noSkipRange, std::nullopt);
|
_pinnedMessages->add(std::move(ids), noSkipRange, count);
|
||||||
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
session().changes().peerUpdated(this, UpdateFlag::PinnedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5225,7 +5225,8 @@ void HistoryWidget::checkPinnedBarState() {
|
||||||
) | rpl::map([=](HistoryView::PinnedId messageId) {
|
) | rpl::map([=](HistoryView::PinnedId messageId) {
|
||||||
return HistoryView::PinnedBarId{
|
return HistoryView::PinnedBarId{
|
||||||
FullMsgId{ peerToChannel(_peer->id), messageId.message },
|
FullMsgId{ peerToChannel(_peer->id), messageId.message },
|
||||||
messageId.type
|
messageId.index,
|
||||||
|
messageId.count
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
_pinnedBar = std::make_unique<Ui::PinnedBar>(
|
_pinnedBar = std::make_unique<Ui::PinnedBar>(
|
||||||
|
|
|
@ -23,10 +23,7 @@ namespace {
|
||||||
|
|
||||||
[[nodiscard]] Ui::MessageBarContent ContentWithoutPreview(
|
[[nodiscard]] Ui::MessageBarContent ContentWithoutPreview(
|
||||||
not_null<HistoryItem*> item) {
|
not_null<HistoryItem*> item) {
|
||||||
const auto media = item->media();
|
|
||||||
const auto poll = media ? media->poll() : nullptr;
|
|
||||||
return Ui::MessageBarContent{
|
return Ui::MessageBarContent{
|
||||||
.id = item->id,
|
|
||||||
.text = { item->inReplyText() },
|
.text = { item->inReplyText() },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -126,17 +123,13 @@ auto WithPinnedTitle(not_null<Main::Session*> session, PinnedBarId id) {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return std::move(content);
|
return std::move(content);
|
||||||
}
|
}
|
||||||
const auto media = item->media();
|
content.title = (id.index + 1 >= id.count)
|
||||||
const auto poll = media ? media->poll() : nullptr;
|
|
||||||
content.title = (id.type == PinnedIdType::First)
|
|
||||||
? tr::lng_pinned_previous(tr::now) // #TODO pinned first?
|
|
||||||
: (id.type == PinnedIdType::Middle)
|
|
||||||
? tr::lng_pinned_previous(tr::now)
|
|
||||||
: !poll
|
|
||||||
? tr::lng_pinned_message(tr::now)
|
? tr::lng_pinned_message(tr::now)
|
||||||
: poll->quiz()
|
: (tr::lng_pinned_message(tr::now) // #TODO pinned
|
||||||
? tr::lng_pinned_quiz(tr::now)
|
+ " #"
|
||||||
: tr::lng_pinned_poll(tr::now);
|
+ QString::number(id.count - id.index));
|
||||||
|
content.count = std::max(id.count, 1);
|
||||||
|
content.index = std::clamp(id.index, 0, content.count - 1);
|
||||||
return std::move(content);
|
return std::move(content);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,16 @@ namespace HistoryView {
|
||||||
enum class PinnedIdType;
|
enum class PinnedIdType;
|
||||||
struct PinnedBarId {
|
struct PinnedBarId {
|
||||||
FullMsgId message;
|
FullMsgId message;
|
||||||
PinnedIdType type = PinnedIdType();
|
int index = 0;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
bool operator<(const PinnedBarId &other) const {
|
bool operator<(const PinnedBarId &other) const {
|
||||||
return std::tie(message, type) < std::tie(other.message, other.type);
|
return std::tie(message, index, count)
|
||||||
|
< std::tie(other.message, other.index, other.count);
|
||||||
}
|
}
|
||||||
bool operator==(const PinnedBarId &other) const {
|
bool operator==(const PinnedBarId &other) const {
|
||||||
return std::tie(message, type) == std::tie(other.message, other.type);
|
return std::tie(message, index, count)
|
||||||
|
== std::tie(other.message, other.index, other.count);
|
||||||
}
|
}
|
||||||
bool operator!=(const PinnedBarId &other) const {
|
bool operator!=(const PinnedBarId &other) const {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
|
|
|
@ -102,15 +102,18 @@ void PinnedTracker::setupViewer(not_null<Data::PinnedMessages*> data) {
|
||||||
_current = PinnedId();
|
_current = PinnedId();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto type = (!after && (snapshot.skippedAfter == 0))
|
const auto count = std::max(
|
||||||
? PinnedIdType::Last
|
snapshot.fullCount.value_or(1),
|
||||||
: (before < 2 && (snapshot.skippedBefore == 0))
|
int(snapshot.ids.size()));
|
||||||
? PinnedIdType::First
|
const auto index = snapshot.skippedBefore.has_value()
|
||||||
: PinnedIdType::Middle;
|
? (*snapshot.skippedBefore + before)
|
||||||
|
: snapshot.skippedAfter.has_value()
|
||||||
|
? (count - *snapshot.skippedAfter - after)
|
||||||
|
: 1;
|
||||||
if (i != begin(snapshot.ids)) {
|
if (i != begin(snapshot.ids)) {
|
||||||
_current = PinnedId{ *(i - 1), type };
|
_current = PinnedId{ *(i - 1), index - 1, count };
|
||||||
} else if (snapshot.skippedBefore == 0) {
|
} else if (snapshot.skippedBefore == 0) {
|
||||||
_current = PinnedId{ snapshot.ids.front(), type };
|
_current = PinnedId{ snapshot.ids.front(), 0, count };
|
||||||
}
|
}
|
||||||
}, _dataLifetime);
|
}, _dataLifetime);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,18 @@ enum class LoadDirection : char;
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
|
||||||
enum class PinnedIdType {
|
|
||||||
First,
|
|
||||||
Middle,
|
|
||||||
Last,
|
|
||||||
};
|
|
||||||
struct PinnedId {
|
struct PinnedId {
|
||||||
MsgId message = 0;
|
MsgId message = 0;
|
||||||
PinnedIdType type = PinnedIdType::Middle;
|
int index = 0;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
bool operator<(const PinnedId &other) const {
|
bool operator<(const PinnedId &other) const {
|
||||||
return std::tie(message, type) < std::tie(other.message, other.type);
|
return std::tie(message, index, count)
|
||||||
|
< std::tie(other.message, other.index, other.count);
|
||||||
}
|
}
|
||||||
bool operator==(const PinnedId &other) const {
|
bool operator==(const PinnedId &other) const {
|
||||||
return std::tie(message, type) == std::tie(other.message, other.type);
|
return std::tie(message, index, count)
|
||||||
|
== std::tie(other.message, other.index, other.count);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/chat/message_bar.h"
|
#include "ui/chat/message_bar.h"
|
||||||
|
|
||||||
#include "ui/text/text_options.h"
|
#include "ui/text/text_options.h"
|
||||||
|
#include "ui/image/image_prepare.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "styles/palette.h"
|
#include "styles/palette.h"
|
||||||
|
|
||||||
|
@ -50,7 +51,8 @@ MessageBar::BodyAnimation MessageBar::DetectBodyAnimationType(
|
||||||
? currentAnimation->bodyAnimation
|
? currentAnimation->bodyAnimation
|
||||||
: BodyAnimation::None;
|
: BodyAnimation::None;
|
||||||
const auto somethingChanged = (currentContent.text != nextContent.text)
|
const auto somethingChanged = (currentContent.text != nextContent.text)
|
||||||
|| (currentContent.id != nextContent.id);
|
|| (currentContent.index != nextContent.index)
|
||||||
|
|| (currentContent.count != nextContent.count);
|
||||||
return (now == BodyAnimation::Full
|
return (now == BodyAnimation::Full
|
||||||
|| currentContent.title != nextContent.title
|
|| currentContent.title != nextContent.title
|
||||||
|| (currentContent.title.isEmpty() && somethingChanged))
|
|| (currentContent.title.isEmpty() && somethingChanged))
|
||||||
|
@ -61,6 +63,9 @@ MessageBar::BodyAnimation MessageBar::DetectBodyAnimationType(
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageBar::tweenTo(MessageBarContent &&content) {
|
void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||||
|
Expects(content.count > 0);
|
||||||
|
Expects(content.index >= 0 && content.index < content.count);
|
||||||
|
|
||||||
_widget.update();
|
_widget.update();
|
||||||
if (!_st.duration || anim::Disabled() || _widget.size().isEmpty()) {
|
if (!_st.duration || anim::Disabled() || _widget.size().isEmpty()) {
|
||||||
updateFromContent(std::move(content));
|
updateFromContent(std::move(content));
|
||||||
|
@ -68,18 +73,22 @@ void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||||
}
|
}
|
||||||
const auto hasImageChanged = (_content.preview.isNull()
|
const auto hasImageChanged = (_content.preview.isNull()
|
||||||
!= content.preview.isNull());
|
!= content.preview.isNull());
|
||||||
const auto bodyChanged = (_content.id != content.id
|
const auto bodyChanged = (_content.index != content.index
|
||||||
|
|| _content.count != content.count
|
||||||
|| _content.title != content.title
|
|| _content.title != content.title
|
||||||
|| _content.text != content.text
|
|| _content.text != content.text
|
||||||
|| _content.preview.constBits() != content.preview.constBits());
|
|| _content.preview.constBits() != content.preview.constBits());
|
||||||
|
const auto barCountChanged = (_content.count != content.count);
|
||||||
|
const auto barFrom = _content.index;
|
||||||
|
const auto barTo = content.index;
|
||||||
auto animation = Animation();
|
auto animation = Animation();
|
||||||
animation.bodyAnimation = DetectBodyAnimationType(
|
animation.bodyAnimation = DetectBodyAnimationType(
|
||||||
_animation.get(),
|
_animation.get(),
|
||||||
_content,
|
_content,
|
||||||
content);
|
content);
|
||||||
animation.movingTo = (content.id > _content.id)
|
animation.movingTo = (content.index > _content.index)
|
||||||
? RectPart::Top
|
? RectPart::Top
|
||||||
: (content.id < _content.id)
|
: (content.index < _content.index)
|
||||||
? RectPart::Bottom
|
? RectPart::Bottom
|
||||||
: RectPart::None;
|
: RectPart::None;
|
||||||
animation.imageFrom = grabImagePart();
|
animation.imageFrom = grabImagePart();
|
||||||
|
@ -92,6 +101,8 @@ void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||||
_animation = std::move(was);
|
_animation = std::move(was);
|
||||||
std::swap(*_animation, animation);
|
std::swap(*_animation, animation);
|
||||||
_animation->imageShown = std::move(animation.imageShown);
|
_animation->imageShown = std::move(animation.imageShown);
|
||||||
|
_animation->barScroll = std::move(animation.barScroll);
|
||||||
|
_animation->barTop = std::move(animation.barTop);
|
||||||
} else {
|
} else {
|
||||||
_animation = std::make_unique<Animation>(std::move(animation));
|
_animation = std::make_unique<Animation>(std::move(animation));
|
||||||
}
|
}
|
||||||
|
@ -110,6 +121,23 @@ void MessageBar::tweenTo(MessageBarContent &&content) {
|
||||||
1.,
|
1.,
|
||||||
_st.duration);
|
_st.duration);
|
||||||
}
|
}
|
||||||
|
if (barCountChanged) {
|
||||||
|
_animation->barScroll.stop();
|
||||||
|
_animation->barTop.stop();
|
||||||
|
} else if (barFrom != barTo) {
|
||||||
|
const auto wasState = countBarState(barFrom);
|
||||||
|
const auto nowState = countBarState(barTo);
|
||||||
|
_animation->barScroll.start(
|
||||||
|
[=] { _widget.update(); },
|
||||||
|
wasState.scroll,
|
||||||
|
nowState.scroll,
|
||||||
|
_st.duration);
|
||||||
|
_animation->barTop.start(
|
||||||
|
[] {},
|
||||||
|
wasState.offset,
|
||||||
|
nowState.offset,
|
||||||
|
_st.duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageBar::updateFromContent(MessageBarContent &&content) {
|
void MessageBar::updateFromContent(MessageBarContent &&content) {
|
||||||
|
@ -239,12 +267,7 @@ void MessageBar::paint(Painter &p) {
|
||||||
? (shiftTo - shiftFull)
|
? (shiftTo - shiftFull)
|
||||||
: (shiftTo + shiftFull);
|
: (shiftTo + shiftFull);
|
||||||
|
|
||||||
const auto bar = QRect(
|
paintLeftBar(p);
|
||||||
st::msgReplyBarSkip + st::msgReplyBarPos.x(),
|
|
||||||
st::msgReplyPadding.top() + st::msgReplyBarPos.y(),
|
|
||||||
st::msgReplyBarSize.width(),
|
|
||||||
st::msgReplyBarSize.height());
|
|
||||||
p.fillRect(bar, st::msgInReplyBarColor);
|
|
||||||
|
|
||||||
if (!_animation) {
|
if (!_animation) {
|
||||||
if (!_image.isNull()) {
|
if (!_image.isNull()) {
|
||||||
|
@ -315,4 +338,150 @@ void MessageBar::paint(Painter &p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto MessageBar::countBarState(int index) const -> BarState {
|
||||||
|
Expects(index >= 0 && index < _content.count);
|
||||||
|
|
||||||
|
auto result = BarState();
|
||||||
|
const auto line = st::msgReplyBarSize.width();
|
||||||
|
const auto height = st::msgReplyBarSize.height();
|
||||||
|
const auto count = _content.count;
|
||||||
|
const auto shownCount = std::min(count, 4);
|
||||||
|
const auto dividers = (shownCount - 1) * line;
|
||||||
|
const auto size = float64(st::msgReplyBarSize.height() - dividers)
|
||||||
|
/ shownCount;
|
||||||
|
const auto fullHeight = count * size + (count - 1) * line;
|
||||||
|
const auto topByIndex = [&](int index) {
|
||||||
|
return index * (size + line);
|
||||||
|
};
|
||||||
|
result.scroll = (count < 5 || index < 2)
|
||||||
|
? 0
|
||||||
|
: (index >= count - 2)
|
||||||
|
? (fullHeight - height)
|
||||||
|
: (topByIndex(index) - (height - size) / 2);
|
||||||
|
result.size = size;
|
||||||
|
result.skip = line;
|
||||||
|
result.offset = topByIndex(index);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MessageBar::countBarState() const -> BarState {
|
||||||
|
return countBarState(_content.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageBar::ensureGradientsCreated(int size) {
|
||||||
|
if (!_topBarGradient.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto rows = size * style::DevicePixelRatio() - 2;
|
||||||
|
auto bottomMask = QImage(
|
||||||
|
QSize(1, size) * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
const auto step = ((1ULL << 24) - 1) / rows;
|
||||||
|
const auto limit = step * rows;
|
||||||
|
auto bits = bottomMask.bits();
|
||||||
|
const auto perLine = bottomMask.bytesPerLine();
|
||||||
|
for (auto counter = uint32(0); counter != limit; counter += step) {
|
||||||
|
const auto value = (counter >> 16);
|
||||||
|
memset(bits, int(value), perLine);
|
||||||
|
bits += perLine;
|
||||||
|
}
|
||||||
|
memset(bits, 255, perLine * 2);
|
||||||
|
auto bottom = style::colorizeImage(bottomMask, st::historyPinnedBg);
|
||||||
|
bottom.setDevicePixelRatio(style::DevicePixelRatio());
|
||||||
|
auto top = bottom.mirrored();
|
||||||
|
_bottomBarGradient = Images::PixmapFast(std::move(bottom));
|
||||||
|
_topBarGradient = Images::PixmapFast(std::move(top));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageBar::paintLeftBar(Painter &p) {
|
||||||
|
const auto state = countBarState();
|
||||||
|
const auto gradientSize = int(std::ceil(state.size * 2.5));
|
||||||
|
if (_content.count > 4) {
|
||||||
|
ensureGradientsCreated(gradientSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto scroll = _animation
|
||||||
|
? _animation->barScroll.value(state.scroll)
|
||||||
|
: state.scroll;
|
||||||
|
const auto offset = _animation
|
||||||
|
? _animation->barTop.value(state.offset)
|
||||||
|
: state.offset;
|
||||||
|
const auto line = st::msgReplyBarSize.width();
|
||||||
|
const auto height = st::msgReplyBarSize.height();
|
||||||
|
const auto activeFrom = offset - scroll;
|
||||||
|
const auto activeTill = activeFrom + state.size;
|
||||||
|
const auto single = state.size + state.skip;
|
||||||
|
|
||||||
|
const auto barSkip = st::msgReplyPadding.top() + st::msgReplyBarPos.y();
|
||||||
|
const auto fullHeight = barSkip + height + barSkip;
|
||||||
|
const auto bar = QRect(
|
||||||
|
st::msgReplyBarSkip + st::msgReplyBarPos.x(),
|
||||||
|
barSkip,
|
||||||
|
line,
|
||||||
|
state.size);
|
||||||
|
const auto paintFromScroll = std::max(scroll - barSkip, 0.);
|
||||||
|
const auto paintFrom = int(std::floor(paintFromScroll / single));
|
||||||
|
const auto paintTillScroll = (scroll + height + barSkip);
|
||||||
|
const auto paintTill = std::min(
|
||||||
|
int(std::floor(paintTillScroll / single)) + 1,
|
||||||
|
_content.count);
|
||||||
|
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
const auto activeBrush = QBrush(st::msgInReplyBarColor);
|
||||||
|
const auto inactiveBrush = QBrush(QColor(
|
||||||
|
st::msgInReplyBarColor->c.red(),
|
||||||
|
st::msgInReplyBarColor->c.green(),
|
||||||
|
st::msgInReplyBarColor->c.blue(),
|
||||||
|
st::msgInReplyBarColor->c.alpha() / 3));
|
||||||
|
const auto radius = line / 2.;
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
for (auto i = paintFrom; i != paintTill; ++i) {
|
||||||
|
const auto top = i * single - scroll;
|
||||||
|
const auto bottom = top + state.size;
|
||||||
|
const auto active = (top == activeFrom);
|
||||||
|
p.setBrush(active ? activeBrush : inactiveBrush);
|
||||||
|
p.drawRoundedRect(bar.translated(0, top), radius, radius);
|
||||||
|
if (active
|
||||||
|
|| bottom - line <= activeFrom
|
||||||
|
|| top + line >= activeTill) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto partFrom = std::max(top, activeFrom);
|
||||||
|
const auto partTill = std::min(bottom, activeTill);
|
||||||
|
p.setBrush(activeBrush);
|
||||||
|
p.drawRoundedRect(
|
||||||
|
QRect(bar.x(), bar.y() + partFrom, line, partTill - partFrom),
|
||||||
|
radius,
|
||||||
|
radius);
|
||||||
|
}
|
||||||
|
if (_content.count > 4) {
|
||||||
|
const auto firstScroll = countBarState(2).scroll;
|
||||||
|
const auto gradientTop = (scroll >= firstScroll)
|
||||||
|
? 0
|
||||||
|
: anim::interpolate(-gradientSize, 0, scroll / firstScroll);
|
||||||
|
const auto lastScroll = countBarState(_content.count - 3).scroll;
|
||||||
|
const auto largestScroll = countBarState(_content.count - 1).scroll;
|
||||||
|
const auto gradientBottom = (scroll <= lastScroll)
|
||||||
|
? fullHeight
|
||||||
|
: anim::interpolate(
|
||||||
|
fullHeight,
|
||||||
|
fullHeight + gradientSize,
|
||||||
|
(scroll - lastScroll) / (largestScroll - lastScroll));
|
||||||
|
if (gradientTop > -gradientSize) {
|
||||||
|
p.drawPixmap(
|
||||||
|
QRect(bar.x(), gradientTop, bar.width(), gradientSize),
|
||||||
|
_topBarGradient);
|
||||||
|
}
|
||||||
|
if (gradientBottom < fullHeight + gradientSize) {
|
||||||
|
p.drawPixmap(
|
||||||
|
QRect(
|
||||||
|
bar.x(),
|
||||||
|
gradientBottom - gradientSize,
|
||||||
|
bar.width(),
|
||||||
|
gradientSize),
|
||||||
|
_bottomBarGradient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -19,7 +19,8 @@ struct MessageBar;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
struct MessageBarContent {
|
struct MessageBarContent {
|
||||||
int id = 0;
|
int index = 0;
|
||||||
|
int count = 1;
|
||||||
QString title;
|
QString title;
|
||||||
TextWithEntities text;
|
TextWithEntities text;
|
||||||
QImage preview;
|
QImage preview;
|
||||||
|
@ -47,6 +48,8 @@ private:
|
||||||
struct Animation {
|
struct Animation {
|
||||||
Ui::Animations::Simple bodyMoved;
|
Ui::Animations::Simple bodyMoved;
|
||||||
Ui::Animations::Simple imageShown;
|
Ui::Animations::Simple imageShown;
|
||||||
|
Ui::Animations::Simple barScroll;
|
||||||
|
Ui::Animations::Simple barTop;
|
||||||
QPixmap bodyOrTextFrom;
|
QPixmap bodyOrTextFrom;
|
||||||
QPixmap bodyOrTextTo;
|
QPixmap bodyOrTextTo;
|
||||||
QPixmap imageFrom;
|
QPixmap imageFrom;
|
||||||
|
@ -54,8 +57,15 @@ private:
|
||||||
BodyAnimation bodyAnimation = BodyAnimation::None;
|
BodyAnimation bodyAnimation = BodyAnimation::None;
|
||||||
RectPart movingTo = RectPart::None;
|
RectPart movingTo = RectPart::None;
|
||||||
};
|
};
|
||||||
|
struct BarState {
|
||||||
|
float64 scroll = 0.;
|
||||||
|
float64 size = 0.;
|
||||||
|
float64 skip = 0.;
|
||||||
|
float64 offset = 0.;
|
||||||
|
};
|
||||||
void setup();
|
void setup();
|
||||||
void paint(Painter &p);
|
void paint(Painter &p);
|
||||||
|
void paintLeftBar(Painter &p);
|
||||||
void tweenTo(MessageBarContent &&content);
|
void tweenTo(MessageBarContent &&content);
|
||||||
void updateFromContent(MessageBarContent &&content);
|
void updateFromContent(MessageBarContent &&content);
|
||||||
[[nodiscard]] QPixmap prepareImage(const QImage &preview);
|
[[nodiscard]] QPixmap prepareImage(const QImage &preview);
|
||||||
|
@ -71,6 +81,10 @@ private:
|
||||||
[[nodiscard]] QPixmap grabBodyPart();
|
[[nodiscard]] QPixmap grabBodyPart();
|
||||||
[[nodiscard]] QPixmap grabTextPart();
|
[[nodiscard]] QPixmap grabTextPart();
|
||||||
|
|
||||||
|
[[nodiscard]] BarState countBarState(int index) const;
|
||||||
|
[[nodiscard]] BarState countBarState() const;
|
||||||
|
void ensureGradientsCreated(int size);
|
||||||
|
|
||||||
[[nodiscard]] static BodyAnimation DetectBodyAnimationType(
|
[[nodiscard]] static BodyAnimation DetectBodyAnimationType(
|
||||||
Animation *currentAnimation,
|
Animation *currentAnimation,
|
||||||
const MessageBarContent ¤tContent,
|
const MessageBarContent ¤tContent,
|
||||||
|
@ -81,7 +95,7 @@ private:
|
||||||
MessageBarContent _content;
|
MessageBarContent _content;
|
||||||
rpl::lifetime _contentLifetime;
|
rpl::lifetime _contentLifetime;
|
||||||
Ui::Text::String _title, _text;
|
Ui::Text::String _title, _text;
|
||||||
QPixmap _image;
|
QPixmap _image, _topBarGradient, _bottomBarGradient;
|
||||||
std::unique_ptr<Animation> _animation;
|
std::unique_ptr<Animation> _animation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue