diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index 7bcaeb649..bbc8d3f10 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -325,7 +325,7 @@ bool HistoryMessageReply::updateData( bool force) { const auto guard = gsl::finally([&] { refreshReplyToMedia(); }); if (!force) { - if (resolvedMessage || resolvedStory || _deleted) { + if (resolvedMessage || resolvedStory || _unavailable) { return true; } } @@ -365,7 +365,9 @@ bool HistoryMessageReply::updateData( const auto external = _fields.externalSenderId || !_fields.externalSenderName.isEmpty(); - if (resolvedMessage || resolvedStory || (external && force)) { + if (resolvedMessage + || resolvedStory + || (external && (!_fields.messageId || force))) { const auto repaint = [=] { holder->customEmojiRepaint(); }; const auto context = Core::MarkedTextContext{ .session = &holder->history()->session(), @@ -403,8 +405,8 @@ bool HistoryMessageReply::updateData( && resolvedMessage->from()->isUser()) ? resolvedMessage->from()->id : PeerId(); - } else { - resolvedMessage = 0; + } else if (!resolvedStory) { + _unavailable = true; } const auto media = resolvedMessage @@ -417,7 +419,7 @@ bool HistoryMessageReply::updateData( } } else if (force) { if (_fields.messageId || _fields.storyId) { - _deleted = true; + _unavailable = true; } _colorKey = 0; spoiler = nullptr; @@ -428,7 +430,7 @@ bool HistoryMessageReply::updateData( return resolvedMessage || resolvedStory || (external && !_fields.messageId) - || _deleted; + || _unavailable; } void HistoryMessageReply::set(ReplyFields fields) { @@ -500,7 +502,7 @@ void HistoryMessageReply::clearData(not_null holder) { resolvedStory.get()); resolvedStory = nullptr; } - _deleted = true; + _unavailable = true; refreshReplyToMedia(); } @@ -693,7 +695,7 @@ void HistoryMessageReply::paint( const auto pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler); if (w > st::msgReplyBarSkip) { - if (resolvedMessage || resolvedStory) { + if (resolvedMessage || resolvedStory || !_text.isEmpty()) { const auto media = resolvedMessage ? resolvedMessage->media() : nullptr; auto hasPreview = (media && media->hasReplyPreview()) || (resolvedStory && resolvedStory->hasReplyPreview()); @@ -791,7 +793,7 @@ void HistoryMessageReply::unloadPersistentAnimation() { } QString HistoryMessageReply::statePhrase() const { - return ((_fields.messageId || _fields.storyId) && !_deleted) + return ((_fields.messageId || _fields.storyId) && !_unavailable) ? tr::lng_profile_loading(tr::now) : _fields.storyId ? tr::lng_deleted_story(tr::now) diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index 4cd033879..c46f838b8 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -344,7 +344,7 @@ private: mutable PeerData *_externalSender = nullptr; mutable int _maxWidth = 0; mutable int _nameVersion = 0; - bool _deleted = false; + bool _unavailable = false; }; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 955263ef2..846be207e 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1656,7 +1656,9 @@ void HistoryWidget::saveDraft(bool delayed) { } void HistoryWidget::saveFieldToHistoryLocalDraft() { - if (!_history) return; + if (!_history) { + return; + } const auto topicRootId = MsgId(); if (_editMsgId) { @@ -6219,13 +6221,16 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) { } else { _forwardPanel->editOptions(controller()->uiShow()); } - } else if (replyTo() && replyTo().messageId.peer != _peer->id) { - // edit options - } else { + } else if (const auto reply = replyTo()) { + HistoryView::Controls::EditReplyOptions( + controller(), + reply, + _history); + } else if (_editMsgId) { controller()->showPeerHistory( _peer, Window::SectionShow::Way::Forward, - _editMsgId ? _editMsgId : replyTo().messageId.msg); + _editMsgId); } } } @@ -7096,6 +7101,7 @@ void HistoryWidget::processReply() { _processingReplyTo.messageId.msg, processContinue()); return; +#if 0 // Now we can "reply" to old legacy group messages. } else if (_processingReplyItem->history() == _migrated) { if (_processingReplyItem->isService()) { controller()->showToast(tr::lng_reply_cant(tr::now)); @@ -7113,10 +7119,11 @@ void HistoryWidget::processReply() { })); } return processCancel(); - } else if (_processingReplyItem->history() != _history - || !_processingReplyItem->isRegular()) { +#endif + } else if (!_processingReplyItem->isRegular()) { return processCancel(); - } else if (const auto forum = _peer->forum()) { + } else if (const auto forum = _peer->forum() + ; forum && _processingReplyItem->history() == _history) { const auto topicRootId = _processingReplyItem->topicRootId(); if (forum->topicDeleted(topicRootId)) { return processCancel(); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp index d1bf5c965..dd6fd636d 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp @@ -29,6 +29,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_chat.h" #include "styles/style_chat_helpers.h" +#include "apiwrap.h" +#include "boxes/peer_list_controllers.h" +#include "data/data_changes.h" +#include "settings/settings_common.h" +#include "ui/widgets/buttons.h" +#include "styles/style_menu_icons.h" +#include "styles/style_settings.h" + namespace HistoryView::Controls { namespace { @@ -395,4 +403,137 @@ void ForwardPanel::paint( }); } +void ShowReplyToChatBox( + not_null window, + FullReplyTo reply, + base::weak_ptr oldThread) { + class Controller final : public ChooseRecipientBoxController { + public: + using Chosen = not_null; + + Controller(not_null session) + : ChooseRecipientBoxController( + session, + [=](Chosen thread) mutable { _singleChosen.fire_copy(thread); }, + nullptr) { + } + + void rowClicked(not_null row) override final { + ChooseRecipientBoxController::rowClicked(row); + } + + [[nodiscard]] rpl::producer singleChosen() const{ + return _singleChosen.events(); + } + + private: + rpl::event_stream _singleChosen; + + }; + + struct State { + not_null box; + not_null controller; + base::unique_qptr menu; + }; + const auto session = &window->session(); + const auto state = [&] { + auto controller = std::make_unique(session); + const auto controllerRaw = controller.get(); + auto box = Box(std::move(controller), nullptr); + const auto boxRaw = box.data(); + window->uiShow()->show(std::move(box)); + auto state = State{ boxRaw, controllerRaw }; + return boxRaw->lifetime().make_state(std::move(state)); + }(); + + auto chosen = [=](not_null thread) mutable { + const auto history = thread->owningHistory(); + const auto topicRootId = thread->topicRootId(); + const auto draft = history->localDraft(topicRootId); + const auto textWithTags = draft + ? draft->textWithTags + : TextWithTags(); + const auto cursor = draft ? draft->cursor : MessageCursor(); + reply.topicRootId = topicRootId; + history->setLocalDraft(std::make_unique( + textWithTags, + reply, + cursor, + Data::PreviewState::Allowed)); + history->clearLocalEditDraft(topicRootId); + history->session().changes().entryUpdated( + thread, + Data::EntryUpdate::Flag::LocalDraftSet); + + // Clear old one. + crl::on_main(oldThread, [=] { + const auto old = oldThread.get(); + const auto history = old->owningHistory(); + const auto topicRootId = old->topicRootId(); + if (const auto local = history->localDraft(topicRootId)) { + if (local->reply.messageId == reply.messageId) { + auto draft = *local; + draft.reply = { .topicRootId = topicRootId }; + if (Data::DraftIsNull(&draft)) { + history->clearLocalDraft(topicRootId); + } else { + history->setLocalDraft( + std::make_unique( + std::move(draft))); + } + old->session().api().saveDraftToCloudDelayed(old); + } + } + }); + return true; + }; + auto callback = [=, chosen = std::move(chosen)]( + Controller::Chosen thread) mutable { + const auto weak = Ui::MakeWeak(state->box); + if (!chosen(thread)) { + return; + } else if (const auto strong = weak.data()) { + strong->closeBox(); + } + }; + state->controller->singleChosen( + ) | rpl::start_with_next(std::move(callback), state->box->lifetime()); +} + +void EditReplyOptions( + not_null controller, + FullReplyTo reply, + not_null thread) { + const auto weak = base::make_weak(thread); + controller->uiShow()->show(Box([=](not_null box) { + box->setTitle(rpl::single(u"Reply to Message"_q)); + + Settings::AddButton( + box->verticalLayout(), + rpl::single(u"Reply in another chat"_q), + st::settingsButton, + { &st::menuIconReply } + )->setClickedCallback([=] { + ShowReplyToChatBox(controller, reply, weak); + }); + + Settings::AddButton( + box->verticalLayout(), + rpl::single(u"Show message"_q), + st::settingsButton, + { &st::menuIconShowInChat } + )->setClickedCallback([=] { + controller->showPeerHistory( + reply.messageId.peer, + Window::SectionShow::Way::Forward, + reply.messageId.msg); + }); + + box->addButton(tr::lng_box_ok(), [=] { + box->closeBox(); + }); + })); +} + } // namespace HistoryView::Controls diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h index 038a0fbf7..26464e36f 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.h @@ -71,4 +71,9 @@ private: }; +void EditReplyOptions( + not_null controller, + FullReplyTo reply, + not_null thread); + } // namespace HistoryView::Controls