Allow selecting text in webpage previews.

This commit is contained in:
John Preston 2023-11-01 09:17:08 +04:00
parent 8e369a4aa5
commit 728ed02a1c
11 changed files with 98 additions and 14 deletions

View File

@ -1673,7 +1673,10 @@ void HistoryInner::mouseActionStart(const QPoint &screenPos, Qt::MouseButton but
Ui::MarkInactivePress(_controller->widget(), false);
}
if (ClickHandler::getPressed()) {
const auto pressed = ClickHandler::getPressed();
if (pressed
&& (!Element::Hovered()
|| !Element::Hovered()->allowTextSelectionByHandler(pressed))) {
_mouseAction = MouseAction::PrepareDrag;
} else if (inSelectionMode()) {
if (_dragStateItem
@ -3837,6 +3840,10 @@ void HistoryInner::mouseActionUpdate() {
selState = view->adjustSelection(selState, _mouseSelectType);
}
}
if (!selState.empty()) {
// We started selecting text in web page preview.
ClickHandler::unpressed();
}
if (_selected[_mouseActionItem] != selState) {
_selected[_mouseActionItem] = selState;
repaintItem(_mouseActionItem);

View File

@ -1424,7 +1424,12 @@ HistoryMessageReply *Element::displayedReply() const {
}
bool Element::toggleSelectionByHandlerClick(
const ClickHandlerPtr &handler) const {
const ClickHandlerPtr &handler) const {
return false;
}
bool Element::allowTextSelectionByHandler(
const ClickHandlerPtr &handler) const {
return false;
}

View File

@ -462,6 +462,8 @@ public:
}
[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
const ClickHandlerPtr &handler) const;
[[nodiscard]] virtual bool allowTextSelectionByHandler(
const ClickHandlerPtr &handler) const;
struct VerticalRepaintRange {
int top = 0;

View File

@ -3148,6 +3148,16 @@ bool Message::toggleSelectionByHandlerClick(
return false;
}
bool Message::allowTextSelectionByHandler(
const ClickHandlerPtr &handler) const {
if (const auto media = this->media()) {
if (media->allowTextSelectionByHandler(handler)) {
return true;
}
}
return false;
}
bool Message::hasFromName() const {
switch (context()) {
case Context::AdminLog:

View File

@ -140,6 +140,8 @@ public:
[[nodiscard]] HistoryMessageReply *displayedReply() const override;
[[nodiscard]] bool toggleSelectionByHandlerClick(
const ClickHandlerPtr &handler) const override;
[[nodiscard]] bool allowTextSelectionByHandler(
const ClickHandlerPtr &handler) const override;
[[nodiscard]] int infoWidth() const override;
[[nodiscard]] int bottomInfoFirstLineWidth() const override;
[[nodiscard]] bool bottomInfoIsWide() const override;

View File

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h"
#include "ui/cached_round_corners.h"
#include "ui/chat/chat_style.h"
#include "ui/effects/ripple_animation.h"
#include "ui/painter.h"
#include "ui/power_saving.h"
#include "core/ui_integration.h"
@ -226,6 +227,13 @@ void Game::draw(Painter &p, const PaintContext &context) const {
Ui::Text::ValidateQuotePaintCache(*cache, _st);
Ui::Text::FillQuotePaint(p, outer, *cache, _st);
if (_ripple) {
_ripple->paint(p, outer.x(), outer.y(), width(), &cache->bg);
if (_ripple->empty()) {
_ripple = nullptr;
}
}
auto lineHeight = UnitedLineHeight();
if (_titleLines) {
p.setPen(cache->icon);
@ -322,7 +330,6 @@ TextState Game::textState(QPoint point, StateRequest request) const {
auto tshift = inner.top();
auto paintw = inner.width();
auto inThumb = false;
auto symbolAdd = 0;
auto lineHeight = UnitedLineHeight();
if (_titleLines) {
@ -353,11 +360,7 @@ TextState Game::textState(QPoint point, StateRequest request) const {
}
tshift += _descriptionLines * lineHeight;
}
if (inThumb) {
if (_parent->data()->isHistoryEntry()) {
result.link = _openl;
}
} else if (_attach) {
if (_attach) {
auto attachAtTop = !_titleLines && !_descriptionLines;
if (!attachAtTop) tshift += st::mediaInBubbleSkip;
@ -375,6 +378,12 @@ TextState Game::textState(QPoint point, StateRequest request) const {
}
}
}
if (_parent->data()->isHistoryEntry()) {
if (!result.link && outer.contains(point)) {
result.link = _openl;
}
}
_lastPoint = point - outer.topLeft();
result.symbol += symbolAdd;
return result;
@ -399,11 +408,41 @@ void Game::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
}
void Game::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
if (p == _openl) {
if (pressed) {
if (!_ripple) {
const auto full = QRect(0, 0, width(), height());
const auto outer = full.marginsRemoved(inBubblePadding());
const auto owner = &parent()->history()->owner();
_ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::RoundRectMask(
outer.size(),
_st.radius),
[=] { owner->requestViewRepaint(parent()); });
}
_ripple->add(_lastPoint);
} else if (_ripple) {
_ripple->lastStop();
}
}
if (_attach) {
_attach->clickHandlerPressedChanged(p, pressed);
}
}
bool Game::toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const {
return _attach && _attach->toggleSelectionByHandlerClick(p);
}
bool Game::allowTextSelectionByHandler(const ClickHandlerPtr &p) const {
return (p == _openl);
}
bool Game::dragItemByHandler(const ClickHandlerPtr &p) const {
return _attach && _attach->dragItemByHandler(p);
}
TextForMimeData Game::selectedText(TextSelection selection) const {
auto titleResult = _title.toTextForMimeData(selection);
auto descriptionResult = _description.toTextForMimeData(

View File

@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class ReplyMarkupClickHandler;
namespace Ui {
class RippleAnimation;
} // namespace Ui
namespace HistoryView {
class Game : public Media {
@ -35,12 +39,11 @@ public:
return false; // we do not add _title and _description in FullSelection text copy.
}
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
return _attach && _attach->toggleSelectionByHandlerClick(p);
}
bool dragItemByHandler(const ClickHandlerPtr &p) const override {
return _attach && _attach->dragItemByHandler(p);
}
bool toggleSelectionByHandlerClick(
const ClickHandlerPtr &p) const override;
bool allowTextSelectionByHandler(
const ClickHandlerPtr &p) const override;
bool dragItemByHandler(const ClickHandlerPtr &p) const override;
TextForMimeData selectedText(TextSelection selection) const override;
@ -102,7 +105,9 @@ private:
const not_null<GameData*> _data;
std::shared_ptr<ReplyMarkupClickHandler> _openl;
std::unique_ptr<Media> _attach;
mutable std::unique_ptr<Ui::RippleAnimation> _ripple;
mutable QPoint _lastPoint;
int _gameTagWidth = 0;
int _descriptionLines = 0;
int _titleLines = 0;

View File

@ -181,6 +181,11 @@ Storage::SharedMediaTypesMask Media::sharedMediaTypes() const {
return {};
}
bool Media::allowTextSelectionByHandler(
const ClickHandlerPtr &handler) const {
return false;
}
not_null<Element*> Media::parent() const {
return _parent;
}

View File

@ -136,6 +136,8 @@ public:
// toggle selection instead of activating the pressed link
[[nodiscard]] virtual bool toggleSelectionByHandlerClick(
const ClickHandlerPtr &p) const = 0;
[[nodiscard]] virtual bool allowTextSelectionByHandler(
const ClickHandlerPtr &p) const;
[[nodiscard]] virtual TextSelection adjustSelection(
TextSelection selection,

View File

@ -904,6 +904,11 @@ bool WebPage::toggleSelectionByHandlerClick(
return _attach && _attach->toggleSelectionByHandlerClick(p);
}
bool WebPage::allowTextSelectionByHandler(
const ClickHandlerPtr &p) const {
return (p == _openl);
}
bool WebPage::dragItemByHandler(const ClickHandlerPtr &p) const {
return _attach && _attach->dragItemByHandler(p);
}

View File

@ -50,6 +50,8 @@ public:
bool toggleSelectionByHandlerClick(
const ClickHandlerPtr &p) const override;
bool allowTextSelectionByHandler(
const ClickHandlerPtr &p) const override;
bool dragItemByHandler(const ClickHandlerPtr &p) const override;
TextForMimeData selectedText(TextSelection selection) const override;