From 10448bcc3d8e7da93152d318274f5e4f3d6699cb Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 18 Aug 2025 17:23:41 +0400 Subject: [PATCH] Support fileref refresh in saved music. --- Telegram/CMakeLists.txt | 4 +- Telegram/SourceFiles/apiwrap.cpp | 12 ++++++ .../SourceFiles/data/data_file_origin.cpp | 10 +++++ Telegram/SourceFiles/data/data_file_origin.h | 1 + .../SourceFiles/data/data_saved_music.cpp | 31 ++++++++++++--- Telegram/SourceFiles/data/data_saved_music.h | 3 +- .../history/history_inner_widget.cpp | 32 ++++----------- .../view/history_view_context_menu.cpp | 34 +--------------- ... => history_view_save_document_action.cpp} | 39 +++++++++++++++---- ....h => history_view_save_document_action.h} | 14 ++++++- .../info/media/info_media_list_widget.cpp | 24 ++++++------ 11 files changed, 116 insertions(+), 88 deletions(-) rename Telegram/SourceFiles/history/view/media/{history_view_save_audio_action.cpp => history_view_save_document_action.cpp} (73%) rename Telegram/SourceFiles/history/view/media/{history_view_save_audio_action.h => history_view_save_document_action.h} (72%) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 2d75c61ad5..96fc51d133 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -817,8 +817,8 @@ PRIVATE history/view/media/history_view_poll.h history/view/media/history_view_premium_gift.cpp history/view/media/history_view_premium_gift.h - history/view/media/history_view_save_audio_action.cpp - history/view/media/history_view_save_audio_action.h + history/view/media/history_view_save_document_action.cpp + history/view/media/history_view_save_document_action.h history/view/media/history_view_service_box.cpp history/view/media/history_view_service_box.h history/view/media/history_view_similar_channels.cpp diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index bc13e0774a..256dbdbfd3 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_forum_topic.h" #include "data/data_forum.h" #include "data/data_saved_messages.h" +#include "data/data_saved_music.h" #include "data/data_saved_sublist.h" #include "data/data_search_controller.h" #include "data/data_session.h" @@ -2479,6 +2480,17 @@ void ApiWrap::refreshFileReference( request(MTPmessages_GetScheduledMessages( item->history()->peer->input, MTP_vector(1, MTP_int(realId)))); + } else if (item->isSavedMusicItem()) { + const auto user = item->history()->peer->asUser(); + const auto media = item->media(); + const auto document = media ? media->document() : nullptr; + if (user && document) { + request(MTPusers_GetSavedMusicByID( + user->inputUser, + MTP_vector(1, document->mtpInput()))); + } else { + fail(); + } } else if (item->isBusinessShortcut()) { const auto &shortcuts = _session->data().shortcutMessages(); const auto realId = shortcuts.lookupId(item); diff --git a/Telegram/SourceFiles/data/data_file_origin.cpp b/Telegram/SourceFiles/data/data_file_origin.cpp index db84988af0..a543c601f9 100644 --- a/Telegram/SourceFiles/data/data_file_origin.cpp +++ b/Telegram/SourceFiles/data/data_file_origin.cpp @@ -204,6 +204,12 @@ struct FileReferenceAccumulator { void push(const MTPstories_Stories &data) { push(data.data().vstories()); } + void push(const MTPusers_SavedMusic &data) { + data.match([&](const MTPDusers_savedMusic &data) { + push(data.vdocuments()); + }, [](const MTPDusers_savedMusicNotModified &data) { + }); + } UpdatedFileReferences result; }; @@ -273,6 +279,10 @@ UpdatedFileReferences GetFileReferences(const MTPstories_Stories &data) { return GetFileReferencesHelper(data); } +UpdatedFileReferences GetFileReferences(const MTPusers_SavedMusic &data) { + return GetFileReferencesHelper(data); +} + UpdatedFileReferences GetFileReferences(const MTPMessageMedia &data) { return GetFileReferencesHelper(data); } diff --git a/Telegram/SourceFiles/data/data_file_origin.h b/Telegram/SourceFiles/data/data_file_origin.h index 33e6a3f0d7..283a0fe034 100644 --- a/Telegram/SourceFiles/data/data_file_origin.h +++ b/Telegram/SourceFiles/data/data_file_origin.h @@ -221,6 +221,7 @@ UpdatedFileReferences GetFileReferences( UpdatedFileReferences GetFileReferences(const MTPhelp_PremiumPromo &data); UpdatedFileReferences GetFileReferences(const MTPmessages_WebPage &data); UpdatedFileReferences GetFileReferences(const MTPstories_Stories &data); +UpdatedFileReferences GetFileReferences(const MTPusers_SavedMusic &data); // Admin Log Event. UpdatedFileReferences GetFileReferences(const MTPMessageMedia &data); diff --git a/Telegram/SourceFiles/data/data_saved_music.cpp b/Telegram/SourceFiles/data/data_saved_music.cpp index 4ae5963ab9..0d0e9d325e 100644 --- a/Telegram/SourceFiles/data/data_saved_music.cpp +++ b/Telegram/SourceFiles/data/data_saved_music.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "base/unixtime.h" #include "data/data_document.h" +#include "data/data_file_origin.h" #include "data/data_peer.h" #include "data/data_session.h" #include "data/data_user.h" @@ -94,7 +95,9 @@ bool SavedMusic::has(not_null document) const { return ranges::contains(_myIds, document->id); } -void SavedMusic::save(not_null document) { +void SavedMusic::save( + not_null document, + Data::FileOrigin origin) { const auto peerId = _owner->session().userPeerId(); auto &entry = _entries[peerId]; if (entry.list.empty() && !entry.loaded) { @@ -109,11 +112,27 @@ void SavedMusic::save(not_null document) { ++entry.total; } _myIds.insert(begin(_myIds), document->id); - _owner->session().api().request(MTPaccount_SaveMusic( - MTP_flags(0), - document->mtpInput(), - MTPInputDocument() - )).send(); + + const auto send = [=](auto resend) -> void { + const auto usedFileReference = document->fileReference(); + _owner->session().api().request(MTPaccount_SaveMusic( + MTP_flags(0), + document->mtpInput(), + MTPInputDocument() + )).fail([=](const MTP::Error &error) { + if (error.code() == 400 + && error.type().startsWith(u"FILE_REFERENCE_"_q)) { + document->session().api().refreshFileReference(origin, [=]( + const auto &) { + if (document->fileReference() != usedFileReference) { + resend(resend); + } + }); + } + }).send(); + }; + send(send); + _changed.fire_copy(peerId); } diff --git a/Telegram/SourceFiles/data/data_saved_music.h b/Telegram/SourceFiles/data/data_saved_music.h index 28c77d11f2..e3711f901e 100644 --- a/Telegram/SourceFiles/data/data_saved_music.h +++ b/Telegram/SourceFiles/data/data_saved_music.h @@ -16,6 +16,7 @@ class PeerData; namespace Data { class Session; +struct FileOrigin; class SavedMusic final { public: @@ -34,7 +35,7 @@ public: void loadIds(); [[nodiscard]] bool has(not_null document) const; - void save(not_null document); + void save(not_null document, FileOrigin origin); void remove(not_null document); void apply(not_null user, const MTPDocument *last); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index cc87f6f5b3..2a938e5bff 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/controls/history_view_forward_panel.h" #include "history/view/controls/history_view_draft_options.h" #include "history/view/controls/history_view_suggest_options.h" -#include "history/view/media/history_view_save_audio_action.h" +#include "history/view/media/history_view_save_document_action.h" #include "history/view/media/history_view_sticker.h" #include "history/view/media/history_view_web_page.h" #include "history/view/reactions/history_view_reactions.h" @@ -2513,9 +2513,6 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { return; } const auto itemId = item ? item->fullId() : FullMsgId(); - const auto lnkIsVideo = document->isVideoFile(); - const auto lnkIsVoice = document->isVoiceMessage(); - const auto lnkIsAudio = document->isAudioFile(); if (document->isGifv()) { const auto notAutoplayedGif = [&] { return item @@ -2548,26 +2545,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { item, document, controller); - if (lnkIsAudio) { - HistoryView::AddSaveAudioAction( - Ui::Menu::CreateAddActionCallback(_menu), - item, - document, - controller); - } else { - const auto text = 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); - const auto &ripple = st::defaultDropdownMenu.menu.ripple; - const auto duration = ripple.hideDuration; - _menu->addAction(text, base::fn_delayed(duration, this, [=] { - saveDocumentToFile(itemId, document); - }), &st::menuIconDownload); - } + HistoryView::AddSaveDocumentAction( + Ui::Menu::CreateAddActionCallback(_menu), + item, + document, + controller); HistoryView::AddCopyFilename( _menu, document, @@ -2581,7 +2563,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { }, &st::menuIconStickers); } if (item - && (lnkIsVoice || document->isVideoMessage()) + && (document->isVoiceMessage() || document->isVideoMessage()) && Menu::HasRateTranscribeItem(item)) { rateTranscriptionItem = item; } diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 53017e65de..476e8b5f8b 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_text.h" #include "history/view/history_view_schedule_box.h" #include "history/view/media/history_view_media.h" +#include "history/view/media/history_view_save_document_action.h" #include "history/view/media/history_view_web_page.h" #include "history/view/reactions/history_view_reactions_list.h" #include "info/info_memento.h" @@ -236,39 +237,6 @@ void ShowInFolder(not_null document) { } } -void AddSaveDocumentAction( - not_null menu, - HistoryItem *item, - not_null document, - not_null list) { - if (list->hasCopyMediaRestriction(item) || ItemHasTtl(item)) { - return; - } - const auto origin = item ? item->fullId() : FullMsgId(); - const auto save = [=] { - DocumentSaveClickHandler::SaveAndTrack( - origin, - document, - DocumentSaveClickHandler::Mode::ToNewFile); - }; - - menu->addAction( - (document->isVideoFile() - ? tr::lng_context_save_video(tr::now) - : (document->isVoiceMessage() - ? tr::lng_context_save_audio(tr::now) - : (document->isAudioFile() - ? tr::lng_context_save_audio_file(tr::now) - : (document->sticker() - ? tr::lng_context_save_image(tr::now) - : tr::lng_context_save_file(tr::now))))), - base::fn_delayed( - st::defaultDropdownMenu.menu.ripple.hideDuration, - &document->session(), - save), - &st::menuIconDownload); -} - void AddDocumentActions( not_null menu, not_null document, diff --git a/Telegram/SourceFiles/history/view/media/history_view_save_audio_action.cpp b/Telegram/SourceFiles/history/view/media/history_view_save_document_action.cpp similarity index 73% rename from Telegram/SourceFiles/history/view/media/history_view_save_audio_action.cpp rename to Telegram/SourceFiles/history/view/media/history_view_save_document_action.cpp index 7fd4de444a..7e9e41c495 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_save_audio_action.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_save_document_action.cpp @@ -5,18 +5,22 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "history/view/media/history_view_save_audio_action.h" +#include "history/view/media/history_view_save_document_action.h" #include "base/call_delayed.h" #include "data/data_document.h" #include "data/data_file_click_handler.h" +#include "data/data_file_origin.h" #include "data/data_peer.h" #include "data/data_saved_music.h" #include "data/data_session.h" +#include "history/view/history_view_context_menu.h" +#include "history/view/history_view_list_widget.h" #include "history/history.h" #include "history/history_item.h" #include "lang/lang_keys.h" #include "ui/widgets/menu/menu_add_action_callback.h" +#include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/widgets/menu/menu_multiline_action.h" #include "ui/widgets/popup_menu.h" #include "window/window_peer_menu.h" @@ -27,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { -void AddSaveAudioAction( +void AddSaveDocumentAction( const Ui::Menu::MenuCallback &addAction, not_null item, not_null document, @@ -46,16 +50,22 @@ void AddSaveAudioAction( DocumentSaveClickHandler::Mode::ToNewFile); }); if (!document->isMusicForProfile() || (fromSaved && inProfile)) { - addAction( - tr::lng_context_save_audio_file(tr::now), - saveAs, - &st::menuIconDownload); + const auto text = document->isVideoFile() + ? tr::lng_context_save_video(tr::now) + : document->isVoiceMessage() + ? tr::lng_context_save_audio(tr::now) + : document->isAudioFile() + ? tr::lng_context_save_audio_file(tr::now) + : document->sticker() + ? tr::lng_context_save_image(tr::now) + : tr::lng_context_save_file(tr::now); + addAction(text, saveAs, &st::menuIconDownload); return; } const auto fill = [&](not_null menu) { if (!inProfile) { const auto saved = [=] { - savedMusic->save(document); + savedMusic->save(document, contextId); show->showToast(tr::lng_saved_music_added(tr::now)); }; menu->addAction( @@ -98,4 +108,19 @@ void AddSaveAudioAction( }); } +void AddSaveDocumentAction( + not_null menu, + HistoryItem *item, + not_null document, + not_null list) { + if (!item || list->hasCopyMediaRestriction(item) || ItemHasTtl(item)) { + return; + } + AddSaveDocumentAction( + Ui::Menu::CreateAddActionCallback(menu), + item, + document, + list->controller()); +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_save_audio_action.h b/Telegram/SourceFiles/history/view/media/history_view_save_document_action.h similarity index 72% rename from Telegram/SourceFiles/history/view/media/history_view_save_audio_action.h rename to Telegram/SourceFiles/history/view/media/history_view_save_document_action.h index 103ac6ae95..d4893fc571 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_save_audio_action.h +++ b/Telegram/SourceFiles/history/view/media/history_view_save_document_action.h @@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class DocumentData; class HistoryItem; +namespace Ui { +class PopupMenu; +} // namespace Ui + namespace Ui::Menu { struct MenuCallback; } // namespace Ui::Menu @@ -20,10 +24,18 @@ class SessionController; namespace HistoryView { -void AddSaveAudioAction( +class ListWidget; + +void AddSaveDocumentAction( const Ui::Menu::MenuCallback &addAction, not_null item, not_null document, not_null controller); +void AddSaveDocumentAction( + not_null menu, + HistoryItem *item, + not_null document, + not_null list); + } // namespace HistoryView diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 1df9f6e459..8dcd58bc87 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -30,15 +30,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_download_manager.h" #include "data/data_forum_topic.h" #include "data/data_saved_sublist.h" -#include "history/history_item.h" -#include "history/history_item_helpers.h" -#include "history/history.h" +#include "history/view/media/history_view_save_document_action.h" #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_service_message.h" +#include "history/history.h" +#include "history/history_item.h" +#include "history/history_item_helpers.h" #include "media/stories/media_stories_controller.h" // ...TogglePinnedToast. #include "media/stories/media_stories_share.h" // PrepareShareBox. #include "window/window_session_controller.h" #include "window/window_peer_menu.h" +#include "ui/widgets/menu/menu_add_action_callback.h" +#include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/widgets/popup_menu.h" #include "ui/boxes/confirm_box.h" #include "ui/controls/delete_message_context_action.h" @@ -1150,16 +1153,11 @@ void ListWidget::showContextMenu( DocumentSaveClickHandler::Mode::ToNewFile); }); if (_provider->allowSaveFileAs(item, lnkDocument)) { - _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); + HistoryView::AddSaveDocumentAction( + Ui::Menu::CreateAddActionCallback(_contextMenu), + item, + lnkDocument, + _controller->parentController()); } } }