mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-13 04:37:11 +02:00
Support about text above reactions strip.
This commit is contained in:
parent
f324c53440
commit
46579ac84d
6 changed files with 148 additions and 28 deletions
|
@ -122,6 +122,8 @@ EmojiPan {
|
|||
removeSet: IconButton;
|
||||
boxLabel: FlatLabel;
|
||||
icons: ComposeIcons;
|
||||
about: FlatLabel;
|
||||
aboutPadding: margins;
|
||||
autocompleteBottomSkip: pixels;
|
||||
}
|
||||
|
||||
|
@ -617,6 +619,14 @@ defaultComposeIcons: ComposeIcons {
|
|||
{ "chat/reactions_expand_panel", windowSubTextFg },
|
||||
};
|
||||
}
|
||||
defaultEmojiPanAbout: FlatLabel(defaultFlatLabel) {
|
||||
minWidth: 10px;
|
||||
align: align(top);
|
||||
textFg: windowSubTextFg;
|
||||
style: TextStyle(defaultTextStyle) {
|
||||
font: font(11px);
|
||||
}
|
||||
}
|
||||
defaultEmojiPan: EmojiPan {
|
||||
margin: margins(7px, 0px, 7px, 0px);
|
||||
padding: margins(7px, 0px, 4px, 7px);
|
||||
|
@ -658,6 +668,8 @@ defaultEmojiPan: EmojiPan {
|
|||
removeSet: stickerPanRemoveSet;
|
||||
boxLabel: boxLabel;
|
||||
icons: defaultComposeIcons;
|
||||
about: defaultEmojiPanAbout;
|
||||
aboutPadding: margins(12px, 2px, 12px, 2px);
|
||||
autocompleteBottomSkip: 0px;
|
||||
}
|
||||
statusEmojiPan: EmojiPan(defaultEmojiPan) {
|
||||
|
|
|
@ -635,7 +635,7 @@ void StickersListFooter::paint(
|
|||
if (context.expanding) {
|
||||
const auto both = clip.intersected(
|
||||
context.clip.marginsRemoved(
|
||||
{ context.radius, 0, context.radius, 0 }));
|
||||
{ 0/*context.radius*/, 0, context.radius, 0 }));
|
||||
if (both.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2636,7 +2636,9 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
desiredPosition,
|
||||
reactItem,
|
||||
[=](ChosenReaction reaction) { reactionChosen(reaction); },
|
||||
TextWithEntities(),
|
||||
(reactItem->reactionsAreTags()
|
||||
? TextWithEntities{ u"Organize your Saved Messages with tags. Learn More..."_q }
|
||||
: TextWithEntities()),
|
||||
_controller->cachedReactionIconFactory().createMethod())
|
||||
: AttachSelectorResult::Skipped;
|
||||
if (attached == AttachSelectorResult::Failed) {
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "history/view/reactions/history_view_reactions_selector.h"
|
||||
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
|
@ -195,6 +196,7 @@ Selector::Selector(
|
|||
const style::EmojiPan &st,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const Data::PossibleItemReactionsRef &reactions,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory,
|
||||
Fn<void(bool fast)> close,
|
||||
bool child)
|
||||
|
@ -207,6 +209,7 @@ Selector::Selector(
|
|||
? ChatHelpers::EmojiListMode::FullReactions
|
||||
: ChatHelpers::EmojiListMode::RecentReactions),
|
||||
{},
|
||||
std::move(about),
|
||||
iconFactory,
|
||||
close,
|
||||
child) {
|
||||
|
@ -227,6 +230,7 @@ Selector::Selector(
|
|||
{ .customAllowed = true },
|
||||
mode,
|
||||
std::move(recent),
|
||||
{},
|
||||
nullptr,
|
||||
close,
|
||||
child) {
|
||||
|
@ -239,6 +243,7 @@ Selector::Selector(
|
|||
const Data::PossibleItemReactionsRef &reactions,
|
||||
ChatHelpers::EmojiListMode mode,
|
||||
std::vector<DocumentId> recent,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory,
|
||||
Fn<void(bool fast)> close,
|
||||
bool child)
|
||||
|
@ -261,6 +266,12 @@ Selector::Selector(
|
|||
crl::guard(this, [=] { update(_inner); }),
|
||||
std::move(iconFactory))
|
||||
: nullptr)
|
||||
, _about(about.empty()
|
||||
? nullptr
|
||||
: std::make_unique<Ui::FlatLabel>(
|
||||
this,
|
||||
rpl::single(about),
|
||||
_st.about))
|
||||
, _size(st::reactStripSize)
|
||||
, _skipx(countSkipLeft())
|
||||
, _skipy((st::reactStripHeight - st::reactStripSize) / 2) {
|
||||
|
@ -269,6 +280,8 @@ Selector::Selector(
|
|||
_useTransparency = child || Ui::Platform::TranslucentWindowsSupported();
|
||||
}
|
||||
|
||||
Selector::~Selector() = default;
|
||||
|
||||
bool Selector::useTransparency() const {
|
||||
return _useTransparency;
|
||||
}
|
||||
|
@ -332,6 +345,27 @@ int Selector::extendTopForCategories() const {
|
|||
return _reactions.customAllowed ? _st.footer : 0;
|
||||
}
|
||||
|
||||
int Selector::extendTopForCategoriesAndAbout(int width) const {
|
||||
if (_about) {
|
||||
const auto padding = _st.aboutPadding;
|
||||
const auto available = width - padding.left() - padding.right();
|
||||
const auto countAboutHeight = [&](int width) {
|
||||
_about->resizeToWidth(width);
|
||||
return _about->height();
|
||||
};
|
||||
const auto desired = Ui::FindNiceTooltipWidth(
|
||||
std::min(available, _st.about.minWidth * 2),
|
||||
available,
|
||||
countAboutHeight);
|
||||
|
||||
_about->resizeToWidth(desired);
|
||||
_aboutExtend = padding.top() + _about->height() + padding.bottom();
|
||||
} else {
|
||||
_aboutExtend = 0;
|
||||
}
|
||||
return std::max(extendTopForCategories(), _aboutExtend);
|
||||
}
|
||||
|
||||
int Selector::minimalHeight() const {
|
||||
return _skipy
|
||||
+ std::min(_recentRows * _size, st::emojiPanMinHeight)
|
||||
|
@ -351,19 +385,33 @@ void Selector::initGeometry(int innerTop) {
|
|||
const auto width = _useTransparency
|
||||
? (innerWidth + margins.left() + margins.right())
|
||||
: parent.width();
|
||||
const auto height = innerHeight + margins.top() + margins.bottom();
|
||||
const auto left = style::RightToLeft() ? 0 : (parent.width() - width);
|
||||
const auto forAbout = width - margins.left() - margins.right();
|
||||
_collapsedTopSkip = _useTransparency
|
||||
? (extendTopForCategories() + _specialExpandTopSkip)
|
||||
? (extendTopForCategoriesAndAbout(forAbout) + _specialExpandTopSkip)
|
||||
: 0;
|
||||
_topAddOnExpand = extendTopForCategories()
|
||||
- _aboutExtend
|
||||
+ _specialExpandTopSkip;
|
||||
const auto height = margins.top()
|
||||
+ _aboutExtend
|
||||
+ innerHeight
|
||||
+ margins.bottom();
|
||||
const auto left = style::RightToLeft() ? 0 : (parent.width() - width);
|
||||
const auto top = innerTop - margins.top() - _collapsedTopSkip;
|
||||
const auto add = _st.icons.stripBubble.height() - margins.bottom();
|
||||
_outer = QRect(0, _collapsedTopSkip, width, height);
|
||||
_outer = QRect(0, _collapsedTopSkip - _aboutExtend, width, height);
|
||||
_outerWithBubble = _outer.marginsAdded({ 0, 0, 0, add });
|
||||
setGeometry(_outerWithBubble.marginsAdded(
|
||||
{ 0, _collapsedTopSkip, 0, 0 }
|
||||
{ 0, _outer.y(), 0, 0}
|
||||
).translated(left, top));
|
||||
_inner = _outer.marginsRemoved(margins);
|
||||
_inner = _outer.marginsRemoved(
|
||||
margins + QMargins{ 0, _aboutExtend, 0, 0 });
|
||||
if (_about) {
|
||||
_about->move(
|
||||
_inner.x() + (_inner.width() - _about->width()) / 2,
|
||||
_outer.y() + margins.top() + _st.aboutPadding.top());
|
||||
_aboutCache = Ui::GrabWidgetToImage(_about.get());
|
||||
}
|
||||
|
||||
if (!_strip) {
|
||||
expand();
|
||||
|
@ -390,6 +438,14 @@ void Selector::updateShowState(
|
|||
&& !appearing
|
||||
&& !_paintBuffer.isNull()) {
|
||||
paintBackgroundToBuffer();
|
||||
if (_about && _about->isHidden()) {
|
||||
_about->show();
|
||||
}
|
||||
} else if (_useTransparency
|
||||
&& !_appearing
|
||||
&& appearing
|
||||
&& _about) {
|
||||
_about->hide();
|
||||
}
|
||||
_appearing = appearing;
|
||||
_toggling = toggling;
|
||||
|
@ -416,7 +472,6 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
Expects(_strip != nullptr);
|
||||
|
||||
p.setOpacity(_appearOpacity);
|
||||
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
if (_paintBuffer.size() != _outerWithBubble.size() * factor) {
|
||||
_paintBuffer = _cachedRound.PrepareImage(_outerWithBubble.size());
|
||||
|
@ -428,7 +483,7 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
const auto fullWidth = _inner.x() + appearedWidth + margins.right();
|
||||
const auto size = QSize(fullWidth, _outer.height());
|
||||
|
||||
q.translate(_inner.topLeft() - QPoint(0, _collapsedTopSkip));
|
||||
q.translate(_inner.topLeft() - QPoint(0, _outer.y()));
|
||||
_strip->paint(
|
||||
q,
|
||||
{ _skipx, _skipy },
|
||||
|
@ -439,7 +494,7 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
|
||||
_cachedRound.setBackgroundColor(_st.bg->c);
|
||||
_cachedRound.setShadowColor(st::shadowFg->c);
|
||||
q.translate(QPoint(0, _collapsedTopSkip) - _inner.topLeft());
|
||||
q.translate(QPoint(0, _outer.y()) - _inner.topLeft());
|
||||
const auto radius = st::reactStripHeight / 2;
|
||||
_cachedRound.overlayExpandedBorder(
|
||||
q,
|
||||
|
@ -460,6 +515,15 @@ void Selector::paintAppearing(QPainter &p) {
|
|||
_outer.topLeft(),
|
||||
_paintBuffer,
|
||||
QRect(QPoint(), QSize(fullWidth, height()) * factor));
|
||||
|
||||
const auto aboutRight = _inner.x() + appearedWidth;
|
||||
if (_about && _about->isHidden() && aboutRight > _about->x()) {
|
||||
const auto aboutWidth = aboutRight - _about->x();
|
||||
p.drawImage(
|
||||
_about->geometry().topLeft(),
|
||||
_aboutCache,
|
||||
QRect(QPoint(), QSize(aboutWidth, _about->height()) * factor));
|
||||
}
|
||||
}
|
||||
|
||||
void Selector::paintBackgroundToBuffer() {
|
||||
|
@ -478,8 +542,11 @@ void Selector::paintBackgroundToBuffer() {
|
|||
auto p = QPainter(&_paintBuffer);
|
||||
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);
|
||||
const auto outer = _outer.translated(0, -_outer.y());
|
||||
const auto fill = _cachedRound.FillWithImage(p, outer, frame);
|
||||
if (!fill.isEmpty()) {
|
||||
p.fillRect(fill, _st.bg);
|
||||
}
|
||||
paintBubble(p, _inner.width());
|
||||
}
|
||||
|
||||
|
@ -507,6 +574,13 @@ void Selector::paintExpanding(Painter &p, float64 progress) {
|
|||
const auto rects = updateExpandingRects(progress);
|
||||
paintExpandingBg(p, rects);
|
||||
progress /= kFullDuration;
|
||||
if (_about && !_aboutCache.isNull()) {
|
||||
p.setClipping(false);
|
||||
p.setOpacity((1. - progress) * (1. - progress));
|
||||
const auto y = _about->y() - _outer.y() + rects.outer.y();
|
||||
p.drawImage(_about->x(), y, _aboutCache);
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
if (_footer) {
|
||||
_footer->paintExpanding(
|
||||
p,
|
||||
|
@ -537,25 +611,36 @@ Selector::ExpandingRects Selector::updateExpandingRects(float64 progress) {
|
|||
: radiusStart;
|
||||
const auto margins = marginsForShadow();
|
||||
const auto expanding = anim::easeOutCirc(1., progress);
|
||||
const auto expandUp = anim::interpolate(0, _collapsedTopSkip, expanding);
|
||||
const auto expandUp = anim::interpolate(0, _topAddOnExpand, expanding);
|
||||
const auto expandDown = anim::interpolate(
|
||||
0,
|
||||
(height() - _outer.y() - _outer.height()),
|
||||
expanding);
|
||||
const auto outer = _outer.marginsAdded({ 0, expandUp, 0, expandDown });
|
||||
const auto categories = anim::interpolate(
|
||||
0,
|
||||
extendTopForCategories(),
|
||||
expanding);
|
||||
const auto inner = outer.marginsRemoved(margins);
|
||||
_shadowTop = inner.y() + categories;
|
||||
const auto inner = outer.marginsRemoved(margins
|
||||
+ QMargins{
|
||||
0,
|
||||
anim::interpolate(_aboutExtend, 0, expanding),
|
||||
0,
|
||||
0 });
|
||||
const auto list = outer.marginsRemoved(margins
|
||||
+ QMargins{
|
||||
0,
|
||||
anim::interpolate(
|
||||
_aboutExtend,
|
||||
extendTopForCategories(),
|
||||
expanding),
|
||||
0,
|
||||
0 });
|
||||
_shadowTop = list.y();
|
||||
const auto categories = list.y() - inner.y();
|
||||
_shadowSkip = (_useTransparency && categories < radius)
|
||||
? int(base::SafeRound(
|
||||
radius - sqrt(categories * (2 * radius - categories))))
|
||||
: 0;
|
||||
return {
|
||||
.categories = QRect(inner.x(), inner.y(), inner.width(), categories),
|
||||
.list = inner.marginsRemoved({ 0, categories, 0, 0 }),
|
||||
.list = list,
|
||||
.radius = radius,
|
||||
.expanding = expanding,
|
||||
.finalBottom = height() - margins.bottom(),
|
||||
|
@ -651,7 +736,7 @@ void Selector::paintBubble(QPainter &p, int innerWidth) {
|
|||
bubble.paint(
|
||||
p,
|
||||
_inner.x() + innerWidth - bubbleRight - bubble.width(),
|
||||
_inner.y() + _inner.height() - _collapsedTopSkip,
|
||||
_inner.y() + _inner.height() - _outer.y(),
|
||||
width());
|
||||
}
|
||||
|
||||
|
@ -804,6 +889,9 @@ void Selector::expand() {
|
|||
|
||||
base::call_delayed(kExpandDelay, this, [this] {
|
||||
const auto full = kExpandDuration + kScaleDuration;
|
||||
if (_about) {
|
||||
_about->hide();
|
||||
}
|
||||
_expanded = true;
|
||||
_paintBuffer = _cachedRound.PrepareImage(size());
|
||||
_expanding.start([=] { update(); }, 0., full, full);
|
||||
|
@ -932,12 +1020,12 @@ bool AdjustMenuGeometryForSelector(
|
|||
const auto maxWidth = menu->st().menu.widthMax + added;
|
||||
const auto width = selector->countWidth(desiredWidth, maxWidth);
|
||||
const auto margins = selector->marginsForShadow();
|
||||
const auto categoriesTop = selector->useTransparency()
|
||||
? selector->extendTopForCategories()
|
||||
const auto categoriesAboutTop = selector->useTransparency()
|
||||
? selector->extendTopForCategoriesAndAbout(width)
|
||||
: 0;
|
||||
menu->setForceWidth(width - added);
|
||||
const auto height = menu->height();
|
||||
const auto fullTop = margins.top() + categoriesTop + extend.top();
|
||||
const auto fullTop = margins.top() + categoriesAboutTop + extend.top();
|
||||
const auto minimalHeight = margins.top()
|
||||
+ selector->minimalHeight()
|
||||
+ margins.bottom();
|
||||
|
@ -1063,7 +1151,7 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
QPoint desiredPosition,
|
||||
not_null<HistoryItem*> item,
|
||||
Fn<void(ChosenReaction)> chosen,
|
||||
TextWithEntities description,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory) {
|
||||
const auto result = AttachSelectorToMenu(
|
||||
menu,
|
||||
|
@ -1071,6 +1159,7 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
st::reactPanelEmojiPan,
|
||||
controller->uiShow(),
|
||||
Data::LookupPossibleReactions(item),
|
||||
std::move(about),
|
||||
std::move(iconFactory));
|
||||
if (!result) {
|
||||
return result.error();
|
||||
|
@ -1103,6 +1192,7 @@ auto AttachSelectorToMenu(
|
|||
const style::EmojiPan &st,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const Data::PossibleItemReactionsRef &reactions,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory)
|
||||
-> base::expected<not_null<Selector*>, AttachSelectorResult> {
|
||||
if (reactions.recent.empty()) {
|
||||
|
@ -1114,6 +1204,7 @@ auto AttachSelectorToMenu(
|
|||
st,
|
||||
std::move(show),
|
||||
std::move(reactions),
|
||||
std::move(about),
|
||||
std::move(iconFactory),
|
||||
[=](bool fast) { menu->hideMenu(fast); },
|
||||
false); // child
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace Ui {
|
|||
class PopupMenu;
|
||||
class ScrollArea;
|
||||
class PlainShadow;
|
||||
class FlatLabel;
|
||||
} // namespace Ui
|
||||
|
||||
namespace HistoryView::Reactions {
|
||||
|
@ -80,6 +81,7 @@ public:
|
|||
const style::EmojiPan &st,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const Data::PossibleItemReactionsRef &reactions,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory,
|
||||
Fn<void(bool fast)> close,
|
||||
bool child = false);
|
||||
|
@ -91,12 +93,14 @@ public:
|
|||
std::vector<DocumentId> recent,
|
||||
Fn<void(bool fast)> close,
|
||||
bool child = false);
|
||||
~Selector();
|
||||
|
||||
[[nodiscard]] bool useTransparency() const;
|
||||
|
||||
int countWidth(int desiredWidth, int maxWidth);
|
||||
[[nodiscard]] QMargins marginsForShadow() const;
|
||||
[[nodiscard]] int extendTopForCategories() const;
|
||||
[[nodiscard]] int extendTopForCategoriesAndAbout(int width) const;
|
||||
[[nodiscard]] int minimalHeight() const;
|
||||
[[nodiscard]] int countAppearedWidth(float64 progress) const;
|
||||
void setSpecialExpandTopSkip(int skip);
|
||||
|
@ -137,6 +141,7 @@ private:
|
|||
const Data::PossibleItemReactionsRef &reactions,
|
||||
ChatHelpers::EmojiListMode mode,
|
||||
std::vector<DocumentId> recent,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory,
|
||||
Fn<void(bool fast)> close,
|
||||
bool child);
|
||||
|
@ -179,6 +184,8 @@ private:
|
|||
Fn<void()> _jumpedToPremium;
|
||||
Ui::RoundAreaWithShadow _cachedRound;
|
||||
std::unique_ptr<Strip> _strip;
|
||||
std::unique_ptr<Ui::FlatLabel> _about;
|
||||
mutable int _aboutExtend = 0;
|
||||
|
||||
rpl::event_stream<ChosenReaction> _chosen;
|
||||
rpl::event_stream<> _willExpand;
|
||||
|
@ -200,9 +207,11 @@ private:
|
|||
QRect _outer;
|
||||
QRect _outerWithBubble;
|
||||
QImage _expandIconCache;
|
||||
QImage _aboutCache;
|
||||
QMargins _padding;
|
||||
int _specialExpandTopSkip = 0;
|
||||
int _collapsedTopSkip = 0;
|
||||
int _topAddOnExpand = 0;
|
||||
const int _size = 0;
|
||||
int _recentRows = 0;
|
||||
int _columns = 0;
|
||||
|
@ -243,7 +252,7 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
QPoint desiredPosition,
|
||||
not_null<HistoryItem*> item,
|
||||
Fn<void(ChosenReaction)> chosen,
|
||||
TextWithEntities description,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory);
|
||||
|
||||
[[nodiscard]] auto AttachSelectorToMenu(
|
||||
|
@ -252,6 +261,7 @@ AttachSelectorResult AttachSelectorToMenu(
|
|||
const style::EmojiPan &st,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
const Data::PossibleItemReactionsRef &reactions,
|
||||
TextWithEntities about,
|
||||
IconFactory iconFactory
|
||||
) -> base::expected<not_null<Selector*>, AttachSelectorResult>;
|
||||
|
||||
|
|
|
@ -675,6 +675,9 @@ void Reactions::Panel::create() {
|
|||
st::storiesReactionsPan,
|
||||
_controller->uiShow(),
|
||||
std::move(reactions),
|
||||
TextWithEntities{ (mode == Mode::Message
|
||||
? u"Send reaction as a private message"_q
|
||||
: QString()) },
|
||||
_controller->cachedReactionIconFactory().createMethod(),
|
||||
[=](bool fast) { hide(mode); });
|
||||
|
||||
|
@ -689,7 +692,8 @@ void Reactions::Panel::create() {
|
|||
const auto maxWidth = desiredWidth * 2;
|
||||
const auto width = _selector->countWidth(desiredWidth, maxWidth);
|
||||
const auto margins = _selector->marginsForShadow();
|
||||
const auto categoriesTop = _selector->extendTopForCategories();
|
||||
const auto categoriesTop = _selector->extendTopForCategoriesAndAbout(
|
||||
width);
|
||||
const auto full = margins.left() + width + margins.right();
|
||||
|
||||
_shownValue = 0.;
|
||||
|
@ -874,6 +878,7 @@ auto Reactions::attachToMenu(
|
|||
st::storiesReactionsPan,
|
||||
show,
|
||||
LookupPossibleReactions(&show->session()),
|
||||
TextWithEntities(),
|
||||
_controller->cachedReactionIconFactory().createMethod());
|
||||
if (!result) {
|
||||
return result.error();
|
||||
|
|
Loading…
Add table
Reference in a new issue