mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-11 17:29:46 +00:00
Handle click on group thumb item in MediaView.
This commit is contained in:
parent
59e5ffe743
commit
0171a4e874
@ -105,7 +105,7 @@ public:
|
||||
Dying,
|
||||
};
|
||||
|
||||
Thumb(Key key, ImagePtr image);
|
||||
Thumb(Key key, ImagePtr image, base::lambda<void()> handler);
|
||||
|
||||
int leftToUpdate() const;
|
||||
int rightToUpdate() const;
|
||||
@ -118,6 +118,7 @@ public:
|
||||
bool removed() const;
|
||||
|
||||
void paint(Painter &p, int x, int y, int outerWidth, float64 progress);
|
||||
ClickHandlerPtr getState(QPoint point) const;
|
||||
|
||||
private:
|
||||
QSize wantedPixSize() const;
|
||||
@ -126,30 +127,33 @@ private:
|
||||
int currentWidth() const;
|
||||
int finalLeft() const;
|
||||
int finalWidth() const;
|
||||
void toggle(bool visible);
|
||||
void animateTo(int left, int width);
|
||||
|
||||
ClickHandlerPtr _link;
|
||||
const Key _key;
|
||||
ImagePtr _image;
|
||||
State _state = State::Alive;
|
||||
QPixmap _full;
|
||||
int _fullWidth = 0;
|
||||
bool _hiding = true;
|
||||
bool _hiding = false;
|
||||
|
||||
anim::value _left = { 0. };
|
||||
anim::value _width = { 0. };
|
||||
anim::value _opacity = { 0. };
|
||||
anim::value _opacity = { 0., 1. };
|
||||
|
||||
};
|
||||
|
||||
GroupThumbs::Thumb::Thumb(Key key, ImagePtr image)
|
||||
GroupThumbs::Thumb::Thumb(
|
||||
Key key,
|
||||
ImagePtr image,
|
||||
base::lambda<void()> handler)
|
||||
: _key(key)
|
||||
, _image(image) {
|
||||
_link = std::make_shared<LambdaClickHandler>(std::move(handler));
|
||||
_fullWidth = std::min(
|
||||
wantedPixSize().width(),
|
||||
st::mediaviewGroupWidthMax);
|
||||
validateImage();
|
||||
toggle(true);
|
||||
}
|
||||
|
||||
QSize GroupThumbs::Thumb::wantedPixSize() const {
|
||||
@ -229,23 +233,21 @@ void GroupThumbs::Thumb::setState(State state) {
|
||||
_left = anim::value(-_fullWidth / 2);
|
||||
_width = anim::value(_fullWidth);
|
||||
} else {
|
||||
toggle(true);
|
||||
_opacity.start(1.);
|
||||
}
|
||||
_hiding = false;
|
||||
animateTo(-_fullWidth / 2, _fullWidth);
|
||||
} else if (_state == State::Alive) {
|
||||
toggle(true);
|
||||
_opacity.start(0.7);
|
||||
_hiding = false;
|
||||
} else if (_state == State::Dying) {
|
||||
toggle(false);
|
||||
_opacity.start(0.);
|
||||
_hiding = true;
|
||||
_left.restart();
|
||||
_width.restart();
|
||||
}
|
||||
}
|
||||
|
||||
void GroupThumbs::Thumb::toggle(bool visible) {
|
||||
_hiding = !visible;
|
||||
_opacity.start(_hiding ? 0. : 1.);
|
||||
}
|
||||
|
||||
void GroupThumbs::Thumb::animateTo(int left, int width) {
|
||||
_left.start(left);
|
||||
_width.start(width);
|
||||
@ -324,6 +326,17 @@ void GroupThumbs::Thumb::paint(
|
||||
p.setOpacity(opacity);
|
||||
}
|
||||
|
||||
ClickHandlerPtr GroupThumbs::Thumb::getState(QPoint point) const {
|
||||
if (_state != State::Alive) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto left = finalLeft();
|
||||
const auto width = finalWidth();
|
||||
return QRect(left, 0, width, st::mediaviewGroupHeight).contains(point)
|
||||
? _link
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
GroupThumbs::GroupThumbs(Context context)
|
||||
: _context(context) {
|
||||
}
|
||||
@ -486,7 +499,12 @@ auto GroupThumbs::createThumb(Key key) -> std::unique_ptr<Thumb> {
|
||||
|
||||
auto GroupThumbs::createThumb(Key key, ImagePtr image)
|
||||
-> std::unique_ptr<Thumb> {
|
||||
return std::make_unique<Thumb>(key, image);
|
||||
const auto weak = base::make_weak(this);
|
||||
return std::make_unique<Thumb>(key, image, [=] {
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->_activateStream.fire_copy(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
auto GroupThumbs::validateCacheEntry(Key key) -> not_null<Thumb*> {
|
||||
@ -597,6 +615,16 @@ void GroupThumbs::paint(
|
||||
}
|
||||
}
|
||||
|
||||
ClickHandlerPtr GroupThumbs::getState(QPoint point) const {
|
||||
point -= QPoint((_width / 2), st::mediaviewGroupPadding.top());
|
||||
for (const auto &[key, thumb] : _cache) {
|
||||
if (auto link = thumb->getState(point)) {
|
||||
return link;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GroupThumbs::countUpdatedRect() {
|
||||
if (_cache.empty()) {
|
||||
return;
|
||||
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#pragma once
|
||||
|
||||
#include "history/history_item_components.h"
|
||||
#include "base/weak_ptr.h"
|
||||
|
||||
class SharedMediaWithLastSlice;
|
||||
class UserPhotosSlice;
|
||||
@ -28,8 +29,10 @@ class UserPhotosSlice;
|
||||
namespace Media {
|
||||
namespace View {
|
||||
|
||||
class GroupThumbs {
|
||||
class GroupThumbs : public base::has_weak_ptr {
|
||||
public:
|
||||
using Key = base::variant<PhotoId, FullMsgId>;
|
||||
|
||||
static void Refresh(
|
||||
std::unique_ptr<GroupThumbs> &instance,
|
||||
const SharedMediaWithLastSlice &slice,
|
||||
@ -49,17 +52,21 @@ public:
|
||||
void checkForAnimationStart();
|
||||
|
||||
void paint(Painter &p, int x, int y, int outerWidth, TimeMs ms);
|
||||
ClickHandlerPtr getState(QPoint point) const;
|
||||
|
||||
rpl::producer<QRect> updateRequests() const {
|
||||
return _updateRequests.events();
|
||||
}
|
||||
|
||||
rpl::producer<Key> activateRequests() const {
|
||||
return _activateStream.events();
|
||||
}
|
||||
|
||||
rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
||||
using Context = base::optional_variant<PeerId, MessageGroupId>;
|
||||
using Key = base::variant<PhotoId, FullMsgId>;
|
||||
|
||||
GroupThumbs(Context context);
|
||||
~GroupThumbs();
|
||||
@ -98,11 +105,12 @@ private:
|
||||
base::flat_map<Key, std::unique_ptr<Thumb>> _cache;
|
||||
int _width = 0;
|
||||
int _limit = 0;
|
||||
rpl::event_stream<QRect> _updateRequests;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
QRect _updatedRect;
|
||||
|
||||
rpl::event_stream<QRect> _updateRequests;
|
||||
rpl::event_stream<Key> _activateStream;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace View
|
||||
|
@ -1288,24 +1288,41 @@ void MediaView::refreshGroupThumbs() {
|
||||
_groupThumbs->resizeToWidth(_groupThumbsAvailableWidth);
|
||||
}
|
||||
if (_groupThumbs && !existed) {
|
||||
_groupThumbs->updateRequests(
|
||||
) | rpl::start_with_next([this](QRect rect) {
|
||||
const auto shift = (width() / 2);
|
||||
_groupThumbsRect = QRect(
|
||||
shift + rect.x(),
|
||||
_groupThumbsTop,
|
||||
rect.width(),
|
||||
_groupThumbs->height());
|
||||
update(_groupThumbsRect);
|
||||
}, _groupThumbs->lifetime());
|
||||
_groupThumbsRect = QRect(
|
||||
_groupThumbsLeft,
|
||||
_groupThumbsTop,
|
||||
width() - 2 * _groupThumbsLeft,
|
||||
height() - _groupThumbsTop);
|
||||
initGroupThumbs();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaView::initGroupThumbs() {
|
||||
Expects(_groupThumbs != nullptr);
|
||||
|
||||
_groupThumbs->updateRequests(
|
||||
) | rpl::start_with_next([this](QRect rect) {
|
||||
const auto shift = (width() / 2);
|
||||
_groupThumbsRect = QRect(
|
||||
shift + rect.x(),
|
||||
_groupThumbsTop,
|
||||
rect.width(),
|
||||
_groupThumbs->height());
|
||||
update(_groupThumbsRect);
|
||||
}, _groupThumbs->lifetime());
|
||||
|
||||
_groupThumbs->activateRequests(
|
||||
) | rpl::start_with_next([this](Media::View::GroupThumbs::Key key) {
|
||||
if (const auto photoId = base::get_if<PhotoId>(&key)) {
|
||||
const auto photo = App::photo(*photoId);
|
||||
moveToEntity({ photo, nullptr });
|
||||
} else if (const auto itemId = base::get_if<FullMsgId>(&key)) {
|
||||
moveToEntity(entityForItemId(*itemId));
|
||||
}
|
||||
}, _groupThumbs->lifetime());
|
||||
|
||||
_groupThumbsRect = QRect(
|
||||
_groupThumbsLeft,
|
||||
_groupThumbsTop,
|
||||
width() - 2 * _groupThumbsLeft,
|
||||
height() - _groupThumbsTop);
|
||||
}
|
||||
|
||||
void MediaView::showPhoto(not_null<PhotoData*> photo, HistoryItem *context) {
|
||||
if (context) {
|
||||
setContext(context);
|
||||
@ -2421,16 +2438,21 @@ MediaView::Entity MediaView::entityForSharedMedia(int index) const {
|
||||
// Last peer photo.
|
||||
return { *photo, nullptr };
|
||||
} else if (const auto itemId = base::get_if<FullMsgId>(&value)) {
|
||||
if (const auto item = App::histItemById(*itemId)) {
|
||||
if (const auto media = item->getMedia()) {
|
||||
if (const auto photo = media->getPhoto()) {
|
||||
return { photo, item };
|
||||
} else if (const auto document = media->getDocument()) {
|
||||
return { document, item };
|
||||
}
|
||||
return entityForItemId(*itemId);
|
||||
}
|
||||
return { base::none, nullptr };
|
||||
}
|
||||
|
||||
MediaView::Entity MediaView::entityForItemId(const FullMsgId &itemId) const {
|
||||
if (const auto item = App::histItemById(itemId)) {
|
||||
if (const auto media = item->getMedia()) {
|
||||
if (const auto photo = media->getPhoto()) {
|
||||
return { photo, item };
|
||||
} else if (const auto document = media->getDocument()) {
|
||||
return { document, item };
|
||||
}
|
||||
return { base::none, item };
|
||||
}
|
||||
return { base::none, item };
|
||||
}
|
||||
return { base::none, nullptr };
|
||||
}
|
||||
@ -2481,12 +2503,14 @@ bool MediaView::moveToNext(int delta) {
|
||||
return false;
|
||||
}
|
||||
auto newIndex = *_index + delta;
|
||||
auto entity = entityByIndex(newIndex);
|
||||
return moveToEntity(entityByIndex(newIndex));
|
||||
}
|
||||
|
||||
bool MediaView::moveToEntity(const Entity &entity, int preloadDelta) {
|
||||
if (!entity.data && !entity.item) {
|
||||
return false;
|
||||
}
|
||||
_index = newIndex;
|
||||
if (auto item = entity.item) {
|
||||
if (const auto item = entity.item) {
|
||||
setContext(item);
|
||||
} else if (_peer) {
|
||||
setContext(_peer);
|
||||
@ -2501,7 +2525,7 @@ bool MediaView::moveToNext(int delta) {
|
||||
} else {
|
||||
displayDocument(nullptr, entity.item);
|
||||
}
|
||||
preloadData(delta);
|
||||
preloadData(preloadDelta);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2695,8 +2719,13 @@ void MediaView::updateOver(QPoint pos) {
|
||||
auto textState = _caption.getState(pos - _captionRect.topLeft(), _captionRect.width());
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
} else if (_groupThumbs && _groupThumbsRect.contains(pos)) {
|
||||
const auto point = pos - QPoint(_groupThumbsLeft, _groupThumbsTop);
|
||||
lnk = _groupThumbs->getState(point);
|
||||
lnkhost = this;
|
||||
}
|
||||
|
||||
|
||||
// retina
|
||||
if (pos.x() == width()) {
|
||||
pos.setX(pos.x() - 1);
|
||||
|
@ -161,6 +161,8 @@ private:
|
||||
Entity entityForUserPhotos(int index) const;
|
||||
Entity entityForSharedMedia(int index) const;
|
||||
Entity entityByIndex(int index) const;
|
||||
Entity entityForItemId(const FullMsgId &itemId) const;
|
||||
bool moveToEntity(const Entity &entity, int preloadDelta = 0);
|
||||
void setContext(base::optional_variant<
|
||||
not_null<HistoryItem*>,
|
||||
not_null<PeerData*>> context);
|
||||
@ -250,8 +252,8 @@ private:
|
||||
bool updateOverState(OverState newState);
|
||||
float64 overLevel(OverState control) const;
|
||||
|
||||
QRect groupThumbsFullRect() const;
|
||||
void checkGroupThumbsAnimation();
|
||||
void initGroupThumbs();
|
||||
|
||||
QBrush _transparentBrush;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user