Added support of draw-to-reply from shared media.

This commit is contained in:
23rd
2026-04-13 10:07:20 +03:00
parent de737b3cbe
commit 52615a3ccb
12 changed files with 236 additions and 41 deletions
@@ -0,0 +1,147 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "window/window_session_controller.h"
#include "apiwrap.h"
#include "boxes/send_files_box.h"
#include "data/data_forum_topic.h"
#include "data/data_peer.h"
#include "data/data_saved_sublist.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/view/history_view_draw_to_reply.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "mainwidget.h"
#include "data/data_session.h"
#include "data/data_thread.h"
#include "storage/localimageloader.h"
#include "storage/storage_media_prepare.h"
#include "styles/style_boxes.h"
#include "window/window_separate_id.h"
namespace Window {
void SessionController::handleDrawToReplyRequest(
Data::DrawToReplyRequest request) {
if (content()->handleDrawToReplyRequest(request)) {
return;
}
auto image = HistoryView::ResolveDrawToReplyImage(
&session().data(),
request);
if (image.isNull()) {
return;
}
HistoryView::OpenDrawToReplyEditor(
this,
std::move(image),
crl::guard(this, [=](QImage &&result) {
if (result.isNull()) {
return;
}
const auto thread = resolveDrawToReplyThread(request);
if (!thread) {
return;
}
auto list = Storage::PrepareMediaFromImage(
std::move(result),
QByteArray(),
st::sendMediaPreviewSize);
showDrawToReplyFilesBox(
thread,
request.messageId,
std::move(list));
}));
}
Data::Thread *SessionController::resolveDrawToReplyThread(
const Data::DrawToReplyRequest &request) const {
if (const auto item = session().data().message(request.messageId)) {
if (const auto topic = item->topic()) {
return topic;
} else if (const auto sublist = item->savedSublist()) {
return sublist;
}
return item->history();
}
if (const auto thread = activeChatCurrent().thread()) {
if (thread->peer()->id == request.messageId.peer) {
return thread;
}
}
if (const auto thread = windowId().thread) {
if (thread->peer()->id == request.messageId.peer) {
return thread;
}
}
return session().data().historyLoaded(request.messageId.peer);
}
void SessionController::showDrawToReplyFilesBox(
not_null<Data::Thread*> thread,
FullMsgId replyTo,
Ui::PreparedList &&list) {
const auto weak = base::make_weak(thread);
const auto peer = thread->peer();
const auto show = uiShow();
show->show(Box<SendFilesBox>(SendFilesBoxDescriptor{
.show = show,
.list = std::move(list),
.caption = TextWithTags(),
.toPeer = peer,
.limits = DefaultLimitsForPeer(peer),
.check = DefaultCheckForPeer(show, peer),
.sendType = Api::SendType::Normal,
.confirmed = crl::guard(this, [=](
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
if (const auto thread = weak.get()) {
sendDrawToReplyFiles(
thread,
replyTo,
std::move(bundle),
options);
}
}),
}));
}
void SessionController::sendDrawToReplyFiles(
not_null<Data::Thread*> thread,
FullMsgId replyTo,
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options) {
if (!bundle) {
return;
}
const auto type = bundle->way.sendImagesAsPhotos()
? SendMediaType::Photo
: SendMediaType::File;
auto action = Api::SendAction(thread, options);
action.clearDraft = false;
action.replyTo = {
.messageId = replyTo,
.topicRootId = thread->topicRootId(),
.monoforumPeerId = thread->monoforumPeerId(),
};
auto &api = session().api();
auto sent = false;
for (auto &group : bundle->groups) {
const auto album = (group.type != Ui::AlbumType::None)
? std::make_shared<SendingAlbum>()
: nullptr;
api.sendFiles(std::move(group.list), type, album, action);
sent = true;
}
if (sent) {
showToast(tr::lng_stories_reply_sent(tr::now));
}
}
} // namespace Window
@@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_saved_messages.h"
#include "data/data_saved_sublist.h"
#include "data/data_session.h"
#include "data/data_thread.h"
#include "data/data_file_origin.h"
#include "data/data_flags.h"
#include "data/data_folder.h"
@@ -118,6 +119,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/cloud_password/settings_cloud_password_start.h"
#include "settings/cloud_password/settings_cloud_password_email_confirm.h"
#include "settings/sections/settings_main.h"
#include "styles/style_chat.h"
#include "settings/sections/settings_premium.h"
#include "settings/sections/settings_privacy_security.h"
#include "styles/style_window.h"
@@ -1875,6 +1877,10 @@ void SessionController::init() {
if (session().supportMode()) {
session().supportHelper().registerWindow(this);
}
session().data().drawToReplyRequests(
) | rpl::on_next([=](Data::DrawToReplyRequest request) {
handleDrawToReplyRequest(std::move(request));
}, lifetime());
setupShortcuts();
}
@@ -26,6 +26,7 @@ enum class WindowLayout;
namespace Data {
struct StoriesContext;
struct DrawToReplyRequest;
class SavedMessages;
enum class StorySourcesList : uchar;
} // namespace Data
@@ -70,8 +71,14 @@ struct ChatThemeBackgroundData;
class MessageSendingAnimationController;
struct BoostCounters;
struct ChatPaintContextArgs;
struct PreparedList;
struct PreparedBundle;
} // namespace Ui
namespace Api {
struct SendOptions;
} // namespace Api
namespace Data {
struct CloudTheme;
enum class CloudThemeType;
@@ -783,6 +790,18 @@ private:
[[nodiscard]] bool openPhotoExternal(
not_null<PhotoData*> photo,
Data::FileOrigin origin);
void handleDrawToReplyRequest(Data::DrawToReplyRequest request);
[[nodiscard]] Data::Thread *resolveDrawToReplyThread(
const Data::DrawToReplyRequest &request) const;
void showDrawToReplyFilesBox(
not_null<Data::Thread*> thread,
FullMsgId replyTo,
Ui::PreparedList &&list);
void sendDrawToReplyFiles(
not_null<Data::Thread*> thread,
FullMsgId replyTo,
std::shared_ptr<Ui::PreparedBundle> bundle,
Api::SendOptions options);
const not_null<Controller*> _window;
const std::unique_ptr<ChatHelpers::EmojiInteractions> _emojiInteractions;