Improve negative rating display.

This commit is contained in:
John Preston
2025-08-01 20:53:59 +04:00
parent 051b8c4b63
commit 667822ca08
9 changed files with 110 additions and 25 deletions
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / Filled / Folder / filled_warning</title>
<g id="Icon-/-Filled-/-Folder-/-filled_warning" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M4.88979533,20 L19.1102047,20 C20.5643501,20 21.4708304,18.4289284 20.7437577,17.1777157 L13.633553,4.93840953 C12.9064803,3.68719682 11.0935197,3.68719682 10.366447,4.93840953 L3.25624234,17.1777157 C2.52916961,18.4289284 3.43564989,20 4.88979533,20 Z M12,9.51724138 C12.4659903,9.51724138 12.84375,9.89500112 12.84375,10.3609914 L12.84375,13.3631466 C12.84375,13.8291368 12.4659903,14.2068966 12,14.2068966 C11.5340097,14.2068966 11.15625,13.8291368 11.15625,13.3631466 L11.15625,10.3609914 C11.15625,9.89500112 11.5340097,9.51724138 12,9.51724138 Z M12.018319,17.1862069 L11.981681,17.1862069 C11.463676,17.1862069 11.04375,16.7662809 11.04375,16.2482759 C11.04375,15.7302709 11.463676,15.3103448 11.981681,15.3103448 L12.018319,15.3103448 C12.536324,15.3103448 12.95625,15.7302709 12.95625,16.2482759 C12.95625,16.7662809 12.536324,17.1862069 12.018319,17.1862069 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+4
View File
@@ -1882,6 +1882,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stars_rating_pending#other" = "The rating updates in 21 days after purchases.\n{count} points are pending. {link}";
"lng_stars_rating_pending_preview" = "Preview {arrow}";
"lng_stars_rating_pending_back" = "Back {arrow}";
"lng_stars_rating_negative_label" = "Negative Rating";
"lng_stars_rating_negative" = "A negative rating indicates that **{name}'s** payments are unreliable.";
"lng_stars_rating_negative_your#one" = "A negative rating indicates that your payments are unreliable. Spend **{count} Star** to fix this issue.";
"lng_stars_rating_negative_your#other" = "A negative rating indicates that your payments are unreliable. Spend **{count} Stars** to fix this issue.";
"lng_stars_rating_about" = "This rating reflects **{name}'s** activity on Telegram. What affects it:";
"lng_stars_rating_about_your" = "This rating reflects your activity on Telegram. What affects it:";
"lng_stars_title_gifts_telegram" = "Gifts from Telegram";
@@ -525,7 +525,11 @@ rpl::producer<Data::StarsRating> StarsRatingValue(
user,
Data::PeerUpdate::Flag::StarsRating
) | rpl::map([=] {
return user->starsRating();
auto result = user->starsRating();
if (!user->isSelf() && result.level < 0) {
result.stars = 0;
}
return result;
});
}
return rpl::single(Data::StarsRating());
@@ -74,3 +74,7 @@ level80: LevelShape(levelBase) {
level90: LevelShape(levelBase) {
icon: icon {{ "levels/level90_inner-31x31", windowBgActive }};
}
levelNegative: LevelShape(levelBase) {
icon: icon {{ "levels/level_warning-18x18", attentionButtonFg, point(6px, 7px) }};
}
levelNegativeBubble: icon {{ "levels/level_warning-28x28", windowFgActive }};
@@ -157,13 +157,19 @@ void FillRatingLimit(
rpl::producer<> showFinished,
not_null<VerticalLayout*> container,
rpl::producer<Counters> data,
Premium::BubbleType type,
style::margins limitLinePadding,
int starsForScale) {
int starsForScale,
bool hideCount) {
const auto addSkip = [&](int skip) {
container->add(object_ptr<Ui::FixedHeightWidget>(container, skip));
};
const auto negative = (type == Premium::BubbleType::NegativeRating);
const auto ratio = [=](Counters rating) {
if (negative) {
return 0.5;
}
const auto min = rating.thisLevelStars;
const auto max = rating.nextLevelStars;
@@ -213,12 +219,14 @@ void FillRatingLimit(
});
Premium::AddBubbleRow(
container,
st::boostBubble,
(hideCount ? st::iconOnlyPremiumBubble : st::boostBubble),
std::move(showFinished),
rpl::duplicate(bubbleRowState),
Premium::BubbleType::StarRating,
BubbleTextFactory(starsForScale),
&st::infoStarsCrown,
type,
(hideCount
? [](int) { return QString(); }
: BubbleTextFactory(starsForScale)),
negative ? &st::levelNegativeBubble : &st::infoStarsCrown,
limitLinePadding);
addSkip(st::premiumLineTextSkip);
@@ -227,30 +235,35 @@ void FillRatingLimit(
};
auto limitState = std::move(
bubbleRowState
) | rpl::map([](const Premium::BubbleRowState &state) {
) | rpl::map([negative](const Premium::BubbleRowState &state) {
return Premium::LimitRowState{
.ratio = state.ratio,
.animateFromZero = state.animateFromZero,
.ratio = negative ? 0.5 : state.ratio,
.animateFromZero = !negative && state.animateFromZero,
.dynamic = state.dynamic
};
});
auto left = rpl::duplicate(
adjustedData
) | rpl::map([=](Counters counters) {
return level(counters.level);
return (counters.level < 0) ? QString() : level(counters.level);
});
auto right = rpl::duplicate(
adjustedData
) | rpl::map([=](Counters counters) {
return level(counters.level + 1);
return (counters.level < 0)
? tr::lng_stars_rating_negative_label(tr::now)
: level(counters.level + 1);
});
Premium::AddLimitRow(
container,
st::boostLimits,
(negative ? st::negativeStarsLimits : st::boostLimits),
Premium::LimitRowLabels{
.leftLabel = std::move(left),
.rightLabel = std::move(right),
.activeLineBg = [=] { return st::windowBgActive->b; },
.activeLineBg = [=] { return negative
? st::attentionButtonFg->b
: st::windowBgActive->b;
},
},
std::move(limitState),
limitLinePadding);
@@ -276,8 +289,12 @@ void AboutRatingBox(
BoxShowFinishes(box),
box->verticalLayout(),
state->data.value(),
(data.level < 0
? Premium::BubbleType::NegativeRating
: Premium::BubbleType::StarRating),
st::boxRowPadding,
data.stars);
data.stars,
(data.level < 0 && !data.stars));
box->setMaxHeight(st::boostBoxMaxHeight);
@@ -294,10 +311,40 @@ void AboutRatingBox(
: tr::lng_stars_rating_about_your(
Ui::Text::RichLangValue) | rpl::type_erased();
if (data.level < 0) {
auto text = (data.stars < 0)
? tr::lng_stars_rating_negative_your(
lt_count_decimal,
rpl::single(-data.stars * 1.),
Ui::Text::RichLangValue)
: tr::lng_stars_rating_negative(
lt_name,
rpl::single(TextWithEntities{ name }),
Ui::Text::RichLangValue);
const auto aboutNegative = box->addRow(
object_ptr<Ui::FlatLabel>(
box,
std::move(text),
st::boostTextNegative),
(st::boxRowPadding
+ QMargins(0, st::boostTextSkip, 0, st::boostBottomSkip)));
aboutNegative->setTryMakeSimilarLines(true);
}
box->addRow(
object_ptr<Ui::FlatLabel>(box, std::move(title), st::infoStarsTitle),
st::boxRowPadding + QMargins(0, st::boostTitleSkip / 2, 0, 0));
AssertIsDebug();
pending = {
.value = {
.level = 10,
.stars = 100,
.thisLevelStars = 90,
.nextLevelStars = 110,
},
.date = 86400,
};
if (pending) {
auto text = state->pending.value(
) | rpl::map([=](bool value) {
@@ -398,6 +445,9 @@ void AboutRatingBox(
}
[[nodiscard]] not_null<const style::LevelShape*> SelectShape(int level) {
if (level < 0) {
return &st::levelNegative;
}
struct Shape {
int level = 0;
not_null<const style::LevelShape*> shape;
@@ -480,7 +530,9 @@ void StarsRating::updateData(Data::StarsRating rating) {
_shape = SelectShape(rating.level);
_collapsedText.setText(
st::levelStyle,
Lang::FormatCountDecimal(rating.level));
(rating.level < 0
? QString()
: Lang::FormatCountDecimal(rating.level)));
_widthValue = _shape->icon.width() - st::levelMargin.left();
}
updateWidth();
@@ -255,6 +255,9 @@ boostLimits: PremiumLimits(defaultPremiumLimits) {
gradientFromLeft: true;
nonPremiumBg: windowBgRipple;
}
negativeStarsLimits: PremiumLimits(boostLimits) {
gradientFromLeft: false;
}
boostBubble: PremiumBubble(defaultPremiumBubble) {
height: 32px;
padding: margins(7px, 0px, 11px, 0px);
@@ -263,6 +266,10 @@ boostBubble: PremiumBubble(defaultPremiumBubble) {
tailSize: size(14px, 6px);
font: font(16px);
}
iconOnlyPremiumBubble: PremiumBubble(boostBubble) {
padding: margins(7px, 0px, 7px, 0px);
textSkip: 0px;
}
boostTitleSkip: 32px;
boostTitle: FlatLabel(defaultFlatLabel) {
minWidth: 40px;
@@ -289,6 +296,9 @@ boostText: FlatLabel(defaultFlatLabel) {
boostTextPending: FlatLabel(boostText) {
textFg: windowSubTextFg;
}
boostTextNegative: FlatLabel(boostText) {
textFg: attentionButtonFg;
}
boostReassignText: FlatLabel(defaultFlatLabel) {
minWidth: 40px;
align: align(top);
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/painter.h"
#include "styles/style_info_levels.h"
#include "styles/style_layers.h"
#include "styles/style_premium.h"
@@ -181,11 +182,9 @@ void Bubble::paintBubble(QPainter &p, const QRect &r, const QBrush &brush) {
p.setPen(st::activeButtonFg);
p.setFont(_st.font);
const auto iconLeft = r.x() + _st.padding.left();
_icon->paint(
p,
iconLeft,
bubbleRect.y() + (bubbleRect.height() - _icon->height()) / 2,
bubbleRect.width());
const auto iconTop = bubbleRect.y()
+ (bubbleRect.height() - _icon->height()) / 2;
_icon->paint(p, iconLeft, iconTop, bubbleRect.width());
_numberAnimation.paint(
p,
iconLeft + _icon->width() + _st.textSkip,
@@ -424,6 +423,7 @@ void BubbleWidget::paintEvent(QPaintEvent *e) {
switch (_type) {
case BubbleType::NoPremium:
case BubbleType::StarRating: return st::windowBgActive->b;
case BubbleType::NegativeRating: return st::attentionButtonFg->b;
case BubbleType::Premium: return QBrush(_cachedGradient);
case BubbleType::Credits: return st::creditsBg3->b;
}
@@ -89,6 +89,7 @@ struct BubbleRowState {
enum class BubbleType : uchar {
StarRating,
NegativeRating,
NoPremium,
Premium,
Credits,
@@ -372,7 +372,6 @@ void Line::recache(const QSize &s) {
}
};
const auto textPadding = st::premiumLineTextSkip;
const auto textTop = (s.height() - _leftLabel.minHeight()) / 2;
const auto rwidth = _rightLabel.maxWidth();
const auto pen = [&](bool gradient) {
return gradient ? st::activeButtonFg : _st.nonPremiumFg;
@@ -385,8 +384,10 @@ void Line::recache(const QSize &s) {
if (_dynamic) {
p.setFont(st::normalFont);
p.setPen(pen(_st.gradientFromLeft));
_leftLabel.drawLeft(p, textPadding, textTop, width, width);
_rightLabel.drawRight(p, textPadding, textTop, rwidth, width);
const auto leftTop = (s.height() - _leftLabel.minHeight()) / 2;
_leftLabel.drawLeft(p, textPadding, leftTop, width, width);
const auto rightTop = (s.height() - _rightLabel.minHeight()) / 2;
_rightLabel.drawRight(p, textPadding, rightTop, rwidth, width);
}
_leftPixmap = std::move(leftPixmap);
}
@@ -398,8 +399,10 @@ void Line::recache(const QSize &s) {
if (_dynamic) {
p.setFont(st::normalFont);
p.setPen(pen(!_st.gradientFromLeft));
_leftLabel.drawLeft(p, textPadding, textTop, width, width);
_rightLabel.drawRight(p, textPadding, textTop, rwidth, width);
const auto leftTop = (s.height() - _leftLabel.minHeight()) / 2;
_leftLabel.drawLeft(p, textPadding, leftTop, width, width);
const auto rightTop = (s.height() - _rightLabel.minHeight()) / 2;
_rightLabel.drawRight(p, textPadding, rightTop, rwidth, width);
}
_rightPixmap = std::move(rightPixmap);
}