mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 14:38:15 +00:00
Show collage/slideshow as an album in MediaView.
This commit is contained in:
@@ -57,21 +57,28 @@ Images::Options VideoThumbOptions(not_null<DocumentData*> document) {
|
||||
} // namespace
|
||||
|
||||
struct MediaView::SharedMedia {
|
||||
SharedMedia(SharedMediaWithLastSlice::Key key) : key(key) {
|
||||
SharedMedia(SharedMediaKey key) : key(key) {
|
||||
}
|
||||
|
||||
SharedMediaWithLastSlice::Key key;
|
||||
SharedMediaKey key;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
struct MediaView::UserPhotos {
|
||||
UserPhotos(UserPhotosSlice::Key key) : key(key) {
|
||||
UserPhotos(UserPhotosKey key) : key(key) {
|
||||
}
|
||||
|
||||
UserPhotosSlice::Key key;
|
||||
UserPhotosKey key;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
struct MediaView::Collage {
|
||||
Collage(CollageKey key) : key(key) {
|
||||
}
|
||||
|
||||
CollageKey key;
|
||||
};
|
||||
|
||||
MediaView::MediaView()
|
||||
: TWidget(nullptr)
|
||||
, _transparentBrush(style::transparentPlaceholderBrush())
|
||||
@@ -121,6 +128,7 @@ MediaView::MediaView()
|
||||
} else {
|
||||
_sharedMedia = nullptr;
|
||||
_userPhotos = nullptr;
|
||||
_collage = nullptr;
|
||||
}
|
||||
};
|
||||
subscribe(Messenger::Instance().authSessionChanged(), [handleAuthSessionChange] {
|
||||
@@ -299,6 +307,9 @@ void MediaView::refreshNavVisibility() {
|
||||
} else if (_userPhotosData) {
|
||||
_leftNavVisible = _index && (*_index > 0);
|
||||
_rightNavVisible = _index && (*_index + 1 < _userPhotosData->size());
|
||||
} else if (_collageData) {
|
||||
_leftNavVisible = _index && (*_index > 0);
|
||||
_rightNavVisible = _index && (*_index + 1 < _collageData->items.size());
|
||||
} else {
|
||||
_leftNavVisible = false;
|
||||
_rightNavVisible = false;
|
||||
@@ -1092,7 +1103,12 @@ void MediaView::onCopy() {
|
||||
|
||||
std::optional<MediaView::SharedMediaType> MediaView::sharedMediaType() const {
|
||||
using Type = SharedMediaType;
|
||||
if (auto item = App::histItemById(_msgid)) {
|
||||
if (const auto item = App::histItemById(_msgid)) {
|
||||
if (const auto media = item->media()) {
|
||||
if (media->webpage()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
if (_photo) {
|
||||
if (item->toHistoryMessage()) {
|
||||
return Type::PhotoVideo;
|
||||
@@ -1225,17 +1241,17 @@ std::optional<MediaView::UserPhotosKey> MediaView::userPhotosKey() const {
|
||||
}
|
||||
|
||||
bool MediaView::validUserPhotos() const {
|
||||
if (auto key = userPhotosKey()) {
|
||||
if (const auto key = userPhotosKey()) {
|
||||
if (!_userPhotos) {
|
||||
return false;
|
||||
}
|
||||
auto countDistanceInData = [](const auto &a, const auto &b) {
|
||||
const auto countDistanceInData = [](const auto &a, const auto &b) {
|
||||
return [&](const UserPhotosSlice &data) {
|
||||
return data.distance(a, b);
|
||||
};
|
||||
};
|
||||
|
||||
auto distance = (key == _userPhotos->key) ? 0 :
|
||||
const auto distance = (key == _userPhotos->key) ? 0 :
|
||||
_userPhotosData
|
||||
| countDistanceInData(*key, _userPhotos->key)
|
||||
| func::abs;
|
||||
@@ -1247,7 +1263,7 @@ bool MediaView::validUserPhotos() const {
|
||||
}
|
||||
|
||||
void MediaView::validateUserPhotos() {
|
||||
if (auto key = userPhotosKey()) {
|
||||
if (const auto key = userPhotosKey()) {
|
||||
_userPhotos = std::make_unique<UserPhotos>(*key);
|
||||
UserPhotosReversedViewer(
|
||||
*key,
|
||||
@@ -1274,6 +1290,66 @@ void MediaView::handleUserPhotosUpdate(UserPhotosSlice &&update) {
|
||||
preloadData(0);
|
||||
}
|
||||
|
||||
std::optional<MediaView::CollageKey> MediaView::collageKey() const {
|
||||
if (const auto item = App::histItemById(_msgid)) {
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto page = media->webpage()) {
|
||||
for (const auto item : page->collage.items) {
|
||||
if (item == _photo || item == _doc) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool MediaView::validCollage() const {
|
||||
if (const auto key = collageKey()) {
|
||||
if (!_collage) {
|
||||
return false;
|
||||
}
|
||||
const auto countDistanceInData = [](const auto &a, const auto &b) {
|
||||
return [&](const WebPageCollage &data) {
|
||||
const auto i = ranges::find(data.items, a);
|
||||
const auto j = ranges::find(data.items, b);
|
||||
return (i != end(data.items) && j != end(data.items))
|
||||
? std::make_optional(i - j)
|
||||
: std::nullopt;
|
||||
};
|
||||
};
|
||||
|
||||
if (key == _collage->key) {
|
||||
return true;
|
||||
} else if (_collageData) {
|
||||
const auto &items = _collageData->items;
|
||||
if (ranges::find(items, *key) != end(items)
|
||||
&& ranges::find(items, _collage->key) != end(items)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (_collage == nullptr);
|
||||
}
|
||||
|
||||
void MediaView::validateCollage() {
|
||||
if (const auto key = collageKey()) {
|
||||
_collage = std::make_unique<Collage>(*key);
|
||||
_collageData = WebPageCollage();
|
||||
if (const auto item = App::histItemById(_msgid)) {
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto page = media->webpage()) {
|
||||
_collageData = page->collage;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_collage = nullptr;
|
||||
_collageData = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaView::refreshMediaViewer() {
|
||||
if (!validSharedMedia()) {
|
||||
validateSharedMedia();
|
||||
@@ -1281,6 +1357,9 @@ void MediaView::refreshMediaViewer() {
|
||||
if (!validUserPhotos()) {
|
||||
validateUserPhotos();
|
||||
}
|
||||
if (!validCollage()) {
|
||||
validateCollage();
|
||||
}
|
||||
findCurrent();
|
||||
updateControls();
|
||||
preloadData(0);
|
||||
@@ -1290,6 +1369,10 @@ void MediaView::refreshCaption(HistoryItem *item) {
|
||||
_caption = Text();
|
||||
if (!item) {
|
||||
return;
|
||||
} else if (const auto media = item->media()) {
|
||||
if (media->webpage()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const auto caption = item->originalText();
|
||||
if (caption.text.isEmpty()) {
|
||||
@@ -1322,6 +1405,12 @@ void MediaView::refreshGroupThumbs() {
|
||||
*_userPhotosData,
|
||||
*_index,
|
||||
_groupThumbsAvailableWidth);
|
||||
} else if (_index && _collageData) {
|
||||
Media::View::GroupThumbs::Refresh(
|
||||
_groupThumbs,
|
||||
{ _msgid, &*_collageData },
|
||||
*_index,
|
||||
_groupThumbsAvailableWidth);
|
||||
} else if (_groupThumbs) {
|
||||
_groupThumbs->clear();
|
||||
_groupThumbs->resizeToWidth(_groupThumbsAvailableWidth);
|
||||
@@ -1347,11 +1436,16 @@ void MediaView::initGroupThumbs() {
|
||||
|
||||
_groupThumbs->activateRequests(
|
||||
) | rpl::start_with_next([this](Media::View::GroupThumbs::Key key) {
|
||||
using CollageKey = Media::View::GroupThumbs::CollageKey;
|
||||
if (const auto photoId = base::get_if<PhotoId>(&key)) {
|
||||
const auto photo = Auth().data().photo(*photoId);
|
||||
moveToEntity({ photo, nullptr });
|
||||
} else if (const auto itemId = base::get_if<FullMsgId>(&key)) {
|
||||
moveToEntity(entityForItemId(*itemId));
|
||||
} else if (const auto collageKey = base::get_if<CollageKey>(&key)) {
|
||||
if (_collageData) {
|
||||
moveToEntity(entityForCollage(collageKey->index));
|
||||
}
|
||||
}
|
||||
}, _groupThumbs->lifetime());
|
||||
|
||||
@@ -2464,7 +2558,7 @@ void MediaView::setZoomLevel(int newZoom) {
|
||||
}
|
||||
|
||||
MediaView::Entity MediaView::entityForUserPhotos(int index) const {
|
||||
Expects(!!_userPhotosData);
|
||||
Expects(_userPhotosData.has_value());
|
||||
|
||||
if (index < 0 || index >= _userPhotosData->size()) {
|
||||
return { std::nullopt, nullptr };
|
||||
@@ -2476,7 +2570,7 @@ MediaView::Entity MediaView::entityForUserPhotos(int index) const {
|
||||
}
|
||||
|
||||
MediaView::Entity MediaView::entityForSharedMedia(int index) const {
|
||||
Expects(!!_sharedMediaData);
|
||||
Expects(_sharedMediaData.has_value());
|
||||
|
||||
if (index < 0 || index >= _sharedMediaData->size()) {
|
||||
return { std::nullopt, nullptr };
|
||||
@@ -2491,6 +2585,22 @@ MediaView::Entity MediaView::entityForSharedMedia(int index) const {
|
||||
return { std::nullopt, nullptr };
|
||||
}
|
||||
|
||||
MediaView::Entity MediaView::entityForCollage(int index) const {
|
||||
Expects(_collageData.has_value());
|
||||
|
||||
const auto item = App::histItemById(_msgid);
|
||||
const auto &items = _collageData->items;
|
||||
if (!item || index < 0 || index >= items.size()) {
|
||||
return { std::nullopt, nullptr };
|
||||
}
|
||||
if (const auto document = base::get_if<DocumentData*>(&items[index])) {
|
||||
return { *document, item };
|
||||
} else if (const auto photo = base::get_if<PhotoData*>(&items[index])) {
|
||||
return { *photo, item };
|
||||
}
|
||||
return { std::nullopt, nullptr };
|
||||
}
|
||||
|
||||
MediaView::Entity MediaView::entityForItemId(const FullMsgId &itemId) const {
|
||||
if (const auto item = App::histItemById(itemId)) {
|
||||
if (const auto media = item->media()) {
|
||||
@@ -2510,6 +2620,8 @@ MediaView::Entity MediaView::entityByIndex(int index) const {
|
||||
return entityForSharedMedia(index);
|
||||
} else if (_userPhotosData) {
|
||||
return entityForUserPhotos(index);
|
||||
} else if (_collageData) {
|
||||
return entityForCollage(index);
|
||||
}
|
||||
return { std::nullopt, nullptr };
|
||||
}
|
||||
@@ -3008,6 +3120,8 @@ void MediaView::setVisible(bool visible) {
|
||||
_sharedMediaDataKey = std::nullopt;
|
||||
_userPhotos = nullptr;
|
||||
_userPhotosData = std::nullopt;
|
||||
_collage = nullptr;
|
||||
_collageData = std::nullopt;
|
||||
if (_menu) _menu->hideMenu(true);
|
||||
_controlsHideTimer.stop();
|
||||
_controlsState = ControlsShown;
|
||||
@@ -3075,6 +3189,15 @@ void MediaView::findCurrent() {
|
||||
? (_index | func::add(*_userPhotosData->skippedBefore()))
|
||||
: std::nullopt;
|
||||
_fullCount = _userPhotosData->fullCount();
|
||||
} else if (_collageData) {
|
||||
const auto item = _photo ? WebPageCollage::Item(_photo) : _doc;
|
||||
const auto &items = _collageData->items;
|
||||
const auto i = ranges::find(items, item);
|
||||
_index = (i != end(items))
|
||||
? std::make_optional(int(i - begin(items)))
|
||||
: std::nullopt;
|
||||
_fullIndex = _index;
|
||||
_fullCount = items.size();
|
||||
} else {
|
||||
_index = _fullIndex = _fullCount = std::nullopt;
|
||||
}
|
||||
|
Reference in New Issue
Block a user