When following a post link push reply-return.

Fixes #4856.
This commit is contained in:
John Preston 2018-07-09 21:13:48 +03:00
parent eb3eef4b80
commit b697824540
25 changed files with 136 additions and 74 deletions

View file

@ -33,7 +33,7 @@ void AboutBox::prepare() {
const auto linkFilter = [](const ClickHandlerPtr &link, auto button) {
if (const auto url = dynamic_cast<UrlClickHandler*>(link.get())) {
url->UrlClickHandler::onClick(button);
url->UrlClickHandler::onClick({ button });
return false;
}
return true;

View file

@ -10,6 +10,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class ClickHandler;
using ClickHandlerPtr = std::shared_ptr<ClickHandler>;
struct ClickContext {
Qt::MouseButton button = Qt::LeftButton;
QVariant other;
};
enum ExpandLinksMode {
ExpandLinksNone,
ExpandLinksShortened,
@ -35,7 +40,7 @@ public:
virtual ~ClickHandler() {
}
virtual void onClick(Qt::MouseButton) const = 0;
virtual void onClick(ClickContext context) const = 0;
// What text to show in a tooltip when mouse is over that click handler as a link in Text.
virtual QString tooltip() const {
@ -159,9 +164,10 @@ private:
class LeftButtonClickHandler : public ClickHandler {
public:
void onClick(Qt::MouseButton button) const override final {
if (button != Qt::LeftButton) return;
onClickImpl();
void onClick(ClickContext context) const override final {
if (context.button == Qt::LeftButton) {
onClickImpl();
}
}
protected:
@ -173,8 +179,8 @@ class LambdaClickHandler : public ClickHandler {
public:
LambdaClickHandler(Fn<void()> handler) : _handler(std::move(handler)) {
}
void onClick(Qt::MouseButton button) const override final {
if (button == Qt::LeftButton && _handler) {
void onClick(ClickContext context) const override final {
if (context.button == Qt::LeftButton && _handler) {
_handler();
}
}

View file

@ -103,7 +103,7 @@ QString UrlClickHandler::url() const {
return result;
}
void UrlClickHandler::doOpen(QString url) {
void UrlClickHandler::Open(QString url, QVariant context) {
Ui::Tooltip::Hide();
if (isEmail(url)) {
@ -114,7 +114,7 @@ void UrlClickHandler::doOpen(QString url) {
url = tryConvertUrlToLocal(url);
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
Messenger::Instance().openLocalUrl(url);
Messenger::Instance().openLocalUrl(url, context);
} else {
QDesktopServices::openUrl(url);
}
@ -140,38 +140,52 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod
return result;
}
void HiddenUrlClickHandler::doOpen(QString url) {
void HiddenUrlClickHandler::Open(QString url, QVariant context) {
auto urlText = tryConvertUrlToLocal(url);
if (urlText.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
Messenger::Instance().openLocalUrl(urlText);
Messenger::Instance().openLocalUrl(urlText, context);
} else {
const auto open = [=] {
UrlClickHandler::Open(urlText, context);
};
auto parsedUrl = QUrl::fromUserInput(urlText);
if (UrlRequiresConfirmation(urlText)) {
auto displayUrl = parsedUrl.isValid() ? parsedUrl.toDisplayString() : urlText;
Ui::show(Box<ConfirmBox>(lang(lng_open_this_link) + qsl("\n\n") + displayUrl, lang(lng_open_link), [urlText] {
Ui::hideLayer();
UrlClickHandler::doOpen(urlText);
}), LayerOption::KeepOther);
auto displayUrl = parsedUrl.isValid()
? parsedUrl.toDisplayString()
: urlText;
Ui::show(
Box<ConfirmBox>(
lang(lng_open_this_link) + qsl("\n\n") + displayUrl,
lang(lng_open_link),
[=] { Ui::hideLayer(); open(); }),
LayerOption::KeepOther);
} else {
UrlClickHandler::doOpen(urlText);
open();
}
}
}
void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const {
void BotGameUrlClickHandler::onClick(ClickContext context) const {
auto urlText = tryConvertUrlToLocal(url());
const auto open = [=] {
UrlClickHandler::Open(urlText, context.other);
};
if (urlText.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
Messenger::Instance().openLocalUrl(urlText);
Messenger::Instance().openLocalUrl(urlText, context.other);
} else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) {
doOpen(urlText);
open();
} else {
Ui::show(Box<ConfirmBox>(lng_allow_bot_pass(lt_bot_name, _bot->name), lang(lng_allow_bot), [bot = _bot, urlText] {
const auto callback = [=, bot = _bot] {
Ui::hideLayer();
Local::makeBotTrusted(bot);
UrlClickHandler::doOpen(urlText);
}));
open();
};
Ui::show(Box<ConfirmBox>(
lng_allow_bot_pass(lt_bot_name, _bot->name),
lang(lng_allow_bot),
callback));
}
}
@ -203,7 +217,8 @@ QString MentionClickHandler::copyToClipboardContextItemText() const {
return lang(lng_context_copy_mention);
}
void MentionClickHandler::onClick(Qt::MouseButton button) const {
void MentionClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
App::openPeerByName(_tag.mid(1), ShowAtProfileMsgId);
}
@ -213,7 +228,8 @@ TextWithEntities MentionClickHandler::getExpandedLinkTextWithEntities(ExpandLink
return simpleTextWithEntity({ EntityInTextMention, entityOffset, textPart.size() });
}
void MentionNameClickHandler::onClick(Qt::MouseButton button) const {
void MentionNameClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
if (auto user = App::userLoaded(_userId)) {
Ui::showPeerProfile(user);
@ -240,7 +256,8 @@ QString HashtagClickHandler::copyToClipboardContextItemText() const {
return lang(lng_context_copy_hashtag);
}
void HashtagClickHandler::onClick(Qt::MouseButton button) const {
void HashtagClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
App::searchByHashtag(_tag, Ui::getPeerForMouseAction());
}
@ -254,7 +271,8 @@ QString CashtagClickHandler::copyToClipboardContextItemText() const {
return lang(lng_context_copy_hashtag);
}
void CashtagClickHandler::onClick(Qt::MouseButton button) const {
void CashtagClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
App::searchByHashtag(_tag, Ui::getPeerForMouseAction());
}
@ -269,7 +287,8 @@ TextWithEntities CashtagClickHandler::getExpandedLinkTextWithEntities(
PeerData *BotCommandClickHandler::_peer = nullptr;
UserData *BotCommandClickHandler::_bot = nullptr;
void BotCommandClickHandler::onClick(Qt::MouseButton button) const {
void BotCommandClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
if (auto peer = peerForCommand()) {
if (auto bot = peer->isUser() ? peer->asUser() : botForCommand()) {

View file

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class TextClickHandler : public ClickHandler {
public:
TextClickHandler(bool fullDisplayed = true)
: _fullDisplayed(fullDisplayed) {
}
@ -56,10 +55,11 @@ public:
int entityOffset,
const QStringRef &textPart) const override;
static void doOpen(QString url);
void onClick(Qt::MouseButton button) const override {
static void Open(QString url, QVariant context = {});
void onClick(ClickContext context) const override {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
doOpen(url());
Open(url(), context.other);
}
}
@ -92,10 +92,11 @@ public:
: UrlClickHandler::copyToClipboardContextItemText();
}
static void doOpen(QString url);
void onClick(Qt::MouseButton button) const override {
static void Open(QString url, QVariant context = {});
void onClick(ClickContext context) const override {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
doOpen(url());
Open(url(), context.other);
}
}
@ -115,7 +116,7 @@ public:
: UrlClickHandler(url, false)
, _bot(bot) {
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
private:
UserData *_bot;
@ -127,7 +128,7 @@ public:
MentionClickHandler(const QString &tag) : _tag(tag) {
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
QString dragText() const override {
return _tag;
@ -158,7 +159,7 @@ public:
, _accessHash(accessHash) {
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
TextWithEntities getExpandedLinkTextWithEntities(
ExpandLinksMode mode,
@ -179,7 +180,7 @@ public:
HashtagClickHandler(const QString &tag) : _tag(tag) {
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
QString dragText() const override {
return _tag;
@ -207,7 +208,7 @@ public:
CashtagClickHandler(const QString &tag) : _tag(tag) {
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
QString dragText() const override {
return _tag;
@ -237,7 +238,7 @@ public:
BotCommandClickHandler(const QString &cmd) : _cmd(cmd) {
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
QString dragText() const override {
return _cmd;

View file

@ -70,8 +70,8 @@ PeerClickHandler::PeerClickHandler(not_null<PeerData*> peer)
: _peer(peer) {
}
void PeerClickHandler::onClick(Qt::MouseButton button) const {
if (button == Qt::LeftButton && App::wnd()) {
void PeerClickHandler::onClick(ClickContext context) const {
if (context.button == Qt::LeftButton && App::wnd()) {
auto controller = App::wnd()->controller();
if (_peer
&& _peer->isChannel()

View file

@ -33,7 +33,7 @@ style::color PeerUserpicColor(PeerId peerId);
class PeerClickHandler : public ClickHandler {
public:
PeerClickHandler(not_null<PeerData*> peer);
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
not_null<PeerData*> peer() const {
return _peer;

View file

@ -206,6 +206,8 @@ struct FullMsgId {
};
Q_DECLARE_METATYPE(FullMsgId);
using MessageIdsList = std::vector<FullMsgId>;
inline PeerId peerFromMessage(const MTPmessage &msg) {

View file

@ -100,9 +100,9 @@ void activateBotCommand(
}
}
if (skipConfirmation) {
UrlClickHandler::doOpen(url);
UrlClickHandler::Open(url);
} else {
HiddenUrlClickHandler::doOpen(url);
HiddenUrlClickHandler::Open(url);
}
} break;
@ -177,12 +177,16 @@ void showSettings() {
}
}
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
crl::on_main(wnd(), [handler, button] {
handler->onClick(button);
void activateClickHandler(ClickHandlerPtr handler, ClickContext context) {
crl::on_main(wnd(), [=] {
handler->onClick(context);
});
}
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
activateClickHandler(handler, ClickContext{ button });
}
} // namespace App
namespace Ui {

View file

@ -74,6 +74,7 @@ void openPeerByName(
void joinGroupByHash(const QString &hash);
void showSettings();
void activateClickHandler(ClickHandlerPtr handler, ClickContext context);
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
} // namespace App

View file

@ -1277,8 +1277,9 @@ void HistoryInner::mouseActionFinish(
}
}
}
if (App::pressedItem()) {
repaintItem(App::pressedItem());
const auto pressedItemView = App::pressedItem();
if (pressedItemView) {
repaintItem(pressedItemView);
App::pressedItem(nullptr);
}
@ -1286,7 +1287,13 @@ void HistoryInner::mouseActionFinish(
if (activated) {
mouseActionCancel();
App::activateClickHandler(activated, button);
const auto pressedItemId = pressedItemView
? pressedItemView->data()->fullId()
: FullMsgId();
App::activateClickHandler(activated, {
button,
QVariant::fromValue(pressedItemId)
});
return;
}
if ((_mouseAction == MouseAction::PrepareSelect)

View file

@ -26,7 +26,7 @@ QString LocationClickHandler::copyToClipboardContextItemText() const {
return lang(lng_context_copy_link);
}
void LocationClickHandler::onClick(Qt::MouseButton button) const {
void LocationClickHandler::onClick(ClickContext context) const {
if (!psLaunchMaps(_coords)) {
QDesktopServices::openUrl(_text);
}

View file

@ -79,7 +79,7 @@ public:
setup();
}
void onClick(Qt::MouseButton button) const override;
void onClick(ClickContext context) const override;
QString tooltip() const override {
return QString();

View file

@ -3546,12 +3546,12 @@ void HistoryWidget::botCallbackDone(
auto url = qs(answerData.vurl);
if (info.game) {
url = AppendShareGameScoreUrl(url, info.msgId);
BotGameUrlClickHandler(info.bot, url).onClick(Qt::LeftButton);
BotGameUrlClickHandler(info.bot, url).onClick({});
if (item) {
updateSendAction(item->history(), SendAction::Type::PlayGame);
}
} else {
UrlClickHandler(url).onClick(Qt::LeftButton);
UrlClickHandler(url).onClick({});
}
}
}

View file

@ -1979,7 +1979,10 @@ void ListWidget::mouseActionFinish(
activated = nullptr;
} else if (activated) {
mouseActionCancel();
App::activateClickHandler(activated, button);
App::activateClickHandler(activated, {
button,
QVariant::fromValue(pressState.itemId)
});
return;
}
if (needItemSelectionToggle) {

View file

@ -29,7 +29,7 @@ public:
// this type used as a flag, we dynamic_cast<> to it
class SendClickHandler : public ClickHandler {
public:
void onClick(Qt::MouseButton) const override {
void onClick(ClickContext context) const override {
}
};

View file

@ -281,17 +281,17 @@ void Result::forget() {
void Result::openFile() {
if (_document) {
DocumentOpenClickHandler(_document).onClick(Qt::LeftButton);
DocumentOpenClickHandler(_document).onClick({});
} else if (_photo) {
PhotoOpenClickHandler(_photo).onClick(Qt::LeftButton);
PhotoOpenClickHandler(_photo).onClick({});
}
}
void Result::cancelFile() {
if (_document) {
DocumentCancelClickHandler(_document).onClick(Qt::LeftButton);
DocumentCancelClickHandler(_document).onClick({});
} else if (_photo) {
PhotoCancelClickHandler(_photo).onClick(Qt::LeftButton);
PhotoCancelClickHandler(_photo).onClick({});
}
}

View file

@ -45,7 +45,7 @@ Locale: ") + Platform::SystemLanguage();
+ "&body="
+ qthelp::url_encode(body);
UrlClickHandler::doOpen(url);
UrlClickHandler::Open(url);
}
} // namespace

View file

@ -3695,7 +3695,11 @@ bool MainWidget::started() {
return _started;
}
void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QString &startToken) {
void MainWidget::openPeerByName(
const QString &username,
MsgId msgId,
const QString &startToken,
FullMsgId clickFromMessageId) {
Messenger::Instance().hideMediaView();
PeerData *peer = App::peerByName(username);
@ -3736,7 +3740,13 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr
_history->updateControlsGeometry();
}
}
InvokeQueued(this, [this, peer, msgId] {
const auto returnToId = clickFromMessageId;
InvokeQueued(this, [=] {
if (const auto returnTo = App::histItemById(returnToId)) {
if (returnTo->history()->peer == peer) {
pushReplyReturn(returnTo);
}
}
_controller->showPeerHistory(
peer->id,
SectionShow::Way::Forward,

View file

@ -97,7 +97,11 @@ public:
void start(const MTPUser *self = nullptr);
void openPeerByName(const QString &name, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
void openPeerByName(
const QString &name,
MsgId msgId = ShowAtUnreadMsgId,
const QString &startToken = QString(),
FullMsgId clickFromMessageId = FullMsgId());
void joinGroupByHash(const QString &hash);
void stickersBox(const MTPInputStickerSet &set);

View file

@ -841,13 +841,13 @@ void Messenger::checkStartUrl() {
if (!cStartUrl().isEmpty() && !locked()) {
auto url = cStartUrl();
cSetStartUrl(QString());
if (!openLocalUrl(url)) {
if (!openLocalUrl(url, {})) {
cSetStartUrl(url);
}
}
}
bool Messenger::openLocalUrl(const QString &url) {
bool Messenger::openLocalUrl(const QString &url, QVariant context) {
auto urlTrimmed = url.trimmed();
if (urlTrimmed.size() > 8192) urlTrimmed = urlTrimmed.mid(0, 8192);
@ -936,7 +936,12 @@ bool Messenger::openLocalUrl(const QString &url) {
startToken = gameParam;
post = ShowAtGameShareMsgId;
}
main->openPeerByName(domain, post, startToken);
const auto clickFromMessageId = context.value<FullMsgId>();
main->openPeerByName(
domain,
post,
startToken,
clickFromMessageId);
return true;
}
}

View file

@ -151,7 +151,7 @@ public:
QString createInternalLink(const QString &query) const;
QString createInternalLinkFull(const QString &query) const;
void checkStartUrl();
bool openLocalUrl(const QString &url);
bool openLocalUrl(const QString &url, QVariant context);
void uploadProfilePhoto(QImage &&tosend, const PeerId &peerId);
void regPhotoUpdate(const PeerId &peer, const FullMsgId &msgId);

View file

@ -2106,7 +2106,7 @@ void FormController::cancelSure() {
: (_serviceErrorText.isEmpty()
? "tg_passport=cancel"
: "tg_passport=error&error=" + _serviceErrorText)));
UrlClickHandler::doOpen(url);
UrlClickHandler::Open(url);
}
const auto timeout = _view->closeGetDuration();
App::CallDelayed(timeout, this, [=] {

View file

@ -101,7 +101,7 @@ void MainWindow::checkLockByTerms() {
if (AuthSession::Exists()) {
Auth().api().acceptTerms(id);
if (!mention.isEmpty()) {
MentionClickHandler(mention).onClick(Qt::LeftButton);
MentionClickHandler(mention).onClick({});
}
}
Messenger::Instance().unlockTerms();

View file

@ -35,7 +35,7 @@ void DateClickHandler::setDate(QDate date) {
_date = date;
}
void DateClickHandler::onClick(Qt::MouseButton) const {
void DateClickHandler::onClick(ClickContext context) const {
App::wnd()->controller()->showJumpToDate(_chat, _date);
}

View file

@ -48,7 +48,7 @@ public:
DateClickHandler(Dialogs::Key chat, QDate date);
void setDate(QDate date);
void onClick(Qt::MouseButton) const override;
void onClick(ClickContext context) const override;
private:
Dialogs::Key _chat;