mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-08 16:13:56 +02:00
Add a way to recreate SendFilesBox content.
This commit is contained in:
parent
202534575b
commit
0539cc9448
11 changed files with 217 additions and 155 deletions
|
@ -4235,6 +4235,7 @@ void ApiWrap::sendFiles(
|
||||||
type = SendMediaType::Photo;
|
type = SendMediaType::Photo;
|
||||||
break;
|
break;
|
||||||
case Ui::PreparedFile::AlbumType::Video:
|
case Ui::PreparedFile::AlbumType::Video:
|
||||||
|
case Ui::PreparedFile::AlbumType::File:
|
||||||
type = SendMediaType::File;
|
type = SendMediaType::File;
|
||||||
break;
|
break;
|
||||||
default: Unexpected("AlbumType in uploadFilesAfterConfirmation");
|
default: Unexpected("AlbumType in uploadFilesAfterConfirmation");
|
||||||
|
|
|
@ -489,7 +489,7 @@ backgroundScroll: ScrollArea(boxScroll) {
|
||||||
deltab: 10px;
|
deltab: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
editMediaButtonSize: 29px;
|
editMediaButtonSize: 28px;
|
||||||
editMediaButtonSkip: 8px;
|
editMediaButtonSkip: 8px;
|
||||||
editMediaButtonFileSkipRight: 1px;
|
editMediaButtonFileSkipRight: 1px;
|
||||||
editMediaButtonFileSkipTop: 7px;
|
editMediaButtonFileSkipTop: 7px;
|
||||||
|
@ -514,6 +514,10 @@ sendBoxAlbumGroupSkipTop: 6px;
|
||||||
sendBoxAlbumGroupRadius: 12px;
|
sendBoxAlbumGroupRadius: 12px;
|
||||||
sendBoxAlbumGroupHeight: 25px;
|
sendBoxAlbumGroupHeight: 25px;
|
||||||
|
|
||||||
|
sendBoxFileGroupSkipTop: 2px;
|
||||||
|
sendBoxFileGroupSkipRight: 0px;
|
||||||
|
sendBoxFileGroupEditInternalSkip: 4px;
|
||||||
|
|
||||||
sendBoxAlbumGroupEditButtonIcon: editMediaButtonIconPhoto;
|
sendBoxAlbumGroupEditButtonIcon: editMediaButtonIconPhoto;
|
||||||
sendBoxAlbumGroupEditButtonIconPosition: point(4px, -1px);
|
sendBoxAlbumGroupEditButtonIconPosition: point(4px, -1px);
|
||||||
|
|
||||||
|
|
|
@ -689,7 +689,7 @@ bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto file = &list.files.front();
|
const auto file = &list.files.front();
|
||||||
if (_isAlbum && (file->type == AlbumType::File)) {
|
if (_isAlbum && (file->type == AlbumType::File || file->type == AlbumType::None)) {
|
||||||
const auto imageAsDoc = [&] {
|
const auto imageAsDoc = [&] {
|
||||||
using Info = Ui::PreparedFileInformation;
|
using Info = Ui::PreparedFileInformation;
|
||||||
const auto fileMedia = &file->information->media;
|
const auto fileMedia = &file->information->media;
|
||||||
|
|
|
@ -100,6 +100,95 @@ rpl::producer<QString> FieldPlaceholder(
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
SendFilesBox::Block::Block(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
not_null<std::vector<Ui::PreparedFile>*> items,
|
||||||
|
int from,
|
||||||
|
int till,
|
||||||
|
Fn<bool()> gifPaused,
|
||||||
|
SendFilesWay way)
|
||||||
|
: _items(items)
|
||||||
|
, _from(from)
|
||||||
|
, _till(till) {
|
||||||
|
Expects(from >= 0);
|
||||||
|
Expects(till > from);
|
||||||
|
Expects(till <= items->size());
|
||||||
|
|
||||||
|
const auto count = till - from;
|
||||||
|
const auto my = gsl::make_span(*items).subspan(from, count);
|
||||||
|
const auto &first = my.front();
|
||||||
|
_isAlbum = (my.size() > 1)
|
||||||
|
|| (first.type == Ui::PreparedFile::AlbumType::Photo);
|
||||||
|
if (_isAlbum) {
|
||||||
|
const auto preview = Ui::CreateChild<Ui::AlbumPreview>(
|
||||||
|
parent.get(),
|
||||||
|
my,
|
||||||
|
way);
|
||||||
|
_preview.reset(preview);
|
||||||
|
} else {
|
||||||
|
const auto media = Ui::SingleMediaPreview::Create(
|
||||||
|
parent,
|
||||||
|
gifPaused,
|
||||||
|
first);
|
||||||
|
if (media) {
|
||||||
|
_preview.reset(media);
|
||||||
|
} else {
|
||||||
|
_preview.reset(
|
||||||
|
Ui::CreateChild<Ui::SingleFilePreview>(parent.get(), first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_preview->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendFilesBox::Block::fromIndex() const {
|
||||||
|
return _from;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendFilesBox::Block::tillIndex() const {
|
||||||
|
return _till;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::RpWidget> SendFilesBox::Block::takeWidget() {
|
||||||
|
return object_ptr<Ui::RpWidget>::fromRaw(_preview.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendFilesBox::Block::setSendWay(Ui::SendFilesWay way) {
|
||||||
|
if (!_isAlbum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyAlbumOrder();
|
||||||
|
const auto album = static_cast<Ui::AlbumPreview*>(_preview.get());
|
||||||
|
album->setSendWay(way);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendFilesBox::Block::applyAlbumOrder() {
|
||||||
|
if (!_isAlbum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto album = static_cast<Ui::AlbumPreview*>(_preview.get());
|
||||||
|
const auto order = album->takeOrder();
|
||||||
|
const auto isIdentity = [&] {
|
||||||
|
for (auto i = 0, count = int(order.size()); i != count; ++i) {
|
||||||
|
if (order[i] != i) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
if (isIdentity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto elements = std::vector<Ui::PreparedFile>();
|
||||||
|
elements.reserve(order.size());
|
||||||
|
for (const auto index : order) {
|
||||||
|
elements.push_back(std::move((*_items)[_from + index]));
|
||||||
|
}
|
||||||
|
for (auto i = 0, count = int(order.size()); i != count; ++i) {
|
||||||
|
(*_items)[_from + i] = std::move(elements[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SendFilesBox::SendFilesBox(
|
SendFilesBox::SendFilesBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
|
@ -147,36 +236,6 @@ void SendFilesBox::initPreview() {
|
||||||
}, _dimensionsLifetime);
|
}, _dimensionsLifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void SendFilesBox::prepareSingleFilePreview() {
|
|
||||||
// const auto &file = _list.files[0];
|
|
||||||
// const auto controller = _controller;
|
|
||||||
// const auto media = Ui::SingleMediaPreview::Create(this, [=] {
|
|
||||||
// return controller->isGifPausedAtLeastFor(
|
|
||||||
// Window::GifPauseReason::Layer);
|
|
||||||
// }, file);
|
|
||||||
// if (media) {
|
|
||||||
// _preview = media;
|
|
||||||
// initPreview(media->desiredHeightValue());
|
|
||||||
// } else {
|
|
||||||
// const auto preview = Ui::CreateChild<Ui::SingleFilePreview>(this, file);
|
|
||||||
// _preview = preview;
|
|
||||||
// initPreview(preview->desiredHeightValue());
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void SendFilesBox::prepareAlbumPreview() {
|
|
||||||
// addThumbButtonHandlers(wrap); // #TODO files
|
|
||||||
//
|
|
||||||
// setupShadows(wrap, _albumPreview);
|
|
||||||
//
|
|
||||||
// initPreview(_albumPreview->desiredHeightValue());
|
|
||||||
//
|
|
||||||
// crl::on_main([=] {
|
|
||||||
// wrap->scrollToY(_lastScrollTop);
|
|
||||||
// _lastScrollTop = 0;
|
|
||||||
// });
|
|
||||||
//}
|
|
||||||
|
|
||||||
void SendFilesBox::addThumbButtonHandlers(not_null<Ui::ScrollArea*> wrap) {
|
void SendFilesBox::addThumbButtonHandlers(not_null<Ui::ScrollArea*> wrap) {
|
||||||
// #TODO files
|
// #TODO files
|
||||||
//_albumPreview->thumbDeleted(
|
//_albumPreview->thumbDeleted(
|
||||||
|
@ -224,14 +283,12 @@ void SendFilesBox::addThumbButtonHandlers(not_null<Ui::ScrollArea*> wrap) {
|
||||||
//}, _albumPreview->lifetime());
|
//}, _albumPreview->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFilesBox::setupShadows(
|
void SendFilesBox::setupShadows() {
|
||||||
not_null<Ui::ScrollArea*> wrap,
|
|
||||||
not_null<Ui::AlbumPreview*> content) {
|
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
|
|
||||||
const auto topShadow = Ui::CreateChild<Ui::FadeShadow>(this);
|
const auto topShadow = Ui::CreateChild<Ui::FadeShadow>(this);
|
||||||
const auto bottomShadow = Ui::CreateChild<Ui::FadeShadow>(this);
|
const auto bottomShadow = Ui::CreateChild<Ui::FadeShadow>(this);
|
||||||
wrap->geometryValue(
|
_scroll->geometryValue(
|
||||||
) | rpl::start_with_next_done([=](const QRect &geometry) {
|
) | rpl::start_with_next_done([=](const QRect &geometry) {
|
||||||
topShadow->resizeToWidth(geometry.width());
|
topShadow->resizeToWidth(geometry.width());
|
||||||
topShadow->move(
|
topShadow->move(
|
||||||
|
@ -246,11 +303,11 @@ void SendFilesBox::setupShadows(
|
||||||
Ui::DestroyChild(b.data());
|
Ui::DestroyChild(b.data());
|
||||||
}, topShadow->lifetime());
|
}, topShadow->lifetime());
|
||||||
|
|
||||||
topShadow->toggleOn(wrap->scrollTopValue() | rpl::map(_1 > 0));
|
topShadow->toggleOn(_scroll->scrollTopValue() | rpl::map(_1 > 0));
|
||||||
bottomShadow->toggleOn(rpl::combine(
|
bottomShadow->toggleOn(rpl::combine(
|
||||||
wrap->scrollTopValue(),
|
_scroll->scrollTopValue(),
|
||||||
wrap->heightValue(),
|
_scroll->heightValue(),
|
||||||
content->heightValue(),
|
_inner->heightValue(),
|
||||||
_1 + _2 < _3));
|
_1 + _2 < _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,9 +326,7 @@ void SendFilesBox::prepare() {
|
||||||
setupSendWayControls();
|
setupSendWayControls();
|
||||||
preparePreview();
|
preparePreview();
|
||||||
initPreview();
|
initPreview();
|
||||||
|
setupShadows();
|
||||||
_scroll->show();
|
|
||||||
_inner->show();
|
|
||||||
|
|
||||||
boxClosing() | rpl::start_with_next([=] {
|
boxClosing() | rpl::start_with_next([=] {
|
||||||
if (!_confirmed && _cancelledCallback) {
|
if (!_confirmed && _cancelledCallback) {
|
||||||
|
@ -364,6 +419,9 @@ void SendFilesBox::initSendWay() {
|
||||||
) | rpl::start_with_next([=](SendFilesWay value) {
|
) | rpl::start_with_next([=](SendFilesWay value) {
|
||||||
updateCaptionPlaceholder();
|
updateCaptionPlaceholder();
|
||||||
updateEmojiPanelGeometry();
|
updateEmojiPanelGeometry();
|
||||||
|
for (auto &block : _blocks) {
|
||||||
|
block.setSendWay(value);
|
||||||
|
}
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
@ -389,73 +447,59 @@ void SendFilesBox::updateCaptionPlaceholder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFilesBox::preparePreview() {
|
void SendFilesBox::preparePreview() {
|
||||||
|
generatePreviewFrom(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendFilesBox::generatePreviewFrom(int fromBlock) {
|
||||||
|
Expects(fromBlock <= _blocks.size());
|
||||||
|
|
||||||
using Type = Ui::PreparedFile::AlbumType;
|
using Type = Ui::PreparedFile::AlbumType;
|
||||||
|
|
||||||
_blocks.clear();
|
_blocks.erase(_blocks.begin() + fromBlock, _blocks.end());
|
||||||
|
|
||||||
|
const auto fromItem = _blocks.empty() ? 0 : _blocks.back().tillIndex();
|
||||||
|
Assert(fromItem <= _list.files.size());
|
||||||
|
|
||||||
auto albumStart = -1;
|
auto albumStart = -1;
|
||||||
const auto finishAlbum = [&](int till) {
|
const auto gifPaused = [controller = _controller] {
|
||||||
if (albumStart < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto count = (till - albumStart);
|
|
||||||
const auto preview = _inner->add(object_ptr<Ui::AlbumPreview>(
|
|
||||||
this,
|
|
||||||
gsl::make_span(_list.files).subspan(albumStart, count),
|
|
||||||
_sendWay.current()));
|
|
||||||
|
|
||||||
auto &block = _blocks.emplace_back();
|
|
||||||
block.fromIndex = albumStart;
|
|
||||||
block.tillIndex = albumStart + count;
|
|
||||||
block.preview.reset(preview);
|
|
||||||
block.preview->show();
|
|
||||||
|
|
||||||
_sendWay.changes(
|
|
||||||
) | rpl::start_with_next([=](SendFilesWay value) {
|
|
||||||
applyAlbumOrder(preview, albumStart);
|
|
||||||
preview->setSendWay(value);
|
|
||||||
}, preview->lifetime());
|
|
||||||
|
|
||||||
albumStart = -1;
|
|
||||||
};
|
|
||||||
const auto finishSingle = [&](int index) {
|
|
||||||
const auto &file = _list.files[index];
|
|
||||||
const auto controller = _controller;
|
|
||||||
auto &block = _blocks.emplace_back();
|
|
||||||
block.fromIndex = index;
|
|
||||||
block.tillIndex = index + 1;
|
|
||||||
const auto media = Ui::SingleMediaPreview::Create(this, [=] {
|
|
||||||
return controller->isGifPausedAtLeastFor(
|
return controller->isGifPausedAtLeastFor(
|
||||||
Window::GifPauseReason::Layer);
|
Window::GifPauseReason::Layer);
|
||||||
}, file);
|
|
||||||
if (media) {
|
|
||||||
block.preview.reset(
|
|
||||||
_inner->add(object_ptr<Ui::SingleMediaPreview>::fromRaw(
|
|
||||||
media)));
|
|
||||||
} else {
|
|
||||||
block.preview.reset(
|
|
||||||
_inner->add(object_ptr<Ui::SingleFilePreview>(this, file)));
|
|
||||||
}
|
|
||||||
block.preview->show();
|
|
||||||
};
|
};
|
||||||
for (auto i = 0, count = int(_list.files.size()); i != count; ++i) {
|
const auto pushBlock = [&](int from, int till) {
|
||||||
|
_blocks.emplace_back(
|
||||||
|
_inner.data(),
|
||||||
|
&_list.files,
|
||||||
|
from,
|
||||||
|
till,
|
||||||
|
gifPaused,
|
||||||
|
_sendWay.current());
|
||||||
|
_inner->add(_blocks.back().takeWidget());
|
||||||
|
};
|
||||||
|
for (auto i = fromItem, till = int(_list.files.size()); i != till; ++i) {
|
||||||
const auto type = _list.files[i].type;
|
const auto type = _list.files[i].type;
|
||||||
if (albumStart >= 0) {
|
if (albumStart >= 0) {
|
||||||
const auto albumCount = (i - albumStart);
|
const auto albumCount = (i - albumStart);
|
||||||
if (type == Type::File || (albumCount == Ui::MaxAlbumItems())) {
|
if ((type == Type::File)
|
||||||
finishAlbum(i);
|
|| (type == Type::None)
|
||||||
|
|| (albumCount == Ui::MaxAlbumItems())) {
|
||||||
|
pushBlock(std::exchange(albumStart, -1), i);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type != Type::File) {
|
if (type != Type::File && type != Type::None) {
|
||||||
if (albumStart < 0) {
|
if (albumStart < 0) {
|
||||||
albumStart = i;
|
albumStart = i;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
finishSingle(i);
|
pushBlock(i, i + 1);
|
||||||
}
|
}
|
||||||
finishAlbum(_list.files.size());
|
if (albumStart >= 0) {
|
||||||
|
pushBlock(albumStart, _list.files.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
_scroll->scrollToY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFilesBox::setupControls() {
|
void SendFilesBox::setupControls() {
|
||||||
|
@ -520,32 +564,6 @@ void SendFilesBox::updateSendWayControlsVisibility() {
|
||||||
_groupFiles->setVisible(!onlyOne);
|
_groupFiles->setVisible(!onlyOne);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFilesBox::applyAlbumOrder(
|
|
||||||
not_null<Ui::AlbumPreview*> preview,
|
|
||||||
int from) {
|
|
||||||
const auto order = preview->takeOrder();
|
|
||||||
const auto isDefault = [&] {
|
|
||||||
for (auto i = 0, count = int(order.size()); i != count; ++i) {
|
|
||||||
if (order[i] != i) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
if (isDefault) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto elements = std::vector<Ui::PreparedFile>();
|
|
||||||
elements.reserve(order.size());
|
|
||||||
for (const auto index : order) {
|
|
||||||
elements.push_back(std::move(_list.files[from + index]));
|
|
||||||
}
|
|
||||||
for (auto i = 0, count = int(order.size()); i != count; ++i) {
|
|
||||||
_list.files[from + i] = std::move(elements[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendFilesBox::setupCaption() {
|
void SendFilesBox::setupCaption() {
|
||||||
_caption->setMaxLength(
|
_caption->setMaxLength(
|
||||||
_controller->session().serverConfig().captionLengthMax);
|
_controller->session().serverConfig().captionLengthMax);
|
||||||
|
@ -854,7 +872,9 @@ void SendFilesBox::send(
|
||||||
Core::App().saveSettingsDelayed();
|
Core::App().saveSettingsDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
//applyAlbumOrder(); // #TODO files
|
for (auto &block : _blocks) {
|
||||||
|
block.applyAlbumOrder();
|
||||||
|
}
|
||||||
_confirmed = true;
|
_confirmed = true;
|
||||||
if (_confirmedCallback) {
|
if (_confirmedCallback) {
|
||||||
auto caption = (_caption && !_caption->isHidden())
|
auto caption = (_caption && !_caption->isHidden())
|
||||||
|
|
|
@ -84,10 +84,32 @@ protected:
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Block {
|
class Block final {
|
||||||
base::unique_qptr<Ui::RpWidget> preview;
|
public:
|
||||||
int fromIndex = 0;
|
Block(
|
||||||
int tillIndex = 0;
|
not_null<QWidget*> parent,
|
||||||
|
not_null<std::vector<Ui::PreparedFile>*> items,
|
||||||
|
int from,
|
||||||
|
int till,
|
||||||
|
Fn<bool()> gifPaused,
|
||||||
|
Ui::SendFilesWay way);
|
||||||
|
Block(Block &&other) = default;
|
||||||
|
Block &operator=(Block &&other) = default;
|
||||||
|
|
||||||
|
[[nodiscard]] int fromIndex() const;
|
||||||
|
[[nodiscard]] int tillIndex() const;
|
||||||
|
[[nodiscard]] object_ptr<Ui::RpWidget> takeWidget();
|
||||||
|
|
||||||
|
void setSendWay(Ui::SendFilesWay way);
|
||||||
|
void applyAlbumOrder();
|
||||||
|
|
||||||
|
private:
|
||||||
|
base::unique_qptr<Ui::RpWidget> _preview;
|
||||||
|
not_null<std::vector<Ui::PreparedFile>*> _items;
|
||||||
|
int _from = 0;
|
||||||
|
int _till = 0;
|
||||||
|
bool _isAlbum = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
void initSendWay();
|
void initSendWay();
|
||||||
void initPreview();
|
void initPreview();
|
||||||
|
@ -95,9 +117,7 @@ private:
|
||||||
void setupControls();
|
void setupControls();
|
||||||
void setupSendWayControls();
|
void setupSendWayControls();
|
||||||
void setupCaption();
|
void setupCaption();
|
||||||
void setupShadows(
|
void setupShadows();
|
||||||
not_null<Ui::ScrollArea*> wrap,
|
|
||||||
not_null<Ui::AlbumPreview*> content);
|
|
||||||
|
|
||||||
void setupEmojiPanel();
|
void setupEmojiPanel();
|
||||||
void updateSendWayControlsVisibility();
|
void updateSendWayControlsVisibility();
|
||||||
|
@ -105,7 +125,7 @@ private:
|
||||||
void emojiFilterForGeometry(not_null<QEvent*> event);
|
void emojiFilterForGeometry(not_null<QEvent*> event);
|
||||||
|
|
||||||
void preparePreview();
|
void preparePreview();
|
||||||
void applyAlbumOrder(not_null<Ui::AlbumPreview*> preview, int from);
|
void generatePreviewFrom(int fromBlock);
|
||||||
|
|
||||||
void send(Api::SendOptions options, bool ctrlShiftEnter = false);
|
void send(Api::SendOptions options, bool ctrlShiftEnter = false);
|
||||||
void sendSilent();
|
void sendSilent();
|
||||||
|
|
|
@ -97,6 +97,8 @@ bool PrepareDetailsIsWaiting(
|
||||||
Assert(!file.preview.isNull());
|
Assert(!file.preview.isNull());
|
||||||
file.preview.setDevicePixelRatio(cRetinaFactor());
|
file.preview.setDevicePixelRatio(cRetinaFactor());
|
||||||
file.type = PreparedFile::AlbumType::Photo;
|
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>(
|
} else if (const auto video = std::get_if<Video>(
|
||||||
&file.information->media)) {
|
&file.information->media)) {
|
||||||
|
@ -257,7 +259,7 @@ PreparedList PrepareMediaFromImage(
|
||||||
QImage &&image,
|
QImage &&image,
|
||||||
QByteArray &&content,
|
QByteArray &&content,
|
||||||
int previewWidth) {
|
int previewWidth) {
|
||||||
auto result = Storage::PreparedList();
|
auto result = PreparedList();
|
||||||
auto file = PreparedFile(QString());
|
auto file = PreparedFile(QString());
|
||||||
file.content = content;
|
file.content = content;
|
||||||
if (file.content.isEmpty()) {
|
if (file.content.isEmpty()) {
|
||||||
|
@ -283,7 +285,7 @@ std::optional<PreparedList> PreparedFileFromFilesDialog(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.remoteContent.isEmpty()) {
|
if (!result.remoteContent.isEmpty()) {
|
||||||
auto list = Storage::PrepareMediaFromImage(
|
auto list = PrepareMediaFromImage(
|
||||||
QImage(),
|
QImage(),
|
||||||
std::move(result.remoteContent),
|
std::move(result.remoteContent),
|
||||||
previewWidth);
|
previewWidth);
|
||||||
|
@ -297,7 +299,8 @@ std::optional<PreparedList> PreparedFileFromFilesDialog(
|
||||||
if (isAlbum) {
|
if (isAlbum) {
|
||||||
const auto file = &list.files.front();
|
const auto file = &list.files.front();
|
||||||
if (!Core::IsMimeAcceptedForAlbum(mimeFile)
|
if (!Core::IsMimeAcceptedForAlbum(mimeFile)
|
||||||
|| file->type == Storage::PreparedFile::AlbumType::File) {
|
|| file->type == PreparedFile::AlbumType::File
|
||||||
|
|| file->type == PreparedFile::AlbumType::File) {
|
||||||
errorCallback(tr::lng_edit_media_album_error);
|
errorCallback(tr::lng_edit_media_album_error);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -306,7 +309,7 @@ std::optional<PreparedList> PreparedFileFromFilesDialog(
|
||||||
return list;
|
return list;
|
||||||
} else if (!result.paths.isEmpty()) {
|
} else if (!result.paths.isEmpty()) {
|
||||||
const auto isSingleFile = (result.paths.size() == 1);
|
const auto isSingleFile = (result.paths.size() == 1);
|
||||||
auto temp = Storage::PrepareMediaList(result.paths, previewWidth);
|
auto temp = PrepareMediaList(result.paths, previewWidth);
|
||||||
if (temp.error != PreparedList::Error::None) {
|
if (temp.error != PreparedList::Error::None) {
|
||||||
errorCallback(tr::lng_send_media_invalid_files);
|
errorCallback(tr::lng_send_media_invalid_files);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
@ -22,13 +22,12 @@ constexpr auto kDragDuration = crl::time(200);
|
||||||
|
|
||||||
AlbumPreview::AlbumPreview(
|
AlbumPreview::AlbumPreview(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
gsl::span<PreparedFile> list,
|
gsl::span<Ui::PreparedFile> items,
|
||||||
SendFilesWay way)
|
SendFilesWay way)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _list(list)
|
|
||||||
, _sendWay(way) {
|
, _sendWay(way) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
prepareThumbs();
|
prepareThumbs(items);
|
||||||
updateSize();
|
updateSize();
|
||||||
updateFileRows();
|
updateFileRows();
|
||||||
}
|
}
|
||||||
|
@ -55,25 +54,26 @@ void AlbumPreview::updateFileRows() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> AlbumPreview::takeOrder() {
|
std::vector<int> AlbumPreview::takeOrder() {
|
||||||
|
Expects(_thumbs.size() == _order.size());
|
||||||
|
Expects(_itemsShownDimensions.size() == _order.size());
|
||||||
|
|
||||||
auto reordered = std::vector<std::unique_ptr<AlbumThumbnail>>();
|
auto reordered = std::vector<std::unique_ptr<AlbumThumbnail>>();
|
||||||
|
auto reorderedShownDimensions = std::vector<QSize>();
|
||||||
reordered.reserve(_thumbs.size());
|
reordered.reserve(_thumbs.size());
|
||||||
|
reorderedShownDimensions.reserve(_itemsShownDimensions.size());
|
||||||
for (auto index : _order) {
|
for (auto index : _order) {
|
||||||
reordered.push_back(std::move(_thumbs[index]));
|
reordered.push_back(std::move(_thumbs[index]));
|
||||||
|
reorderedShownDimensions.push_back(_itemsShownDimensions[index]);
|
||||||
}
|
}
|
||||||
_thumbs = std::move(reordered);
|
_thumbs = std::move(reordered);
|
||||||
|
_itemsShownDimensions = std::move(reorderedShownDimensions);
|
||||||
return std::exchange(_order, defaultOrder());
|
return std::exchange(_order, defaultOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AlbumPreview::generateOrderedLayout() const
|
auto AlbumPreview::generateOrderedLayout() const
|
||||||
-> std::vector<GroupMediaLayout> {
|
-> std::vector<GroupMediaLayout> {
|
||||||
auto sizes = ranges::view::all(
|
|
||||||
_order
|
|
||||||
) | ranges::view::transform([&](int index) {
|
|
||||||
return _list[index].shownDimensions;
|
|
||||||
}) | ranges::to_vector;
|
|
||||||
|
|
||||||
auto layout = LayoutMediaGroup(
|
auto layout = LayoutMediaGroup(
|
||||||
sizes,
|
_itemsShownDimensions,
|
||||||
st::sendMediaPreviewSize,
|
st::sendMediaPreviewSize,
|
||||||
st::historyGroupWidthMin / 2,
|
st::historyGroupWidthMin / 2,
|
||||||
st::historyGroupSkip / 2);
|
st::historyGroupSkip / 2);
|
||||||
|
@ -81,20 +81,29 @@ auto AlbumPreview::generateOrderedLayout() const
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> AlbumPreview::defaultOrder() const {
|
std::vector<int> AlbumPreview::defaultOrder(int count) const {
|
||||||
const auto count = int(_list.size());
|
Expects(count > 0 || !_order.empty());
|
||||||
|
|
||||||
|
if (count < 0) {
|
||||||
|
count = _order.size();
|
||||||
|
}
|
||||||
return ranges::view::ints(0, count) | ranges::to_vector;
|
return ranges::view::ints(0, count) | ranges::to_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlbumPreview::prepareThumbs() {
|
void AlbumPreview::prepareThumbs(gsl::span<Ui::PreparedFile> items) {
|
||||||
_order = defaultOrder();
|
_order = defaultOrder(items.size());
|
||||||
|
_itemsShownDimensions = ranges::view::all(
|
||||||
|
_order
|
||||||
|
) | ranges::view::transform([&](int index) {
|
||||||
|
return items[index].shownDimensions;
|
||||||
|
}) | ranges::to_vector;
|
||||||
|
|
||||||
const auto count = int(_list.size());
|
const auto count = int(_order.size());
|
||||||
const auto layout = generateOrderedLayout();
|
const auto layout = generateOrderedLayout();
|
||||||
_thumbs.reserve(count);
|
_thumbs.reserve(count);
|
||||||
for (auto i = 0; i != count; ++i) {
|
for (auto i = 0; i != count; ++i) {
|
||||||
_thumbs.push_back(std::make_unique<AlbumThumbnail>(
|
_thumbs.push_back(std::make_unique<AlbumThumbnail>(
|
||||||
_list[i],
|
items[i],
|
||||||
layout[i],
|
layout[i],
|
||||||
this,
|
this,
|
||||||
[=] { changeThumbByIndex(thumbIndex(thumbUnderCursor())); },
|
[=] { changeThumbByIndex(thumbIndex(thumbUnderCursor())); },
|
||||||
|
|
|
@ -20,7 +20,7 @@ class AlbumPreview final : public RpWidget {
|
||||||
public:
|
public:
|
||||||
AlbumPreview(
|
AlbumPreview(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
gsl::span<PreparedFile> list,
|
gsl::span<Ui::PreparedFile> items,
|
||||||
SendFilesWay way);
|
SendFilesWay way);
|
||||||
~AlbumPreview();
|
~AlbumPreview();
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ private:
|
||||||
int countLayoutHeight(
|
int countLayoutHeight(
|
||||||
const std::vector<GroupMediaLayout> &layout) const;
|
const std::vector<GroupMediaLayout> &layout) const;
|
||||||
std::vector<GroupMediaLayout> generateOrderedLayout() const;
|
std::vector<GroupMediaLayout> generateOrderedLayout() const;
|
||||||
std::vector<int> defaultOrder() const;
|
std::vector<int> defaultOrder(int count = -1) const;
|
||||||
void prepareThumbs();
|
void prepareThumbs(gsl::span<Ui::PreparedFile> items);
|
||||||
void updateSizeAnimated(const std::vector<GroupMediaLayout> &layout);
|
void updateSizeAnimated(const std::vector<GroupMediaLayout> &layout);
|
||||||
void updateSize();
|
void updateSize();
|
||||||
void updateFileRows();
|
void updateFileRows();
|
||||||
|
@ -73,10 +73,10 @@ private:
|
||||||
void cancelDrag();
|
void cancelDrag();
|
||||||
void finishDrag();
|
void finishDrag();
|
||||||
|
|
||||||
gsl::span<PreparedFile> _list;
|
|
||||||
SendFilesWay _sendWay;
|
SendFilesWay _sendWay;
|
||||||
style::cursor _cursor = style::cur_default;
|
style::cursor _cursor = style::cur_default;
|
||||||
std::vector<int> _order;
|
std::vector<int> _order;
|
||||||
|
std::vector<QSize> _itemsShownDimensions;
|
||||||
std::vector<std::unique_ptr<AlbumThumbnail>> _thumbs;
|
std::vector<std::unique_ptr<AlbumThumbnail>> _thumbs;
|
||||||
int _thumbsHeight = 0;
|
int _thumbsHeight = 0;
|
||||||
int _photosHeight = 0;
|
int _photosHeight = 0;
|
||||||
|
|
|
@ -127,12 +127,12 @@ void AlbumThumbnail::updateFileRow(int row) {
|
||||||
const auto fileHeight = st::sendMediaFileThumbSize
|
const auto fileHeight = st::sendMediaFileThumbSize
|
||||||
+ st::sendMediaFileThumbSkip;
|
+ st::sendMediaFileThumbSkip;
|
||||||
|
|
||||||
const auto top = row * fileHeight + st::sendBoxAlbumGroupSkipTop;
|
const auto top = row * fileHeight + st::sendBoxFileGroupSkipTop;
|
||||||
const auto size = st::editMediaButtonSize;
|
const auto size = st::editMediaButtonSize;
|
||||||
|
|
||||||
auto right = st::sendBoxAlbumGroupSkipRight + size;
|
auto right = st::sendBoxFileGroupSkipRight + size;
|
||||||
_deleteMedia->moveToRight(right, top);
|
_deleteMedia->moveToRight(right, top);
|
||||||
right += st::sendBoxAlbumGroupEditInternalSkip + size;
|
right += st::sendBoxFileGroupEditInternalSkip + size;
|
||||||
_editMedia->moveToRight(right, top);
|
_editMedia->moveToRight(right, top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,10 @@ bool PreparedList::canBeSentInSlowmode() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto hasNonGrouping = ranges::contains(
|
||||||
|
files,
|
||||||
|
PreparedFile::AlbumType::None,
|
||||||
|
&PreparedFile::type);
|
||||||
const auto hasFiles = ranges::contains(
|
const auto hasFiles = ranges::contains(
|
||||||
files,
|
files,
|
||||||
PreparedFile::AlbumType::File,
|
PreparedFile::AlbumType::File,
|
||||||
|
@ -78,7 +82,7 @@ bool PreparedList::canBeSentInSlowmode() const {
|
||||||
&PreparedFile::type);
|
&PreparedFile::type);
|
||||||
|
|
||||||
// File-s and Video-s never can be grouped.
|
// File-s and Video-s never can be grouped.
|
||||||
return !hasFiles || !hasVideos;
|
return !hasNonGrouping && (!hasFiles || !hasVideos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PreparedList::canAddCaption(bool groupMediaInAlbums) const {
|
bool PreparedList::canAddCaption(bool groupMediaInAlbums) const {
|
||||||
|
|
|
@ -46,6 +46,7 @@ struct PreparedFile {
|
||||||
File,
|
File,
|
||||||
Photo,
|
Photo,
|
||||||
Video,
|
Video,
|
||||||
|
None,
|
||||||
};
|
};
|
||||||
|
|
||||||
PreparedFile(const QString &path);
|
PreparedFile(const QString &path);
|
||||||
|
|
Loading…
Add table
Reference in a new issue