Use click handler property instead of dynamic cast.

This commit is contained in:
John Preston 2022-01-13 20:31:35 +03:00
parent 8a071fe1fe
commit f24f78c0cc
6 changed files with 122 additions and 90 deletions

View file

@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/basic_click_handlers.h" #include "ui/basic_click_handlers.h"
constexpr auto kPeerLinkPeerIdProperty = 0x01; constexpr auto kPeerLinkPeerIdProperty = 0x01;
constexpr auto kPhotoLinkMediaIdProperty = 0x02;
constexpr auto kDocumentLinkMediaIdProperty = 0x03;
namespace Main { namespace Main {
class Session; class Session;

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "data/data_file_click_handler.h" #include "data/data_file_click_handler.h"
#include "core/click_handler_types.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_photo.h" #include "data/data_photo.h"
@ -44,6 +45,9 @@ DocumentClickHandler::DocumentClickHandler(
FullMsgId context) FullMsgId context)
: FileClickHandler(context) : FileClickHandler(context)
, _document(document) { , _document(document) {
setProperty(
kDocumentLinkMediaIdProperty,
QVariant(qulonglong(_document->id)));
} }
DocumentOpenClickHandler::DocumentOpenClickHandler( DocumentOpenClickHandler::DocumentOpenClickHandler(
@ -146,6 +150,7 @@ PhotoClickHandler::PhotoClickHandler(
: FileClickHandler(context) : FileClickHandler(context)
, _photo(photo) , _photo(photo)
, _peer(peer) { , _peer(peer) {
setProperty(kPhotoLinkMediaIdProperty, QVariant(qulonglong(_photo->id)));
} }
not_null<PhotoData*> PhotoClickHandler::photo() const { not_null<PhotoData*> PhotoClickHandler::photo() const {

View file

@ -1169,11 +1169,21 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
auto view = App::hoveredItem() auto view = App::hoveredItem()
? App::hoveredItem() ? App::hoveredItem()
: App::hoveredLinkItem(); : App::hoveredLinkItem();
auto lnkPhoto = dynamic_cast<PhotoClickHandler*>(link.get()); const auto lnkPhotoId = PhotoId(link
auto lnkDocument = dynamic_cast<DocumentClickHandler*>(link.get()); ? link->property(kPhotoLinkMediaIdProperty).toULongLong()
auto lnkIsVideo = lnkDocument ? lnkDocument->document()->isVideoFile() : false; : 0);
auto lnkIsVoice = lnkDocument ? lnkDocument->document()->isVoiceMessage() : false; const auto lnkDocumentId = DocumentId(link
auto lnkIsAudio = lnkDocument ? lnkDocument->document()->isAudioFile() : false; ? link->property(kDocumentLinkMediaIdProperty).toULongLong()
: 0);
const auto lnkPhoto = lnkPhotoId
? session().data().photo(lnkPhotoId).get()
: nullptr;
const auto lnkDocument = lnkDocumentId
? session().data().document(lnkDocumentId).get()
: nullptr;
auto lnkIsVideo = lnkDocument ? lnkDocument->isVideoFile() : false;
auto lnkIsVoice = lnkDocument ? lnkDocument->isVoiceMessage() : false;
auto lnkIsAudio = lnkDocument ? lnkDocument->isAudioFile() : false;
const auto fromId = PeerId(link const auto fromId = PeerId(link
? link->property(kPeerLinkPeerIdProperty).toULongLong() ? link->property(kPeerLinkPeerIdProperty).toULongLong()
: 0); : 0);
@ -1184,21 +1194,20 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}, &st::menuIconCopy); }, &st::menuIconCopy);
} }
if (lnkPhoto) { if (lnkPhoto) {
const auto photo = lnkPhoto->photo(); const auto media = lnkPhoto->activeMediaView();
const auto media = photo->activeMediaView(); if (!lnkPhoto->isNull() && media && media->loaded()) {
if (!photo->isNull() && media && media->loaded()) {
_menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] { _menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] {
savePhotoToFile(photo); savePhotoToFile(lnkPhoto);
}), &st::menuIconSaveImage); }), &st::menuIconSaveImage);
_menu->addAction(tr::lng_context_copy_image(tr::now), [=] { _menu->addAction(tr::lng_context_copy_image(tr::now), [=] {
copyContextImage(photo); copyContextImage(lnkPhoto);
}, &st::menuIconCopy); }, &st::menuIconCopy);
} }
if (photo->hasAttachedStickers()) { if (lnkPhoto->hasAttachedStickers()) {
const auto controller = _controller; const auto controller = _controller;
auto callback = [=] { auto callback = [=] {
auto &attached = session().api().attachedStickers(); auto &attached = session().api().attachedStickers();
attached.requestAttachedStickerSets(controller, photo); attached.requestAttachedStickerSets(controller, lnkPhoto);
}; };
_menu->addAction( _menu->addAction(
tr::lng_context_attached_stickers(tr::now), tr::lng_context_attached_stickers(tr::now),
@ -1206,22 +1215,21 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
&st::menuIconStickers); &st::menuIconStickers);
} }
} else { } else {
auto document = lnkDocument->document(); if (lnkDocument->loading()) {
if (document->loading()) {
_menu->addAction(tr::lng_context_cancel_download(tr::now), [=] { _menu->addAction(tr::lng_context_cancel_download(tr::now), [=] {
cancelContextDownload(document); cancelContextDownload(lnkDocument);
}, &st::menuIconCancel); }, &st::menuIconCancel);
} else { } else {
const auto itemId = view const auto itemId = view
? view->data()->fullId() ? view->data()->fullId()
: FullMsgId(); : FullMsgId();
if (const auto item = document->session().data().message(itemId)) { if (const auto item = session().data().message(itemId)) {
const auto notAutoplayedGif = [&] { const auto notAutoplayedGif = [&] {
return document->isGifv() return lnkDocument->isGifv()
&& !Data::AutoDownload::ShouldAutoPlay( && !Data::AutoDownload::ShouldAutoPlay(
document->session().settings().autoDownload(), session().settings().autoDownload(),
item->history()->peer, item->history()->peer,
document); lnkDocument);
}(); }();
if (notAutoplayedGif) { if (notAutoplayedGif) {
_menu->addAction(tr::lng_context_open_gif(tr::now), [=] { _menu->addAction(tr::lng_context_open_gif(tr::now), [=] {
@ -1229,19 +1237,19 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}, &st::menuIconShowInChat); }, &st::menuIconShowInChat);
} }
} }
if (!document->filepath(true).isEmpty()) { if (!lnkDocument->filepath(true).isEmpty()) {
_menu->addAction(Platform::IsMac() ? tr::lng_context_show_in_finder(tr::now) : tr::lng_context_show_in_folder(tr::now), [=] { _menu->addAction(Platform::IsMac() ? tr::lng_context_show_in_finder(tr::now) : tr::lng_context_show_in_folder(tr::now), [=] {
showContextInFolder(document); showContextInFolder(lnkDocument);
}, &st::menuIconShowInFolder); }, &st::menuIconShowInFolder);
} }
_menu->addAction(lnkIsVideo ? tr::lng_context_save_video(tr::now) : (lnkIsVoice ? tr::lng_context_save_audio(tr::now) : (lnkIsAudio ? tr::lng_context_save_audio_file(tr::now) : tr::lng_context_save_file(tr::now))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, document] { _menu->addAction(lnkIsVideo ? tr::lng_context_save_video(tr::now) : (lnkIsVoice ? tr::lng_context_save_audio(tr::now) : (lnkIsAudio ? tr::lng_context_save_audio_file(tr::now) : tr::lng_context_save_file(tr::now))), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [this, lnkDocument] {
saveDocumentToFile(document); saveDocumentToFile(lnkDocument);
}), &st::menuIconDownload); }), &st::menuIconDownload);
if (document->hasAttachedStickers()) { if (lnkDocument->hasAttachedStickers()) {
const auto controller = _controller; const auto controller = _controller;
auto callback = [=, doc = document] { auto callback = [=] {
auto &attached = session().api().attachedStickers(); auto &attached = session().api().attachedStickers();
attached.requestAttachedStickerSets(controller, doc); attached.requestAttachedStickerSets(controller, lnkDocument);
}; };
_menu->addAction( _menu->addAction(
tr::lng_context_attached_stickers(tr::now), tr::lng_context_attached_stickers(tr::now),

View file

@ -2045,9 +2045,13 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}; };
const auto link = ClickHandler::getActive(); const auto link = ClickHandler::getActive();
auto lnkPhoto = dynamic_cast<PhotoClickHandler*>(link.get()); const auto lnkPhotoId = PhotoId(link
auto lnkDocument = dynamic_cast<DocumentClickHandler*>(link.get()); ? link->property(kPhotoLinkMediaIdProperty).toULongLong()
if (lnkPhoto || lnkDocument) { : 0);
const auto lnkDocumentId = DocumentId(link
? link->property(kDocumentLinkMediaIdProperty).toULongLong()
: 0);
if (lnkPhotoId || lnkDocumentId) {
const auto item = _dragStateItem; const auto item = _dragStateItem;
const auto itemId = item ? item->fullId() : FullMsgId(); const auto itemId = item ? item->fullId() : FullMsgId();
if (isUponSelected > 0 && !hasCopyRestrictionForSelected()) { if (isUponSelected > 0 && !hasCopyRestrictionForSelected()) {
@ -2059,10 +2063,10 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
&st::menuIconCopy); &st::menuIconCopy);
} }
addItemActions(item, item); addItemActions(item, item);
if (lnkPhoto) { if (lnkPhotoId) {
addPhotoActions(lnkPhoto->photo(), item); addPhotoActions(session->data().photo(lnkPhotoId), item);
} else { } else {
addDocumentActions(lnkDocument->document(), item); addDocumentActions(session->data().document(lnkDocumentId), item);
} }
if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) { if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) {
_menu->addAction(item->history()->peer->isMegagroup() ? tr::lng_context_copy_message_link(tr::now) : tr::lng_context_copy_post_link(tr::now), [=] { _menu->addAction(item->history()->peer->isMegagroup() ? tr::lng_context_copy_message_link(tr::now) : tr::lng_context_copy_post_link(tr::now), [=] {

View file

@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_scheduled_messages.h" #include "data/data_scheduled_messages.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "core/click_handler_types.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "window/window_peer_menu.h" #include "window/window_peer_menu.h"
#include "window/window_controller.h" #include "window/window_controller.h"
@ -921,12 +922,17 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
const auto view = request.view; const auto view = request.view;
const auto item = request.item; const auto item = request.item;
const auto itemId = item ? item->fullId() : FullMsgId(); const auto itemId = item ? item->fullId() : FullMsgId();
const auto rawLink = link.get(); const auto lnkPhotoId = PhotoId(link
const auto linkPhoto = dynamic_cast<PhotoClickHandler*>(rawLink); ? link->property(kPhotoLinkMediaIdProperty).toULongLong()
const auto linkDocument = dynamic_cast<DocumentClickHandler*>(rawLink); : 0);
const auto photo = linkPhoto ? linkPhoto->photo().get() : nullptr; const auto lnkDocumentId = DocumentId(link
const auto document = linkDocument ? link->property(kDocumentLinkMediaIdProperty).toULongLong()
? linkDocument->document().get() : 0);
const auto photo = lnkPhotoId
? list->session().data().photo(lnkPhotoId).get()
: nullptr;
const auto document = lnkDocumentId
? list->session().data().document(lnkDocumentId).get()
: nullptr; : nullptr;
const auto poll = item const auto poll = item
? (item->media() ? item->media()->poll() : nullptr) ? (item->media() ? item->media()->poll() : nullptr)
@ -951,9 +957,9 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
} }
AddTopMessageActions(result, request, list); AddTopMessageActions(result, request, list);
if (linkPhoto) { if (photo) {
AddPhotoActions(result, photo, item, list); AddPhotoActions(result, photo, item, list);
} else if (linkDocument) { } else if (document) {
AddDocumentActions(result, document, item, list); AddDocumentActions(result, document, item, list);
} else if (poll) { } else if (poll) {
AddPollActions(result, poll, item, list->elementContext()); AddPollActions(result, poll, item, list->elementContext());

View file

@ -1593,68 +1593,75 @@ void ListWidget::showContextMenu(
}, },
&st::menuIconShowInChat); &st::menuIconShowInChat);
auto photoLink = dynamic_cast<PhotoClickHandler*>(link.get()); const auto lnkPhotoId = PhotoId(link
auto fileLink = dynamic_cast<DocumentClickHandler*>(link.get()); ? link->property(kPhotoLinkMediaIdProperty).toULongLong()
if (photoLink || fileLink) { : 0);
const auto lnkDocumentId = DocumentId(link
? link->property(kDocumentLinkMediaIdProperty).toULongLong()
: 0);
const auto lnkPhoto = lnkPhotoId
? session().data().photo(lnkPhotoId).get()
: nullptr;
const auto lnkDocument = lnkDocumentId
? session().data().document(lnkDocumentId).get()
: nullptr;
if (lnkPhoto || lnkDocument) {
auto [isVideo, isVoice, isAudio] = [&] { auto [isVideo, isVoice, isAudio] = [&] {
if (fileLink) { if (lnkDocument) {
auto document = fileLink->document();
return std::make_tuple( return std::make_tuple(
document->isVideoFile(), lnkDocument->isVideoFile(),
document->isVoiceMessage(), lnkDocument->isVoiceMessage(),
document->isAudioFile() lnkDocument->isAudioFile()
); );
} }
return std::make_tuple(false, false, false); return std::make_tuple(false, false, false);
}(); }();
if (photoLink) { if (lnkPhoto) {
} else { } else {
if (auto document = fileLink->document()) { if (lnkDocument->loading()) {
if (document->loading()) { _contextMenu->addAction(
_contextMenu->addAction( tr::lng_context_cancel_download(tr::now),
tr::lng_context_cancel_download(tr::now), [lnkDocument] {
[document] { lnkDocument->cancel();
document->cancel(); },
}, &st::menuIconCancel);
&st::menuIconCancel); } else {
} else { auto filepath = lnkDocument->filepath(true);
auto filepath = document->filepath(true); if (!filepath.isEmpty()) {
if (!filepath.isEmpty()) {
auto handler = App::LambdaDelayed(
st::defaultDropdownMenu.menu.ripple.hideDuration,
this,
[filepath] {
File::ShowInFolder(filepath);
});
_contextMenu->addAction(
(Platform::IsMac()
? tr::lng_context_show_in_finder(tr::now)
: tr::lng_context_show_in_folder(tr::now)),
std::move(handler),
&st::menuIconShowInFolder);
}
auto handler = App::LambdaDelayed( auto handler = App::LambdaDelayed(
st::defaultDropdownMenu.menu.ripple.hideDuration, st::defaultDropdownMenu.menu.ripple.hideDuration,
this, this,
[=] { [filepath] {
DocumentSaveClickHandler::Save( File::ShowInFolder(filepath);
itemFullId,
document,
DocumentSaveClickHandler::Mode::ToNewFile);
}); });
if (_peer->allowsForwarding() && !item->forbidsForward()) { _contextMenu->addAction(
_contextMenu->addAction( (Platform::IsMac()
(isVideo ? tr::lng_context_show_in_finder(tr::now)
? tr::lng_context_save_video(tr::now) : tr::lng_context_show_in_folder(tr::now)),
: isVoice std::move(handler),
? tr::lng_context_save_audio(tr::now) &st::menuIconShowInFolder);
: isAudio }
? tr::lng_context_save_audio_file(tr::now) auto handler = App::LambdaDelayed(
: tr::lng_context_save_file(tr::now)), st::defaultDropdownMenu.menu.ripple.hideDuration,
std::move(handler), this,
&st::menuIconDownload); [=] {
} DocumentSaveClickHandler::Save(
itemFullId,
lnkDocument,
DocumentSaveClickHandler::Mode::ToNewFile);
});
if (_peer->allowsForwarding() && !item->forbidsForward()) {
_contextMenu->addAction(
(isVideo
? tr::lng_context_save_video(tr::now)
: isVoice
? tr::lng_context_save_audio(tr::now)
: isAudio
? tr::lng_context_save_audio_file(tr::now)
: tr::lng_context_save_file(tr::now)),
std::move(handler),
&st::menuIconDownload);
} }
} }
} }