From 31a901cae1e9fe3489aa4185a2d4e783eae361b4 Mon Sep 17 00:00:00 2001 From: danalec Date: Thu, 13 Mar 2025 14:53:41 -0300 Subject: [PATCH] added Chat Folders for Downloads --- Telegram/Resources/langs/lang.strings | 2 + Telegram/SourceFiles/core/core_settings.h | 7 +- Telegram/SourceFiles/data/data_document.cpp | 64 ++++++++++++++----- .../SourceFiles/settings/settings_chat.cpp | 15 +++++ 4 files changed, 70 insertions(+), 18 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1cf93bef0..5f834024a 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4094,6 +4094,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_translate_undo" = "Undo"; "lng_downloads_section" = "Downloads"; +"lng_downloads_settings_save_to_chat_folders" = "Save files to chat folders"; +"lng_downloads_settings_save_to_chat_folders_about" = "When enabled, files will be saved to separate folders named after their source chat."; "lng_downloads_view_in_chat" = "View in chat"; "lng_downloads_view_in_section" = "View in downloads"; "lng_downloads_delete_sure_one" = "Do you want to delete this file?"; diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index 4f4711b23..286c07a79 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -954,6 +954,9 @@ public: void resetOnLastLogout(); + [[nodiscard]] bool saveToFoldersByChat() const { return _saveToFoldersByChat; } + void setSaveToFoldersByChat(bool value) { _saveToFoldersByChat = value; } + private: void resolveRecentEmoji() const; @@ -1094,7 +1097,7 @@ private: QByteArray _photoEditorBrush; + bool _saveToFoldersByChat = false; // Default to disabled }; -} // namespace Core - +} // namespace Core \ No newline at end of file diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index c6befff04..73ed5d15b 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -210,11 +210,10 @@ QString FileNameForSave( return result; } -QString DocumentFileNameForSave( - not_null data, - bool forceSavingAs, - const QString &already, - const QDir &dir) { +QString DocumentFileNameForSave(not_null data, + bool forceSavingAs, + const QString &already, + const QDir &dir) { auto alreadySavingFilename = data->loadingFilePath(); if (!alreadySavingFilename.isEmpty()) { return alreadySavingFilename; @@ -253,20 +252,53 @@ QString DocumentFileNameForSave( } else { filter = mimeType.filterString() + u";;"_q + FileDialog::AllFilesFilter(); } - caption = data->isAudioFile() - ? tr::lng_save_audio_file(tr::now) - : tr::lng_save_file(tr::now); + caption = data->isAudioFile() ? tr::lng_save_audio_file(tr::now) : tr::lng_save_file(tr::now); prefix = u"doc"_q; } - return FileNameForSave( - &data->session(), - caption, - filter, - prefix, - name, - forceSavingAs, - dir); + // Try to get chat information + QString chatFolder; + + // Get window controller + if (const auto controller = data->session().windows().empty() ? nullptr : data->session().windows().front().get()) { + + // Get the active chat history + if (const auto history = controller->activeChatCurrent().history()) { + if (const auto peer = history->peer) { + chatFolder = peer->name(); + // Sanitize folder name + chatFolder.replace(QRegularExpression("[\\\\/:*?\"<>|]"), "_"); + } + } + } + + // Get base download path + auto path = [&] + { + const auto path = Core::App().settings().downloadPath(); + if (path.isEmpty()) { + return File::DefaultDownloadPath(&data->session()); + } else if (path == FileDialog::Tmp()) { + return data->session().local().tempDirectory(); + } else { + return path; + } + }(); + + // Create chat subfolder if we have a chat name and setting is enabled + if (!chatFolder.isEmpty() && !path.isEmpty() && !forceSavingAs && Core::App().settings().saveToFoldersByChat()) { + // Create full path with chat subfolder + QDir baseDir(path); + if (!baseDir.exists(chatFolder)) { + baseDir.mkdir(chatFolder); + } + QDir chatDir(path + "/" + chatFolder); + + // Use the chat directory instead of the base directory + return FileNameForSave(&data->session(), caption, filter, prefix, name, forceSavingAs, chatDir); + } + + return FileNameForSave(&data->session(), caption, filter, prefix, name, forceSavingAs, dir); } Data::FileOrigin StickerData::setOrigin() const { diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp index a6005c120..981722f68 100644 --- a/Telegram/SourceFiles/settings/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/settings_chat.cpp @@ -1096,6 +1096,21 @@ void SetupDataStorage( const auto showpath = container->lifetime( ).make_state>(); + container->add(object_ptr( + container, + tr::lng_downloads_settings_save_to_chat_folders(), + Core::App().settings().saveToFoldersByChat(), + st::settingsCheckbox), + st::settingsCheckboxPadding)->checkedChanges() | + rpl::start_with_next( + [=](bool checked) { + Core::App().settings().setSaveToFoldersByChat(checked); + Core::App().saveSettingsDelayed(); + }, + container->lifetime()); + + Ui::AddDividerText(container, tr::lng_downloads_settings_save_to_chat_folders_about()); + const auto path = container->add( object_ptr>( container,