Generate album mini previews with up-to-three images.

This commit is contained in:
John Preston 2021-10-04 16:18:47 +04:00
parent 8cdd2f113f
commit 992d636680
7 changed files with 84 additions and 18 deletions

View file

@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/data_groups.h"
#include "history/history.h"
#include "history/history_item.h"
#include "dialogs/ui/dialogs_message_view.h"
#include "data/data_media_types.h"
#include "data/data_session.h"
@ -140,8 +142,13 @@ const Group *Groups::find(not_null<const HistoryItem*> item) const {
}
void Groups::refreshViews(const HistoryItemsList &items) {
if (items.empty()) {
return;
}
const auto history = items.front()->history();
for (const auto &item : items) {
_data->requestItemViewRefresh(item);
history->lastItemDialogsView.itemInvalidated(item);
}
}

View file

@ -15,7 +15,6 @@ class Session;
struct Group {
HistoryItemsList items;
};
class Groups {

View file

@ -60,6 +60,7 @@ namespace Data {
namespace {
constexpr auto kFastRevokeRestriction = 24 * 60 * TimeId(60);
constexpr auto kMaxPreviewImages = 3;
using ItemPreview = HistoryView::ItemPreview;
@ -406,6 +407,52 @@ std::unique_ptr<HistoryView::Media> Media::createView(
return createView(message, message->data(), replacing);
}
ItemPreview Media::toGroupPreview(
const HistoryItemsList &items,
ToPreviewOptions options) const {
const auto genericText = textcmdLink(
1,
TextUtilities::Clean(tr::lng_in_dlg_album(tr::now)));
auto result = ItemPreview();
auto loadingContext = std::vector<std::any>();
for (const auto &item : items) {
if (const auto media = item->media()) {
auto copy = options;
copy.ignoreGroup = true;
const auto already = int(result.images.size());
const auto left = kMaxPreviewImages - already;
auto single = left ? media->toPreview(copy) : ItemPreview();
if (!single.images.empty()) {
while (single.images.size() > left) {
single.images.pop_back();
}
result.images.insert(
end(result.images),
std::make_move_iterator(begin(single.images)),
std::make_move_iterator(end(single.images)));
}
if (single.loadingContext.has_value()) {
loadingContext.push_back(std::move(single.loadingContext));
}
const auto original = item->originalText().text;
if (!original.isEmpty()) {
if (result.text.isEmpty()) {
result.text = TextUtilities::Clean(original);
} else {
result.text = genericText;
}
}
}
}
if (result.text.isEmpty()) {
result.text = genericText;
}
if (!loadingContext.empty()) {
result.loadingContext = std::move(loadingContext);
}
return result;
}
MediaPhoto::MediaPhoto(
not_null<HistoryItem*> parent,
not_null<PhotoData*> photo)
@ -478,11 +525,17 @@ QString MediaPhoto::notificationText() const {
}
ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const {
const auto item = parent();
if (!options.ignoreGroup && item->groupId()) {
if (const auto group = item->history()->owner().groups().find(item)
; group && group->items.size() > 1) {
return toGroupPreview(group->items, options);
}
}
const auto caption = options.hideCaption
? QString()
: parent()->originalText().text;
auto images = std::vector<QImage>();
// #TODO minis support albums
const auto media = _photo->createMediaView();
const auto radius = _chat
? ImageRoundRadius::Ellipse
@ -666,6 +719,13 @@ bool MediaFile::replyPreviewLoaded() const {
}
ItemPreview MediaFile::toPreview(ToPreviewOptions options) const {
const auto item = parent();
if (!options.ignoreGroup && item->groupId()) {
if (const auto group = item->history()->owner().groups().find(item)
; group && group->items.size() > 1) {
return toGroupPreview(group->items, options);
}
}
if (const auto sticker = _document->sticker()) {
return Media::toPreview(options);
}
@ -690,7 +750,6 @@ ItemPreview MediaFile::toPreview(ToPreviewOptions options) const {
const auto caption = options.hideCaption
? QString()
: parent()->originalText().text;
// #TODO minis support albums
auto images = std::vector<QImage>();
const auto media = TryFilePreview(_document)
? _document->createMediaView()

View file

@ -127,6 +127,11 @@ public:
not_null<HistoryView::Element*> message,
HistoryView::Element *replacing = nullptr);
protected:
[[nodiscard]] ItemPreview toGroupPreview(
const HistoryItemsList &items,
ToPreviewOptions options) const;
private:
const not_null<HistoryItem*> _parent;

View file

@ -78,7 +78,8 @@ struct MessageView::LoadingContext {
};
MessageView::MessageView()
: _textCache(st::dialogsTextWidthMin) {
: _senderCache(st::dialogsTextWidthMin)
, _textCache(st::dialogsTextWidthMin) {
}
MessageView::~MessageView() = default;
@ -111,6 +112,8 @@ void MessageView::paint(
preview.text.mid(0, preview.imagesInTextPosition).trimmed(),
DialogTextOptions());
preview.text = preview.text.mid(preview.imagesInTextPosition);
} else {
_senderCache = { st::dialogsTextWidthMin };
}
_textCache.setText(
st::dialogsTextStyle,

View file

@ -205,14 +205,14 @@ void HistoryItem::applyServiceDateEdition(const MTPDmessageService &data) {
}
void HistoryItem::finishEdition(int oldKeyboardTop) {
_history->owner().requestItemViewRefresh(this);
invalidateChatListEntry();
if (const auto group = _history->owner().groups().find(this)) {
const auto leader = group->items.front();
if (leader != this) {
_history->owner().requestItemViewRefresh(leader);
leader->invalidateChatListEntry();
for (const auto &item : group->items) {
_history->owner().requestItemViewRefresh(item);
item->invalidateChatListEntry();
}
} else {
_history->owner().requestItemViewRefresh(this);
invalidateChatListEntry();
}
// Should be completely redesigned as the oldTop no longer exists.
@ -942,14 +942,6 @@ QString HistoryItem::notificationText() const {
ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const {
auto result = [&]() -> ItemPreview {
if (_media) {
if (_groupId) {
// #TODO minis generate albums correctly
return {
.text = textcmdLink(
1,
TextUtilities::Clean(tr::lng_in_dlg_album(tr::now))),
};
}
return _media->toPreview(options);
} else if (!emptyText()) {
return { .text = TextUtilities::Clean(_text.toString()) };

View file

@ -61,6 +61,7 @@ struct ToPreviewOptions {
bool hideSender = false;
bool hideCaption = false;
bool generateImages = true;
bool ignoreGroup = false;
};
struct ItemPreview {