Handle repost preview clicks.

This commit is contained in:
John Preston 2023-11-26 22:42:05 +04:00
parent 8f9123bb96
commit 5aaf119b36
8 changed files with 129 additions and 10 deletions

View file

@ -618,6 +618,12 @@ void Controller::drawRepostInfo(
_repostView->draw(p, x, y, availableWidth);
}
RepostClickHandler Controller::lookupRepostHandler(QPoint position) const {
return _repostView
? _repostView->lookupHandler(position)
: RepostClickHandler();
}
void Controller::toggleLiked() {
_reactions->toggleLiked();
}

View file

@ -70,6 +70,7 @@ class CaptionFullView;
class RepostView;
enum class ReactionsMode;
class SuggestedReactionView;
struct RepostClickHandler;
enum class HeaderLayout {
Normal,
@ -130,6 +131,8 @@ public:
[[nodiscard]] QMargins repostCaptionPadding() const;
void drawRepostInfo(Painter &p, int x, int y, int availableWidth) const;
[[nodiscard]] RepostClickHandler lookupRepostHandler(
QPoint position) const;
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
[[nodiscard]] auto stickerOrEmojiChosen() const

View file

@ -7,14 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "media/stories/media_stories_repost_view.h"
#include "chat_helpers/compose/compose_show.h"
#include "core/ui_integration.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/data_stories.h"
#include "history/view/history_view_reply.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "media/stories/media_stories_controller.h"
#include "media/stories/media_stories_view.h"
#include "ui/effects/ripple_animation.h"
#include "ui/layers/box_content.h"
#include "ui/text/text_custom_emoji.h"
#include "ui/text/text_options.h"
#include "ui/painter.h"
@ -60,7 +64,7 @@ void RepostView::draw(Painter &p, int x, int y, int availableWidth) {
if (simple) {
y += st::normalFont->height;
}
const auto w = std::min(int(_maxWidth), availableWidth);
const auto w = _lastWidth = std::min(int(_maxWidth), availableWidth);
const auto h = height() - (simple ? st::normalFont->height : 0);
const auto rect = QRect(x, y, w, h);
const auto colorPeer = _story->repostSourcePeer();
@ -147,6 +151,39 @@ void RepostView::draw(Painter &p, int x, int y, int availableWidth) {
}
}
RepostClickHandler RepostView::lookupHandler(QPoint position) {
if (_loading) {
return {};
}
const auto simple = _text.isEmpty();
const auto w = _lastWidth;
const auto skip = simple ? st::normalFont->height : 0;
const auto h = height() - skip;
const auto rect = QRect(0, skip, w, h);
if (!rect.contains(position)) {
return {};
} else if (!_link) {
_link = std::make_shared<LambdaClickHandler>(crl::guard(this, [=] {
const auto peer = _story->repostSourcePeer();
const auto owner = &_story->owner();
if (const auto id = peer ? _story->repostSourceId() : 0) {
const auto of = owner->stories().lookup({ peer->id, id });
if (of) {
using namespace Data;
_controller->show(*of, { StoriesContextSingle() });
} else {
_controller->uiShow()->show(PrepareShortInfoBox(peer));
}
} else {
_controller->uiShow()->showToast(
tr::lng_forwarded_story_expired(tr::now));
}
}));
}
_lastPosition = position;
return { _link, this };
}
void RepostView::recountDimensions() {
const auto sender = _story->repostSourcePeer();
const auto name = sender ? sender->name() : _story->repostSourceName();
@ -216,4 +253,29 @@ void RepostView::recountDimensions() {
+ st::historyReplyPadding.right();
}
void RepostView::clickHandlerPressedChanged(
const ClickHandlerPtr &action,
bool pressed) {
if (action == _link) {
if (pressed) {
const auto simple = _text.isEmpty();
const auto skip = simple ? st::normalFont->height : 0;
if (!_ripple) {
const auto h = height() - skip;
_ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::RoundRectMask(
QSize(_lastWidth, h),
(simple
? st::storiesRepostSimpleStyle
: st::messageQuoteStyle).radius),
[=] { _controller->repaint(); });
}
_ripple->add(_lastPosition - QPoint(0, skip));
} else if (_ripple) {
_ripple->lastStop();
}
}
}
} // namespace Media::Stories

View file

@ -23,8 +23,11 @@ class RippleAnimation;
namespace Media::Stories {
class Controller;
struct RepostClickHandler;
class RepostView final : public base::has_weak_ptr {
class RepostView final
: public base::has_weak_ptr
, public ClickHandlerHost {
public:
RepostView(
not_null<Controller*> controller,
@ -33,12 +36,18 @@ public:
[[nodiscard]] int height() const;
void draw(Painter &p, int x, int y, int availableWidth);
[[nodiscard]] RepostClickHandler lookupHandler(QPoint position);
private:
void recountDimensions();
void clickHandlerPressedChanged(
const ClickHandlerPtr &action,
bool pressed);
const not_null<Controller*> _controller;
const not_null<Data::Story*> _story;
ClickHandlerPtr _link;
std::unique_ptr<Ui::RippleAnimation> _ripple;
Ui::Text::String _name;
@ -46,6 +55,8 @@ private:
Ui::Text::QuotePaintCache _quoteCache;
Ui::BackgroundEmojiData _backgroundEmojiData;
Ui::ColorIndicesCompressed _colorIndices;
QPoint _lastPosition;
mutable int _lastWidth = 0;
uint32 _maxWidth : 31 = 0;
uint32 _loading : 1 = 0;

View file

@ -162,6 +162,10 @@ void View::drawRepostInfo(
_controller->drawRepostInfo(p, x, y, availableWidth);
}
RepostClickHandler View::lookupRepostHandler(QPoint position) const {
return _controller->lookupRepostHandler(position);
}
void View::showFullCaption() {
_controller->showFullCaption();
}

View file

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
class ClickHandlerHost;
namespace Data {
class Story;
struct StoriesContext;
@ -58,6 +60,15 @@ struct SiblingView {
}
};
struct RepostClickHandler {
ClickHandlerPtr link;
ClickHandlerHost *host = nullptr;
explicit operator bool() const {
return link && host;
}
};
inline constexpr auto kCollapsedCaptionLines = 2;
inline constexpr auto kMaxShownCaptionLines = 4;
@ -83,6 +94,8 @@ public:
[[nodiscard]] QMargins repostCaptionPadding() const;
void drawRepostInfo(Painter &p, int x, int y, int availableWidth) const;
[[nodiscard]] RepostClickHandler lookupRepostHandler(
QPoint position) const;
void updatePlayback(const Player::TrackState &state);
[[nodiscard]] ClickHandlerPtr lookupAreaHandler(QPoint point) const;

View file

@ -2173,14 +2173,22 @@ void OverlayWidget::assignMediaPointer(not_null<PhotoData*> photo) {
}
}
void OverlayWidget::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
setCursor((active || ClickHandler::getPressed()) ? style::cur_pointer : style::cur_default);
update(QRegion(_saveMsg) + _captionRect);
void OverlayWidget::clickHandlerActiveChanged(
const ClickHandlerPtr &p,
bool active) {
setCursor((active || ClickHandler::getPressed())
? style::cur_pointer
: style::cur_default);
update(QRegion(_saveMsg) + captionGeometry());
}
void OverlayWidget::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
setCursor((pressed || ClickHandler::getActive()) ? style::cur_pointer : style::cur_default);
update(QRegion(_saveMsg) + _captionRect);
void OverlayWidget::clickHandlerPressedChanged(
const ClickHandlerPtr &p,
bool pressed) {
setCursor((pressed || ClickHandler::getActive())
? style::cur_pointer
: style::cur_default);
update(QRegion(_saveMsg) + captionGeometry());
}
rpl::lifetime &OverlayWidget::lifetime() {
@ -5707,7 +5715,15 @@ void OverlayWidget::updateOver(QPoint pos) {
}
lnkhost = this;
} else if (_stories && captionGeometry().contains(pos)) {
//_stories->repostState();
const auto padding = st::mediaviewCaptionPadding;
const auto handler = _stories->lookupRepostHandler(
pos - captionGeometry().marginsRemoved(padding).topLeft());
if (handler) {
lnk = handler.link;
lnkhost = handler.host;
setCursor(style::cur_pointer);
_cursorOverriden = true;
}
} else if (_groupThumbs && _groupThumbsRect.contains(pos)) {
const auto point = pos - QPoint(_groupThumbsLeft, _groupThumbsTop);
lnk = _groupThumbs->getState(point);
@ -5717,7 +5733,6 @@ void OverlayWidget::updateOver(QPoint pos) {
lnkhost = this;
}
// retina
if (pos.x() == width()) {
pos.setX(pos.x() - 1);
@ -5726,6 +5741,10 @@ void OverlayWidget::updateOver(QPoint pos) {
pos.setY(pos.y() - 1);
}
if (_cursorOverriden && (!lnkhost || lnkhost == this)) {
_cursorOverriden = false;
setCursor(style::cur_default);
}
ClickHandler::setActive(lnk, lnkhost);
if (_pressed || _dragging) return;

View file

@ -611,6 +611,7 @@ private:
float64 _zoomToDefault = 0.;
QPoint _mStart;
bool _pressed = false;
bool _cursorOverriden = false;
int32 _dragging = 0;
QImage _staticContent;
bool _staticContentTransparent = false;