Allow adding any amount of files in SendFilesBox.

This commit is contained in:
John Preston 2020-10-16 17:11:23 +03:00
parent 0539cc9448
commit 843fba61ee
7 changed files with 306 additions and 226 deletions

View file

@ -50,6 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_options.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/controls/emoji_button.h"
#include "ui/toast/toast.h"
#include "ui/cached_round_corners.h"
#include "window/window_session_controller.h"
#include "confirm_box.h"
@ -485,7 +486,8 @@ void EditCaptionBox::updateEditPreview() {
const auto fileinfo = QFileInfo(file->path);
const auto filename = fileinfo.fileName();
_isImage = Core::FileIsImage(filename, file->mime);
const auto mime = file->information->filemime;
_isImage = Core::FileIsImage(filename, mime);
_isAudio = false;
_animated = false;
_photo = false;
@ -525,7 +527,7 @@ void EditCaptionBox::updateEditPreview() {
}
const auto getExt = [&] {
auto patterns = Core::MimeTypeForName(file->mime).globPatterns();
auto patterns = Core::MimeTypeForName(mime).globPatterns();
if (!patterns.isEmpty()) {
return patterns.front().replace('*', QString());
}
@ -588,14 +590,33 @@ void EditCaptionBox::updateEditMediaButton() {
void EditCaptionBox::createEditMediaButton() {
const auto callback = [=](FileDialog::OpenResult &&result) {
auto showBoxErrorCallback = [](tr::phrase<> t) {
Ui::show(Box<InformBox>(t(tr::now)), Ui::LayerOption::KeepOther);
auto showError = [](tr::phrase<> t) {
Ui::Toast::Show(t(tr::now));
};
const auto checkResult = [=](const Ui::PreparedList &list) {
if (list.files.size() != 1) {
return false;
}
const auto &file = list.files.front();
const auto mime = file.information->filemime;
if (Core::IsMimeSticker(mime)) {
showError(tr::lng_edit_media_invalid_file);
return false;
} else if (_isAlbum) { // #TODO edit in file-albums
if (!Core::IsMimeAcceptedForAlbum(mime)
|| file.type == Ui::PreparedFile::AlbumType::File
|| file.type == Ui::PreparedFile::AlbumType::None) {
showError(tr::lng_edit_media_album_error);
return false;
}
}
return true;
};
auto list = Storage::PreparedFileFromFilesDialog(
std::move(result),
_isAlbum,
std::move(showBoxErrorCallback),
checkResult,
showError,
st::sendMediaPreviewSize);
if (list) {

View file

@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/format_values.h"
#include "ui/grouped_layout.h"
#include "ui/text/text_options.h"
#include "ui/toast/toast.h"
#include "ui/controls/emoji_button.h"
#include "lottie/lottie_single_player.h"
#include "data/data_document.h"
@ -71,16 +72,16 @@ inline bool IsSingleItem(const Ui::PreparedList &list) {
void FileDialogCallback(
FileDialog::OpenResult &&result,
bool isAlbum,
Fn<bool(const Ui::PreparedList&)> checkResult,
Fn<void(Ui::PreparedList)> callback) {
auto showBoxErrorCallback = [](tr::phrase<> text) {
Ui::show(Box<InformBox>(text(tr::now)), Ui::LayerOption::KeepOther);
auto showError = [](tr::phrase<> text) {
Ui::Toast::Show(text(tr::now));
};
auto list = Storage::PreparedFileFromFilesDialog(
std::move(result),
isAlbum,
std::move(showBoxErrorCallback),
checkResult,
showError,
st::sendMediaPreviewSize);
if (!list) {
@ -212,12 +213,13 @@ SendFilesBox::SendFilesBox(
, _inner(
_scroll->setOwnedWidget(
object_ptr<Ui::VerticalLayout>(_scroll.data()))) {
enqueueNextPrepare();
}
void SendFilesBox::initPreview() {
using namespace rpl::mappers;
setupControls();
refreshControls();
updateBoxSize();
@ -260,7 +262,6 @@ void SendFilesBox::addThumbButtonHandlers(not_null<Ui::ScrollArea*> wrap) {
// const auto callback = [=](FileDialog::OpenResult &&result) {
// FileDialogCallback(
// std::move(result),
// true,
// [=] (auto list) {
// _list.files[index] = std::move(list.files.front());
// applyAlbumOrder();
@ -277,12 +278,38 @@ void SendFilesBox::addThumbButtonHandlers(not_null<Ui::ScrollArea*> wrap) {
// FileDialog::GetOpenPath(
// this,
// tr::lng_choose_file(tr::now),
// FileDialog::AlbumFilesFilter(),
// FileDialog::AllOrImagesFilter(),
// crl::guard(this, callback));
//}, _albumPreview->lifetime());
}
void SendFilesBox::enqueueNextPrepare() {
if (_preparing) {
return;
}
while (!_list.filesToProcess.empty()
&& _list.filesToProcess.front().information) {
addFile(std::move(_list.filesToProcess.front()));
_list.filesToProcess.pop_front();
}
if (_list.filesToProcess.empty()) {
return;
}
auto file = std::move(_list.filesToProcess.front());
_list.filesToProcess.pop_front();
const auto weak = Ui::MakeWeak(this);
_preparing = true;
crl::async([weak, file = std::move(file)]() mutable {
Storage::PrepareDetails(file, st::sendMediaPreviewSize);
crl::on_main([weak, file = std::move(file)]() mutable {
if (weak) {
weak->addPreparedAsyncFile(std::move(file));
}
});
});
}
void SendFilesBox::setupShadows() {
using namespace rpl::mappers;
@ -369,33 +396,42 @@ void SendFilesBox::setupDragArea() {
};
areas.document->setDroppedCallback(droppedCallback(false));
areas.photo->setDroppedCallback(droppedCallback(true));
_albumChanged.events(
) | rpl::start_with_next([=] {
areas.document->raise();
areas.photo->raise();
}, lifetime());
}
void SendFilesBox::refreshAllAfterAlbumChanges() {
preparePreview();
void SendFilesBox::refreshAllAfterChanges(int fromItem) {
auto fromBlock = 0;
for (auto count = int(_blocks.size()); fromBlock != count; ++fromBlock) {
if (_blocks[fromBlock].tillIndex() >= fromItem) {
break;
}
}
generatePreviewFrom(fromBlock);
_inner->resizeToWidth(st::boxWideWidth);
refreshControls();
captionResized();
_albumChanged.fire({});
}
void SendFilesBox::openDialogToAddFileToAlbum() {
const auto checkResult = [=](const Ui::PreparedList &list) {
if (_sendLimit != SendLimit::One) {
return true;
} else if (!_list.canBeSentInSlowmodeWith(list)) {
Ui::Toast::Show(tr::lng_slowmode_no_many(tr::now));
return false;
}
return true;
};
const auto callback = [=](FileDialog::OpenResult &&result) {
FileDialogCallback(
std::move(result),
true,
[=] (auto list) {
addFiles(std::move(list));
});
checkResult,
[=](Ui::PreparedList list) { addFiles(std::move(list)); });
};
FileDialog::GetOpenPaths(
this,
tr::lng_choose_file(tr::now),
FileDialog::AlbumFilesFilter(),
FileDialog::AllOrImagesFilter(),
crl::guard(this, callback));
}
@ -455,7 +491,11 @@ void SendFilesBox::generatePreviewFrom(int fromBlock) {
using Type = Ui::PreparedFile::AlbumType;
_blocks.erase(_blocks.begin() + fromBlock, _blocks.end());
const auto eraseFrom = _blocks.begin() + fromBlock;
for (auto i = eraseFrom; i != _blocks.end(); ++i) {
i->applyAlbumOrder();
}
_blocks.erase(eraseFrom, _blocks.end());
const auto fromItem = _blocks.empty() ? 0 : _blocks.back().tillIndex();
Assert(fromItem <= _list.files.size());
@ -498,12 +538,10 @@ void SendFilesBox::generatePreviewFrom(int fromBlock) {
if (albumStart >= 0) {
pushBlock(albumStart, _list.files.size());
}
_scroll->scrollToY(0);
}
void SendFilesBox::setupControls() {
setupTitleText();
void SendFilesBox::refreshControls() {
refreshTitleText();
updateSendWayControlsVisibility();
}
@ -669,20 +707,6 @@ void SendFilesBox::captionResized() {
bool SendFilesBox::canAddFiles(not_null<const QMimeData*> data) const {
return (data->hasUrls() && CanAddUrls(data->urls())) || data->hasImage();
//const auto urls = data->hasUrls() ? data->urls() : QList<QUrl>();
//auto filesCount = CanAddUrls(urls) ? urls.size() : 0;
//if (!filesCount && data->hasImage()) {
// ++filesCount;
//}
//if (_list.files.size() + filesCount > Ui::MaxAlbumItems()) { // #TODO files
// return false;
//} else if (_list.files.size() > 1 && !_albumPreview) {
// return false;
//} else if (!IsFirstAlbumItem(_list)) {
// return false;
//}
//return true;
}
bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
@ -713,36 +737,54 @@ bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
}
bool SendFilesBox::addFiles(Ui::PreparedList list) {
const auto sumFiles = _list.files.size() + list.files.size();
const auto cutToAlbumSize = (sumFiles > Ui::MaxAlbumItems());
if (list.error != Ui::PreparedList::Error::None) {
return false;
//} else if (!IsSingleItem(list) && !list.albumIsPossible) { // #TODO files
// return false;
//} else if (!IsFirstAlbumItem(list)) {
// return false;
//} else if (_list.files.size() > 1 && !_albumPreview) {
// return false;
//} else if (!IsFirstAlbumItem(_list)) {
// return false;
}
//applyAlbumOrder();
//delete base::take(_preview);
//_albumPreview = nullptr;
return false;
_list.mergeToEnd(std::move(list), cutToAlbumSize);
refreshAllAfterAlbumChanges();
const auto count = int(_list.files.size());
_list.filesToProcess.insert(
_list.filesToProcess.end(),
std::make_move_iterator(list.files.begin()),
std::make_move_iterator(list.files.end()));
_list.filesToProcess.insert(
_list.filesToProcess.end(),
std::make_move_iterator(list.filesToProcess.begin()),
std::make_move_iterator(list.filesToProcess.end()));
enqueueNextPrepare();
if (_list.files.size() > count) {
refreshAllAfterChanges(count);
}
return true;
}
void SendFilesBox::setupTitleText() {
if (_list.files.size() > 1) {
const auto onlyImages = false;/* #TODO files (_compressConfirm != CompressConfirm::None)
&& (_albumVideosCount == 0);*/
_titleText = onlyImages
? tr::lng_send_images_selected(tr::now, lt_count, _list.files.size())
: tr::lng_send_files_selected(tr::now, lt_count, _list.files.size());
void SendFilesBox::addPreparedAsyncFile(Ui::PreparedFile &&file) {
Expects(file.information != nullptr);
_preparing = false;
const auto count = int(_list.files.size());
addFile(std::move(file));
enqueueNextPrepare();
if (_list.files.size() > count) {
refreshAllAfterChanges(count);
}
}
void SendFilesBox::addFile(Ui::PreparedFile &&file) {
_list.files.push_back(std::move(file));
if (_sendLimit == SendLimit::One && !_list.canBeSentInSlowmode()) {
_list.files.pop_back();
}
}
void SendFilesBox::refreshTitleText() {
const auto count = int(_list.files.size());
if (count > 1) {
const auto imagesCount = ranges::count(
_list.files,
Ui::PreparedFile::AlbumType::Photo,
&Ui::PreparedFile::type);
_titleText = (imagesCount == count)
? tr::lng_send_images_selected(tr::now, lt_count, count)
: tr::lng_send_files_selected(tr::now, lt_count, count);
_titleHeight = st::boxTitleHeight;
} else {
_titleText = QString();

View file

@ -114,7 +114,7 @@ private:
void initSendWay();
void initPreview();
void setupControls();
void refreshControls();
void setupSendWayControls();
void setupCaption();
void setupShadows();
@ -133,7 +133,7 @@ private:
void captionResized();
void setupDragArea();
void setupTitleText();
void refreshTitleText();
void updateBoxSize();
void updateControlsGeometry();
void updateCaptionPlaceholder();
@ -143,9 +143,13 @@ private:
bool canAddFiles(not_null<const QMimeData*> data) const;
bool addFiles(not_null<const QMimeData*> data);
bool addFiles(Ui::PreparedList list);
void addFile(Ui::PreparedFile &&file);
void openDialogToAddFileToAlbum();
void refreshAllAfterAlbumChanges();
void refreshAllAfterChanges(int fromItem);
void enqueueNextPrepare();
void addPreparedAsyncFile(Ui::PreparedFile &&file);
const not_null<Window::SessionController*> _controller;
const Api::SendType _sendType = Api::SendType();
@ -178,12 +182,12 @@ private:
rpl::variable<Ui::SendFilesWay> _sendWay = Ui::SendFilesWay();
rpl::variable<int> _footerHeight = 0;
rpl::event_stream<> _albumChanged;
rpl::lifetime _dimensionsLifetime;
object_ptr<Ui::ScrollArea> _scroll;
QPointer<Ui::VerticalLayout> _inner;
std::vector<Block> _blocks;
bool _preparing = false;
int _lastScrollTop = 0;

View file

@ -62,77 +62,20 @@ QSize PrepareShownDimensions(const QImage &preview) {
: result;
}
bool PrepareDetailsIsWaiting(
QSemaphore &semaphore,
PreparedFile &file,
int previewWidth) {
crl::async([=, &semaphore, &file] {
const auto guard = gsl::finally([&] { semaphore.release(); });
if (!file.path.isEmpty()) {
file.mime = Core::MimeTypeForFile(QFileInfo(file.path)).name();
file.information = FileLoadTask::ReadMediaInformation(
file.path,
QByteArray(),
file.mime);
} else if (!file.content.isEmpty()) {
file.mime = Core::MimeTypeForData(file.content).name();
file.information = FileLoadTask::ReadMediaInformation(
QString(),
file.content,
file.mime);
} else {
Assert(file.information != nullptr);
}
using Image = PreparedFileInformation::Image;
using Video = PreparedFileInformation::Video;
if (const auto image = std::get_if<Image>(
&file.information->media)) {
if (ValidPhotoForAlbum(*image, file.mime)) {
file.shownDimensions = PrepareShownDimensions(image->data);
file.preview = Images::prepareOpaque(image->data.scaledToWidth(
std::min(previewWidth, style::ConvertScale(image->data.width()))
* cIntRetinaFactor(),
Qt::SmoothTransformation));
Assert(!file.preview.isNull());
file.preview.setDevicePixelRatio(cRetinaFactor());
file.type = PreparedFile::AlbumType::Photo;
} else if (Core::IsMimeSticker(file.mime)) {
file.type = PreparedFile::AlbumType::None;
}
} else if (const auto video = std::get_if<Video>(
&file.information->media)) {
if (ValidVideoForAlbum(*video)) {
auto blurred = Images::prepareBlur(Images::prepareOpaque(video->thumbnail));
file.shownDimensions = PrepareShownDimensions(video->thumbnail);
file.preview = std::move(blurred).scaledToWidth(
previewWidth * cIntRetinaFactor(),
Qt::SmoothTransformation);
Assert(!file.preview.isNull());
file.preview.setDevicePixelRatio(cRetinaFactor());
file.type = PreparedFile::AlbumType::Video;
}
}
});
return true;
}
void PrepareDetailsInParallel(PreparedList &result, int previewWidth) {
Expects(result.files.size() <= Ui::MaxAlbumItems());
auto waiting = 0;
if (result.files.empty()) {
return;
}
QSemaphore semaphore;
for (auto &file : result.files) {
if (PrepareDetailsIsWaiting(
semaphore,
file,
previewWidth)) {
++waiting;
}
}
if (waiting > 0) {
semaphore.acquire(waiting);
crl::async([=, &semaphore, &file] {
PrepareDetails(file, previewWidth);
semaphore.release();
});
}
semaphore.acquire(result.files.size());
}
} // namespace
@ -277,91 +220,152 @@ PreparedList PrepareMediaFromImage(
std::optional<PreparedList> PreparedFileFromFilesDialog(
FileDialog::OpenResult &&result,
bool isAlbum,
Fn<bool(const Ui::PreparedList&)> checkResult,
Fn<void(tr::phrase<>)> errorCallback,
int previewWidth) {
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
return std::nullopt;
}
if (!result.remoteContent.isEmpty()) {
auto list = PrepareMediaFromImage(
auto list = result.remoteContent.isEmpty()
? PrepareMediaList(result.paths, previewWidth)
: PrepareMediaFromImage(
QImage(),
std::move(result.remoteContent),
previewWidth);
const auto mimeFile = list.files.front().mime;
if (Core::IsMimeSticker(mimeFile)) {
errorCallback(tr::lng_edit_media_invalid_file);
return std::nullopt;
}
if (isAlbum) {
const auto file = &list.files.front();
if (!Core::IsMimeAcceptedForAlbum(mimeFile)
|| file->type == PreparedFile::AlbumType::File
|| file->type == PreparedFile::AlbumType::File) {
errorCallback(tr::lng_edit_media_album_error);
return std::nullopt;
}
}
Expects(list.files.size() == 1);
return list;
} else if (!result.paths.isEmpty()) {
const auto isSingleFile = (result.paths.size() == 1);
auto temp = PrepareMediaList(result.paths, previewWidth);
if (temp.error != PreparedList::Error::None) {
if (list.error != PreparedList::Error::None) {
errorCallback(tr::lng_send_media_invalid_files);
return std::nullopt;
}
auto filteredFiles = ranges::view::all(
temp.files
) | ranges::view::filter([&](const auto &file) {
const auto info = QFileInfo(file.path);
if (Core::IsMimeSticker(Core::MimeTypeForFile(info).name())) {
if (isSingleFile) {
errorCallback(tr::lng_edit_media_invalid_file);
}
return false;
}
if (!isAlbum) {
return true;
}
using Info = PreparedFileInformation;
const auto media = &file.information->media;
const auto valid = v::match(*media, [](const Info::Image &data) {
return Ui::ValidateThumbDimensions(
data.data.width(),
data.data.height())
&& !data.animated;
}, [](Info::Video &data) {
data.isGifv = false;
return true;
}, [](auto &&other) {
return false;
});
if (!valid && isSingleFile) {
errorCallback(tr::lng_edit_media_album_error);
}
return valid;
}) | ranges::view::transform([](auto &file) {
return std::move(file);
}) | ranges::to_vector;
if (!filteredFiles.size()) {
if (!isSingleFile) {
errorCallback(tr::lng_send_media_invalid_files);
}
} else if (!checkResult(list)) {
return std::nullopt;
}
auto list = PreparedList(temp.error, temp.errorData);
list.files = std::move(filteredFiles);
} else {
return list;
}
return std::nullopt;
//if (!result.remoteContent.isEmpty()) {
// auto list = PrepareMediaFromImage(
// QImage(),
// std::move(result.remoteContent),
// previewWidth);
// const auto mimeFile = list.files.front().information->filemime;
// if (Core::IsMimeSticker(mimeFile)) {
// errorCallback(tr::lng_edit_media_invalid_file);
// return std::nullopt;
// }
// if (isAlbum) {
// const auto file = &list.files.front();
// if (!Core::IsMimeAcceptedForAlbum(mimeFile)
// || file->type == PreparedFile::AlbumType::File
// || file->type == PreparedFile::AlbumType::None) {
// errorCallback(tr::lng_edit_media_album_error);
// return std::nullopt;
// }
// }
// Ensures(list.files.size() == 1);
// return list;
//} else if (!result.paths.isEmpty()) {
// auto temp = PrepareMediaList(result.paths, previewWidth);
// const auto isSingleFile = (temp.files.size() == 1);
// if (temp.error != PreparedList::Error::None) {
// errorCallback(tr::lng_send_media_invalid_files);
// return std::nullopt;
// }
// auto filteredFiles = ranges::view::all(
// temp.files
// ) | ranges::view::filter([&](const auto &file) {
// const auto info = QFileInfo(file.path);
// if (Core::IsMimeSticker(Core::MimeTypeForFile(info).name())) {
// if (isSingleFile) {
// errorCallback(tr::lng_edit_media_invalid_file);
// }
// return false;
// }
// if (!isAlbum) {
// return true;
// }
// using Info = PreparedFileInformation;
// const auto media = &file.information->media;
// const auto valid = v::match(*media, [](const Info::Image &data) {
// return Ui::ValidateThumbDimensions(
// data.data.width(),
// data.data.height())
// && !data.animated;
// }, [](Info::Video &data) {
// data.isGifv = false;
// return true;
// }, [](auto &&other) {
// return false;
// });
// if (!valid && isSingleFile) {
// errorCallback(tr::lng_edit_media_album_error);
// }
// return valid;
// }) | ranges::view::transform([](auto &file) {
// return std::move(file);
// }) | ranges::to_vector;
// if (!filteredFiles.size()) {
// if (!isSingleFile) {
// errorCallback(tr::lng_send_media_invalid_files);
// }
// return std::nullopt;
// }
// auto list = PreparedList(temp.error, temp.errorData);
// list.files = std::move(filteredFiles);
// return list;
//}
//return std::nullopt;
}
void PrepareDetails(PreparedFile &file, int previewWidth) {
if (!file.path.isEmpty()) {
file.information = FileLoadTask::ReadMediaInformation(
file.path,
QByteArray(),
Core::MimeTypeForFile(QFileInfo(file.path)).name());
} else if (!file.content.isEmpty()) {
file.information = FileLoadTask::ReadMediaInformation(
QString(),
file.content,
Core::MimeTypeForData(file.content).name());
} else {
Assert(file.information != nullptr);
}
using Image = PreparedFileInformation::Image;
using Video = PreparedFileInformation::Video;
if (const auto image = std::get_if<Image>(
&file.information->media)) {
if (ValidPhotoForAlbum(*image, file.information->filemime)) {
file.shownDimensions = PrepareShownDimensions(image->data);
file.preview = Images::prepareOpaque(image->data.scaledToWidth(
std::min(previewWidth, style::ConvertScale(image->data.width()))
* cIntRetinaFactor(),
Qt::SmoothTransformation));
Assert(!file.preview.isNull());
file.preview.setDevicePixelRatio(cRetinaFactor());
file.type = PreparedFile::AlbumType::Photo;
} else if (Core::IsMimeSticker(file.information->filemime)) {
file.type = PreparedFile::AlbumType::None;
}
} else if (const auto video = std::get_if<Video>(
&file.information->media)) {
if (ValidVideoForAlbum(*video)) {
auto blurred = Images::prepareBlur(Images::prepareOpaque(video->thumbnail));
file.shownDimensions = PrepareShownDimensions(video->thumbnail);
file.preview = std::move(blurred).scaledToWidth(
previewWidth * cIntRetinaFactor(),
Qt::SmoothTransformation);
Assert(!file.preview.isNull());
file.preview.setDevicePixelRatio(cRetinaFactor());
file.type = PreparedFile::AlbumType::Video;
}
}
}
} // namespace Storage

View file

@ -27,7 +27,7 @@ enum class MimeDataState {
std::optional<Ui::PreparedList> PreparedFileFromFilesDialog(
FileDialog::OpenResult &&result,
bool isAlbum,
Fn<bool(const Ui::PreparedList&)> checkResult,
Fn<void(tr::phrase<>)> errorCallback,
int previewWidth);
MimeDataState ComputeMimeDataState(const QMimeData *data);
@ -38,5 +38,6 @@ Ui::PreparedList PrepareMediaFromImage(
QImage &&image,
QByteArray &&content,
int previewWidth);
void PrepareDetails(Ui::PreparedFile &file, int previewWidth);
} // namespace Storage

View file

@ -60,24 +60,29 @@ void PreparedList::mergeToEnd(PreparedList &&other, bool cutToAlbumSize) {
}
bool PreparedList::canBeSentInSlowmode() const {
if (!filesToProcess.empty()) {
return canBeSentInSlowmodeWith(PreparedList());
}
bool PreparedList::canBeSentInSlowmodeWith(const PreparedList &other) const {
if (!filesToProcess.empty() || !other.filesToProcess.empty()) {
return false;
} else if (files.size() < 2) {
} else if (files.size() + other.files.size() < 2) {
return true;
} else if (files.size() > kMaxAlbumCount) {
} else if (files.size() + other.files.size() > kMaxAlbumCount) {
return false;
}
auto &&all = ranges::view::concat(files, other.files);
const auto hasNonGrouping = ranges::contains(
files,
all,
PreparedFile::AlbumType::None,
&PreparedFile::type);
const auto hasFiles = ranges::contains(
files,
all,
PreparedFile::AlbumType::File,
&PreparedFile::type);
const auto hasVideos = ranges::contains(
files,
all,
PreparedFile::AlbumType::Video,
&PreparedFile::type);
@ -92,7 +97,9 @@ bool PreparedList::canAddCaption(bool groupMediaInAlbums) const {
return false;
}
if (files.size() == 1) {
const auto isSticker = Core::IsMimeSticker(files.front().mime)
Assert(files.front().information != nullptr);
const auto isSticker = Core::IsMimeSticker(
files.front().information->filemime)
|| files.front().path.endsWith(
qstr(".tgs"),
Qt::CaseInsensitive);

View file

@ -56,7 +56,6 @@ struct PreparedFile {
QString path;
QByteArray content;
QString mime;
int size = 0;
std::unique_ptr<Ui::PreparedFileInformation> information;
QImage preview;
@ -85,6 +84,8 @@ struct PreparedList {
[[nodiscard]] bool canAddCaption(bool groupMediaInAlbums) const;
[[nodiscard]] bool canBeSentInSlowmode() const;
[[nodiscard]] bool canBeSentInSlowmodeWith(
const PreparedList &other) const;
Error error = Error::None;
QString errorData;