mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 23:53:58 +02:00
Allow adding any amount of files in SendFilesBox.
This commit is contained in:
parent
0539cc9448
commit
843fba61ee
7 changed files with 306 additions and 226 deletions
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue