Simplify file sending, always attach a caption.

This commit is contained in:
John Preston
2026-03-06 21:08:22 +04:00
parent 2de7fb5c25
commit 5507e9c00d
19 changed files with 288 additions and 684 deletions
+13 -85
View File
@@ -6331,47 +6331,13 @@ void HistoryWidget::updateFieldPlaceholder() {
bool HistoryWidget::showSendingFilesError(
const Ui::PreparedList &list) const {
return showSendingFilesError(list, std::nullopt);
const auto show = controller()->uiShow();
return Data::ShowSendError(show, _peer, list, std::nullopt);
}
bool HistoryWidget::showSendingFilesError(
const Ui::PreparedList &list,
std::optional<bool> compress) const {
const auto error = [&]() -> Data::SendError {
const auto error = _peer
? Data::FileRestrictionError(_peer, list, compress)
: Data::SendError();
if (!_peer || error) {
return error;
} else if (const auto left = _peer->slowmodeSecondsLeft()) {
return tr::lng_slowmode_enabled(
tr::now,
lt_left,
Ui::FormatDurationWordsSlowmode(left));
}
using Error = Ui::PreparedList::Error;
switch (list.error) {
case Error::None: return QString();
case Error::EmptyFile:
case Error::Directory:
case Error::NonLocalUrl: return tr::lng_send_image_empty(
tr::now,
lt_name,
list.errorData);
case Error::TooLargeFile: return u"(toolarge)"_q;
}
return tr::lng_forward_send_files_cant(tr::now);
}();
if (!error) {
return false;
} else if (error.text == u"(toolarge)"_q) {
const auto fileSize = list.files.back().size;
controller()->show(
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
return true;
}
Data::ShowSendErrorToast(controller(), _peer, error);
return true;
const Ui::PreparedBundle &bundle) const {
return Data::ShowSendError(controller()->uiShow(), _peer, bundle);
}
MsgId HistoryWidget::resolveReplyToTopicRootId() {
@@ -6467,7 +6433,7 @@ bool HistoryWidget::confirmSendingFiles(
}
controller()->showToast(tr::lng_edit_caption_attach(tr::now));
return false;
} else if (showSendingFilesError(list)) {
} else if (!_peer || showSendingFilesError(list)) {
return false;
}
@@ -6484,17 +6450,9 @@ bool HistoryWidget::confirmSendingFiles(
sendMenuDetails());
_field->setTextWithTags({});
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
sendingFilesConfirmed(
std::move(list),
way,
std::move(caption),
options,
ctrlShiftEnter);
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
sendingFilesConfirmed(std::move(bundle), options);
}));
box->setCancelledCallback(crl::guard(this, [=] {
_field->setTextWithTags(text);
@@ -6519,33 +6477,12 @@ bool HistoryWidget::confirmSendingFiles(
}
void HistoryWidget::sendingFilesConfirmed(
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
Expects(list.filesToProcess.empty());
const auto compress = way.sendImagesAsPhotos();
if (showSendingFilesError(list, compress)) {
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
if (!_peer || showSendingFilesError(*bundle)) {
return;
}
auto groups = DivideByGroups(
std::move(list),
way,
_peer->slowmodeApplied());
auto bundle = PrepareFilesBundle(
std::move(groups),
way,
std::move(caption),
ctrlShiftEnter);
sendingFilesConfirmed(std::move(bundle), options);
}
void HistoryWidget::sendingFilesConfirmed(
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
const auto compress = bundle->way.sendImagesAsPhotos();
const auto type = compress ? SendMediaType::Photo : SendMediaType::File;
auto action = prepareSendAction(options);
@@ -6564,21 +6501,12 @@ void HistoryWidget::sendingFilesConfirmed(
return;
}
if (bundle->sendComment) {
auto message = Api::MessageToSend(action);
message.textWithTags = base::take(bundle->caption);
session().api().sendMessage(std::move(message));
}
auto &api = session().api();
for (auto &group : bundle->groups) {
const auto album = (group.type != Ui::AlbumType::None)
? std::make_shared<SendingAlbum>()
: nullptr;
session().api().sendFiles(
std::move(group.list),
type,
base::take(bundle->caption),
album,
action);
api.sendFiles(std::move(group.list), type, album, action);
}
}
@@ -484,21 +484,14 @@ private:
Ui::PreparedList &&list,
const QString &insertTextOnCancel = QString());
bool showSendingFilesError(const Ui::PreparedList &list) const;
bool showSendingFilesError(
const Ui::PreparedList &list,
std::optional<bool> compress) const;
bool showSendingFilesError(const Ui::PreparedBundle &bundle) const;
bool showSendMessageError(
const TextWithTags &textWithTags,
bool ignoreSlowmodeCountdown,
Fn<void(int starsApproved)> withPaymentApproved = nullptr,
Api::SendOptions options = {});
void sendingFilesConfirmed(
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter);
void sendingFilesConfirmed(
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options);
@@ -1168,17 +1168,9 @@ bool ChatWidget::confirmSendingFiles(
sendMenuDetails());
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
sendingFilesConfirmed(
std::move(list),
way,
std::move(caption),
options,
ctrlShiftEnter);
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
sendingFilesConfirmed(std::move(bundle), options);
}));
box->setCancelledCallback(_composeControls->restoreTextCallback(
insertTextOnCancel));
@@ -1192,29 +1184,6 @@ bool ChatWidget::confirmSendingFiles(
return true;
}
void ChatWidget::sendingFilesConfirmed(
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
Expects(list.filesToProcess.empty());
if (showSendingFilesError(list, way.sendImagesAsPhotos())) {
return;
}
auto groups = DivideByGroups(
std::move(list),
way,
_peer->slowmodeApplied());
auto bundle = PrepareFilesBundle(
std::move(groups),
way,
std::move(caption),
ctrlShiftEnter);
sendingFilesConfirmed(std::move(bundle), options);
}
bool ChatWidget::checkSendPayment(
int messagesCount,
Api::SendOptions options,
@@ -1230,6 +1199,10 @@ bool ChatWidget::checkSendPayment(
void ChatWidget::sendingFilesConfirmed(
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
if (showSendingFilesError(*bundle)) {
return;
}
const auto withPaymentApproved = [=](int approved) {
auto copy = options;
copy.starsApproved = approved;
@@ -1247,21 +1220,12 @@ void ChatWidget::sendingFilesConfirmed(
const auto type = compress ? SendMediaType::Photo : SendMediaType::File;
auto action = prepareSendAction(options);
action.clearDraft = false;
if (bundle->sendComment) {
auto message = Api::MessageToSend(action);
message.textWithTags = base::take(bundle->caption);
session().api().sendMessage(std::move(message));
}
auto &api = session().api();
for (auto &group : bundle->groups) {
const auto album = (group.type != Ui::AlbumType::None)
? std::make_shared<SendingAlbum>()
: nullptr;
session().api().sendFiles(
std::move(group.list),
type,
base::take(bundle->caption),
album,
action);
api.sendFiles(std::move(group.list), type, album, action);
}
if (_composeControls->replyingToMessage().messageId
== action.replyTo.messageId) {
@@ -1342,47 +1306,13 @@ void ChatWidget::uploadFile(
bool ChatWidget::showSendingFilesError(
const Ui::PreparedList &list) const {
return showSendingFilesError(list, std::nullopt);
const auto show = controller()->uiShow();
return Data::ShowSendError(show, _peer, list, std::nullopt);
}
bool ChatWidget::showSendingFilesError(
const Ui::PreparedList &list,
std::optional<bool> compress) const {
const auto error = [&]() -> Data::SendError {
const auto peer = _peer;
const auto error = Data::FileRestrictionError(peer, list, compress);
if (error) {
return error;
} else if (const auto left = _peer->slowmodeSecondsLeft()) {
return tr::lng_slowmode_enabled(
tr::now,
lt_left,
Ui::FormatDurationWordsSlowmode(left));
}
using Error = Ui::PreparedList::Error;
switch (list.error) {
case Error::None: return QString();
case Error::EmptyFile:
case Error::Directory:
case Error::NonLocalUrl: return tr::lng_send_image_empty(
tr::now,
lt_name,
list.errorData);
case Error::TooLargeFile: return u"(toolarge)"_q;
}
return tr::lng_forward_send_files_cant(tr::now);
}();
if (!error) {
return false;
} else if (error.text == u"(toolarge)"_q) {
const auto fileSize = list.files.back().size;
controller()->show(
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
return true;
}
Data::ShowSendErrorToast(controller(), _peer, error);
return true;
const Ui::PreparedBundle &bundle) const {
return Data::ShowSendError(controller()->uiShow(), _peer, bundle);
}
Api::SendAction ChatWidget::prepareSendAction(
@@ -341,15 +341,8 @@ private:
std::optional<bool> overrideSendImagesAsPhotos,
const QString &insertTextOnCancel = QString());
bool showSendingFilesError(const Ui::PreparedList &list) const;
bool showSendingFilesError(
const Ui::PreparedList &list,
std::optional<bool> compress) const;
void sendingFilesConfirmed(
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter);
bool showSendingFilesError(const Ui::PreparedBundle &bundle) const;
void sendingFilesConfirmed(
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options);
@@ -567,17 +567,9 @@ bool ScheduledWidget::confirmSendingFiles(
SendMenu::Details());
box->setConfirmedCallback(crl::guard(this, [=](
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
sendingFilesConfirmed(
std::move(list),
way,
std::move(caption),
options,
ctrlShiftEnter);
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
sendingFilesConfirmed(std::move(bundle), options);
}));
box->setCancelledCallback(_composeControls->restoreTextCallback(
insertTextOnCancel));
@@ -592,46 +584,29 @@ bool ScheduledWidget::confirmSendingFiles(
}
void ScheduledWidget::sendingFilesConfirmed(
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter) {
Expects(list.filesToProcess.empty());
if (showSendingFilesError(list, way.sendImagesAsPhotos())) {
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
if (showSendingFilesError(*bundle)) {
return;
}
auto groups = DivideByGroups(std::move(list), way, false);
const auto captionAttached = CaptionWillBeAttached(groups);
const auto type = way.sendImagesAsPhotos()
? SendMediaType::Photo
: SendMediaType::File;
const auto compress = bundle->way.sendImagesAsPhotos();
const auto type = compress ? SendMediaType::Photo : SendMediaType::File;
auto action = prepareSendAction(options);
action.clearDraft = false;
if (!captionAttached && !caption.text.isEmpty()) {
auto message = Api::MessageToSend(action);
message.textWithTags = base::take(caption);
session().api().sendMessage(std::move(message));
}
for (auto &group : groups) {
auto &api = session().api();
for (auto &group : bundle->groups) {
const auto album = (group.type != Ui::AlbumType::None)
? std::make_shared<SendingAlbum>()
: nullptr;
session().api().sendFiles(
std::move(group.list),
type,
base::take(caption),
album,
action);
api.sendFiles(std::move(group.list), type, album, action);
}
}
bool ScheduledWidget::confirmSendingFiles(
QImage &&image,
QByteArray &&content,
std::optional<bool> overrideSendImagesAsPhotos,
const QString &insertTextOnCancel) {
QImage &&image,
QByteArray &&content,
std::optional<bool> overrideSendImagesAsPhotos,
const QString &insertTextOnCancel) {
if (image.isNull()) {
return false;
}
@@ -667,8 +642,8 @@ void ScheduledWidget::checkReplyReturns() {
}
void ScheduledWidget::uploadFile(
const QByteArray &fileContent,
SendMediaType type) {
const QByteArray &fileContent,
SendMediaType type) {
const auto callback = [=](Api::SendOptions options) {
session().api().sendFile(
fileContent,
@@ -680,46 +655,20 @@ void ScheduledWidget::uploadFile(
}
bool ScheduledWidget::showSendingFilesError(
const Ui::PreparedList &list) const {
return showSendingFilesError(list, std::nullopt);
const Ui::PreparedList &list) const {
const auto peer = _history->peer;
const auto show = controller()->uiShow();
return Data::ShowSendError(show, peer, list, std::nullopt, true);
}
bool ScheduledWidget::showSendingFilesError(
const Ui::PreparedList &list,
std::optional<bool> compress) const {
const auto error = [&]() -> Data::SendError {
using Error = Ui::PreparedList::Error;
const auto peer = _history->peer;
const auto error = Data::FileRestrictionError(peer, list, compress);
if (error) {
return error;
} else switch (list.error) {
case Error::None: return QString();
case Error::EmptyFile:
case Error::Directory:
case Error::NonLocalUrl: return tr::lng_send_image_empty(
tr::now,
lt_name,
list.errorData);
case Error::TooLargeFile: return u"(toolarge)"_q;
}
return tr::lng_forward_send_files_cant(tr::now);
}();
if (!error) {
return false;
} else if (error.text == u"(toolarge)"_q) {
const auto fileSize = list.files.back().size;
controller()->show(
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
return true;
}
Data::ShowSendErrorToast(controller(), _history->peer, error);
return true;
const Ui::PreparedBundle &bundle) const {
const auto show = controller()->uiShow();
return Data::ShowSendError(show, _history->peer, bundle, true);
}
Api::SendAction ScheduledWidget::prepareSendAction(
Api::SendOptions options) const {
Api::SendOptions options) const {
auto result = Api::SendAction(_history, options);
result.options.sendAs = _composeControls->sendAsPeer();
if (_forumTopic) {
@@ -40,6 +40,7 @@ class ScrollArea;
class PlainShadow;
class FlatButton;
struct PreparedList;
struct PreparedBundle;
class SendFilesWay;
class ImportantTooltip;
} // namespace Ui
@@ -256,15 +257,11 @@ private:
std::optional<bool> overrideSendImagesAsPhotos,
const QString &insertTextOnCancel = QString());
bool showSendingFilesError(const Ui::PreparedList &list) const;
bool showSendingFilesError(
const Ui::PreparedList &list,
std::optional<bool> compress) const;
bool showSendingFilesError(const Ui::PreparedBundle &bundle) const;
void sendingFilesConfirmed(
Ui::PreparedList &&list,
Ui::SendFilesWay way,
TextWithTags &&caption,
Api::SendOptions options,
bool ctrlShiftEnter);
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options);
bool sendExistingDocument(
not_null<DocumentData*> document,