Show applied boosts in message bubbles.

This commit is contained in:
John Preston 2024-02-02 17:08:56 +04:00
parent e32cbf468b
commit 33207b78d5
11 changed files with 108 additions and 44 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1118,6 +1118,8 @@ void ApplyChannelUpdate(
if (stickersChanged) {
session->changes().peerUpdated(channel, UpdateFlag::StickersSet);
}
channel->mgInfo->boostsApplied = update.vboosts_applied().value_or_empty();
}
channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
channel->setTranslationDisabled(update.is_translations_disabled());

View file

@ -132,6 +132,7 @@ public:
};
mutable int lastParticipantsStatus = LastParticipantsUpToDate;
int lastParticipantsCount = 0;
int boostsApplied = 0;
private:
ChatData *_migratedFrom = nullptr;

View file

@ -139,6 +139,7 @@ struct HistoryItem::CreateConfig {
UserId viaBotId = 0;
int viewsCount = -1;
int forwardsCount = -1;
int boostsApplied = 0;
QString postAuthor;
MsgId originalId = 0;
@ -352,6 +353,8 @@ HistoryItem::HistoryItem(
FlagsFromMTP(id, data.vflags().v, localFlags),
data.vdate().v,
data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) {
_boostsApplied = data.vfrom_boosts_applied().value_or_empty();
const auto media = data.vmedia();
const auto checked = media
? CheckMessageMedia(*media)
@ -1474,8 +1477,9 @@ void HistoryItem::returnSavedMedia() {
return;
}
const auto wasGrouped = history()->owner().groups().isGrouped(this);
_media = std::move(_savedLocalEditMediaData->media);
setText(_savedLocalEditMediaData->text);
const auto data = Get<HistoryMessageSavedMediaData>();
_media = std::move(data->media);
setText(data->text);
clearSavedMedia();
if (wasGrouped) {
history()->owner().groups().refreshMessage(this, true);
@ -1488,19 +1492,18 @@ void HistoryItem::returnSavedMedia() {
void HistoryItem::savePreviousMedia() {
Expects(_media != nullptr);
using Data = SavedMediaData;
_savedLocalEditMediaData = std::make_unique<Data>(Data{
.text = originalText(),
.media = _media->clone(this),
});
AddComponents(HistoryMessageSavedMediaData::Bit());
const auto data = Get<HistoryMessageSavedMediaData>();
data->text = originalText();
data->media = _media->clone(this);
}
bool HistoryItem::isEditingMedia() const {
return _savedLocalEditMediaData != nullptr;
return Has<HistoryMessageSavedMediaData>();
}
void HistoryItem::clearSavedMedia() {
_savedLocalEditMediaData = nullptr;
RemoveComponents(HistoryMessageSavedMediaData::Bit());
}
bool HistoryItem::definesReplyKeyboard() const {
@ -1652,9 +1655,10 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
// }
//}
const auto editingMedia = isEditingMedia();
const auto updatingSavedLocalEdit = !edition.savePreviousMedia
&& (_savedLocalEditMediaData != nullptr);
if (!_savedLocalEditMediaData && edition.savePreviousMedia) {
&& editingMedia;
if (!editingMedia && edition.savePreviousMedia) {
savePreviousMedia();
}
Assert(!updatingSavedLocalEdit || !isLocalUpdateMedia());
@ -1683,7 +1687,7 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
setReplyMarkup(base::take(edition.replyMarkup));
}
if (updatingSavedLocalEdit) {
_savedLocalEditMediaData->media = edition.mtpMedia
Get<HistoryMessageSavedMediaData>()->media = edition.mtpMedia
? CreateMedia(this, *edition.mtpMedia)
: nullptr;
} else {
@ -1700,13 +1704,13 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
setForwardsCount(edition.forwards);
}
const auto &checkedMedia = updatingSavedLocalEdit
? _savedLocalEditMediaData->media
? Get<HistoryMessageSavedMediaData>()->media
: _media;
auto updatedText = checkedMedia
? edition.textWithEntities
: EnsureNonEmpty(edition.textWithEntities);
if (updatingSavedLocalEdit) {
_savedLocalEditMediaData->text = std::move(updatedText);
Get<HistoryMessageSavedMediaData>()->text = std::move(updatedText);
} else {
setText(std::move(updatedText));
addToSharedMediaIndex();
@ -1866,7 +1870,7 @@ void HistoryItem::applySentMessage(
void HistoryItem::updateSentContent(
const TextWithEntities &textWithEntities,
const MTPMessageMedia *media) {
if (_savedLocalEditMediaData) {
if (isEditingMedia()) {
return;
}
setText(textWithEntities);
@ -1998,10 +2002,9 @@ void HistoryItem::destroyHistoryEntry() {
}
Storage::SharedMediaTypesMask HistoryItem::sharedMediaTypes() const {
auto result = Storage::SharedMediaTypesMask {};
const auto media = _savedLocalEditMediaData
? _savedLocalEditMediaData->media.get()
: _media.get();
auto result = Storage::SharedMediaTypesMask{};
const auto saved = Get<HistoryMessageSavedMediaData>();
const auto media = saved ? saved->media.get() : _media.get();
if (media) {
result.set(media->sharedMediaTypes());
}
@ -3403,6 +3406,12 @@ void HistoryItem::createComponents(CreateConfig &&config) {
} else {
_flags &= ~MessageFlag::HasReplyMarkup;
}
if (out() && isSending()) {
if (const auto channel = _history->peer->asMegagroup()) {
_boostsApplied = channel->mgInfo->boostsApplied;
}
}
}
bool HistoryItem::checkRepliesPts(

View file

@ -21,6 +21,7 @@ struct HistoryMessageMarkupData;
struct HistoryMessageReplyMarkup;
struct HistoryMessageTranslation;
struct HistoryMessageForwarded;
struct HistoryMessageSavedMediaData;
struct HistoryServiceDependentData;
enum class HistorySelfDestructType;
struct PreparedServiceText;
@ -536,16 +537,15 @@ public:
return _ttlDestroyAt;
}
[[nodiscard]] int boostsApplied() const {
return _boostsApplied;
}
MsgId id;
private:
struct CreateConfig;
struct SavedMediaData {
TextWithEntities text;
std::unique_ptr<Data::Media> media;
};
HistoryItem(
not_null<History*> history,
MsgId id,
@ -655,13 +655,13 @@ private:
TextWithEntities _text;
std::unique_ptr<SavedMediaData> _savedLocalEditMediaData;
std::unique_ptr<Data::Media> _media;
std::unique_ptr<Data::MessageReactions> _reactions;
crl::time _reactionsLastRefreshed = 0;
TimeId _date = 0;
TimeId _ttlDestroyAt = 0;
int _boostsApplied = 0;
HistoryView::Element *_mainView = nullptr;
MessageGroupId _groupId = MessageGroupId();
@ -672,3 +672,5 @@ private:
friend class HistoryView::ServiceMessagePainter;
};
constexpr auto kSize = int(sizeof(HistoryItem));

View file

@ -149,6 +149,11 @@ struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded
bool story = false;
};
struct HistoryMessageSavedMediaData : public RuntimeComponent<HistoryMessageSavedMediaData, HistoryItem> {
TextWithEntities text;
std::unique_ptr<Data::Media> media;
};
struct HistoryMessageSaved : public RuntimeComponent<HistoryMessageSaved, HistoryItem> {
Data::SavedSublist *sublist = nullptr;
};

View file

@ -454,19 +454,20 @@ void Message::setReactions(std::unique_ptr<Reactions::InlineList> list) {
}
void Message::refreshRightBadge() {
const auto item = data();
const auto text = [&] {
if (data()->isDiscussionPost()) {
if (item->isDiscussionPost()) {
return (delegate()->elementContext() == Context::Replies)
? QString()
: tr::lng_channel_badge(tr::now);
} else if (data()->author()->isMegagroup()) {
if (const auto msgsigned = data()->Get<HistoryMessageSigned>()) {
} else if (item->author()->isMegagroup()) {
if (const auto msgsigned = item->Get<HistoryMessageSigned>()) {
Assert(msgsigned->isAnonymousRank);
return msgsigned->postAuthor;
}
}
const auto channel = data()->history()->peer->asMegagroup();
const auto user = data()->author()->asUser();
const auto channel = item->history()->peer->asMegagroup();
const auto user = item->author()->asUser();
if (!channel || !user) {
return QString();
}
@ -485,13 +486,41 @@ void Message::refreshRightBadge() {
? tr::lng_admin_badge(tr::now)
: QString();
}();
const auto badge = text.isEmpty()
? delegate()->elementAuthorRank(this)
: TextUtilities::RemoveEmoji(TextUtilities::SingleLine(text));
if (badge.isEmpty()) {
auto badge = TextWithEntities{
(text.isEmpty()
? delegate()->elementAuthorRank(this)
: TextUtilities::RemoveEmoji(TextUtilities::SingleLine(text)))
};
_rightBadgeHasBoosts = 0;
if (const auto boosts = item->boostsApplied()) {
_rightBadgeHasBoosts = 1;
const auto many = (boosts > 1);
const auto &icon = many
? st::boostsMessageIcon
: st::boostMessageIcon;
const auto padding = many
? st::boostsMessageIconPadding
: st::boostMessageIconPadding;
const auto owner = &item->history()->owner();
auto added = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(icon, padding)
).append(many ? QString::number(boosts) : QString());
badge.append(' ').append(Ui::Text::Colorized(added, 1));
}
if (badge.empty()) {
_rightBadge.clear();
} else {
_rightBadge.setText(st::defaultTextStyle, badge);
const auto context = Core::MarkedTextContext{
.session = &item->history()->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
_rightBadge.setMarkedText(
st::defaultTextStyle,
badge,
Ui::NameTextOptions(),
context);
}
}
@ -1482,20 +1511,30 @@ void Message::paintFromName(
}
if (rightWidth) {
p.setPen(stm->msgDateFg);
p.setFont(ClickHandler::showAsActive(_fastReplyLink)
? st::msgFont->underline()
: st::msgFont);
if (replyWidth) {
p.setFont(ClickHandler::showAsActive(_fastReplyLink)
? st::msgFont->underline()
: st::msgFont);
p.drawText(
trect.left() + trect.width() - rightWidth,
trect.top() + st::msgFont->ascent,
FastReplyText());
} else {
_rightBadge.draw(
p,
trect.left() + trect.width() - rightWidth,
trect.top(),
rightWidth);
const auto shift = QPoint(trect.width() - rightWidth, 0);
const auto pen = !_rightBadgeHasBoosts
? QPen()
: !context.outbg
? QPen(FromNameFg(context, colorIndex()))
: stm->msgServiceFg->p;
auto colored = std::array<Ui::Text::SpecialColor, 1>{
{ { &pen, &pen } },
};
_rightBadge.draw(p, {
.position = trect.topLeft() + shift,
.availableWidth = rightWidth,
.colors = colored,
.now = context.now,
});
}
}
trect.setY(trect.y() + st::msgNameFont->height);

View file

@ -305,9 +305,10 @@ private:
mutable std::unique_ptr<FromNameStatus> _fromNameStatus;
Ui::Text::String _rightBadge;
mutable int _fromNameVersion = 0;
uint32 _bubbleWidthLimit : 30 = 0;
uint32 _bubbleWidthLimit : 29 = 0;
uint32 _invertMedia : 1 = 0;
uint32 _hideReply : 1 = 0;
uint32 _rightBadgeHasBoosts : 1 = 0;
BottomInfo _bottomInfo;

View file

@ -1042,3 +1042,8 @@ chatSimilarSkip: 12px;
premiumRequiredWidth: 186px;
premiumRequiredIcon: icon{{ "chat/large_lockedchat", msgServiceFg }};
premiumRequiredCircle: 60px;
boostMessageIcon: icon {{ "stories/boost_mini", windowFg }};
boostMessageIconPadding: margins(0px, 2px, 0px, 0px);
boostsMessageIcon: icon {{ "stories/boosts_mini", windowFg }};
boostsMessageIconPadding: margins(0px, 2px, 0px, 0px);