/* This file is part of Telegram Desktop, 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 "ui/chat/attach/attach_prepare.h" #include "ui/rp_widget.h" #include "ui/widgets/popup_menu.h" #include "ui/chat/attach/attach_send_files_way.h" #include "ui/image/image_prepare.h" #include "ui/ui_utility.h" #include "core/mime_type.h" #include namespace Ui { namespace { constexpr auto kMaxAlbumCount = 10; struct GroupRange { int from = 0; int till = 0; AlbumType type = AlbumType::None; [[nodiscard]] int size() const { return till - from; } [[nodiscard]] bool sentWithCaption() const { return (size() == 1) || (type == AlbumType::PhotoVideo); } }; [[nodiscard]] AlbumType GroupTypeForFile( PreparedFile::Type type, bool groupFiles, bool sendImagesAsPhotos) { using Type = PreparedFile::Type; return (type == Type::Music) ? (groupFiles ? AlbumType::Music : AlbumType::None) : (type == Type::Video) ? (groupFiles ? AlbumType::PhotoVideo : AlbumType::None) : (type == Type::Photo) ? ((groupFiles && sendImagesAsPhotos) ? AlbumType::PhotoVideo : (groupFiles && !sendImagesAsPhotos) ? AlbumType::File : AlbumType::None) : (type == Type::File) ? (groupFiles ? AlbumType::File : AlbumType::None) : AlbumType::None; } [[nodiscard]] std::vector GroupRanges( const std::vector &files, SendFilesWay way, bool slowmode) { const auto sendImagesAsPhotos = way.sendImagesAsPhotos(); const auto groupFiles = way.groupFiles() || slowmode; auto result = std::vector(); if (files.empty()) { return result; } auto from = 0; auto groupType = AlbumType::None; for (auto i = 0; i != int(files.size()); ++i) { const auto fileGroupType = GroupTypeForFile( files[i].type, groupFiles, sendImagesAsPhotos); const auto count = (i - from); if ((i > from && groupType != fileGroupType) || ((groupType != AlbumType::None) && (count == kMaxAlbumCount))) { result.push_back(GroupRange{ .from = from, .till = i, .type = (count > 1) ? groupType : AlbumType::None, }); from = i; } groupType = fileGroupType; } const auto till = int(files.size()); const auto count = (till - from); result.push_back(GroupRange{ .from = from, .till = till, .type = (count > 1) ? groupType : AlbumType::None, }); return result; } [[nodiscard]] bool CaptionWillBeAttachedFromRanges( const std::vector &ranges, int filesCount) { const auto hasGroupedFileAlbum = ranges::any_of(ranges, [](const auto &r) { return (r.size() > 1) && (r.type == AlbumType::File); }); return ((filesCount > 1) && hasGroupedFileAlbum) || ((ranges.size() == 1) && ranges.front().sentWithCaption()); } } // namespace PreparedFile::PreparedFile(const QString &path) : path(path) { const auto fileInfo = QFileInfo(path); displayName = fileInfo.fileName(); } PreparedFile::PreparedFile(PreparedFile &&other) = default; PreparedFile &PreparedFile::operator=(PreparedFile &&other) = default; PreparedFile::~PreparedFile() = default; bool PreparedFile::canBeInAlbumType(AlbumType album) const { return CanBeInAlbumType(type, album); } bool PreparedFile::isSticker() const { Expects(information != nullptr); return (type == PreparedFile::Type::Photo) && Core::IsMimeSticker(information->filemime); } bool PreparedFile::isVideoFile() const { Expects(information != nullptr); using Video = Ui::PreparedFileInformation::Video; return (type == PreparedFile::Type::Video) && v::is