Improve 5-line reply text elision.

This commit is contained in:
John Preston 2023-11-06 12:35:27 +04:00
parent d7539349c7
commit b2eeab53c5
15 changed files with 65 additions and 57 deletions

View file

@ -420,7 +420,7 @@ void PaintRow(
.now = context.now, .now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat), .pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler), .pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionOneLine = true, .elisionLines = 1,
}); });
} else if (draft } else if (draft
|| (supportMode || (supportMode
@ -514,7 +514,7 @@ void PaintRow(
.now = context.now, .now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat), .pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler), .pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionOneLine = true, .elisionLines = 1,
}); });
} }
} else if (!item) { } else if (!item) {

View file

@ -141,7 +141,7 @@ void TopicsView::paint(
.now = context.now, .now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat), .pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler), .pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionOneLine = true, .elisionLines = 1,
}); });
const auto skip = skipBig const auto skip = skipBig
? context.st->topicsSkipBig ? context.st->topicsSkipBig

View file

@ -3349,13 +3349,15 @@ void HistoryItem::createComponentsHelper(
: (replyTo.messageId.peer == history()->peer->id) : (replyTo.messageId.peer == history()->peer->id)
? replyTo.messageId.msg ? replyTo.messageId.msg
: MsgId(); : MsgId();
const auto forum = _history->asForum();
const auto topic = forum
? forum->topicFor(replyTo.topicRootId)
: nullptr;
if (!config.reply.externalPeerId if (!config.reply.externalPeerId
&& to && topic
&& config.reply.topicPost && topic->rootId() != to->topicRootId()) {
&& replyTo.topicRootId != to->topicRootId()) {
config.reply.externalPeerId = replyTo.messageId.peer; config.reply.externalPeerId = replyTo.messageId.peer;
} }
const auto forum = _history->asForum();
config.reply.topicPost = config.reply.externalPeerId config.reply.topicPost = config.reply.externalPeerId
? (replyTo.topicRootId ? (replyTo.topicRootId
&& (replyTo.topicRootId != Data::ForumTopic::kGeneralId)) && (replyTo.topicRootId != Data::ForumTopic::kGeneralId))

View file

@ -424,12 +424,14 @@ bool HistoryMessageReply::updateData(
} }
} }
const auto external = this->external(); const auto asExternal = displayAsExternal(holder);
_multiline = !_fields.storyId && (external || !_fields.quote.empty()); const auto nonEmptyQuote = !_fields.quote.empty()
&& (asExternal || _fields.manualQuote);
_multiline = !_fields.storyId && (asExternal || nonEmptyQuote);
const auto displaying = resolvedMessage const auto displaying = resolvedMessage
|| resolvedStory || resolvedStory
|| ((!_fields.quote.empty() || _fields.externalMedia) || ((nonEmptyQuote || _fields.externalMedia)
&& (!_fields.messageId || force)); && (!_fields.messageId || force));
_displaying = displaying ? 1 : 0; _displaying = displaying ? 1 : 0;
@ -446,7 +448,7 @@ bool HistoryMessageReply::updateData(
} }
return resolvedMessage return resolvedMessage
|| resolvedStory || resolvedStory
|| (external && !_fields.messageId && !_fields.storyId) || (!_fields.messageId && !_fields.storyId && external())
|| _unavailable; || _unavailable;
} }
@ -508,6 +510,15 @@ bool HistoryMessageReply::external() const {
|| !_fields.externalSenderName.isEmpty(); || !_fields.externalSenderName.isEmpty();
} }
bool HistoryMessageReply::displayAsExternal(
not_null<HistoryItem*> holder) const {
// Don't display replies that could be local as external.
return external()
&& (!resolvedMessage
|| (holder->history() != resolvedMessage->history())
|| (holder->topicRootId() != resolvedMessage->topicRootId()));
}
void HistoryMessageReply::itemRemoved( void HistoryMessageReply::itemRemoved(
not_null<HistoryItem*> holder, not_null<HistoryItem*> holder,
not_null<HistoryItem*> removed) { not_null<HistoryItem*> removed) {

View file

@ -279,6 +279,8 @@ struct HistoryMessageReply
void clearData(not_null<HistoryItem*> holder); void clearData(not_null<HistoryItem*> holder);
[[nodiscard]] bool external() const; [[nodiscard]] bool external() const;
[[nodiscard]] bool displayAsExternal(
not_null<HistoryItem*> holder) const;
void itemRemoved( void itemRemoved(
not_null<HistoryItem*> holder, not_null<HistoryItem*> holder,
not_null<HistoryItem*> removed); not_null<HistoryItem*> removed);

View file

@ -7951,7 +7951,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
.now = now, .now = now,
.pausedEmoji = paused || On(PowerSaving::kEmojiChat), .pausedEmoji = paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler, .pausedSpoiler = pausedSpoiler,
.elisionOneLine = true, .elisionLines = 1,
}); });
} else { } else {
p.setFont(st::msgDateFont); p.setFont(st::msgDateFont);

View file

@ -629,7 +629,7 @@ void FieldHeader::paintEditOrReplyToMessage(Painter &p) {
.now = crl::now(), .now = crl::now(),
.pausedEmoji = p.inactive() || On(PowerSaving::kEmojiChat), .pausedEmoji = p.inactive() || On(PowerSaving::kEmojiChat),
.pausedSpoiler = p.inactive() || On(PowerSaving::kChatSpoiler), .pausedSpoiler = p.inactive() || On(PowerSaving::kChatSpoiler),
.elisionOneLine = true, .elisionLines = 1,
}); });
} }

View file

@ -669,6 +669,7 @@ void DraftOptionsBox(
}); });
} }
const auto weak = Ui::MakeWeak(box);
Settings::AddButton( Settings::AddButton(
bottom, bottom,
tr::lng_reply_show_in_chat(), tr::lng_reply_show_in_chat(),
@ -676,6 +677,9 @@ void DraftOptionsBox(
{ &st::menuIconShowInChat } { &st::menuIconShowInChat }
)->setClickedCallback([=] { )->setClickedCallback([=] {
highlight(resolveReply()); highlight(resolveReply());
if (const auto strong = weak.data()) {
strong->closeBox();
}
}); });
Settings::AddButton( Settings::AddButton(

View file

@ -396,7 +396,7 @@ void ForwardPanel::paint(
.now = now, .now = now,
.pausedEmoji = paused || On(PowerSaving::kEmojiChat), .pausedEmoji = paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler, .pausedSpoiler = pausedSpoiler,
.elisionOneLine = true, .elisionLines = 1,
}); });
} }

View file

@ -210,10 +210,10 @@ void Reply::update(
const auto text = (!_displaying && data->unavailable()) const auto text = (!_displaying && data->unavailable())
? TextWithEntities() ? TextWithEntities()
: (message && (fields.quote.empty() || !fields.manualQuote))
? message->inReplyText()
: !fields.quote.empty() : !fields.quote.empty()
? fields.quote ? fields.quote
: message
? message->inReplyText()
: story : story
? story->inReplyText() ? story->inReplyText()
: externalMedia : externalMedia
@ -400,7 +400,9 @@ void Reply::updateName(
const auto externalPeer = fields.externalPeerId const auto externalPeer = fields.externalPeerId
? view->history()->owner().peer(fields.externalPeerId).get() ? view->history()->owner().peer(fields.externalPeerId).get()
: nullptr; : nullptr;
const auto groupNameAdded = externalPeer const auto displayAsExternal = data->displayAsExternal(view->data());
const auto groupNameAdded = displayAsExternal
&& externalPeer
&& (externalPeer != sender) && (externalPeer != sender)
&& (externalPeer->isChat() || externalPeer->isMegagroup()); && (externalPeer->isChat() || externalPeer->isMegagroup());
const auto shorten = !viaBotUsername.isEmpty() || groupNameAdded; const auto shorten = !viaBotUsername.isEmpty() || groupNameAdded;
@ -433,7 +435,7 @@ void Reply::updateName(
icon.second)); icon.second));
}; };
auto nameFull = TextWithEntities(); auto nameFull = TextWithEntities();
if (!groupNameAdded && data->external() && !fields.storyId) { if (displayAsExternal && !groupNameAdded && !fields.storyId) {
nameFull.append(peerEmoji(sender)); nameFull.append(peerEmoji(sender));
} }
nameFull.append(name); nameFull.append(name);
@ -509,7 +511,7 @@ int Reply::resizeToWidth(int width) const {
: 0; : 0;
if (width >= _maxWidth || !_multiline) { if (width >= _maxWidth || !_multiline) {
_nameTwoLines = 0; _nameTwoLines = 0;
_expandable = 0; _expandable = _minHeightExpandable;
_height = _minHeight; _height = _minHeight;
return height(); return height();
} }
@ -521,20 +523,13 @@ int Reply::resizeToWidth(int width) const {
_nameTwoLines = (desiredNameHeight > st::semiboldFont->height) ? 1 : 0; _nameTwoLines = (desiredNameHeight > st::semiboldFont->height) ? 1 : 0;
const auto nameh = (_nameTwoLines ? 2 : 1) * st::semiboldFont->height; const auto nameh = (_nameTwoLines ? 2 : 1) * st::semiboldFont->height;
const auto firstLineSkip = _nameTwoLines ? 0 : previewSkip; const auto firstLineSkip = _nameTwoLines ? 0 : previewSkip;
auto lineCounter = 0;
auto elided = false; auto elided = false;
const auto texth = _text.countDimensions( const auto texth = _text.countDimensions(
textGeometry(innerw, firstLineSkip, &lineCounter, &elided)).height; textGeometry(innerw, firstLineSkip, &elided)).height;
const auto useh = elided _expandable = elided ? 1 : 0;
? (kNonExpandedLinesLimit * st::normalFont->height)
: std::max(texth, st::normalFont->height);
if (!texth) {
int a = 0;
}
_expandable = (_multiline && elided) ? 1 : 0;
_height = st::historyReplyPadding.top() _height = st::historyReplyPadding.top()
+ nameh + nameh
+ useh + std::max(texth, st::normalFont->height)
+ st::historyReplyPadding.bottom(); + st::historyReplyPadding.bottom();
return height(); return height();
} }
@ -542,21 +537,17 @@ int Reply::resizeToWidth(int width) const {
Ui::Text::GeometryDescriptor Reply::textGeometry( Ui::Text::GeometryDescriptor Reply::textGeometry(
int available, int available,
int firstLineSkip, int firstLineSkip,
not_null<int*> line, bool *outElided) const {
not_null<bool*> outElided) const { return { .layout = [=](int line) {
return { .layout = [=](Ui::Text::LineGeometry in) { const auto skip = (line ? 0 : firstLineSkip);
const auto skip = (*line ? 0 : firstLineSkip); const auto elided = !_multiline
++*line; || (!_expanded && (line + 1 >= kNonExpandedLinesLimit));
*outElided = *outElided return Ui::Text::LineGeometry{
|| !_multiline .left = skip,
|| (!_expanded .width = available - skip,
&& (*line == kNonExpandedLinesLimit) .elided = elided,
&& in.width > available - skip); };
in.width = available - skip; }, .outElided = outElided };
in.left += skip;
in.elided = *outElided;
return in;
} };
} }
int Reply::height() const { int Reply::height() const {
@ -570,10 +561,10 @@ QMargins Reply::margins() const {
QSize Reply::countMultilineOptimalSize( QSize Reply::countMultilineOptimalSize(
int previewSkip) const { int previewSkip) const {
auto elided = false; auto elided = false;
auto lineCounter = 0;
const auto max = previewSkip + _text.maxWidth(); const auto max = previewSkip + _text.maxWidth();
const auto result = _text.countDimensions( const auto result = _text.countDimensions(
textGeometry(max, previewSkip, &lineCounter, &elided)); textGeometry(max, previewSkip, &elided));
_minHeightExpandable = elided ? 1 : 0;
return { return {
result.width, result.width,
std::max(result.height, st::normalFont->height), std::max(result.height, st::normalFont->height),
@ -767,18 +758,16 @@ void Reply::paint(
copy->linkFg = owned->color(); copy->linkFg = owned->color();
replyToTextPalette = &*copy; replyToTextPalette = &*copy;
} }
auto l = 0;
auto e = false;
_text.draw(p, { _text.draw(p, {
.position = { textLeft, textTop }, .position = { textLeft, textTop },
.geometry = textGeometry(textw, firstLineSkip, &l, &e), .geometry = textGeometry(textw, firstLineSkip),
.palette = replyToTextPalette, .palette = replyToTextPalette,
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,
.pausedEmoji = (context.paused .pausedEmoji = (context.paused
|| On(PowerSaving::kEmojiChat)), || On(PowerSaving::kEmojiChat)),
.pausedSpoiler = pausedSpoiler, .pausedSpoiler = pausedSpoiler,
.elisionOneLine = true, .elisionLines = 1,
}); });
p.setTextPalette(stm->textPalette); p.setTextPalette(stm->textPalette);
} }

View file

@ -67,8 +67,7 @@ private:
[[nodiscard]] Ui::Text::GeometryDescriptor textGeometry( [[nodiscard]] Ui::Text::GeometryDescriptor textGeometry(
int available, int available,
int firstLineSkip, int firstLineSkip,
not_null<int*> line, bool *outElided = nullptr) const;
not_null<bool*> outElided) const;
[[nodiscard]] QSize countMultilineOptimalSize( [[nodiscard]] QSize countMultilineOptimalSize(
int firstLineSkip) const; int firstLineSkip) const;
void setLinkFrom( void setLinkFrom(
@ -101,11 +100,12 @@ private:
mutable int _minHeight = 0; mutable int _minHeight = 0;
mutable int _height = 0; mutable int _height = 0;
mutable int _nameVersion = 0; mutable int _nameVersion = 0;
uint8 _hiddenSenderColorIndexPlusOne = 0; uint8 _hiddenSenderColorIndexPlusOne : 7 = 0;
uint8 _hasQuoteIcon : 1 = 0; uint8 _hasQuoteIcon : 1 = 0;
uint8 _replyToStory : 1 = 0; uint8 _replyToStory : 1 = 0;
uint8 _expanded : 1 = 0; uint8 _expanded : 1 = 0;
mutable uint8 _expandable : 1 = 0; mutable uint8 _expandable : 1 = 0;
mutable uint8 _minHeightExpandable : 1 = 0;
mutable uint8 _nameTwoLines : 1 = 0; mutable uint8 _nameTwoLines : 1 = 0;
mutable uint8 _hasPreview : 1 = 0; mutable uint8 _hasPreview : 1 = 0;
mutable uint8 _displaying : 1 = 0; mutable uint8 _displaying : 1 = 0;

View file

@ -388,7 +388,7 @@ void Giveaway::paintChannels(
.align = style::al_left, .align = style::al_left,
.palette = &stm->textPalette, .palette = &stm->textPalette,
.now = context.now, .now = context.now,
.elisionOneLine = true, .elisionLines = 1,
.elisionBreakEverywhere = true, .elisionBreakEverywhere = true,
}); });
} }

View file

@ -455,7 +455,7 @@ void MessageBar::paint(Painter &p) {
.now = now, .now = now,
.pausedEmoji = paused || On(PowerSaving::kEmojiChat), .pausedEmoji = paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler, .pausedSpoiler = pausedSpoiler,
.elisionOneLine = true, .elisionLines = 1,
}); });
} }
} else if (_animation->bodyAnimation == BodyAnimation::Text) { } else if (_animation->bodyAnimation == BodyAnimation::Text) {

View file

@ -828,7 +828,7 @@ void Notification::paintTitle(Painter &p) {
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.pausedEmoji = On(PowerSaving::kEmojiChat), .pausedEmoji = On(PowerSaving::kEmojiChat),
.pausedSpoiler = On(PowerSaving::kChatSpoiler), .pausedSpoiler = On(PowerSaving::kChatSpoiler),
.elisionOneLine = true, .elisionLines = 1,
}); });
} }

@ -1 +1 @@
Subproject commit 08235c5e06ac56564157f2856702804a2149d45e Subproject commit 65310f32dcc980aeca0b13253b1278a6f3ce722e