Put mini-previews after sender name.

This commit is contained in:
John Preston 2021-10-04 11:58:31 +04:00
parent 84f561b251
commit d5f935b73d
8 changed files with 143 additions and 46 deletions

View File

@ -106,20 +106,23 @@ using ItemPreview = HistoryView::ItemPreview;
[[nodiscard]] QString WithCaptionDialogsText(
const QString &attachType,
const QString &caption) {
const QString &caption,
bool hasMiniImages) {
if (caption.isEmpty()) {
return textcmdLink(1, TextUtilities::Clean(attachType));
}
return tr::lng_dialogs_text_media(
tr::now,
lt_media_part,
textcmdLink(1, tr::lng_dialogs_text_media_wrapped(
return hasMiniImages
? TextUtilities::Clean(caption)
: tr::lng_dialogs_text_media(
tr::now,
lt_media,
TextUtilities::Clean(attachType))),
lt_caption,
TextUtilities::Clean(caption));
lt_media_part,
textcmdLink(1, tr::lng_dialogs_text_media_wrapped(
tr::now,
lt_media,
TextUtilities::Clean(attachType))),
lt_caption,
TextUtilities::Clean(caption));
}
[[nodiscard]] QString WithCaptionNotificationText(
@ -491,10 +494,9 @@ ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const {
context = media;
}
}
const auto type = tr::lng_in_dlg_photo(tr::now);
return {
.text = WithCaptionDialogsText(
tr::lng_in_dlg_photo(tr::now),
caption),
.text = WithCaptionDialogsText(type, caption, !images.empty()),
.images = std::move(images),
.loadingContext = std::move(context),
};
@ -706,7 +708,7 @@ ItemPreview MediaFile::toPreview(ToPreviewOptions options) const {
}
}
return {
.text = WithCaptionDialogsText(type, caption),
.text = WithCaptionDialogsText(type, caption, !images.empty()),
.images = std::move(images),
.loadingContext = std::move(context),
};
@ -1029,10 +1031,9 @@ Data::CloudImage *MediaLocation::location() const {
}
ItemPreview MediaLocation::toPreview(ToPreviewOptions options) const {
// #TODO minis generate images
return {
.text = WithCaptionDialogsText(tr::lng_maps_point(tr::now), _title),
};
const auto type = tr::lng_maps_point(tr::now);
const auto hasMiniImages = false;
return { .text = WithCaptionDialogsText(type, _title, hasMiniImages) };
}
QString MediaLocation::notificationText() const {

View File

@ -296,6 +296,7 @@ dialogsScamFont: font(9px semibold);
dialogsScamSkip: 4px;
dialogsScamRadius: 2px;
dialogsMiniPreviewTop: 1px;
dialogsMiniPreview: 16px;
dialogsMiniPreviewSkip: 2px;
dialogsMiniPreviewRight: 3px;

View File

@ -12,8 +12,61 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "ui/text/text_options.h"
#include "ui/image/image.h"
#include "lang/lang_keys.h"
#include "styles/style_dialogs.h"
namespace {
template <ushort kTag>
struct TextWithTagOffset {
TextWithTagOffset(QString text) : text(text) {
}
static TextWithTagOffset FromString(const QString &text) {
return { text };
}
QString text;
int offset = -1;
};
} // namespace
namespace Lang {
template <ushort kTag>
struct ReplaceTag<TextWithTagOffset<kTag>> {
static TextWithTagOffset<kTag> Call(
TextWithTagOffset<kTag> &&original,
ushort tag,
const TextWithTagOffset<kTag> &replacement);
};
template <ushort kTag>
TextWithTagOffset<kTag> ReplaceTag<TextWithTagOffset<kTag>>::Call(
TextWithTagOffset<kTag> &&original,
ushort tag,
const TextWithTagOffset<kTag> &replacement) {
const auto replacementPosition = FindTagReplacementPosition(
original.text,
tag);
if (replacementPosition < 0) {
return std::move(original);
}
original.text = ReplaceTag<QString>::Replace(
std::move(original.text),
replacement.text,
replacementPosition);
if (tag == kTag) {
original.offset = replacementPosition;
} else if (original.offset > replacementPosition) {
constexpr auto kReplaceCommandLength = 4;
original.offset += replacement.text.size() - kReplaceCommandLength;
}
return std::move(original);
}
} // namespace Lang
namespace Dialogs::Ui {
namespace {
@ -52,9 +105,16 @@ void MessageView::paint(
}
if (_textCachedFor != item.get()) {
auto preview = item->toPreview(options);
if (!preview.images.empty() && preview.imagesInTextPosition > 0) {
_senderCache.setText(
st::dialogsTextStyle,
preview.text.mid(0, preview.imagesInTextPosition).trimmed(),
DialogTextOptions());
preview.text = preview.text.mid(preview.imagesInTextPosition);
}
_textCache.setText(
st::dialogsTextStyle,
preview.text,
preview.text.trimmed(),
DialogTextOptions());
_textCachedFor = item;
_imagesCache = std::move(preview.images);
@ -71,12 +131,34 @@ void MessageView::paint(
_loadingContext = nullptr;
}
}
p.setTextPalette(active
? st::dialogsTextPaletteActive
: selected
? st::dialogsTextPaletteOver
: st::dialogsTextPalette);
p.setFont(st::dialogsTextFont);
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg));
const auto guard = gsl::finally([&] {
p.restoreTextPalette();
});
auto rect = geometry;
if (!_senderCache.isEmpty()) {
_senderCache.drawElided(
p,
rect.left(),
rect.top(),
rect.width(),
rect.height() / st::dialogsTextFont->height);
const auto skip = st::dialogsMiniPreviewSkip
+ st::dialogsMiniPreviewRight;
rect.setLeft(rect.x() + _senderCache.maxWidth() + skip);
}
for (const auto &image : _imagesCache) {
if (rect.width() < st::dialogsMiniPreview) {
break;
}
p.drawImage(rect.topLeft(), image);
p.drawImage(rect.x(), rect.y() + st::dialogsMiniPreviewTop, image);
rect.setLeft(rect.x()
+ st::dialogsMiniPreview
+ st::dialogsMiniPreviewSkip);
@ -87,20 +169,29 @@ void MessageView::paint(
if (rect.isEmpty()) {
return;
}
p.setTextPalette(active
? st::dialogsTextPaletteActive
: selected
? st::dialogsTextPaletteOver
: st::dialogsTextPalette);
p.setFont(st::dialogsTextFont);
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg));
_textCache.drawElided(
p,
rect.left(),
rect.top(),
rect.width(),
rect.height() / st::dialogsTextFont->height);
p.restoreTextPalette();
}
HistoryView::ItemPreview PreviewWithSender(
HistoryView::ItemPreview &&preview,
const QString &sender) {
auto textWithOffset = tr::lng_dialogs_text_with_from(
tr::now,
lt_from_part,
sender,
lt_message,
std::move(preview.text),
TextWithTagOffset<lt_from_part>::FromString);
preview.text = std::move(textWithOffset.text);
preview.imagesInTextPosition = (textWithOffset.offset < 0)
? 0
: textWithOffset.offset + sender.size();
return preview;
}
} // namespace Dialogs::Ui

View File

@ -48,10 +48,15 @@ private:
struct LoadingContext;
mutable const HistoryItem *_textCachedFor = nullptr;
mutable Ui::Text::String _senderCache;
mutable Ui::Text::String _textCache;
mutable std::vector<QImage> _imagesCache;
mutable std::unique_ptr<LoadingContext> _loadingContext;
};
[[nodiscard]] HistoryView::ItemPreview PreviewWithSender(
HistoryView::ItemPreview &&preview,
const QString &sender);
} // namespace Dialogs::Ui

View File

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/crash_reports.h"
#include "base/unixtime.h"
#include "api/api_text_entities.h"
#include "dialogs/ui/dialogs_message_view.h"
#include "data/data_scheduled_messages.h" // kScheduledUntilOnlineTimestamp
#include "data/data_changes.h"
#include "data/data_session.h"
@ -965,24 +966,19 @@ ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const {
}
return nullptr;
}();
if (sender) {
const auto fromText = sender->isSelf()
? tr::lng_from_you(tr::now)
: sender->shortName();
const auto fromWrapped = textcmdLink(
1,
tr::lng_dialogs_text_from_wrapped(
tr::now,
lt_from,
TextUtilities::Clean(fromText)));
result.text = tr::lng_dialogs_text_with_from(
tr::now,
lt_from_part,
fromWrapped,
lt_message,
std::move(result.text));
if (!sender) {
return result;
}
return result;
const auto fromText = sender->isSelf()
? tr::lng_from_you(tr::now)
: sender->shortName();
const auto fromWrapped = textcmdLink(
1,
tr::lng_dialogs_text_from_wrapped(
tr::now,
lt_from,
TextUtilities::Clean(fromText)));
return Dialogs::Ui::PreviewWithSender(std::move(result), fromWrapped);
}
Ui::Text::IsolatedEmoji HistoryItem::isolatedEmoji() const {

View File

@ -66,6 +66,7 @@ struct ToPreviewOptions {
struct ItemPreview {
QString text;
std::vector<QImage> images;
int imagesInTextPosition = 0;
std::any loadingContext;
};

View File

@ -6853,7 +6853,6 @@ void HistoryWidget::updateForwardingTexts() {
}
if (count < 2) {
// #TODO minis use images
text = _toForward.items.front()->toPreview({
.hideSender = true,
.hideCaption = !keepCaptions,

View File

@ -377,11 +377,14 @@ bool SendActionPainter::updateNeedsAnimating(crl::time now, bool force) {
if (force
|| sendActionChanged
|| (sendActionResult && !anim::Disabled())) {
const auto height = std::max(
st::normalFont->height,
st::dialogsMiniPreviewTop + st::dialogsMiniPreview);
_history->peer->owner().sendActionManager().updateAnimation({
_history,
0,
_sendActionAnimation.width() + _animationLeft,
st::normalFont->height,
height,
(force || sendActionChanged)
});
}