From 8d93b21947df70ee108efa121b4dc8ff5a50f754 Mon Sep 17 00:00:00 2001 From: ZavaruKitsu Date: Fri, 29 Dec 2023 01:22:07 +0300 Subject: [PATCH] feat: message details feat: rework `Hide` feat: context menu configuration --- Telegram/CMakeLists.txt | 3 + Telegram/Resources/langs/lang.strings | 24 + Telegram/SourceFiles/ayu/ayu_settings.cpp | 129 ++-- Telegram/SourceFiles/ayu/ayu_settings.h | 65 +- Telegram/SourceFiles/ayu/ayu_state.cpp | 27 + Telegram/SourceFiles/ayu/ayu_state.h | 36 +- .../ayu/ui/context_menu/context_menu.cpp | 232 ++++++- .../ayu/ui/context_menu/context_menu.h | 6 + .../ayu/ui/context_menu/menu_item_subtext.cpp | 301 +++++++++ .../ayu/ui/context_menu/menu_item_subtext.h | 36 + .../ayu/ui/settings/settings_ayu.cpp | 625 +++++++++++------- .../ayu/ui/settings/settings_ayu.h | 3 + .../ayu/utils/qt_key_modifiers_extended.h | 21 + .../ayu/utils/telegram_helpers.cpp | 388 ++++++++++- .../SourceFiles/ayu/utils/telegram_helpers.h | 13 + Telegram/SourceFiles/data/data_session.cpp | 6 + Telegram/SourceFiles/history/history.cpp | 5 + .../history/history_inner_widget.cpp | 1 + .../view/history_view_context_menu.cpp | 9 +- .../history/view/history_view_element.cpp | 8 +- .../history_view_reactions_selector.cpp | 20 + Telegram/SourceFiles/mainwidget.cpp | 4 - 22 files changed, 1611 insertions(+), 351 deletions(-) create mode 100644 Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.cpp create mode 100644 Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.h create mode 100644 Telegram/SourceFiles/ayu/utils/qt_key_modifiers_extended.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 6cc03d2b7..5f3eb6ea2 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -107,6 +107,7 @@ PRIVATE ayu/ayu_constants.h ayu/utils/ayu_mapper.cpp ayu/utils/ayu_mapper.h + ayu/utils/qt_key_modifiers_extended.h ayu/utils/telegram_helpers.cpp ayu/utils/telegram_helpers.h ayu/utils/windows_utils.cpp @@ -123,6 +124,8 @@ PRIVATE ayu/ui/settings/settings_ayu.h ayu/ui/context_menu/context_menu.cpp ayu/ui/context_menu/context_menu.h + ayu/ui/context_menu/menu_item_subtext.cpp + ayu/ui/context_menu/menu_item_subtext.h ayu/ui/sections/edited/edited_log_inner.cpp ayu/ui/sections/edited/edited_log_inner.h ayu/ui/sections/edited/edited_log_item.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 2a99b8bd8..9709b376a 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4633,6 +4633,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "ayu_SettingsShowID_Hide" = "Hide"; "ayu_SettingsRecentStickersCount" = "Recent stickers count"; "ayu_SettingsCustomizationHint" = "After making changes to the \"Customization\" section, you must restart the application."; +"ayu_SettingsContextMenuTitle" = "Select item show type"; +"ayu_SettingsContextMenuDescription" = "Extended menu items will be displayed if you hold CTRL or SHIFT while right-clicking on the message."; +"ayu_SettingsContextMenuItemHidden" = "Hidden"; +"ayu_SettingsContextMenuItemShown" = "Shown"; +"ayu_SettingsContextMenuItemExtended" = "Extended menu"; +"ayu_SettingsContextMenuReactionsPanel" = "Reactions Panel"; +"ayu_SettingsContextMenuViewsPanel" = "Views Panel"; +"ayu_ContextMenuElementsHeader" = "Context Menu Elements"; "ayu_DrawerElementsHeader" = "Drawer Elements"; "ayu_TrayElementsHeader" = "Tray Elements"; "ayu_RegexFilters" = "Message Filters"; @@ -4690,6 +4698,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "ayu_StickerConfirmation" = "For stickers"; "ayu_GIFConfirmation" = "For GIFs"; "ayu_VoiceConfirmation" = "For voice messages"; +"ayu_MessageDetailsPC" = "Details"; +"ayu_MessageDetailsViewsPC" = "Views"; +"ayu_MessageDetailsSharesPC" = "Shares"; +"ayu_MessageDetailsDatePC" = "Date"; +"ayu_MessageDetailsEditedDatePC" = "Edit Date"; +"ayu_MessageDetailsForwardedDatePC" = "Forward Date"; +"ayu_MessageDetailsFileSizePC" = "File Size"; +"ayu_MessageDetailsFileNamePC" = "File Name"; +"ayu_MessageDetailsFilePathPC" = "File Path"; +"ayu_MessageDetailsResolutionPC" = "Resolution"; +"ayu_MessageDetailsBitratePC" = "Bitrate"; +"ayu_MessageDetailsMimeTypePC" = "Mime Type"; +"ayu_MessageDetailsDatacenterPC" = "Datacenter"; +"ayu_MessageDetailsPackOwnerPC" = "Pack Owner"; +"ayu_MessageDetailsPackOwnerFetchingPC" = "fetching..."; +"ayu_MessageDetailsPackOwnerNotFoundPC" = "not found"; "ayu_KillApp" = "Kill App"; "ayu_LReadMessages" = "Read on Local"; "ayu_SReadMessages" = "Read on Server"; diff --git a/Telegram/SourceFiles/ayu/ayu_settings.cpp b/Telegram/SourceFiles/ayu/ayu_settings.cpp index a380a6de3..aac6805d5 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.cpp +++ b/Telegram/SourceFiles/ayu/ayu_settings.cpp @@ -59,54 +59,64 @@ void initialize() settings = AyuGramSettings(); - sendReadMessagesReactive.value() | rpl::filter([=](bool val) - { - return (val != settings->sendReadMessages); - }) | start_with_next([=](bool val) - { - ghostModeEnabled = - ghostModeEnabled_util(settings.value()); - }, lifetime); + sendReadMessagesReactive.value() | rpl::filter( + [=](bool val) + { + return (val != settings->sendReadMessages); + }) | start_with_next( + [=](bool val) + { + ghostModeEnabled = + ghostModeEnabled_util(settings.value()); + }, lifetime); // .. - sendReadStoriesReactive.value() | rpl::filter([=](bool val) - { - return (val != settings->sendReadStories); - }) | start_with_next([=](bool val) - { - ghostModeEnabled = - ghostModeEnabled_util(settings.value()); - }, lifetime); + sendReadStoriesReactive.value() | rpl::filter( + [=](bool val) + { + return (val != settings->sendReadStories); + }) | start_with_next( + [=](bool val) + { + ghostModeEnabled = + ghostModeEnabled_util(settings.value()); + }, lifetime); // .. - sendOnlinePacketsReactive.value() | rpl::filter([=](bool val) - { - return (val != settings->sendOnlinePackets); - }) | start_with_next([=](bool val) - { - ghostModeEnabled = - ghostModeEnabled_util(settings - .value()); - }, lifetime); + sendOnlinePacketsReactive.value() | rpl::filter( + [=](bool val) + { + return (val != settings->sendOnlinePackets); + }) | start_with_next( + [=](bool val) + { + ghostModeEnabled = + ghostModeEnabled_util(settings + .value()); + }, lifetime); // .. - sendUploadProgressReactive.value() | rpl::filter([=](bool val) - { - return (val != settings->sendUploadProgress); - }) | start_with_next([=](bool val) - { - ghostModeEnabled = - ghostModeEnabled_util(settings - .value()); - }, lifetime); + sendUploadProgressReactive.value() | rpl::filter( + [=](bool val) + { + return (val != settings->sendUploadProgress); + }) | start_with_next( + [=](bool val) + { + ghostModeEnabled = + ghostModeEnabled_util(settings + .value()); + }, lifetime); // .. - sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val) - { - return (val - != settings->sendOfflinePacketAfterOnline); - }) | start_with_next([=](bool val) - { - ghostModeEnabled = - ghostModeEnabled_util( - settings.value()); - }, lifetime); + sendOfflinePacketAfterOnlineReactive.value() | rpl::filter( + [=](bool val) + { + return (val + != settings->sendOfflinePacketAfterOnline); + }) | start_with_next( + [=](bool val) + { + ghostModeEnabled = + ghostModeEnabled_util( + settings.value()); + }, lifetime); } void postinitialize() @@ -150,7 +160,8 @@ void load() catch (...) { LOG(("AyuGramSettings: failed to parse settings file")); } - } catch (...) { + } + catch (...) { LOG(("AyuGramSettings: failed to read settings file (not json-like)")); } postinitialize(); @@ -279,7 +290,8 @@ void AyuGramSettings::set_appIcon(QString val) appIcon = std::move(val); } -void AyuGramSettings::set_simpleQuotesAndReplies(bool val) { +void AyuGramSettings::set_simpleQuotesAndReplies(bool val) +{ simpleQuotesAndReplies = val; } @@ -300,6 +312,31 @@ void AyuGramSettings::set_recentStickersCount(int val) recentStickersCount = val; } +void AyuGramSettings::set_showReactionsPanelInContextMenu(int val) +{ + showReactionsPanelInContextMenu = val; +} + +void AyuGramSettings::set_showViewsPanelInContextMenu(int val) +{ + showViewsPanelInContextMenu = val; +} + +void AyuGramSettings::set_showHideMessageInContextMenu(int val) +{ + showHideMessageInContextMenu = val; +} + +void AyuGramSettings::set_showUserMessagesInContextMenu(int val) +{ + showUserMessagesInContextMenu = val; +} + +void AyuGramSettings::set_showMessageDetailsInContextMenu(int val) +{ + showMessageDetailsInContextMenu = val; +} + void AyuGramSettings::set_showLReadToggleInDrawer(bool val) { showLReadToggleInDrawer = val; diff --git a/Telegram/SourceFiles/ayu/ayu_settings.h b/Telegram/SourceFiles/ayu/ayu_settings.h index a0dc93795..30a9e85ee 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.h +++ b/Telegram/SourceFiles/ayu/ayu_settings.h @@ -67,6 +67,15 @@ public: editedMark = tr::lng_edited(tr::now); recentStickersCount = 50; + // context menu items + // 0 - hide + // 1 - show normally + // 2 - show with SHIFT or CTRL pressed + showReactionsPanelInContextMenu = 1; + showViewsPanelInContextMenu = 1; + showUserMessagesInContextMenu = 2; + showMessageDetailsInContextMenu = 2; + showLReadToggleInDrawer = true; showSReadToggleInDrawer = true; showGhostToggleInDrawer = true; @@ -99,12 +108,15 @@ public: bool sendOnlinePackets; bool sendUploadProgress; bool sendOfflinePacketAfterOnline; + bool markReadAfterSend; bool markReadAfterReaction; bool markReadAfterPoll; bool useScheduledMessages; + bool saveDeletedMessages; bool saveMessagesHistory; + bool disableAds; bool disableStories; bool collapseSimilarChannels; @@ -112,101 +124,92 @@ public: bool disableNotificationsDelay; bool localPremium; bool copyUsernameAsLink; + QString appIcon; bool simpleQuotesAndReplies; QString deletedMark; QString editedMark; int recentStickersCount; + + int showReactionsPanelInContextMenu; + int showViewsPanelInContextMenu; + int showHideMessageInContextMenu; + int showUserMessagesInContextMenu; + int showMessageDetailsInContextMenu; + bool showLReadToggleInDrawer; bool showSReadToggleInDrawer; bool showGhostToggleInDrawer; bool showStreamerToggleInDrawer; + bool showGhostToggleInTray; bool showStreamerToggleInTray; + QString mainFont; QString monoFont; + int showPeerId; bool hideAllChatsFolder; bool showMessageSeconds; + bool stickerConfirmation; bool gifConfirmation; bool voiceConfirmation; public: void set_sendReadMessages(bool val); - void set_sendReadStories(bool val); - void set_sendOnlinePackets(bool val); - void set_sendUploadProgress(bool val); - void set_sendOfflinePacketAfterOnline(bool val); void set_ghostModeEnabled(bool val); void set_markReadAfterSend(bool val); - void set_markReadAfterReaction(bool val); - void set_markReadAfterPoll(bool val); - void set_useScheduledMessages(bool val); void set_saveDeletedMessages(bool val); - void set_saveMessagesHistory(bool val); void set_disableAds(bool val); - void set_disableStories(bool val); - void set_collapseSimilarChannels(bool val); - void set_hideSimilarChannels(bool val); - void set_disableNotificationsDelay(bool val); - void set_localPremium(bool val); - void set_copyUsernameAsLink(bool val); void set_appIcon(QString val); - void set_simpleQuotesAndReplies(bool val); - void set_deletedMark(QString val); - void set_editedMark(QString val); - void set_recentStickersCount(int val); + void set_showReactionsPanelInContextMenu(int val); + void set_showViewsPanelInContextMenu(int val); + void set_showHideMessageInContextMenu(int val); + void set_showUserMessagesInContextMenu(int val); + void set_showMessageDetailsInContextMenu(int val); + void set_showLReadToggleInDrawer(bool val); - void set_showSReadToggleInDrawer(bool val); - void set_showGhostToggleInDrawer(bool val); - void set_showStreamerToggleInDrawer(bool val); void set_showGhostToggleInTray(bool val); - void set_showStreamerToggleInTray(bool val); void set_mainFont(QString val); - void set_monoFont(QString val); void set_showPeerId(int val); - void set_showMessageSeconds(bool val); - void set_hideAllChatsFolder(bool val); void set_stickerConfirmation(bool val); - void set_gifConfirmation(bool val); - void set_voiceConfirmation(bool val); }; @@ -235,6 +238,11 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( deletedMark, editedMark, recentStickersCount, + showReactionsPanelInContextMenu, + showViewsPanelInContextMenu, + showHideMessageInContextMenu, + showUserMessagesInContextMenu, + showMessageDetailsInContextMenu, showLReadToggleInDrawer, showSReadToggleInDrawer, showGhostToggleInDrawer, @@ -254,17 +262,14 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( AyuGramSettings &getInstance(); void load(); - void save(); rpl::producer get_deletedMarkReactive(); - rpl::producer get_editedMarkReactive(); rpl::producer get_showPeerIdReactive(); bool get_ghostModeEnabled(); - rpl::producer get_ghostModeEnabledReactive(); } diff --git a/Telegram/SourceFiles/ayu/ayu_state.cpp b/Telegram/SourceFiles/ayu/ayu_state.cpp index c8e84144a..e0bbff720 100644 --- a/Telegram/SourceFiles/ayu/ayu_state.cpp +++ b/Telegram/SourceFiles/ayu/ayu_state.cpp @@ -8,4 +8,31 @@ namespace AyuState { + +std::unordered_map> hiddenMessages; + +void hide(PeerId peerId, MsgId messageId) +{ + hiddenMessages[peerId].insert(messageId); +} + +void hide(not_null item) +{ + hide(item->history()->peer->id, item->id); +} + +bool isHidden(PeerId peerId, MsgId messageId) +{ + auto it = hiddenMessages.find(peerId); + if (it != hiddenMessages.end()) { + return it->second.find(messageId) != it->second.end(); + } + return false; +} + +bool isHidden(not_null item) +{ + return isHidden(item->history()->peer->id, item->id); +} + } diff --git a/Telegram/SourceFiles/ayu/ayu_state.h b/Telegram/SourceFiles/ayu/ayu_state.h index dc890b91e..425164462 100644 --- a/Telegram/SourceFiles/ayu/ayu_state.h +++ b/Telegram/SourceFiles/ayu/ayu_state.h @@ -8,37 +8,15 @@ #include "ayu_settings.h" +#include "history/history.h" +#include "history/history_item.h" + namespace AyuState { -namespace -{ - -class AyuStateVariable -{ -public: - bool val; - int resetAfter; -}; - -AyuStateVariable allowSendReadPacket; - -bool processVariable(AyuStateVariable &variable) -{ - if (variable.resetAfter == -1) { - return variable.val; - } - - variable.resetAfter -= 1; - auto val = variable.val; - - if (variable.resetAfter == 0) { - variable.val = false; - } - - return val; -} - -} +void hide(PeerId peerId, MsgId messageId); +void hide(not_null item); +bool isHidden(PeerId peerId, MsgId messageId); +bool isHidden(not_null item); } diff --git a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp index e7810b591..8478596d1 100644 --- a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp +++ b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.cpp @@ -5,13 +5,18 @@ // // Copyright @Radolyn, 2023 #include "ayu/ui/context_menu/context_menu.h" +#include "ayu/utils/qt_key_modifiers_extended.h" +#include "history/history_item_components.h" #include "lang_auto.h" #include "ayu/ayu_state.h" #include "ayu/messages/ayu_messages_controller.h" -#include "ayu/ui/boxes/message_history_box.h" +#include "ayu/ui/context_menu/menu_item_subtext.h" #include "mainwidget.h" +#include "core/mime_type.h" #include "styles/style_ayu_icons.h" +#include "window/window_peer_menu.h" +#include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/widgets/popup_menu.h" #include "ayu/ui/sections/edited/edited_log_section.h" @@ -21,6 +26,11 @@ namespace AyuUi { +bool needToShowItem(int state) +{ + return state == 1 || state == 2 && base::IsExtendedContextMenuModifierPressed(); +} + void AddHistoryAction(not_null menu, HistoryItem *item) { if (AyuMessages::getInstance().hasRevisions(item)) { @@ -34,21 +44,28 @@ void AddHistoryAction(not_null menu, HistoryItem *item) void AddHideMessageAction(not_null menu, HistoryItem *item) { - // todo: rework -// const auto settings = &AyuSettings::getInstance(); -// const auto history = item->history(); -// menu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]() -// { -// const auto initSaveDeleted = settings->saveDeletedMessages; -// -// settings->set_saveDeletedMessages(false); -// history->destroyMessage(item); -// settings->set_saveDeletedMessages(initSaveDeleted); -// }, &st::menuIconClear); + const auto settings = &AyuSettings::getInstance(); + if (!needToShowItem(settings->showHideMessageInContextMenu)) { + return; + } + + const auto history = item->history(); + menu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]() + { + item->destroy(); + history->requestChatListMessage(); + + AyuState::hide(item); + }, &st::menuIconClear); } void AddUserMessagesAction(not_null menu, HistoryItem *item) { + const auto settings = &AyuSettings::getInstance(); + if (!needToShowItem(settings->showUserMessagesInContextMenu)) { + return; + } + if (item->history()->peer->isChat() || item->history()->peer->isMegagroup()) { menu->addAction(tr::ayu_UserMessagesMenuText(tr::now), [=] { @@ -60,15 +77,202 @@ void AddUserMessagesAction(not_null menu, HistoryItem *item) ? Dialogs::Key{item->topic()} : Dialogs::Key{item->history()} : Dialogs::Key(); - mainWidget->content()->searchMessages("", key, item->from()->asUser()); + mainWidget->content()->searchMessages(QString(), key, item->from()->asUser()); } } - }, &st::menuIconInfo); + }, &st::menuIconTTL); } } +void AddMessageDetailsAction(not_null menu, HistoryItem *item) +{ + const auto settings = &AyuSettings::getInstance(); + if (!needToShowItem(settings->showMessageDetailsInContextMenu)) { + return; + } + + if (item->isLocal()) { + return; + } + + const auto view = item->mainView(); + const auto forwarded = item->Get(); + const auto views = item->Get(); + const auto media = item->media(); + + const auto isSticker = media && media->document() && media->document()->sticker(); + const auto isForwarded = forwarded && !forwarded->story && forwarded->psaType.isEmpty(); + + const auto messageId = QString::number(item->id.bare); + const auto messageDate = base::unixtime::parse(item->date()); + const auto messageEditDate = base::unixtime::parse(view ? view->displayedEditDate() : TimeId(0)); + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "NullDereference" + const auto messageForwardedDate = + isForwarded ? base::unixtime::parse(forwarded->originalDate) + : QDateTime(); +#pragma clang diagnostic pop + + const auto + messageViews = item->hasViews() && item->viewsCount() > 0 ? QString::number(item->viewsCount()) : QString(); + const auto messageForwards = views && views->forwardsCount > 0 ? QString::number(views->forwardsCount) : QString(); + + const auto mediaSize = media ? getMediaSize(item) : QString(); + const auto mediaMime = media ? getMediaMime(item) : QString(); + // todo: bitrate (?) + const auto mediaName = media ? getMediaName(item) : QString(); + const auto mediaResolution = media ? getMediaResolution(item) : QString(); + const auto mediaDC = media ? getMediaDC(item) : QString(); + + const auto hasAnyPostField = + !messageViews.isEmpty() || + !messageForwards.isEmpty(); + + const auto hasAnyMediaField = + !mediaSize.isEmpty() || + !mediaMime.isEmpty() || + !mediaName.isEmpty() || + !mediaResolution.isEmpty() || + !mediaDC.isEmpty(); + + const auto callback = Ui::Menu::CreateAddActionCallback(menu); + + callback(Window::PeerMenuCallback::Args{ + .text = tr::ayu_MessageDetailsPC(tr::now), + .handler = nullptr, + .icon = &st::menuIconInfo, + .fillSubmenu = [&](not_null menu2) + { + if (hasAnyPostField) { + if (!messageViews.isEmpty()) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconShowInChat, + tr::ayu_MessageDetailsViewsPC(tr::now), + messageViews + )); + } + + if (!messageForwards.isEmpty()) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconViewReplies, + tr::ayu_MessageDetailsSharesPC(tr::now), + messageForwards + )); + } + + menu2->addSeparator(); + } + + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconInfo, + QString("ID"), + messageId + )); + + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconSchedule, + tr::ayu_MessageDetailsDatePC(tr::now), + formatDateTime(messageDate) + )); + + if (view && view->displayedEditDate()) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconEdit, + tr::ayu_MessageDetailsEditedDatePC(tr::now), + formatDateTime(messageEditDate) + )); + } + + if (isForwarded) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconTTL, + tr::ayu_MessageDetailsForwardedDatePC(tr::now), + formatDateTime(messageForwardedDate) + )); + } + + if (media && hasAnyMediaField) { + menu2->addSeparator(); + + if (!mediaSize.isEmpty()) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconDownload, + tr::ayu_MessageDetailsFileSizePC(tr::now), + mediaSize + )); + } + + if (!mediaMime.isEmpty()) { + const auto mime = Core::MimeTypeForName(mediaMime); + + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconShowAll, + tr::ayu_MessageDetailsMimeTypePC(tr::now), + mime.name() + )); + } + + if (!mediaName.isEmpty()) { + auto const shortified = mediaName.length() > 20 ? "…" + mediaName.right(20) : mediaName; + + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::ayuEditsHistoryIcon, + tr::ayu_MessageDetailsFileNamePC(tr::now), + shortified, + [=] + { + QGuiApplication::clipboard()->setText(mediaName); + } + )); + } + + if (!mediaResolution.isEmpty()) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconStats, + tr::ayu_MessageDetailsResolutionPC(tr::now), + mediaResolution + )); + } + + if (!mediaDC.isEmpty()) { + menu2->addAction(Ui::ContextActionWithSubText( + menu2->menu(), + st::menuIconBoosts, + tr::ayu_MessageDetailsDatacenterPC(tr::now), + mediaDC + )); + } + + if (isSticker) { + const auto authorId = media->document()->sticker()->set.id >> 32; + menu2->addAction(Ui::ContextActionStickerAuthor( + menu2->menu(), + &item->history()->session(), + authorId + )); + } + } + }, + }); +} + void AddReadUntilAction(not_null menu, HistoryItem *item) { + if (item->isLocal()) { + return; + } + const auto settings = &AyuSettings::getInstance(); if (settings->sendReadMessages) { return; diff --git a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h index 3ae393840..3f3826662 100644 --- a/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h +++ b/Telegram/SourceFiles/ayu/ui/context_menu/context_menu.h @@ -78,17 +78,23 @@ #include "history/view/history_view_context_menu.h" #include "ayu/ayu_settings.h" +#include "ayu/utils/qt_key_modifiers_extended.h" + #include "styles/style_info.h" namespace AyuUi { +bool needToShowItem(int state); + void AddHistoryAction(not_null menu, HistoryItem *item); void AddHideMessageAction(not_null menu, HistoryItem *item); void AddUserMessagesAction(not_null menu, HistoryItem *item); +void AddMessageDetailsAction(not_null menu, HistoryItem *item); + void AddReadUntilAction(not_null menu, HistoryItem *item); } diff --git a/Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.cpp b/Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.cpp new file mode 100644 index 000000000..e71cdeeb4 --- /dev/null +++ b/Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.cpp @@ -0,0 +1,301 @@ +// This is the source code of AyuGram for Desktop. +// +// We do not and cannot prevent the use of our code, +// but be respectful and credit the original author. +// +// Copyright @Radolyn, 2023 +#include + +#include "ayu/ui/context_menu/menu_item_subtext.h" + +#include "ayu/utils/telegram_helpers.h" +#include "ayu/database/entities.h" +#include "mainwindow.h" +#include "qguiapplication.h" + +#include "ui/widgets/menu/menu_action.h" +#include "ui/effects/ripple_animation.h" +#include "ui/painter.h" +#include "data/data_user.h" +#include "lang/lang_keys.h" +#include "base/unixtime.h" +#include "styles/style_chat.h" +#include "styles/style_menu_icons.h" +#include "window/window_session_controller.h" + +namespace Ui +{ +namespace +{ + +class ActionWithSubText : public Menu::ItemBase +{ +public: + ActionWithSubText( + not_null parent, + const style::Menu &st, + const style::icon &icon, + Fn callback, + const QString &title, + QString subtext); + + bool isEnabled() const override; + not_null action() const override; + + void handleKeyPress(not_null e) override; + +protected: + QPoint prepareRippleStartPosition() const override; + QImage prepareRippleMask() const override; + + int contentHeight() const override; + + void prepare(const QString &title); + void paint(Painter &p); + + const not_null _dummyAction; + const style::Menu &_st; + const style::icon &_icon; + + Text::String _title; + int _textWidth = 0; + QString _subText; + const int _height; + +}; + +class ActionStickerPackAuthor final : public ActionWithSubText +{ +public: + ActionStickerPackAuthor(not_null menu, not_null session, ID authorId); + +private: + not_null _session; + + void searchAuthor(ID authorId); +}; + +TextParseOptions MenuTextOptions = { + TextParseLinks, // flags + 0, // maxw + 0, // maxh + Qt::LayoutDirectionAuto, // dir +}; + +ActionWithSubText::ActionWithSubText( + not_null parent, + const style::Menu &st, + const style::icon &icon, + Fn callback, + const QString &title, + QString subtext) + : ItemBase(parent, st), + _dummyAction(new QAction(parent)), + _st(st), + _icon(icon), + _subText(std::move(subtext)), + _height(st::ttlItemPadding.top() + + _st.itemStyle.font->height + + st::ttlItemTimerFont->height + + st::ttlItemPadding.bottom()) +{ + setAcceptBoth(true); + initResizeHook(parent->sizeValue()); + setClickedCallback(std::move(callback)); + + paintRequest( + ) | rpl::start_with_next([=] + { + Painter p(this); + paint(p); + }, lifetime()); + + enableMouseSelecting(); + prepare(title); +} + +void ActionWithSubText::paint(Painter &p) +{ + const auto selected = isSelected(); + if (selected && _st.itemBgOver->c.alpha() < 255) { + p.fillRect(0, 0, width(), _height, _st.itemBg); + } + p.fillRect(0, 0, width(), _height, selected ? _st.itemBgOver : _st.itemBg); + if (isEnabled()) { + paintRipple(p, 0, 0); + } + + const auto normalHeight = _st.itemPadding.top() + + _st.itemStyle.font->height + + _st.itemPadding.bottom(); + const auto deltaHeight = _height - normalHeight; + _icon.paint( + p, + _st.itemIconPosition + QPoint(0, deltaHeight / 2), + width()); + + p.setPen(selected ? _st.itemFgOver : _st.itemFg); + _title.drawLeftElided( + p, + _st.itemPadding.left(), + st::ttlItemPadding.top(), + _textWidth, + width()); + + p.setFont(st::ttlItemTimerFont); + p.setPen(selected ? _st.itemFgShortcutOver : _st.itemFgShortcut); + p.drawTextLeft( + _st.itemPadding.left(), + st::ttlItemPadding.top() + _st.itemStyle.font->height, + width(), + _subText); +} + +void ActionWithSubText::prepare(const QString &title) +{ + _title.setMarkedText( + _st.itemStyle, + {title}, + MenuTextOptions); + const auto textWidth = _title.maxWidth(); + const auto &padding = _st.itemPadding; + + const auto goodWidth = padding.left() + + textWidth + + padding.right(); + const auto subTextMaxWidth = padding.left() + + st::ttlItemTimerFont->width(_subText) + + padding.right(); + + const auto w = std::clamp( + std::max({goodWidth, subTextMaxWidth}), + _st.widthMin, + _st.widthMax); + _textWidth = w - (goodWidth - textWidth); + setMinWidth(w); + update(); +} + +bool ActionWithSubText::isEnabled() const +{ + return true; +} + +not_null ActionWithSubText::action() const +{ + return _dummyAction; +} + +QPoint ActionWithSubText::prepareRippleStartPosition() const +{ + return mapFromGlobal(QCursor::pos()); +} + +QImage ActionWithSubText::prepareRippleMask() const +{ + return Ui::RippleAnimation::RectMask(size()); +} + +int ActionWithSubText::contentHeight() const +{ + return _height; +} + +void ActionWithSubText::handleKeyPress(not_null e) +{ + if (!isSelected()) { + return; + } + const auto key = e->key(); + if (key == Qt::Key_Enter || key == Qt::Key_Return) { + setClicked(Menu::TriggeredSource::Keyboard); + } +} + +ActionStickerPackAuthor::ActionStickerPackAuthor(not_null menu, + not_null session, + ID authorId) + : ActionWithSubText(menu, menu->st(), st::menuIconStickers, [=] +{ }, tr::ayu_MessageDetailsPackOwnerPC(tr::now), tr::ayu_MessageDetailsPackOwnerFetchingPC(tr::now)), + _session(session) +{ + searchAuthor(authorId); +} + +void ActionStickerPackAuthor::searchAuthor(ID authorId) +{ + searchById(authorId, _session, [=](const QString &username, UserData *user) + { + if (username.isEmpty() && !user) { + _subText = tr::ayu_MessageDetailsPackOwnerNotFoundPC(tr::now); + setClickedCallback([=] { + const auto text = QString("int32: %1\nint64: %2").arg(authorId).arg(0x100000000L + authorId); + QGuiApplication::clipboard()->setText(text); + }); + + crl::on_main([=] + { + update(); + }); + return; + } + + const auto title = username.isEmpty() ? user ? user->name() : QString() : username; + const auto callback = [=] + { + if (user) { + if (const auto window = _session->tryResolveWindow()) { + if (const auto mainWidget = window->widget()->sessionController()) { + mainWidget->showPeer(user); + } + } + } + else { + QGuiApplication::clipboard()->setText(title); + } + }; + + setClickedCallback(callback); + + _subText = title; + crl::on_main([=] + { + update(); + }); + }); +} + +} // namespace + +base::unique_qptr ContextActionWithSubText( + not_null menu, + const style::icon &icon, + const QString &title, + const QString &subtext, + Fn callback) +{ + if (!callback) { + callback = [=]() + { + QGuiApplication::clipboard()->setText(subtext); + }; + } + + return base::make_unique_q( + menu, + menu->st(), + icon, + std::move(callback), + title, + subtext); +} + +base::unique_qptr ContextActionStickerAuthor( + not_null menu, + not_null session, + ID authorId) +{ + return base::make_unique_q(menu, session, authorId); +} + +} // namespace Ui diff --git a/Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.h b/Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.h new file mode 100644 index 000000000..464c2d2bf --- /dev/null +++ b/Telegram/SourceFiles/ayu/ui/context_menu/menu_item_subtext.h @@ -0,0 +1,36 @@ +// This is the source code of AyuGram for Desktop. +// +// We do not and cannot prevent the use of our code, +// but be respectful and credit the original author. +// +// Copyright @Radolyn, 2023 +#pragma once + +#include "ayu/database/entities.h" +#include "main/main_session.h" + +#include "base/unique_qptr.h" + +namespace Ui +{ +namespace Menu +{ +class Menu; +class ItemBase; +} // namespace Menu + +class PopupMenu; + +[[nodiscard]] base::unique_qptr ContextActionWithSubText( + not_null menu, + const style::icon &icon, + const QString &title, + const QString &subtext, + Fn callback = nullptr); + +[[nodiscard]] base::unique_qptr ContextActionStickerAuthor( + not_null menu, + not_null session, + ID authorId); + +} // namespace Ui diff --git a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp index f4de6a2d9..9772f2a5a 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp @@ -28,6 +28,7 @@ #include "styles/style_basic.h" #include "styles/style_boxes.h" #include "styles/style_info.h" +#include "styles/style_menu_icons.h" #include "styles/style_settings.h" #include "styles/style_widgets.h" #include "styles/style_ayu_styles.h" @@ -333,6 +334,50 @@ void AddCollapsibleToggle(not_null container, }, raw->lifetime()); } +void AddChooseButtonWithIconAndRightText(not_null container, + not_null controller, + int initialState, + std::vector options, + rpl::producer text, + rpl::producer boxTitle, + const style::icon &icon, + const Fn &setter) +{ + auto reactiveVal = container->lifetime().make_state>(initialState); + + rpl::producer rightTextReactive = reactiveVal->value() | rpl::map( + [=](int val) + { + return options[val]; + }); + + Settings::AddButtonWithLabel( + container, + std::move(text), + rightTextReactive, + st::settingsButton, + {&icon})->addClickHandler( + [=] + { + controller->show(Box( + [=](not_null box) + { + const auto save = [=](int index) mutable + { + setter(index); + + reactiveVal->force_assign(index); + }; + SingleChoiceBox(box, { + .title = boxTitle, + .options = options, + .initialSelection = reactiveVal->current(), + .callback = save, + }); + })); + }); +} + namespace Settings { @@ -436,22 +481,25 @@ void Ayu::SetupGhostEssentials(not_null container) AddButtonWithIcon( container, - tr::ayu_UseScheduledMessages() | rpl::map([=](QString val) - { - return val + " β"; - }), + tr::ayu_UseScheduledMessages() | rpl::map( + [=](QString val) + { + return val + " β"; + }), st::settingsButtonNoIcon )->toggleOn( rpl::single(settings->useScheduledMessages) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->useScheduledMessages); - }) | start_with_next([=](bool enabled) - { - settings->set_useScheduledMessages(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->useScheduledMessages); + }) | start_with_next( + [=](bool enabled) + { + settings->set_useScheduledMessages(enabled); + AyuSettings::save(); + }, container->lifetime()); } void Ayu::SetupSpyEssentials(not_null container) @@ -462,22 +510,25 @@ void Ayu::SetupSpyEssentials(not_null container) AddButtonWithIcon( container, - tr::ayu_SaveDeletedMessages() | rpl::map([=](QString val) - { - return val + " β"; - }), + tr::ayu_SaveDeletedMessages() | rpl::map( + [=](QString val) + { + return val + " β"; + }), st::settingsButtonNoIcon )->toggleOn( rpl::single(settings->saveDeletedMessages) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->saveDeletedMessages); - }) | start_with_next([=](bool enabled) - { - settings->set_saveDeletedMessages(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->saveDeletedMessages); + }) | start_with_next( + [=](bool enabled) + { + settings->set_saveDeletedMessages(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -486,14 +537,16 @@ void Ayu::SetupSpyEssentials(not_null container) )->toggleOn( rpl::single(settings->saveMessagesHistory) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->saveMessagesHistory); - }) | start_with_next([=](bool enabled) - { - settings->set_saveMessagesHistory(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->saveMessagesHistory); + }) | start_with_next( + [=](bool enabled) + { + settings->set_saveMessagesHistory(enabled); + AyuSettings::save(); + }, container->lifetime()); } void Ayu::SetupQoLToggles(not_null container) @@ -509,14 +562,16 @@ void Ayu::SetupQoLToggles(not_null container) )->toggleOn( rpl::single(settings->disableAds) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->disableAds); - }) | start_with_next([=](bool enabled) - { - settings->set_disableAds(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->disableAds); + }) | start_with_next( + [=](bool enabled) + { + settings->set_disableAds(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -525,14 +580,16 @@ void Ayu::SetupQoLToggles(not_null container) )->toggleOn( rpl::single(settings->disableStories) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->disableStories); - }) | start_with_next([=](bool enabled) - { - settings->set_disableStories(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->disableStories); + }) | start_with_next( + [=](bool enabled) + { + settings->set_disableStories(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -541,14 +598,16 @@ void Ayu::SetupQoLToggles(not_null container) )->toggleOn( rpl::single(settings->simpleQuotesAndReplies) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->simpleQuotesAndReplies); - }) | start_with_next([=](bool enabled) - { - settings->set_simpleQuotesAndReplies(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->simpleQuotesAndReplies); + }) | start_with_next( + [=](bool enabled) + { + settings->set_simpleQuotesAndReplies(enabled); + AyuSettings::save(); + }, container->lifetime()); std::vector checkboxes = { NestedEntry{ @@ -580,14 +639,16 @@ void Ayu::SetupQoLToggles(not_null container) )->toggleOn( rpl::single(settings->disableNotificationsDelay) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->disableNotificationsDelay); - }) | start_with_next([=](bool enabled) - { - settings->set_disableNotificationsDelay(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->disableNotificationsDelay); + }) | start_with_next( + [=](bool enabled) + { + settings->set_disableNotificationsDelay(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -596,14 +657,16 @@ void Ayu::SetupQoLToggles(not_null container) )->toggleOn( rpl::single(settings->localPremium) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->localPremium); - }) | start_with_next([=](bool enabled) - { - settings->set_localPremium(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->localPremium); + }) | start_with_next( + [=](bool enabled) + { + settings->set_localPremium(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -612,14 +675,16 @@ void Ayu::SetupQoLToggles(not_null container) )->toggleOn( rpl::single(settings->copyUsernameAsLink) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->copyUsernameAsLink); - }) | start_with_next([=](bool enabled) - { - settings->set_copyUsernameAsLink(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->copyUsernameAsLink); + }) | start_with_next( + [=](bool enabled) + { + settings->set_copyUsernameAsLink(enabled); + AyuSettings::save(); + }, container->lifetime()); } void Ayu::SetupAppIcon(not_null container) @@ -647,11 +712,12 @@ void Ayu::SetupCustomization(not_null container, AyuSettings::get_deletedMarkReactive(), st::settingsButtonNoIcon ); - btn->addClickHandler([=]() - { - auto box = Box(); - Ui::show(std::move(box)); - }); + btn->addClickHandler( + [=]() + { + auto box = Box(); + Ui::show(std::move(box)); + }); auto btn2 = AddButtonWithLabel( container, @@ -659,11 +725,12 @@ void Ayu::SetupCustomization(not_null container, AyuSettings::get_editedMarkReactive(), st::settingsButtonNoIcon ); - btn2->addClickHandler([=]() - { - auto box = Box(); - Ui::show(std::move(box)); - }); + btn2->addClickHandler( + [=]() + { + auto box = Box(); + Ui::show(std::move(box)); + }); AddSkip(container); AddDivider(container); @@ -684,14 +751,16 @@ void Ayu::SetupCustomization(not_null container, )->toggleOn( rpl::single(settings->hideAllChatsFolder) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->hideAllChatsFolder); - }) | start_with_next([=](bool enabled) - { - settings->set_hideAllChatsFolder(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->hideAllChatsFolder); + }) | start_with_next( + [=](bool enabled) + { + settings->set_hideAllChatsFolder(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -700,17 +769,20 @@ void Ayu::SetupCustomization(not_null container, )->toggleOn( rpl::single(settings->showMessageSeconds) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showMessageSeconds); - }) | start_with_next([=](bool enabled) - { - settings->set_showMessageSeconds(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showMessageSeconds); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showMessageSeconds(enabled); + AyuSettings::save(); + }, container->lifetime()); AddSkip(container); AddDivider(container); + SetupContextMenuElements(container, controller); SetupDrawerElements(container); AddSkip(container); AddDivider(container); @@ -721,6 +793,91 @@ void Ayu::SetupCustomization(not_null container, SetupFonts(container, controller); } +void Ayu::SetupContextMenuElements(not_null container, + not_null controller) +{ + auto settings = &AyuSettings::getInstance(); + + AddSkip(container); + AddSubsectionTitle(container, tr::ayu_ContextMenuElementsHeader()); + + const auto options = std::vector{ + tr::ayu_SettingsContextMenuItemHidden(tr::now), + tr::ayu_SettingsContextMenuItemShown(tr::now), + tr::ayu_SettingsContextMenuItemExtended(tr::now), + }; + + AddChooseButtonWithIconAndRightText( + container, + controller, + settings->showReactionsPanelInContextMenu, + options, + tr::ayu_SettingsContextMenuReactionsPanel(), + tr::ayu_SettingsContextMenuTitle(), + st::menuIconReactions, + [=](int index) + { + settings->set_showReactionsPanelInContextMenu(index); + AyuSettings::save(); + }); + AddChooseButtonWithIconAndRightText( + container, + controller, + settings->showViewsPanelInContextMenu, + options, + tr::ayu_SettingsContextMenuViewsPanel(), + tr::ayu_SettingsContextMenuTitle(), + st::menuIconShowInChat, + [=](int index) + { + settings->set_showViewsPanelInContextMenu(index); + AyuSettings::save(); + }); + + AddChooseButtonWithIconAndRightText( + container, + controller, + settings->showHideMessageInContextMenu, + options, + tr::ayu_ContextHideMessage(), + tr::ayu_SettingsContextMenuTitle(), + st::menuIconClear, + [=](int index) + { + settings->set_showHideMessageInContextMenu(index); + AyuSettings::save(); + }); + AddChooseButtonWithIconAndRightText( + container, + controller, + settings->showUserMessagesInContextMenu, + options, + tr::ayu_UserMessagesMenuText(), + tr::ayu_SettingsContextMenuTitle(), + st::menuIconTTL, + [=](int index) + { + settings->set_showUserMessagesInContextMenu(index); + AyuSettings::save(); + }); + AddChooseButtonWithIconAndRightText( + container, + controller, + settings->showMessageDetailsInContextMenu, + options, + tr::ayu_MessageDetailsPC(), + tr::ayu_SettingsContextMenuTitle(), + st::menuIconInfo, + [=](int index) + { + settings->set_showMessageDetailsInContextMenu(index); + AyuSettings::save(); + }); + + AddSkip(container); + AddDividerText(container, tr::ayu_SettingsContextMenuDescription()); +} + void Ayu::SetupDrawerElements(not_null container) { auto settings = &AyuSettings::getInstance(); @@ -736,14 +893,16 @@ void Ayu::SetupDrawerElements(not_null container) )->toggleOn( rpl::single(settings->showLReadToggleInDrawer) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showLReadToggleInDrawer); - }) | start_with_next([=](bool enabled) - { - settings->set_showLReadToggleInDrawer(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showLReadToggleInDrawer); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showLReadToggleInDrawer(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -753,14 +912,16 @@ void Ayu::SetupDrawerElements(not_null container) )->toggleOn( rpl::single(settings->showSReadToggleInDrawer) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showSReadToggleInDrawer); - }) | start_with_next([=](bool enabled) - { - settings->set_showSReadToggleInDrawer(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showSReadToggleInDrawer); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showSReadToggleInDrawer(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -770,14 +931,16 @@ void Ayu::SetupDrawerElements(not_null container) )->toggleOn( rpl::single(settings->showGhostToggleInDrawer) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showGhostToggleInDrawer); - }) | start_with_next([=](bool enabled) - { - settings->set_showGhostToggleInDrawer(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showGhostToggleInDrawer); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showGhostToggleInDrawer(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -787,14 +950,16 @@ void Ayu::SetupDrawerElements(not_null container) )->toggleOn( rpl::single(settings->showStreamerToggleInDrawer) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showStreamerToggleInDrawer); - }) | start_with_next([=](bool enabled) - { - settings->set_showStreamerToggleInDrawer(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showStreamerToggleInDrawer); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showStreamerToggleInDrawer(enabled); + AyuSettings::save(); + }, container->lifetime()); } void Ayu::SetupTrayElements(not_null container) @@ -811,14 +976,16 @@ void Ayu::SetupTrayElements(not_null container) )->toggleOn( rpl::single(settings->showGhostToggleInTray) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showGhostToggleInTray); - }) | start_with_next([=](bool enabled) - { - settings->set_showGhostToggleInTray(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showGhostToggleInTray); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showGhostToggleInTray(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -827,14 +994,16 @@ void Ayu::SetupTrayElements(not_null container) )->toggleOn( rpl::single(settings->showStreamerToggleInTray) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->showStreamerToggleInTray); - }) | start_with_next([=](bool enabled) - { - settings->set_showStreamerToggleInTray(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->showStreamerToggleInTray); + }) | start_with_next( + [=](bool enabled) + { + settings->set_showStreamerToggleInTray(enabled); + AyuSettings::save(); + }, container->lifetime()); } void Ayu::SetupShowPeerId(not_null container, @@ -848,33 +1017,36 @@ void Ayu::SetupShowPeerId(not_null container, QString("Bot API") }; - auto currentVal = AyuSettings::get_showPeerIdReactive() | rpl::map([=](int val) - { - return options[val]; - }); + auto currentVal = AyuSettings::get_showPeerIdReactive() | rpl::map( + [=](int val) + { + return options[val]; + }); const auto button = AddButtonWithLabel( container, tr::ayu_SettingsShowID(), currentVal, st::settingsButtonNoIcon); - button->addClickHandler([=] - { - controller->show(Box([=](not_null box) - { - const auto save = [=](int index) - { - settings->set_showPeerId(index); - AyuSettings::save(); - }; - SingleChoiceBox(box, { - .title = tr::ayu_SettingsShowID(), - .options = options, - .initialSelection = settings->showPeerId, - .callback = save, - }); - })); - }); + button->addClickHandler( + [=] + { + controller->show(Box( + [=](not_null box) + { + const auto save = [=](int index) + { + settings->set_showPeerId(index); + AyuSettings::save(); + }; + SingleChoiceBox(box, { + .title = tr::ayu_SettingsShowID(), + .options = options, + .initialSelection = settings->showPeerId, + .callback = save, + }); + })); + }); } void Ayu::SetupRecentStickersLimitSlider(not_null container) @@ -932,16 +1104,17 @@ void Ayu::SetupFonts(not_null container, not_null(commonButton.get()); - commonButton->addClickHandler([=] - { - *commonGuard = AyuUi::FontSelectorBox::Show(controller, [=](QString font) - { - auto ayuSettings = &AyuSettings::getInstance(); + commonButton->addClickHandler( + [=] + { + *commonGuard = AyuUi::FontSelectorBox::Show(controller, [=](QString font) + { + auto ayuSettings = &AyuSettings::getInstance(); - ayuSettings->set_mainFont(std::move(font)); - AyuSettings::save(); - }); - }); + ayuSettings->set_mainFont(std::move(font)); + AyuSettings::save(); + }); + }); const auto monoButton = AddButtonWithLabel( container, @@ -952,16 +1125,17 @@ void Ayu::SetupFonts(not_null container, not_null(monoButton.get()); - monoButton->addClickHandler([=] - { - *monoGuard = AyuUi::FontSelectorBox::Show(controller, [=](QString font) - { - auto ayuSettings = &AyuSettings::getInstance(); + monoButton->addClickHandler( + [=] + { + *monoGuard = AyuUi::FontSelectorBox::Show(controller, [=](QString font) + { + auto ayuSettings = &AyuSettings::getInstance(); - ayuSettings->set_monoFont(std::move(font)); - AyuSettings::save(); - }); - }); + ayuSettings->set_monoFont(std::move(font)); + AyuSettings::save(); + }); + }); } @@ -975,11 +1149,12 @@ void Ayu::SetupAyuSync(not_null container) container, text, st::settingsButtonNoIcon - )->addClickHandler([=] - { - auto controller = &AyuSync::getInstance(); - controller->initializeAgent(); - }); + )->addClickHandler( + [=] + { + auto controller = &AyuSync::getInstance(); + controller->initializeAgent(); + }); } void Ayu::SetupSendConfirmations(not_null container) @@ -995,14 +1170,16 @@ void Ayu::SetupSendConfirmations(not_null container) )->toggleOn( rpl::single(settings->stickerConfirmation) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->stickerConfirmation); - }) | start_with_next([=](bool enabled) - { - settings->set_stickerConfirmation(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->stickerConfirmation); + }) | start_with_next( + [=](bool enabled) + { + settings->set_stickerConfirmation(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -1011,14 +1188,16 @@ void Ayu::SetupSendConfirmations(not_null container) )->toggleOn( rpl::single(settings->gifConfirmation) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->gifConfirmation); - }) | start_with_next([=](bool enabled) - { - settings->set_gifConfirmation(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->gifConfirmation); + }) | start_with_next( + [=](bool enabled) + { + settings->set_gifConfirmation(enabled); + AyuSettings::save(); + }, container->lifetime()); AddButtonWithIcon( container, @@ -1027,14 +1206,16 @@ void Ayu::SetupSendConfirmations(not_null container) )->toggleOn( rpl::single(settings->voiceConfirmation) )->toggledValue( - ) | rpl::filter([=](bool enabled) - { - return (enabled != settings->voiceConfirmation); - }) | start_with_next([=](bool enabled) - { - settings->set_voiceConfirmation(enabled); - AyuSettings::save(); - }, container->lifetime()); + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->voiceConfirmation); + }) | start_with_next( + [=](bool enabled) + { + settings->set_voiceConfirmation(enabled); + AyuSettings::save(); + }, container->lifetime()); } void Ayu::SetupAyuGramSettings(not_null container, diff --git a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.h b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.h index a24724031..f330c2156 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.h +++ b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.h @@ -44,6 +44,9 @@ private: void SetupCustomization(not_null container, not_null controller); + void SetupContextMenuElements(not_null container, + not_null controller); + void SetupDrawerElements(not_null container); void SetupTrayElements(not_null container); diff --git a/Telegram/SourceFiles/ayu/utils/qt_key_modifiers_extended.h b/Telegram/SourceFiles/ayu/utils/qt_key_modifiers_extended.h new file mode 100644 index 000000000..799c3472a --- /dev/null +++ b/Telegram/SourceFiles/ayu/utils/qt_key_modifiers_extended.h @@ -0,0 +1,21 @@ +// This is the source code of AyuGram for Desktop. +// +// We do not and cannot prevent the use of our code, +// but be respectful and credit the original author. +// +// Copyright @Radolyn, 2023 +#pragma once + +#include "base/qt/qt_key_modifiers.h" + +namespace base { + +[[nodiscard]] inline bool IsShiftPressed() { + return (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier); +} + +[[nodiscard]] inline bool IsExtendedContextMenuModifierPressed() { + return IsShiftPressed() || IsCtrlPressed(); +} + +} // namespace base diff --git a/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp b/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp index 41d4cc1c2..1878d9d7c 100644 --- a/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp +++ b/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp @@ -10,10 +10,16 @@ #include "api/api_text_entities.h" +#include "core/mime_type.h" #include "data/data_channel.h" +#include "data/data_document_media.h" +#include "data/data_photo.h" +#include "data/data_photo_media.h" +#include "inline_bots/inline_bot_result.h" #include "lang_auto.h" #include "apiwrap.h" #include "data/data_forum.h" +#include "data/data_user.h" #include "data/data_forum_topic.h" #include "data/data_histories.h" #include "data/data_peer_id.h" @@ -21,10 +27,12 @@ #include "ayu/sync/models.h" #include "data/data_session.h" +#include "data/data_document.h" #include "history/history.h" #include "history/history_item.h" #include "history/history_unread_things.h" #include "data/data_histories.h" +#include "ui/text/format_values.h" // https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java std::unordered_set ayugram_channels = { @@ -328,4 +336,382 @@ QString formatTTL(int time) } return QString("🕓 %1s").arg(time); -} \ No newline at end of file +} + +QString getDCName(int dc) +{ + const auto getName = [=](int dc) + { + switch (dc) { + case 1: + case 3: return "Miami FL, USA"; + case 2: + case 4: return "Amsterdam, NL"; + case 5: return "Singapore, SG"; + default: return "UNKNOWN"; + } + }; + + if (dc < 1) { + return {"DC_UNKNOWN"}; + } + + return QString("DC%1, %2").arg(dc).arg(getName(dc)); +} + +QString getLocalizedAt() +{ + static const auto val = tr::lng_mediaview_date_time( + tr::now, + lt_date, + "", + lt_time, + ""); + return val; +} + +QString formatDateTime(const QDateTime &date) +{ + const auto locale = QLocale::system(); + const auto datePart = locale.toString(date.date(), QLocale::ShortFormat); + const auto timePart = locale.toString(date, "HH:mm:ss"); + + return datePart + getLocalizedAt() + timePart; +} + +QString getMediaSize(not_null message) +{ + if (!message->media()) { + return {}; + } + + const auto media = message->media(); + + const auto document = media->document(); + const auto photo = media->photo(); + + int64 size = -1; + if (document) { // any file + size = document->size; + } + else if (photo && photo->hasVideo()) { // video + size = photo->videoByteSize(Data::PhotoSize::Large); + if (size == 0) { + size = photo->videoByteSize(Data::PhotoSize::Small); + } + if (size == 0) { + size = photo->videoByteSize(Data::PhotoSize::Thumbnail); + } + } + else if (photo && !photo->hasVideo()) { // photo + size = photo->imageByteSize(Data::PhotoSize::Large); + if (size == 0) { + size = photo->imageByteSize(Data::PhotoSize::Small); + } + if (size == 0) { + size = photo->imageByteSize(Data::PhotoSize::Thumbnail); + } + } + + if (size == -1) { + return {}; + } + + return Ui::FormatSizeText(size); +} + +QString getMediaMime(not_null message) +{ + if (!message->media()) { + return {}; + } + + const auto media = message->media(); + + const auto document = media->document(); + const auto photo = media->photo(); + + if (document) { // any file + return document->mimeString(); + } + else if (photo && photo->hasVideo()) { // video + return "video/mp4"; + } + else if (photo && !photo->hasVideo()) { // photo + return "image/jpeg"; + } + + return {}; +} + +QString getMediaName(not_null message) +{ + if (!message->media()) { + return {}; + } + + const auto media = message->media(); + + const auto document = media->document(); + + if (document) { + return document->filename(); + } + + return {}; +} + +QString getMediaResolution(not_null message) +{ + if (!message->media()) { + return {}; + } + + const auto media = message->media(); + + const auto document = media->document(); + const auto photo = media->photo(); + + const auto formatQSize = [=](QSize size) + { + if (size.isNull() || size.isEmpty() || !size.isValid()) { + return QString(); + } + + return QString("%1x%2").arg(size.width()).arg(size.height()); + }; + + if (document) { + return formatQSize(document->dimensions); + } + else if (photo) { + auto result = photo->size(Data::PhotoSize::Large); + if (!result.has_value()) { + result = photo->size(Data::PhotoSize::Small); + } + if (!result.has_value()) { + result = photo->size(Data::PhotoSize::Thumbnail); + } + return result.has_value() ? formatQSize(result.value()) : QString(); + } + + return {}; +} + +QString getMediaDC(not_null message) +{ + if (!message->media()) { + return {}; + } + + const auto media = message->media(); + + const auto document = media->document(); + const auto photo = media->photo(); + + if (document) { + return getDCName(document->getDC()); + } + else if (photo) { + return getDCName(photo->getDC()); + } + + return {}; +} + +void resolveUser(ID userId, const QString &username, Main::Session *session, const Callback &callback) +{ + auto normalized = username.trimmed().toLower(); + if (normalized.isEmpty()) { + callback(QString(), nullptr); + return; + } + normalized = normalized.startsWith("@") ? normalized.mid(1) : normalized; + + if (normalized.isEmpty()) { + callback(QString(), nullptr); + return; + } + + session->api().request(MTPcontacts_ResolveUsername( + MTP_string(normalized) + )).done([=](const MTPcontacts_ResolvedPeer &result) + { + Expects(result.type() == mtpc_contacts_resolvedPeer); + + auto &data = result.c_contacts_resolvedPeer(); + session->data().processUsers(data.vusers()); + session->data().processChats(data.vchats()); + const auto peer = session->data().peerLoaded( + peerFromMTP(data.vpeer())); + if (const auto user = peer ? peer->asUser() : nullptr) { + if (user->id.value == userId) { + callback(normalized, user); + return; + } + } + + callback(normalized, nullptr); + }).fail([=] + { + callback(QString(), nullptr); + }).send(); +} + +void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cache, const Callback &callback) +{ + const auto botId = 1696868284; + const auto bot = session->data().userLoaded(botId); + + if (!bot) { + if (searchUserFlag) { + resolveUser(botId, "tgdb_bot", session, [=](const QString &title, UserData *data) + { + searchUser(userId, session, false, false, callback); + }); + } + else { + callback(QString(), nullptr); + } + return; + } + + session->api().request(MTPmessages_GetInlineBotResults( + MTP_flags(0), + bot->inputUser, + MTP_inputPeerEmpty(), + MTPInputGeoPoint(), + MTP_string(QString::number(userId)), + MTP_string("") + )).done([=](const MTPmessages_BotResults &result) + { + if (result.type() != mtpc_messages_botResults) { + callback(QString(), nullptr); + return; + } + auto &d = result.c_messages_botResults(); + session->data().processUsers(d.vusers()); + + auto &v = d.vresults().v; + auto queryId = d.vquery_id().v; + + auto added = 0; + for (const auto &res : v) { + const auto message = res.match( + [&](const MTPDbotInlineResult &data) + { + return &data.vsend_message(); + }, [&](const MTPDbotInlineMediaResult &data) + { + return &data.vsend_message(); + }); + + const auto text = message->match( + [&](const MTPDbotInlineMessageMediaAuto &data) + { + return QString(); + }, [&](const MTPDbotInlineMessageText &data) + { + return qs(data.vmessage()); + }, [&](const MTPDbotInlineMessageMediaGeo &data) + { + return QString(); + }, [&](const MTPDbotInlineMessageMediaVenue &data) + { + return QString(); + }, [&](const MTPDbotInlineMessageMediaContact &data) + { + return QString(); + }, [&](const MTPDbotInlineMessageMediaInvoice &data) + { + return QString(); + }, [&](const MTPDbotInlineMessageMediaWebPage &data) + { + return QString(); + }); + + if (text.isEmpty()) { + continue; + } + + ID id = 0; // 🆔 + QString title; // 🏷 + QString username; // 📧 + + for (const auto &line : text.split('\n')) { + if (line.startsWith("🆔")) { + id = line.mid(line.indexOf(':') + 1).toLongLong(); + } + else if (line.startsWith("🏷")) { + title = line.mid(line.indexOf(':') + 1); + } + else if (line.startsWith("📧")) { + username = line.mid(line.indexOf(':') + 1); + } + } + + if (id == 0) { + continue; + } + + if (id != userId) { + continue; + } + + if (!username.isEmpty()) { + resolveUser(id, username, session, [=](const QString &titleInner, UserData *data) + { + if (data) { + callback(titleInner, data); + } + else { + callback(title, nullptr); + } + }); + return; + } + + if (!title.isEmpty()) { + callback(title, nullptr); + } + } + + callback(QString(), nullptr); + }).fail([=] + { + callback(QString(), nullptr); + }).handleAllErrors().send(); +} + +void searchById(ID userId, Main::Session *session, bool retry, const Callback &callback) +{ + if (userId == 0) { + return; + } + + const auto dataLoaded = session->data().userLoaded(userId); + if (dataLoaded) { + callback(dataLoaded->username(), dataLoaded); + return; + } + + searchUser(userId, session, true, true, [=](const QString &title, UserData *data) + { + if (data && data->accessHash()) { + callback(title, data); + } + else { + if (retry) { + searchById(0x100000000 + userId, session, false, callback); + } + else { + callback(QString(), nullptr); + } + } + }); +} + +void searchById(ID userId, Main::Session *session, const Callback &callback) +{ + searchById(userId, session, true, callback); +} diff --git a/Telegram/SourceFiles/ayu/utils/telegram_helpers.h b/Telegram/SourceFiles/ayu/utils/telegram_helpers.h index 55c33b4ac..a2f05bd9c 100644 --- a/Telegram/SourceFiles/ayu/utils/telegram_helpers.h +++ b/Telegram/SourceFiles/ayu/utils/telegram_helpers.h @@ -14,6 +14,8 @@ #include "main/main_session.h" #include "dialogs/dialogs_main_list.h" +using Callback = Fn; + Main::Session *getSession(ID userId); bool accountExists(ID userId); void dispatchToMainThread(std::function callback, int delay = 0); @@ -32,3 +34,14 @@ void MarkAsReadThread(not_null thread); void readHistory(not_null message); QString formatTTL(int time); +QString formatDateTime(const QDateTime &date); + +QString getDCName(int dc); + +QString getMediaSize(not_null message); +QString getMediaMime(not_null message); +QString getMediaName(not_null message); +QString getMediaResolution(not_null message); +QString getMediaDC(not_null message); + +void searchById(ID userId, Main::Session *session, const Callback& callback); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index a452a3c2c..67e1a52e2 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -78,6 +78,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ayu/ayu_settings.h" #include "ayu/database/ayu_database.h" #include "ayu/messages/ayu_messages_controller.h" +#include "ayu/ayu_state.h" namespace Data { @@ -2353,6 +2354,11 @@ void Session::registerMessage(not_null item) { const auto peerId = item->history()->peer->id; const auto list = messagesListForInsert(peerId); const auto itemId = item->id; + + if (AyuState::isHidden(item)) { + return; + } + const auto i = list->find(itemId); if (i != list->end()) { LOG(("App Error: Trying to re-registerMessage().")); diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 027c84c50..a77b0ed6e 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -65,6 +65,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL // AyuGram includes #include "ayu/ayu_settings.h" +#include "ayu/ayu_state.h" namespace { @@ -1427,6 +1428,10 @@ void History::viewReplaced(not_null was, Element *now) { void History::addItemToBlock(not_null item) { Expects(!item->mainView()); + if (AyuState::isHidden(item)) { + return; + } + auto block = prepareBlockForAddingItem(); block->messages.push_back(item->createView(_delegateMixin->delegate())); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index a6a5bd81a..d78aec6ac 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2263,6 +2263,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { AyuUi::AddHistoryAction(_menu, item); AyuUi::AddHideMessageAction(_menu, item); AyuUi::AddUserMessagesAction(_menu, item); + AyuUi::AddMessageDetailsAction(_menu, item); }; const auto addPhotoActions = [&](not_null photo, HistoryItem *item) { const auto media = photo->activeMediaView(); diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 2e15f3ad1..a599e7f2c 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -961,6 +961,7 @@ void AddMessageActions( AyuUi::AddHistoryAction(menu, request.item); AyuUi::AddHideMessageAction(menu, request.item); AyuUi::AddUserMessagesAction(menu, request.item); + AyuUi::AddMessageDetailsAction(menu, request.item); } AddPostLinkAction(menu, request); @@ -972,8 +973,7 @@ void AddMessageActions( AddSelectionAction(menu, request, list); AddRescheduleAction(menu, request, list); - if (request.item) - { + if (request.item) { AyuUi::AddReadUntilAction(menu, request.item); } } @@ -1278,6 +1278,11 @@ void AddWhoReactedAction( not_null context, not_null item, not_null controller) { + const auto settings = &AyuSettings::getInstance(); + if (!AyuUi::needToShowItem(settings->showViewsPanelInContextMenu)) { + return; + } + const auto whoReadIds = std::make_shared(); const auto weak = Ui::MakeWeak(menu.get()); const auto participantChosen = [=](uint64 id) { diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 1d0a890b6..34b7a39e0 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -272,9 +272,11 @@ QString DateTooltipText(not_null view) { msgsigned->postAuthor); } } - dateText += '\n'; - dateText += "ID: "; - dateText += QString::number(item->id.bare); + if (!item->isLocal()) { // local messages have strange ID + dateText += '\n'; + dateText += "ID: "; + dateText += QString::number(item->id.bare); + } return dateText; } diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp index 0516e3d2b..496ab0484 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp @@ -29,6 +29,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_chat_helpers.h" #include "styles/style_chat.h" +// AyuGram includes +#include "ayu/ui/context_menu/context_menu.h" +#include "ayu/ayu_settings.h" + + namespace HistoryView::Reactions { namespace { @@ -932,6 +937,11 @@ bool AdjustMenuGeometryForSelector( not_null menu, QPoint desiredPosition, not_null selector) { + const auto settings = &AyuSettings::getInstance(); + if (!AyuUi::needToShowItem(settings->showReactionsPanelInContextMenu)) { + return false; + } + const auto useTransparency = selector->useTransparency(); const auto extend = useTransparency ? st::reactStripExtend @@ -1072,6 +1082,11 @@ AttachSelectorResult AttachSelectorToMenu( Fn chosen, Fn showPremiumPromo, IconFactory iconFactory) { + const auto settings = &AyuSettings::getInstance(); + if (!AyuUi::needToShowItem(settings->showReactionsPanelInContextMenu)) { + return AttachSelectorResult::Skipped; + } + const auto result = AttachSelectorToMenu( menu, desiredPosition, @@ -1117,6 +1132,11 @@ auto AttachSelectorToMenu( const Data::PossibleItemReactionsRef &reactions, IconFactory iconFactory) -> base::expected, AttachSelectorResult> { + const auto settings = &AyuSettings::getInstance(); + if (!AyuUi::needToShowItem(settings->showReactionsPanelInContextMenu)) { + return base::make_unexpected(AttachSelectorResult::Skipped); + } + if (reactions.recent.empty() && !reactions.morePremiumAvailable) { return base::make_unexpected(AttachSelectorResult::Skipped); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 400ca9c6c..143a347d1 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -88,10 +88,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -// AyuGram includes -#include "ayu/utils/telegram_helpers.h" - - enum StackItemType { HistoryStackItem, SectionStackItem,