mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support replying to a different chat.
This commit is contained in:
parent
4240568ea5
commit
394883b986
5 changed files with 173 additions and 18 deletions
|
@ -325,7 +325,7 @@ bool HistoryMessageReply::updateData(
|
||||||
bool force) {
|
bool force) {
|
||||||
const auto guard = gsl::finally([&] { refreshReplyToMedia(); });
|
const auto guard = gsl::finally([&] { refreshReplyToMedia(); });
|
||||||
if (!force) {
|
if (!force) {
|
||||||
if (resolvedMessage || resolvedStory || _deleted) {
|
if (resolvedMessage || resolvedStory || _unavailable) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,9 @@ bool HistoryMessageReply::updateData(
|
||||||
|
|
||||||
const auto external = _fields.externalSenderId
|
const auto external = _fields.externalSenderId
|
||||||
|| !_fields.externalSenderName.isEmpty();
|
|| !_fields.externalSenderName.isEmpty();
|
||||||
if (resolvedMessage || resolvedStory || (external && force)) {
|
if (resolvedMessage
|
||||||
|
|| resolvedStory
|
||||||
|
|| (external && (!_fields.messageId || force))) {
|
||||||
const auto repaint = [=] { holder->customEmojiRepaint(); };
|
const auto repaint = [=] { holder->customEmojiRepaint(); };
|
||||||
const auto context = Core::MarkedTextContext{
|
const auto context = Core::MarkedTextContext{
|
||||||
.session = &holder->history()->session(),
|
.session = &holder->history()->session(),
|
||||||
|
@ -403,8 +405,8 @@ bool HistoryMessageReply::updateData(
|
||||||
&& resolvedMessage->from()->isUser())
|
&& resolvedMessage->from()->isUser())
|
||||||
? resolvedMessage->from()->id
|
? resolvedMessage->from()->id
|
||||||
: PeerId();
|
: PeerId();
|
||||||
} else {
|
} else if (!resolvedStory) {
|
||||||
resolvedMessage = 0;
|
_unavailable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto media = resolvedMessage
|
const auto media = resolvedMessage
|
||||||
|
@ -417,7 +419,7 @@ bool HistoryMessageReply::updateData(
|
||||||
}
|
}
|
||||||
} else if (force) {
|
} else if (force) {
|
||||||
if (_fields.messageId || _fields.storyId) {
|
if (_fields.messageId || _fields.storyId) {
|
||||||
_deleted = true;
|
_unavailable = true;
|
||||||
}
|
}
|
||||||
_colorKey = 0;
|
_colorKey = 0;
|
||||||
spoiler = nullptr;
|
spoiler = nullptr;
|
||||||
|
@ -428,7 +430,7 @@ bool HistoryMessageReply::updateData(
|
||||||
return resolvedMessage
|
return resolvedMessage
|
||||||
|| resolvedStory
|
|| resolvedStory
|
||||||
|| (external && !_fields.messageId)
|
|| (external && !_fields.messageId)
|
||||||
|| _deleted;
|
|| _unavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessageReply::set(ReplyFields fields) {
|
void HistoryMessageReply::set(ReplyFields fields) {
|
||||||
|
@ -500,7 +502,7 @@ void HistoryMessageReply::clearData(not_null<HistoryItem*> holder) {
|
||||||
resolvedStory.get());
|
resolvedStory.get());
|
||||||
resolvedStory = nullptr;
|
resolvedStory = nullptr;
|
||||||
}
|
}
|
||||||
_deleted = true;
|
_unavailable = true;
|
||||||
refreshReplyToMedia();
|
refreshReplyToMedia();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +695,7 @@ void HistoryMessageReply::paint(
|
||||||
const auto pausedSpoiler = context.paused
|
const auto pausedSpoiler = context.paused
|
||||||
|| On(PowerSaving::kChatSpoiler);
|
|| On(PowerSaving::kChatSpoiler);
|
||||||
if (w > st::msgReplyBarSkip) {
|
if (w > st::msgReplyBarSkip) {
|
||||||
if (resolvedMessage || resolvedStory) {
|
if (resolvedMessage || resolvedStory || !_text.isEmpty()) {
|
||||||
const auto media = resolvedMessage ? resolvedMessage->media() : nullptr;
|
const auto media = resolvedMessage ? resolvedMessage->media() : nullptr;
|
||||||
auto hasPreview = (media && media->hasReplyPreview())
|
auto hasPreview = (media && media->hasReplyPreview())
|
||||||
|| (resolvedStory && resolvedStory->hasReplyPreview());
|
|| (resolvedStory && resolvedStory->hasReplyPreview());
|
||||||
|
@ -791,7 +793,7 @@ void HistoryMessageReply::unloadPersistentAnimation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HistoryMessageReply::statePhrase() const {
|
QString HistoryMessageReply::statePhrase() const {
|
||||||
return ((_fields.messageId || _fields.storyId) && !_deleted)
|
return ((_fields.messageId || _fields.storyId) && !_unavailable)
|
||||||
? tr::lng_profile_loading(tr::now)
|
? tr::lng_profile_loading(tr::now)
|
||||||
: _fields.storyId
|
: _fields.storyId
|
||||||
? tr::lng_deleted_story(tr::now)
|
? tr::lng_deleted_story(tr::now)
|
||||||
|
|
|
@ -344,7 +344,7 @@ private:
|
||||||
mutable PeerData *_externalSender = nullptr;
|
mutable PeerData *_externalSender = nullptr;
|
||||||
mutable int _maxWidth = 0;
|
mutable int _maxWidth = 0;
|
||||||
mutable int _nameVersion = 0;
|
mutable int _nameVersion = 0;
|
||||||
bool _deleted = false;
|
bool _unavailable = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1656,7 +1656,9 @@ void HistoryWidget::saveDraft(bool delayed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::saveFieldToHistoryLocalDraft() {
|
void HistoryWidget::saveFieldToHistoryLocalDraft() {
|
||||||
if (!_history) return;
|
if (!_history) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto topicRootId = MsgId();
|
const auto topicRootId = MsgId();
|
||||||
if (_editMsgId) {
|
if (_editMsgId) {
|
||||||
|
@ -6219,13 +6221,16 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
_forwardPanel->editOptions(controller()->uiShow());
|
_forwardPanel->editOptions(controller()->uiShow());
|
||||||
}
|
}
|
||||||
} else if (replyTo() && replyTo().messageId.peer != _peer->id) {
|
} else if (const auto reply = replyTo()) {
|
||||||
// edit options
|
HistoryView::Controls::EditReplyOptions(
|
||||||
} else {
|
controller(),
|
||||||
|
reply,
|
||||||
|
_history);
|
||||||
|
} else if (_editMsgId) {
|
||||||
controller()->showPeerHistory(
|
controller()->showPeerHistory(
|
||||||
_peer,
|
_peer,
|
||||||
Window::SectionShow::Way::Forward,
|
Window::SectionShow::Way::Forward,
|
||||||
_editMsgId ? _editMsgId : replyTo().messageId.msg);
|
_editMsgId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7096,6 +7101,7 @@ void HistoryWidget::processReply() {
|
||||||
_processingReplyTo.messageId.msg,
|
_processingReplyTo.messageId.msg,
|
||||||
processContinue());
|
processContinue());
|
||||||
return;
|
return;
|
||||||
|
#if 0 // Now we can "reply" to old legacy group messages.
|
||||||
} else if (_processingReplyItem->history() == _migrated) {
|
} else if (_processingReplyItem->history() == _migrated) {
|
||||||
if (_processingReplyItem->isService()) {
|
if (_processingReplyItem->isService()) {
|
||||||
controller()->showToast(tr::lng_reply_cant(tr::now));
|
controller()->showToast(tr::lng_reply_cant(tr::now));
|
||||||
|
@ -7113,10 +7119,11 @@ void HistoryWidget::processReply() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return processCancel();
|
return processCancel();
|
||||||
} else if (_processingReplyItem->history() != _history
|
#endif
|
||||||
|| !_processingReplyItem->isRegular()) {
|
} else if (!_processingReplyItem->isRegular()) {
|
||||||
return processCancel();
|
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();
|
const auto topicRootId = _processingReplyItem->topicRootId();
|
||||||
if (forum->topicDeleted(topicRootId)) {
|
if (forum->topicDeleted(topicRootId)) {
|
||||||
return processCancel();
|
return processCancel();
|
||||||
|
|
|
@ -29,6 +29,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "styles/style_chat_helpers.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 HistoryView::Controls {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -395,4 +403,137 @@ void ForwardPanel::paint(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowReplyToChatBox(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
FullReplyTo reply,
|
||||||
|
base::weak_ptr<Data::Thread> oldThread) {
|
||||||
|
class Controller final : public ChooseRecipientBoxController {
|
||||||
|
public:
|
||||||
|
using Chosen = not_null<Data::Thread*>;
|
||||||
|
|
||||||
|
Controller(not_null<Main::Session*> session)
|
||||||
|
: ChooseRecipientBoxController(
|
||||||
|
session,
|
||||||
|
[=](Chosen thread) mutable { _singleChosen.fire_copy(thread); },
|
||||||
|
nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void rowClicked(not_null<PeerListRow*> row) override final {
|
||||||
|
ChooseRecipientBoxController::rowClicked(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<Chosen> singleChosen() const{
|
||||||
|
return _singleChosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rpl::event_stream<Chosen> _singleChosen;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
not_null<PeerListBox*> box;
|
||||||
|
not_null<Controller*> controller;
|
||||||
|
base::unique_qptr<Ui::PopupMenu> menu;
|
||||||
|
};
|
||||||
|
const auto session = &window->session();
|
||||||
|
const auto state = [&] {
|
||||||
|
auto controller = std::make_unique<Controller>(session);
|
||||||
|
const auto controllerRaw = controller.get();
|
||||||
|
auto box = Box<PeerListBox>(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<State>(std::move(state));
|
||||||
|
}();
|
||||||
|
|
||||||
|
auto chosen = [=](not_null<Data::Thread*> 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<Data::Draft>(
|
||||||
|
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<Data::Draft>(
|
||||||
|
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<Window::SessionController*> controller,
|
||||||
|
FullReplyTo reply,
|
||||||
|
not_null<Data::Thread*> thread) {
|
||||||
|
const auto weak = base::make_weak(thread);
|
||||||
|
controller->uiShow()->show(Box([=](not_null<Ui::GenericBox*> 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
|
} // namespace HistoryView::Controls
|
||||||
|
|
|
@ -71,4 +71,9 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void EditReplyOptions(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
FullReplyTo reply,
|
||||||
|
not_null<Data::Thread*> thread);
|
||||||
|
|
||||||
} // namespace HistoryView::Controls
|
} // namespace HistoryView::Controls
|
||||||
|
|
Loading…
Add table
Reference in a new issue