Show correctly change suggestions.

This commit is contained in:
John Preston 2025-06-20 14:31:31 +04:00
parent e29dcf7489
commit 498116c3f6
8 changed files with 167 additions and 56 deletions

View file

@ -619,6 +619,8 @@ void AboutView::make(Data::ChatIntro data, bool preview) {
const auto sendIntroSticker = [=](not_null<DocumentData*> sticker) {
_sendIntroSticker.fire_copy(sticker);
};
owned->data()->setCustomServiceLink(
std::make_shared<LambdaClickHandler>(handler));
owned->overrideMedia(std::make_unique<HistoryView::MediaGeneric>(
owned.get(),
GenerateChatIntro(
@ -629,7 +631,6 @@ void AboutView::make(Data::ChatIntro data, bool preview) {
sendIntroSticker),
HistoryView::MediaGenericDescriptor{
.maxWidth = st::chatIntroWidth,
.serviceLink = std::make_shared<LambdaClickHandler>(handler),
.service = true,
.hideServiceText = preview || text.isEmpty(),
}));

View file

@ -1107,9 +1107,8 @@ void Element::refreshMedia(Element *replacing) {
GenerateSuggestDecisionMedia(this, decision),
MediaGenericDescriptor{
.maxWidth = st::chatSuggestInfoWidth,
.serviceLink = decision->lnk,
.fullAreaLink = decision->lnk,
.service = true,
.fullAreaLink = true,
.hideServiceText = true,
});
} else {

View file

@ -421,7 +421,9 @@ Message::Message(
, _bottomInfo(
&data->history()->owner().reactions(),
BottomInfoDataFromMessage(this)) {
if (const auto media = data->media()) {
if (data->Get<HistoryMessageSuggestedPost>()) {
_hideReply = 1;
} else if (const auto media = data->media()) {
if (media->giveawayResults()) {
_hideReply = 1;
}
@ -455,21 +457,33 @@ Message::~Message() {
}
}
void Message::refreshSuggestedInfo(
not_null<HistoryItem*> item,
not_null<const HistoryMessageSuggestedPost*> suggest,
const HistoryMessageReply *replyData) {
const auto link = (replyData && replyData->resolvedMessage)
? JumpToMessageClickHandler(
replyData->resolvedMessage.get(),
item->fullId())
: ClickHandlerPtr();
setServicePreMessage({}, link, std::make_unique<MediaGeneric>(
this,
GenerateSuggestRequestMedia(this, suggest),
MediaGenericDescriptor{
.maxWidth = st::chatSuggestWidth,
.fullAreaLink = link,
.service = true,
.hideServiceText = true,
}));
}
void Message::initPaidInformation() {
const auto item = data();
if (!item->history()->peer->isUser()) {
if (item->history()->peer->isMonoforum()) {
if (const auto suggest = item->Get<HistoryMessageSuggestedPost>()) {
setServicePreMessage({}, {}, std::make_unique<MediaGeneric>(
this,
GenerateSuggestRequestMedia(this, suggest),
MediaGenericDescriptor{
.maxWidth = st::chatSuggestWidth,
.service = true,
.hideServiceText = true,
}));
const auto replyData = item->Get<HistoryMessageReply>();
refreshSuggestedInfo(item, suggest, replyData);
}
return;
}
const auto media = this->media();
@ -828,6 +842,22 @@ QSize Message::performCountOptimalSize() {
RemoveComponents(Reply::Bit());
}
if (item->history()->peer->isMonoforum()) {
if (const auto suggest = item->Get<HistoryMessageSuggestedPost>()) {
if (const auto service = Get<ServicePreMessage>()) {
// Ok, we didn't have the message, but now we have.
// That means this is not a plain post suggestion,
// but a suggestion of changes to previous suggestion.
if (service->media
&& !service->handler
&& replyData
&& replyData->resolvedMessage) {
refreshSuggestedInfo(item, suggest, replyData);
}
}
}
}
const auto factcheck = item->Get<HistoryMessageFactcheck>();
if (factcheck && !factcheck->data.text.empty()) {
AddComponents(Factcheck::Bit());

View file

@ -15,6 +15,8 @@ class HistoryItem;
struct HistoryMessageEdited;
struct HistoryMessageForwarded;
struct HistoryMessageReplyMarkup;
struct HistoryMessageSuggestedPost;
struct HistoryMessageReply;
namespace Data {
struct ReactionId;
@ -175,6 +177,10 @@ private:
bool updateBottomInfo();
void initPaidInformation();
void refreshSuggestedInfo(
not_null<HistoryItem*> item,
not_null<const HistoryMessageSuggestedPost*> suggest,
const HistoryMessageReply *reply);
void initLogEntryOriginal();
void initPsa();
void fromNameUpdated(int width) const;

View file

@ -77,19 +77,15 @@ MediaGeneric::MediaGeneric(
MediaGenericDescriptor &&descriptor)
: Media(parent)
, _paintBg(std::move(descriptor.paintBg))
, _fullAreaLink(descriptor.fullAreaLink)
, _maxWidthCap(descriptor.maxWidth)
, _service(descriptor.service)
, _fullAreaLink(descriptor.fullAreaLink)
, _hideServiceText(descriptor.hideServiceText) {
generate(this, [&](std::unique_ptr<Part> part) {
_entries.push_back({
.object = std::move(part),
});
});
if (descriptor.serviceLink) {
parent->data()->setCustomServiceLink(
std::move(descriptor.serviceLink));
}
}
MediaGeneric::~MediaGeneric() {
@ -164,11 +160,8 @@ TextState MediaGeneric::textState(
}
if (_fullAreaLink && QRect(0, 0, width(), height()).contains(point)) {
const auto link = _parent->data()->Get<HistoryServiceCustomLink>();
if (link) {
result.link = link->link;
return result;
}
result.link = _fullAreaLink;
return result;
}
for (const auto &entry : _entries) {

View file

@ -57,9 +57,8 @@ struct MediaGenericDescriptor {
Painter&,
const PaintContext&,
not_null<const MediaGeneric*>)> paintBg;
ClickHandlerPtr serviceLink;
ClickHandlerPtr fullAreaLink;
bool service = false;
bool fullAreaLink = false;
bool hideServiceText = false;
};
@ -129,9 +128,9 @@ private:
Painter&,
const PaintContext&,
not_null<const MediaGeneric*>)> _paintBg;
ClickHandlerPtr _fullAreaLink;
int _maxWidthCap = 0;
bool _service : 1 = false;
bool _fullAreaLink : 1 = false;
bool _hideServiceText : 1 = false;
};

View file

@ -57,6 +57,53 @@ enum EmojiType {
return QString::fromUtf8(Raw(type));
}
struct Changes {
bool date = false;
bool price = false;
bool message = true;
};
[[nodiscard]] std::optional<Changes> ResolveChanges(
not_null<HistoryItem*> changed,
HistoryItem *original) {
const auto wasSuggest = original
? original->Get<HistoryMessageSuggestedPost>()
: nullptr;
const auto nowSuggest = changed->Get<HistoryMessageSuggestedPost>();
if (!wasSuggest || !nowSuggest) {
return {};
}
auto result = Changes();
if (wasSuggest->date != nowSuggest->date) {
result.date = true;
}
if (wasSuggest->stars != nowSuggest->stars) {
result.price = true;
}
const auto wasText = original->originalText();
const auto nowText = changed->originalText();
const auto mediaSame = [&] {
const auto wasMedia = original->media();
const auto nowMedia = changed->media();
if (!wasMedia && !nowMedia) {
return true;
} else if (!wasMedia
|| !nowMedia
|| !wasMedia->allowsEditCaption()
|| !nowMedia->allowsEditCaption()) {
return false;
}
// We treat as "same" only same photo or same file.
return (wasMedia->photo() == nowMedia->photo())
&& (wasMedia->document() == nowMedia->document());
};
if (!result.price && !result.date) {
result.message = true;
} else if (wasText == nowText && mediaSame()) {
result.message = false;
}
return result;
}
} // namespace
auto GenerateSuggestDecisionMedia(
@ -224,8 +271,14 @@ auto GenerateSuggestRequestMedia(
result.setAlphaF(result.alphaF() * kFadedOpacity);
return result;
};
const auto from = parent->data()->from();
const auto peer = parent->history()->peer;
const auto item = parent->data();
const auto replyData = item->Get<HistoryMessageReply>();
const auto original = replyData
? replyData->resolvedMessage.get()
: nullptr;
const auto changes = ResolveChanges(item, original);
const auto from = item->from();
const auto peer = item->history()->peer;
auto pushText = [&](
TextWithEntities text,
@ -242,39 +295,67 @@ auto GenerateSuggestRequestMedia(
};
pushText(
(from->isSelf()
((!changes && from->isSelf())
? tr::lng_suggest_action_your(
tr::now,
Ui::Text::WithEntities)
: tr::lng_suggest_action_his(
tr::now,
lt_from,
Ui::Text::Bold(from->shortName()),
Ui::Text::WithEntities)),
: (!changes
? tr::lng_suggest_action_his
: changes->message
? tr::lng_suggest_change_content
: (changes->date && changes->price)
? tr::lng_suggest_change_price_time
: changes->price
? tr::lng_suggest_change_price
: tr::lng_suggest_change_time)(
tr::now,
lt_from,
Ui::Text::Bold(from->shortName()),
Ui::Text::WithEntities)),
st::chatSuggestInfoTitleMargin,
style::al_top);
auto entries = std::vector<AttributeTable::Entry>();
entries.push_back({
tr::lng_suggest_action_price_label(tr::now),
Ui::Text::Bold(suggest->stars
? tr::lng_prize_credits_amount(
if (!changes || changes->price) {
entries.push_back({
(changes
? tr::lng_suggest_change_price_label
: tr::lng_suggest_action_price_label)(tr::now),
Ui::Text::Bold(suggest->stars
? tr::lng_prize_credits_amount(
tr::now,
lt_count,
suggest->stars)
: tr::lng_suggest_action_price_free(tr::now)),
});
}
if (!changes || changes->date) {
entries.push_back({
(changes
? tr::lng_suggest_change_time_label
: tr::lng_suggest_action_time_label)(tr::now),
Ui::Text::Bold(suggest->date
? Ui::FormatDateTime(base::unixtime::parse(suggest->date))
: tr::lng_suggest_action_time_any(tr::now)),
});
}
if (!entries.empty()) {
push(std::make_unique<AttributeTable>(
std::move(entries),
((changes && changes->message)
? st::chatSuggestTableMiddleMargin
: st::chatSuggestTableLastMargin),
fadedFg,
normalFg));
}
if (changes && changes->message) {
push(std::make_unique<TextPartColored>(
tr::lng_suggest_change_text_label(
tr::now,
lt_count,
suggest->stars)
: tr::lng_suggest_action_price_free(tr::now)),
});
entries.push_back({
tr::lng_suggest_action_time_label(tr::now),
Ui::Text::Bold(suggest->date
? Ui::FormatDateTime(base::unixtime::parse(suggest->date))
: tr::lng_suggest_action_time_any(tr::now)),
});
push(std::make_unique<AttributeTable>(
std::move(entries),
st::chatSuggestInfoLastMargin,
fadedFg,
normalFg));
Ui::Text::WithEntities),
st::chatSuggestInfoLastMargin,
fadedFg));
}
};
}

View file

@ -1052,11 +1052,13 @@ chatSimilarName: TextStyle(defaultTextStyle) {
chatSimilarWidthMax: 424px;
chatSimilarSkip: 12px;
chatSuggestWidth: 216px;
chatSuggestWidth: 236px;
chatSuggestInfoWidth: 272px;
chatSuggestInfoTitleMargin: margins(16px, 16px, 16px, 6px);
chatSuggestInfoMiddleMargin: margins(16px, 4px, 16px, 4px);
chatSuggestInfoLastMargin: margins(16px, 4px, 16px, 16px);
chatSuggestTableMiddleMargin: margins(8px, 4px, 8px, 4px);
chatSuggestTableLastMargin: margins(8px, 4px, 8px, 16px);
chatSuggestInfoFullMargin: margins(16px, 16px, 16px, 16px);
premiumRequiredWidth: 186px;