mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show applied boosts in message bubbles.
This commit is contained in:
parent
e32cbf468b
commit
33207b78d5
11 changed files with 108 additions and 44 deletions
BIN
Telegram/Resources/icons/stories/boosts_mini.png
Normal file
BIN
Telegram/Resources/icons/stories/boosts_mini.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 374 B |
BIN
Telegram/Resources/icons/stories/boosts_mini@2x.png
Normal file
BIN
Telegram/Resources/icons/stories/boosts_mini@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 690 B |
BIN
Telegram/Resources/icons/stories/boosts_mini@3x.png
Normal file
BIN
Telegram/Resources/icons/stories/boosts_mini@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
|
@ -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());
|
||||
|
|
|
@ -132,6 +132,7 @@ public:
|
|||
};
|
||||
mutable int lastParticipantsStatus = LastParticipantsUpToDate;
|
||||
int lastParticipantsCount = 0;
|
||||
int boostsApplied = 0;
|
||||
|
||||
private:
|
||||
ChatData *_migratedFrom = nullptr;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue