Implement drag-n-drop to forum topics.

This commit is contained in:
John Preston 2022-11-01 11:18:56 +04:00
parent 6d215d3729
commit d5ea0149e8
23 changed files with 232 additions and 133 deletions

View file

@ -3200,7 +3200,7 @@ void ApiWrap::forwardMessages(
messageFromId, messageFromId,
messagePostAuthor, messagePostAuthor,
item, item,
action.topicRootId); // #TODO forum forward action.topicRootId);
_session->data().registerMessageRandomId(randomId, newId); _session->data().registerMessageRandomId(randomId, newId);
if (!localIds) { if (!localIds) {
localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>(); localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();

View file

@ -497,20 +497,24 @@ void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
(*weak)->closeBox(); (*weak)->closeBox();
} }
}; };
const auto filter = [=](not_null<Data::ForumTopic*> topic) {
return guard && (!_filter || _filter(topic));
};
auto owned = Box<PeerListBox>( auto owned = Box<PeerListBox>(
std::make_unique<ChooseTopicBoxController>( std::make_unique<ChooseTopicBoxController>(
forum, forum,
std::move(callback)), std::move(callback),
filter),
[=](not_null<PeerListBox*> box) { [=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [=] { box->addButton(tr::lng_cancel(), [=] {
box->closeBox(); box->closeBox();
}); });
forum->destroyed( forum->destroyed(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
box->closeBox(); box->closeBox();
}, box->lifetime()); }, box->lifetime());
}); });
*weak = owned.data(); *weak = owned.data();
delegate()->peerListShowBox(std::move(owned)); delegate()->peerListShowBox(std::move(owned));
return; return;
@ -604,6 +608,49 @@ bool ChooseTopicSearchController::loadMoreRows() {
return !_allLoaded; return !_allLoaded;
} }
ChooseTopicBoxController::Row::Row(not_null<Data::ForumTopic*> topic)
: PeerListRow(topic->rootId().bare)
, _topic(topic) {
}
QString ChooseTopicBoxController::Row::generateName() {
return _topic->title();
}
QString ChooseTopicBoxController::Row::generateShortName() {
return _topic->title();
}
auto ChooseTopicBoxController::Row::generatePaintUserpicCallback()
-> PaintRoundImageCallback {
return [=](
Painter &p,
int x,
int y,
int outerWidth,
int size) {
auto view = std::shared_ptr<Data::CloudImageView>();
p.translate(x, y);
_topic->paintUserpic(p, view, {
.st = &st::forumTopicRow,
.now = crl::now(),
.width = outerWidth,
.paused = false,
});
p.translate(-x, -y);
};
}
auto ChooseTopicBoxController::Row::generateNameFirstLetters() const
-> const base::flat_set<QChar> & {
return _topic->chatListFirstLetters();
}
auto ChooseTopicBoxController::Row::generateNameWords() const
-> const base::flat_set<QString> & {
return _topic->chatListNameWords();
}
ChooseTopicBoxController::ChooseTopicBoxController( ChooseTopicBoxController::ChooseTopicBoxController(
not_null<Data::Forum*> forum, not_null<Data::Forum*> forum,
FnMut<void(not_null<Data::ForumTopic*>)> callback, FnMut<void(not_null<Data::ForumTopic*>)> callback,
@ -656,8 +703,10 @@ void ChooseTopicBoxController::refreshRows(bool initial) {
const auto id = topic->rootId().bare; const auto id = topic->rootId().bare;
auto already = delegate()->peerListFindRow(id); auto already = delegate()->peerListFindRow(id);
if (initial || !already) { if (initial || !already) {
delegate()->peerListAppendRow(createRow(topic)); if (auto created = createRow(topic)) {
added = true; delegate()->peerListAppendRow(std::move(created));
added = true;
}
} else if (already->isSearchResult()) { } else if (already->isSearchResult()) {
delegate()->peerListAppendFoundRow(already); delegate()->peerListAppendFoundRow(already);
added = true; added = true;
@ -681,49 +730,6 @@ std::unique_ptr<PeerListRow> ChooseTopicBoxController::createSearchRow(
return nullptr; return nullptr;
} }
ChooseTopicBoxController::Row::Row(not_null<Data::ForumTopic*> topic)
: PeerListRow(topic->rootId().bare)
, _topic(topic) {
}
QString ChooseTopicBoxController::Row::generateName() {
return _topic->title();
}
QString ChooseTopicBoxController::Row::generateShortName() {
return _topic->title();
}
auto ChooseTopicBoxController::Row::generatePaintUserpicCallback()
-> PaintRoundImageCallback {
return [=](
Painter &p,
int x,
int y,
int outerWidth,
int size) {
auto view = std::shared_ptr<Data::CloudImageView>();
p.translate(x, y);
_topic->paintUserpic(p, view, {
.st = &st::forumTopicRow,
.now = crl::now(),
.width = outerWidth,
.paused = false,
});
p.translate(-x, -y);
};
}
auto ChooseTopicBoxController::Row::generateNameFirstLetters() const
-> const base::flat_set<QChar> & {
return _topic->chatListFirstLetters();
}
auto ChooseTopicBoxController::Row::generateNameWords() const
-> const base::flat_set<QString> & {
return _topic->chatListNameWords();
}
auto ChooseTopicBoxController::createRow(not_null<Data::ForumTopic*> topic) auto ChooseTopicBoxController::createRow(not_null<Data::ForumTopic*> topic)
-> std::unique_ptr<Row> { -> std::unique_ptr<Row> {
const auto skip = _filter ? !_filter(topic) : !topic->canWrite(); const auto skip = _filter ? !_filter(topic) : !topic->canWrite();

View file

@ -1204,7 +1204,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
auto object = Box<ShareBox>(ShareBox::Descriptor{ auto object = Box<ShareBox>(ShareBox::Descriptor{
.session = &peer->session(), .session = &peer->session(),
.copyCallback = std::move(copyCallback), .copyCallback = std::move(copyCallback),
.submitCallback = std::move(submitCallback), // #TODO forum forward .submitCallback = std::move(submitCallback), // #TODO forum share
.filterCallback = [](auto peer) { return peer->canWrite(); }, .filterCallback = [](auto peer) { return peer->canWrite(); },
}); });
*box = Ui::MakeWeak(object.data()); *box = Ui::MakeWeak(object.data());

View file

@ -1292,7 +1292,7 @@ void FastShareMessage(
} }
const auto error = [&] { const auto error = [&] {
for (const auto peer : result) { // #TODO forum forward for (const auto peer : result) { // #TODO forum share
const auto error = GetErrorTextForSending( const auto error = GetErrorTextForSending(
peer, peer,
{ .forward = &items, .text = &comment }); { .forward = &items, .text = &comment });
@ -1398,7 +1398,7 @@ void FastShareMessage(
} }
}; };
auto filterCallback = [isGame](PeerData *peer) { auto filterCallback = [isGame](PeerData *peer) {
if (peer->canWrite()) { // #TODO forum forward if (peer->canWrite()) { // #TODO forum share
if (auto channel = peer->asChannel()) { if (auto channel = peer->asChannel()) {
return isGame ? (!channel->isBroadcast()) : true; return isGame ? (!channel->isBroadcast()) : true;
} }

View file

@ -142,7 +142,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
} }
const auto error = [&] { const auto error = [&] {
for (const auto peer : result) { // #TODO forum forward for (const auto peer : result) { // #TODO forum share
const auto error = GetErrorTextForSending( const auto error = GetErrorTextForSending(
peer, peer,
{ .text = &comment }); { .text = &comment });
@ -196,7 +196,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
showToast(tr::lng_share_done(tr::now)); showToast(tr::lng_share_done(tr::now));
}; };
auto filterCallback = [](PeerData *peer) { auto filterCallback = [](PeerData *peer) {
return peer->canWrite(); // #TODO forum forward return peer->canWrite(); // #TODO forum share
}; };
const auto scheduleStyle = [&] { const auto scheduleStyle = [&] {

View file

@ -7,7 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "core/mime_type.h" #include "core/mime_type.h"
#include "core/utils.h"
#include <QtCore/QMimeDatabase> #include <QtCore/QMimeDatabase>
#include <QtCore/QMimeData>
namespace Core { namespace Core {
@ -152,4 +155,19 @@ bool FileIsImage(const QString &name, const QString &mime) {
return false; return false;
} }
std::shared_ptr<QMimeData> ShareMimeMediaData(
not_null<const QMimeData*> original) {
auto result = std::make_shared<QMimeData>();
if (original->hasFormat(u"application/x-td-forward"_q)) {
result->setData(u"application/x-td-forward"_q, "1");
}
if (original->hasImage()) {
result->setImageData(original->imageData());
}
if (auto list = base::GetMimeUrls(original); !list.isEmpty()) {
result->setUrls(std::move(list));
}
return result;
}
} // namespace Core } // namespace Core

View file

@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QMimeType> #include <QtCore/QMimeType>
class QMimeData;
namespace Core { namespace Core {
class MimeType { class MimeType {
@ -47,4 +49,7 @@ private:
[[nodiscard]] bool FileIsImage(const QString &name, const QString &mime); [[nodiscard]] bool FileIsImage(const QString &name, const QString &mime);
[[nodiscard]] std::shared_ptr<QMimeData> ShareMimeMediaData(
not_null<const QMimeData*> original);
} // namespace Core } // namespace Core

View file

@ -449,8 +449,8 @@ editTopicMaxHeight: 408px;
chooseTopicListItem: PeerListItem(defaultPeerListItem) { chooseTopicListItem: PeerListItem(defaultPeerListItem) {
height: 44px; height: 44px;
photoSize: 28px; photoSize: 28px;
photoPosition: point(16px, 5px); photoPosition: point(8px, 5px);
namePosition: point(71px, 11px); namePosition: point(55px, 11px);
nameStyle: TextStyle(defaultTextStyle) { nameStyle: TextStyle(defaultTextStyle) {
font: font(14px semibold); font: font(14px semibold);
linkFont: font(14px semibold); linkFont: font(14px semibold);

View file

@ -1437,7 +1437,7 @@ ClickHandlerPtr goToMessageClickHandler(
returnToId returnToId
}; };
if (const auto item = peer->owner().message(peer, msgId)) { if (const auto item = peer->owner().message(peer, msgId)) {
controller->showMessage(item); controller->showMessage(item, params);
} else { } else {
controller->showPeerHistory(peer, params, msgId); controller->showPeerHistory(peer, params, msgId);
} }

View file

@ -150,8 +150,6 @@ public:
bool confirmSendingFiles(const QStringList &files); bool confirmSendingFiles(const QStringList &files);
bool confirmSendingFiles(not_null<const QMimeData*> data); bool confirmSendingFiles(not_null<const QMimeData*> data);
void sendFileConfirmed(const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId = std::nullopt);
void updateControlsVisibility(); void updateControlsVisibility();
void updateControlsGeometry(); void updateControlsGeometry();

View file

@ -341,7 +341,8 @@ void CornerButtons::finishAnimations() {
Fn<void(bool found)> CornerButtons::doneJumpFrom( Fn<void(bool found)> CornerButtons::doneJumpFrom(
FullMsgId targetId, FullMsgId targetId,
FullMsgId originId) { FullMsgId originId,
bool ignoreMessageNotFound) {
return [=](bool found) { return [=](bool found) {
skipReplyReturn(targetId); skipReplyReturn(targetId);
if (originId) { if (originId) {
@ -351,7 +352,7 @@ Fn<void(bool found)> CornerButtons::doneJumpFrom(
} }
} }
} }
if (!found) { if (!found && !ignoreMessageNotFound) {
Ui::Toast::Show( Ui::Toast::Show(
_scroll.get(), _scroll.get(),
tr::lng_message_not_found(tr::now)); tr::lng_message_not_found(tr::now));

View file

@ -87,7 +87,8 @@ public:
} }
[[nodiscard]] Fn<void(bool found)> doneJumpFrom( [[nodiscard]] Fn<void(bool found)> doneJumpFrom(
FullMsgId targetId, FullMsgId targetId,
FullMsgId originId); FullMsgId originId,
bool ignoreMessageNotFound = false);
private: private:
bool eventFilter(QObject *o, QEvent *e) override; bool eventFilter(QObject *o, QEvent *e) override;

View file

@ -687,7 +687,7 @@ bool ListWidget::showAtPositionNow(
} }
if (done) { if (done) {
const auto found = !position.fullId.peer const auto found = !position.fullId.peer
|| !position.fullId.msg || !IsServerMsgId(position.fullId.msg)
|| viewForItem(position.fullId); || viewForItem(position.fullId);
done(found); done(found);
} }

View file

@ -1796,10 +1796,11 @@ void RepliesWidget::showAtPosition(
anim::type animated) { anim::type animated) {
_lastShownAt = position.fullId; _lastShownAt = position.fullId;
controller()->setActiveChatEntry(activeChat()); controller()->setActiveChatEntry(activeChat());
const auto ignore = (position.fullId.msg == _rootId);
_inner->showAtPosition( _inner->showAtPosition(
position, position,
animated, animated,
_cornerButtons.doneJumpFrom(position.fullId, originItemId)); _cornerButtons.doneJumpFrom(position.fullId, originItemId, ignore));
} }
void RepliesWidget::updateAdaptiveLayout() { void RepliesWidget::updateAdaptiveLayout() {
@ -1962,6 +1963,23 @@ Window::SectionActionResult RepliesWidget::sendBotCommand(
return Window::SectionActionResult::Handle; return Window::SectionActionResult::Handle;
} }
bool RepliesWidget::confirmSendingFiles(const QStringList &files) {
return confirmSendingFiles(files, QString());
}
bool RepliesWidget::confirmSendingFiles(not_null<const QMimeData*> data) {
return confirmSendingFiles(data, std::nullopt);
}
bool RepliesWidget::confirmSendingFiles(
const QStringList &files,
const QString &insertTextOnCancel) {
const auto premium = controller()->session().user()->isPremium();
return confirmSendingFiles(
Storage::PrepareMediaList(files, st::sendMediaPreviewSize, premium),
insertTextOnCancel);
}
void RepliesWidget::replyToMessage(FullMsgId itemId) { void RepliesWidget::replyToMessage(FullMsgId itemId) {
_composeControls->replyToMessage(itemId); _composeControls->replyToMessage(itemId);
refreshTopBarActiveChat(); refreshTopBarActiveChat();

View file

@ -104,6 +104,9 @@ public:
Window::SectionActionResult sendBotCommand( Window::SectionActionResult sendBotCommand(
Bot::SendCommandRequest request) override; Bot::SendCommandRequest request) override;
bool confirmSendingFiles(const QStringList &files) override;
bool confirmSendingFiles(not_null<const QMimeData*> data) override;
void setInternalState( void setInternalState(
const QRect &geometry, const QRect &geometry,
not_null<RepliesMemento*> memento); not_null<RepliesMemento*> memento);
@ -261,12 +264,15 @@ private:
QByteArray &&content, QByteArray &&content,
std::optional<bool> overrideSendImagesAsPhotos = std::nullopt, std::optional<bool> overrideSendImagesAsPhotos = std::nullopt,
const QString &insertTextOnCancel = QString()); const QString &insertTextOnCancel = QString());
bool confirmSendingFiles(
const QStringList &files,
const QString &insertTextOnCancel);
bool confirmSendingFiles( bool confirmSendingFiles(
Ui::PreparedList &&list, Ui::PreparedList &&list,
const QString &insertTextOnCancel = QString()); const QString &insertTextOnCancel = QString());
bool confirmSendingFiles( bool confirmSendingFiles(
not_null<const QMimeData*> data, not_null<const QMimeData*> data,
std::optional<bool> overrideSendImagesAsPhotos = std::nullopt, std::optional<bool> overrideSendImagesAsPhotos,
const QString &insertTextOnCancel = QString()); const QString &insertTextOnCancel = QString());
bool showSendingFilesError(const Ui::PreparedList &list) const; bool showSendingFilesError(const Ui::PreparedList &list) const;
void sendingFilesConfirmed( void sendingFilesConfirmed(

View file

@ -92,6 +92,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/shortcuts.h" #include "core/shortcuts.h"
#include "core/application.h" #include "core/application.h"
#include "core/changelogs.h" #include "core/changelogs.h"
#include "core/mime_type.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "calls/calls_call.h" #include "calls/calls_call.h"
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
@ -323,7 +324,6 @@ MainWidget::MainWidget(
Data::EntryUpdate::Flag::LocalDraftSet Data::EntryUpdate::Flag::LocalDraftSet
) | rpl::start_with_next([=](const Data::EntryUpdate &update) { ) | rpl::start_with_next([=](const Data::EntryUpdate &update) {
controller->showThread(update.entry->asThread(), ShowAtUnreadMsgId); controller->showThread(update.entry->asThread(), ShowAtUnreadMsgId);
_history->applyDraft(); // #TODO forum drop
controller->hideLayer(); controller->hideLayer();
}, lifetime()); }, lifetime());
@ -574,7 +574,7 @@ bool MainWidget::shareUrl(
bool MainWidget::inlineSwitchChosen( bool MainWidget::inlineSwitchChosen(
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
const QString &botAndQuery) const { const QString &botAndQuery) const {
if (!thread->canWrite()) { // #TODO forum forward if (!thread->canWrite()) {
Ui::show(Ui::MakeInformBox(tr::lng_inline_switch_cant())); Ui::show(Ui::MakeInformBox(tr::lng_inline_switch_cant()));
return false; return false;
} }
@ -617,26 +617,33 @@ bool MainWidget::sendPaths(not_null<Data::Thread*> thread) {
ShowAtTheEndMsgId, ShowAtTheEndMsgId,
Window::SectionShow::Way::ClearStack); Window::SectionShow::Way::ClearStack);
} }
// #TODO forum drop
return (controller()->activeChatCurrent().thread() == thread) return (controller()->activeChatCurrent().thread() == thread)
&& _history->confirmSendingFiles(cSendPaths()); && (_mainSection
? _mainSection->confirmSendingFiles(cSendPaths())
: _history->confirmSendingFiles(cSendPaths()));
} }
void MainWidget::onFilesOrForwardDrop( bool MainWidget::onFilesOrForwardDrop(
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
const QMimeData *data) { not_null<const QMimeData*> data) {
const auto history = thread->asHistory();
if (const auto forum = history ? history->peer->forum() : nullptr) {
Window::ShowDropMediaBox(
_controller,
Core::ShareMimeMediaData(data),
forum);
if (_hider) {
_hider->startHide();
clearHider(_hider);
}
return true;
}
if (data->hasFormat(qsl("application/x-td-forward"))) { if (data->hasFormat(qsl("application/x-td-forward"))) {
auto draft = Data::ForwardDraft{ auto draft = Data::ForwardDraft{
.ids = session().data().takeMimeForwardIds(), .ids = session().data().takeMimeForwardIds(),
}; };
const auto history = thread->asHistory(); if (setForwardDraft(thread, std::move(draft))) {
if (const auto forum = history ? history->peer->forum() : nullptr) { return true;
Window::ShowForwardMessagesBox(
_controller,
std::move(draft),
forum);
} else if (setForwardDraft(thread, std::move(draft))) {
return;
} }
// We've already released the mouse button, // We've already released the mouse button,
// so the forwarding is cancelled. // so the forwarding is cancelled.
@ -644,17 +651,22 @@ void MainWidget::onFilesOrForwardDrop(
_hider->startHide(); _hider->startHide();
clearHider(_hider); clearHider(_hider);
} }
return false;
} else if (!thread->canWrite()) { } else if (!thread->canWrite()) {
Ui::show(Ui::MakeInformBox(tr::lng_forward_send_files_cant())); Ui::show(Ui::MakeInformBox(tr::lng_forward_send_files_cant()));
return false;
} else { } else {
controller()->showThread( controller()->showThread(
thread, thread,
ShowAtTheEndMsgId, ShowAtTheEndMsgId,
Window::SectionShow::Way::ClearStack); Window::SectionShow::Way::ClearStack);
if (thread->asHistory()) { if (controller()->activeChatCurrent().thread() != thread) {
// #TODO forum drop return false;
_history->confirmSendingFiles(data);
} }
(_mainSection
? _mainSection->confirmSendingFiles(data)
: _history->confirmSendingFiles(data));
return true;
} }
} }
@ -1264,7 +1276,10 @@ void MainWidget::chooseThread(
if (selectingPeer()) { if (selectingPeer()) {
_hider->offerThread(thread); _hider->offerThread(thread);
} else { } else {
controller()->showThread(thread, showAtMsgId); controller()->showThread(
thread,
showAtMsgId,
Window::SectionShow::Way::ClearStack);
} }
} }
@ -1522,6 +1537,31 @@ void MainWidget::ui_showPeerHistory(
floatPlayerCheckVisibility(); floatPlayerCheckVisibility();
} }
void MainWidget::showMessage(
not_null<const HistoryItem*> item,
const SectionShow &params) {
const auto peerId = item->history()->peer->id;
const auto itemId = item->id;
if (!v::is_null(params.origin)) {
if (_mainSection) {
if (_mainSection->showMessage(peerId, params, itemId)) {
return;
}
} else if (_history->peer() == item->history()->peer) {
ui_showPeerHistory(peerId, params, itemId);
return;
}
}
if (const auto topic = item->topic()) {
_controller->showTopic(topic, item->id, params);
} else {
_controller->showPeerHistory(
item->history(),
params,
item->id);
}
}
PeerData *MainWidget::peer() const { PeerData *MainWidget::peer() const {
return _history->peer(); return _history->peer();
} }
@ -2710,31 +2750,31 @@ bool MainWidget::contentOverlapped(const QRect &globalRect) {
void MainWidget::activate() { void MainWidget::activate() {
if (_a_show.animating()) { if (_a_show.animating()) {
return; return;
} else if (!_mainSection) { } else if (!cSendPaths().isEmpty()) {
if (_hider) { const auto interpret = qstr("interpret://");
const auto path = cSendPaths()[0];
if (path.startsWith(interpret)) {
cSetSendPaths(QStringList());
const auto error = Support::InterpretSendPath(
_controller,
path.mid(interpret.size()));
if (!error.isEmpty()) {
Ui::show(Ui::MakeInformBox(error));
}
} else {
showSendPathsLayer();
}
} else if (_mainSection) {
_mainSection->setInnerFocus();
} else if (_hider) {
Assert(_dialogs != nullptr);
_dialogs->setInnerFocus();
} else if (!Ui::isLayerShown()) {
if (_history->peer()) {
_history->activate();
} else {
Assert(_dialogs != nullptr); Assert(_dialogs != nullptr);
_dialogs->setInnerFocus(); _dialogs->setInnerFocus();
} else if (!Ui::isLayerShown()) {
if (!cSendPaths().isEmpty()) {
const auto interpret = qstr("interpret://");
const auto path = cSendPaths()[0];
if (path.startsWith(interpret)) {
cSetSendPaths(QStringList());
const auto error = Support::InterpretSendPath(
_controller,
path.mid(interpret.size()));
if (!error.isEmpty()) {
Ui::show(Ui::MakeInformBox(error));
}
} else {
showSendPathsLayer();
}
} else if (_history->peer()) {
_history->activate();
} else {
Assert(_dialogs != nullptr);
_dialogs->setInnerFocus();
}
} }
} }
_controller->widget()->fixOrder(); _controller->widget()->fixOrder();

View file

@ -179,9 +179,9 @@ public:
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
Data::ForwardDraft &&draft); Data::ForwardDraft &&draft);
bool sendPaths(not_null<Data::Thread*> thread); bool sendPaths(not_null<Data::Thread*> thread);
void onFilesOrForwardDrop( bool onFilesOrForwardDrop(
not_null<Data::Thread*> thread, not_null<Data::Thread*> thread,
const QMimeData *data); not_null<const QMimeData*> data);
bool selectingPeer() const; bool selectingPeer() const;
void clearSelectingPeer(); void clearSelectingPeer();
@ -222,6 +222,9 @@ public:
PeerId peer, PeerId peer,
const SectionShow &params, const SectionShow &params,
MsgId msgId); MsgId msgId);
void showMessage(
not_null<const HistoryItem*> item,
const SectionShow &params);
bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo); bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo);

View file

@ -151,6 +151,13 @@ public:
return SectionActionResult::Ignore; return SectionActionResult::Ignore;
} }
virtual bool confirmSendingFiles(const QStringList &files) {
return false;
}
virtual bool confirmSendingFiles(not_null<const QMimeData*> data) {
return false;
}
// Create a memento of that section to store it in the history stack. // Create a memento of that section to store it in the history stack.
// This method may modify the section ("take" heavy items). // This method may modify the section ("take" heavy items).
virtual std::shared_ptr<SectionMemento> createMemento(); virtual std::shared_ptr<SectionMemento> createMemento();

View file

@ -1542,20 +1542,20 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
std::move(successCallback)); std::move(successCallback));
} }
QPointer<Ui::BoxContent> ShowForwardMessagesBox( QPointer<Ui::BoxContent> ShowDropMediaBox(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
Data::ForwardDraft &&draft, std::shared_ptr<QMimeData> data,
not_null<Data::Forum*> forum, not_null<Data::Forum*> forum,
FnMut<void()> &&successCallback) { FnMut<void()> &&successCallback) {
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>(); const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
auto chosen = [ auto chosen = [
draft = std::move(draft), data = std::move(data),
callback = std::move(successCallback), callback = std::move(successCallback),
weak, weak,
navigation navigation
](not_null<Data::ForumTopic*> topic) mutable { ](not_null<Data::ForumTopic*> topic) mutable {
const auto content = navigation->parentController()->content(); const auto content = navigation->parentController()->content();
if (!content->setForwardDraft(topic, std::move(draft))) { if (!content->onFilesOrForwardDrop(topic, data.get())) {
return; return;
} else if (const auto strong = *weak) { } else if (const auto strong = *weak) {
strong->closeBox(); strong->closeBox();

View file

@ -122,9 +122,9 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
MessageIdsList &&items, MessageIdsList &&items,
FnMut<void()> &&successCallback = nullptr); FnMut<void()> &&successCallback = nullptr);
QPointer<Ui::BoxContent> ShowForwardMessagesBox( QPointer<Ui::BoxContent> ShowDropMediaBox(
not_null<Window::SessionNavigation*> navigation, not_null<Window::SessionNavigation*> navigation,
Data::ForwardDraft &&draft, std::shared_ptr<QMimeData> data,
not_null<Data::Forum*> forum, not_null<Data::Forum*> forum,
FnMut<void()> &&successCallback = nullptr); FnMut<void()> &&successCallback = nullptr);

View file

@ -1670,26 +1670,19 @@ void SessionController::showPeerHistory(
} }
void SessionController::showMessage( void SessionController::showMessage(
not_null<const HistoryItem*> item) { not_null<const HistoryItem*> item,
const SectionShow &params) {
_window->invokeForSessionController( _window->invokeForSessionController(
&item->history()->peer->session().account(), &item->history()->session().account(),
item->history()->peer, item->history()->peer,
[&](not_null<SessionController*> controller) { [&](not_null<SessionController*> controller) {
if (item->isScheduled()) { if (item->isScheduled()) {
controller->showSection( controller->showSection(
std::make_shared<HistoryView::ScheduledMemento>( std::make_shared<HistoryView::ScheduledMemento>(
item->history()), item->history()),
SectionShow::Way::ClearStack); params);
} else if (const auto topic = item->topic()) {
controller->showTopic(
topic,
item->id,
SectionShow::Way::ClearStack);
} else { } else {
controller->showPeerHistory( controller->content()->showMessage(item, params);
item->history()->peer,
SectionShow::Way::ClearStack,
item->id);
} }
}); });
} }

View file

@ -431,7 +431,9 @@ public:
const SectionShow &params = SectionShow::Way::ClearStack, const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId) override; MsgId msgId = ShowAtUnreadMsgId) override;
void showMessage(not_null<const HistoryItem*> item); void showMessage(
not_null<const HistoryItem*> item,
const SectionShow &params = SectionShow::Way::ClearStack);
void cancelUploadLayer(not_null<HistoryItem*> item); void cancelUploadLayer(not_null<HistoryItem*> item);
void showLayer( void showLayer(

View file

@ -294,4 +294,5 @@ PRIVATE
desktop-app::lib_webview desktop-app::lib_webview
desktop-app::lib_webrtc desktop-app::lib_webrtc
desktop-app::lib_stripe desktop-app::lib_stripe
desktop-app::external_kcoreaddons
) )