Allow replying inside replies section.
This commit is contained in:
parent
f22a804220
commit
17549ad5ea
|
@ -67,35 +67,37 @@ WebPageText ProcessWebPageData(WebPageData *page) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class FieldHeader : public Ui::RpWidget {
|
class FieldHeader final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
FieldHeader(QWidget *parent, not_null<Data::Session*> data);
|
FieldHeader(QWidget *parent, not_null<Data::Session*> data);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void editMessage(FullMsgId edit);
|
void editMessage(FullMsgId id);
|
||||||
|
void replyToMessage(FullMsgId id);
|
||||||
void previewRequested(
|
void previewRequested(
|
||||||
rpl::producer<QString> title,
|
rpl::producer<QString> title,
|
||||||
rpl::producer<QString> description,
|
rpl::producer<QString> description,
|
||||||
rpl::producer<WebPageData*> page);
|
rpl::producer<WebPageData*> page);
|
||||||
|
|
||||||
bool isDisplayed() const;
|
[[nodiscard]] bool isDisplayed() const;
|
||||||
bool isEditingMessage() const;
|
[[nodiscard]] bool isEditingMessage() const;
|
||||||
rpl::producer<FullMsgId> editMsgId() const;
|
[[nodiscard]] FullMsgId replyingToMessage() const;
|
||||||
rpl::producer<FullMsgId> scrollToItemRequests() const;
|
[[nodiscard]] rpl::producer<FullMsgId> editMsgId() const;
|
||||||
MessageToEdit queryToEdit();
|
[[nodiscard]] rpl::producer<FullMsgId> scrollToItemRequests() const;
|
||||||
WebPageId webPageId() const;
|
[[nodiscard]] MessageToEdit queryToEdit();
|
||||||
|
[[nodiscard]] WebPageId webPageId() const;
|
||||||
|
|
||||||
rpl::producer<bool> visibleChanged();
|
[[nodiscard]] rpl::producer<bool> visibleChanged();
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateControlsGeometry(QSize size);
|
void updateControlsGeometry(QSize size);
|
||||||
void updateVisible();
|
void updateVisible();
|
||||||
|
void setShownMessage(HistoryItem *message);
|
||||||
|
void updateShownMessageText();
|
||||||
|
|
||||||
void paintWebPage(Painter &p);
|
void paintWebPage(Painter &p);
|
||||||
void paintEditMessage(Painter &p);
|
void paintEditOrReplyToMessage(Painter &p);
|
||||||
|
|
||||||
struct Preview {
|
struct Preview {
|
||||||
WebPageData *data = nullptr;
|
WebPageData *data = nullptr;
|
||||||
|
@ -110,8 +112,13 @@ private:
|
||||||
|
|
||||||
bool hasPreview() const;
|
bool hasPreview() const;
|
||||||
|
|
||||||
Ui::Text::String _editMsgText;
|
|
||||||
rpl::variable<FullMsgId> _editMsgId;
|
rpl::variable<FullMsgId> _editMsgId;
|
||||||
|
rpl::variable<FullMsgId> _replyToId;
|
||||||
|
|
||||||
|
HistoryItem *_shownMessage = nullptr;
|
||||||
|
Ui::Text::String _shownMessageName;
|
||||||
|
Ui::Text::String _shownMessageText;
|
||||||
|
int _shownMessageNameVersion = -1;
|
||||||
|
|
||||||
const not_null<Data::Session*> _data;
|
const not_null<Data::Session*> _data;
|
||||||
const not_null<Ui::IconButton*> _cancel;
|
const not_null<Ui::IconButton*> _cancel;
|
||||||
|
@ -141,37 +148,46 @@ void FieldHeader::init() {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
p.fillRect(rect(), st::historyComposeAreaBg);
|
p.fillRect(rect(), st::historyComposeAreaBg);
|
||||||
|
|
||||||
if (isEditingMessage()) {
|
|
||||||
const auto position = st::historyReplyIconPosition;
|
const auto position = st::historyReplyIconPosition;
|
||||||
|
if (isEditingMessage()) {
|
||||||
st::historyEditIcon.paint(p, position, width());
|
st::historyEditIcon.paint(p, position, width());
|
||||||
|
} else if (replyingToMessage()) {
|
||||||
|
st::historyReplyIcon.paint(p, position, width());
|
||||||
}
|
}
|
||||||
|
|
||||||
(!ShowWebPagePreview(_preview.data) || *leftIconPressed)
|
(!ShowWebPagePreview(_preview.data) || *leftIconPressed)
|
||||||
? paintEditMessage(p)
|
? paintEditOrReplyToMessage(p)
|
||||||
: paintWebPage(p);
|
: paintWebPage(p);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
const auto checkPreview = [=](not_null<const HistoryItem*> item) {
|
|
||||||
_preview = {};
|
|
||||||
if (const auto media = item->media()) {
|
|
||||||
if (const auto page = media->webpage()) {
|
|
||||||
const auto preview = ProcessWebPageData(page);
|
|
||||||
_title = preview.title;
|
|
||||||
_description = preview.description;
|
|
||||||
_preview.data = page;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_editMsgId.value(
|
_editMsgId.value(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=](FullMsgId value) {
|
||||||
updateVisible();
|
const auto shown = value ? value : _replyToId.current();
|
||||||
if (const auto item = _data->message(_editMsgId.current())) {
|
setShownMessage(_data->message(shown));
|
||||||
_editMsgText.setText(
|
}, lifetime());
|
||||||
st::messageTextStyle,
|
|
||||||
item->inReplyText(),
|
_replyToId.value(
|
||||||
Ui::DialogTextOptions());
|
) | rpl::start_with_next([=](FullMsgId value) {
|
||||||
checkPreview(item);
|
if (!_editMsgId.current()) {
|
||||||
|
setShownMessage(_data->message(value));
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_data->session().changes().messageUpdates(
|
||||||
|
Data::MessageUpdate::Flag::Edited
|
||||||
|
| Data::MessageUpdate::Flag::Destroyed
|
||||||
|
) | rpl::filter([=](const Data::MessageUpdate &update) {
|
||||||
|
return (update.item == _shownMessage);
|
||||||
|
}) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
|
||||||
|
if (update.flags & Data::MessageUpdate::Flag::Destroyed) {
|
||||||
|
if (_editMsgId.current() == update.item->fullId()) {
|
||||||
|
editMessage({});
|
||||||
|
}
|
||||||
|
if (_replyToId.current() == update.item->fullId()) {
|
||||||
|
replyToMessage({});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateShownMessageText();
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
@ -179,8 +195,10 @@ void FieldHeader::init() {
|
||||||
if (hasPreview()) {
|
if (hasPreview()) {
|
||||||
_preview = {};
|
_preview = {};
|
||||||
update();
|
update();
|
||||||
} else {
|
} else if (_editMsgId.current()) {
|
||||||
_editMsgId = {};
|
editMessage({});
|
||||||
|
} else if (_replyToId.current()) {
|
||||||
|
replyToMessage({});
|
||||||
}
|
}
|
||||||
updateVisible();
|
updateVisible();
|
||||||
});
|
});
|
||||||
|
@ -246,6 +264,46 @@ void FieldHeader::init() {
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FieldHeader::updateShownMessageText() {
|
||||||
|
Expects(_shownMessage != nullptr);
|
||||||
|
|
||||||
|
_shownMessageText.setText(
|
||||||
|
st::messageTextStyle,
|
||||||
|
_shownMessage->inReplyText(),
|
||||||
|
Ui::DialogTextOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldHeader::setShownMessage(HistoryItem *item) {
|
||||||
|
_shownMessage = item;
|
||||||
|
if (item) {
|
||||||
|
updateShownMessageText();
|
||||||
|
if (item->fullId() == _editMsgId.current()) {
|
||||||
|
_preview = {};
|
||||||
|
if (const auto media = item->media()) {
|
||||||
|
if (const auto page = media->webpage()) {
|
||||||
|
const auto preview = ProcessWebPageData(page);
|
||||||
|
_title = preview.title;
|
||||||
|
_description = preview.description;
|
||||||
|
_preview.data = page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_shownMessageText.clear();
|
||||||
|
}
|
||||||
|
if (isEditingMessage()) {
|
||||||
|
_shownMessageName.setText(
|
||||||
|
st::msgNameStyle,
|
||||||
|
tr::lng_edit_message(tr::now),
|
||||||
|
Ui::NameTextOptions());
|
||||||
|
} else {
|
||||||
|
_shownMessageName.clear();
|
||||||
|
_shownMessageNameVersion = -1;
|
||||||
|
}
|
||||||
|
updateVisible();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void FieldHeader::previewRequested(
|
void FieldHeader::previewRequested(
|
||||||
rpl::producer<QString> title,
|
rpl::producer<QString> title,
|
||||||
rpl::producer<QString> description,
|
rpl::producer<QString> description,
|
||||||
|
@ -315,23 +373,43 @@ void FieldHeader::paintWebPage(Painter &p) {
|
||||||
elidedWidth);
|
elidedWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldHeader::paintEditMessage(Painter &p) {
|
void FieldHeader::paintEditOrReplyToMessage(Painter &p) {
|
||||||
|
Expects(_shownMessage != nullptr);
|
||||||
|
|
||||||
const auto replySkip = st::historyReplySkip;
|
const auto replySkip = st::historyReplySkip;
|
||||||
|
const auto availableWidth = width()
|
||||||
|
- replySkip
|
||||||
|
- _cancel->width()
|
||||||
|
- st::msgReplyPadding.right();
|
||||||
|
|
||||||
|
if (!isEditingMessage()) {
|
||||||
|
const auto user = _shownMessage->displayFrom()
|
||||||
|
? _shownMessage->displayFrom()
|
||||||
|
: _shownMessage->author().get();
|
||||||
|
if (user->nameVersion > _shownMessageNameVersion) {
|
||||||
|
_shownMessageName.setText(
|
||||||
|
st::msgNameStyle,
|
||||||
|
user->name,
|
||||||
|
Ui::NameTextOptions());
|
||||||
|
_shownMessageNameVersion = user->nameVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p.setPen(st::historyReplyNameFg);
|
p.setPen(st::historyReplyNameFg);
|
||||||
p.setFont(st::msgServiceNameFont);
|
p.setFont(st::msgServiceNameFont);
|
||||||
p.drawTextLeft(
|
_shownMessageName.drawElided(
|
||||||
|
p,
|
||||||
replySkip,
|
replySkip,
|
||||||
st::msgReplyPadding.top(),
|
st::msgReplyPadding.top(),
|
||||||
width(),
|
availableWidth);
|
||||||
tr::lng_edit_message(tr::now));
|
|
||||||
|
|
||||||
p.setPen(st::historyComposeAreaFg);
|
p.setPen(st::historyComposeAreaFg);
|
||||||
p.setTextPalette(st::historyComposeAreaPalette);
|
p.setTextPalette(st::historyComposeAreaPalette);
|
||||||
_editMsgText.drawElided(
|
_shownMessageText.drawElided(
|
||||||
p,
|
p,
|
||||||
replySkip,
|
replySkip,
|
||||||
st::msgReplyPadding.top() + st::msgServiceNameFont->height,
|
st::msgReplyPadding.top() + st::msgServiceNameFont->height,
|
||||||
width() - replySkip - _cancel->width() - st::msgReplyPadding.right());
|
availableWidth);
|
||||||
p.restoreTextPalette();
|
p.restoreTextPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,13 +423,17 @@ rpl::producer<bool> FieldHeader::visibleChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FieldHeader::isDisplayed() const {
|
bool FieldHeader::isDisplayed() const {
|
||||||
return isEditingMessage() || hasPreview();
|
return isEditingMessage() || replyingToMessage() || hasPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FieldHeader::isEditingMessage() const {
|
bool FieldHeader::isEditingMessage() const {
|
||||||
return !!_editMsgId.current();
|
return !!_editMsgId.current();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FullMsgId FieldHeader::replyingToMessage() const {
|
||||||
|
return _replyToId.current();
|
||||||
|
}
|
||||||
|
|
||||||
bool FieldHeader::hasPreview() const {
|
bool FieldHeader::hasPreview() const {
|
||||||
return ShowWebPagePreview(_preview.data);
|
return ShowWebPagePreview(_preview.data);
|
||||||
}
|
}
|
||||||
|
@ -368,6 +450,10 @@ void FieldHeader::editMessage(FullMsgId id) {
|
||||||
_editMsgId = id;
|
_editMsgId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FieldHeader::replyToMessage(FullMsgId id) {
|
||||||
|
_replyToId = id;
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<FullMsgId> FieldHeader::editMsgId() const {
|
rpl::producer<FullMsgId> FieldHeader::editMsgId() const {
|
||||||
return _editMsgId.value();
|
return _editMsgId.value();
|
||||||
}
|
}
|
||||||
|
@ -550,6 +636,7 @@ TextWithTags ComposeControls::getTextWithAppliedMarkdown() const {
|
||||||
|
|
||||||
void ComposeControls::clear() {
|
void ComposeControls::clear() {
|
||||||
setText(TextWithTags());
|
setText(TextWithTags());
|
||||||
|
cancelReplyMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::setText(const TextWithTags &textWithTags) {
|
void ComposeControls::setText(const TextWithTags &textWithTags) {
|
||||||
|
@ -863,15 +950,24 @@ void ComposeControls::updateHeight() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::editMessage(FullMsgId edit) {
|
void ComposeControls::editMessage(FullMsgId id) {
|
||||||
cancelEditMessage();
|
cancelEditMessage();
|
||||||
_header->editMessage(std::move(edit));
|
_header->editMessage(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::cancelEditMessage() {
|
void ComposeControls::cancelEditMessage() {
|
||||||
_header->editMessage({});
|
_header->editMessage({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComposeControls::replyToMessage(FullMsgId id) {
|
||||||
|
cancelReplyMessage();
|
||||||
|
_header->replyToMessage(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComposeControls::cancelReplyMessage() {
|
||||||
|
_header->replyToMessage({});
|
||||||
|
}
|
||||||
|
|
||||||
void ComposeControls::initWebpageProcess() {
|
void ComposeControls::initWebpageProcess() {
|
||||||
Expects(_history);
|
Expects(_history);
|
||||||
const auto peer = _history->peer;
|
const auto peer = _history->peer;
|
||||||
|
@ -1060,4 +1156,8 @@ bool ComposeControls::isEditingMessage() const {
|
||||||
return _header->isEditingMessage();
|
return _header->isEditingMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FullMsgId ComposeControls::replyingToMessage() const {
|
||||||
|
return _header->replyingToMessage();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -104,15 +104,19 @@ public:
|
||||||
const Window::SectionShow ¶ms);
|
const Window::SectionShow ¶ms);
|
||||||
bool returnTabbedSelector();
|
bool returnTabbedSelector();
|
||||||
|
|
||||||
bool isEditingMessage() const;
|
[[nodiscard]] bool isEditingMessage() const;
|
||||||
|
[[nodiscard]] FullMsgId replyingToMessage() const;
|
||||||
|
|
||||||
void showForGrab();
|
void showForGrab();
|
||||||
void showStarted();
|
void showStarted();
|
||||||
void showFinished();
|
void showFinished();
|
||||||
|
|
||||||
void editMessage(FullMsgId edit);
|
void editMessage(FullMsgId id);
|
||||||
void cancelEditMessage();
|
void cancelEditMessage();
|
||||||
|
|
||||||
|
void replyToMessage(FullMsgId id);
|
||||||
|
void cancelReplyMessage();
|
||||||
|
|
||||||
[[nodiscard]] TextWithTags getTextWithAppliedMarkdown() const;
|
[[nodiscard]] TextWithTags getTextWithAppliedMarkdown() const;
|
||||||
[[nodiscard]] WebPageId webPageId() const;
|
[[nodiscard]] WebPageId webPageId() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
|
|
@ -75,7 +75,7 @@ MsgId ItemIdAcrossData(not_null<HistoryItem*> item) {
|
||||||
return session->data().scheduledMessages().lookupId(item);
|
return session->data().scheduledMessages().lookupId(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasEditScheduledMessageAction(const ContextMenuRequest &request) {
|
bool HasEditMessageAction(const ContextMenuRequest &request) {
|
||||||
const auto item = request.item;
|
const auto item = request.item;
|
||||||
if (!item
|
if (!item
|
||||||
|| item->isSending()
|
|| item->isSending()
|
||||||
|
@ -415,7 +415,8 @@ bool AddSendNowMessageAction(
|
||||||
bool AddRescheduleMessageAction(
|
bool AddRescheduleMessageAction(
|
||||||
not_null<Ui::PopupMenu*> menu,
|
not_null<Ui::PopupMenu*> menu,
|
||||||
const ContextMenuRequest &request) {
|
const ContextMenuRequest &request) {
|
||||||
if (!HasEditScheduledMessageAction(request)) {
|
if (!HasEditMessageAction(request)
|
||||||
|
|| !request.item->isScheduled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto item = request.item;
|
const auto item = request.item;
|
||||||
|
@ -458,11 +459,33 @@ bool AddRescheduleMessageAction(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddReplyToMessageAction(
|
||||||
|
not_null<Ui::PopupMenu*> menu,
|
||||||
|
const ContextMenuRequest &request,
|
||||||
|
not_null<ListWidget*> list) {
|
||||||
|
const auto item = request.item;
|
||||||
|
if (!item
|
||||||
|
|| !IsServerMsgId(item->id)
|
||||||
|
|| !item->history()->peer->canWrite()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto owner = &item->history()->owner();
|
||||||
|
const auto itemId = item->fullId();
|
||||||
|
menu->addAction(tr::lng_context_reply_msg(tr::now), [=] {
|
||||||
|
const auto item = owner->message(itemId);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list->replyToMessageRequestNotify(item->fullId());
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool AddEditMessageAction(
|
bool AddEditMessageAction(
|
||||||
not_null<Ui::PopupMenu*> menu,
|
not_null<Ui::PopupMenu*> menu,
|
||||||
const ContextMenuRequest &request,
|
const ContextMenuRequest &request,
|
||||||
not_null<ListWidget*> list) {
|
not_null<ListWidget*> list) {
|
||||||
if (!HasEditScheduledMessageAction(request)) {
|
if (!HasEditMessageAction(request)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto item = request.item;
|
const auto item = request.item;
|
||||||
|
@ -630,11 +653,18 @@ void AddSelectionAction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddTopMessageActions(
|
||||||
|
not_null<Ui::PopupMenu*> menu,
|
||||||
|
const ContextMenuRequest &request,
|
||||||
|
not_null<ListWidget*> list) {
|
||||||
|
AddReplyToMessageAction(menu, request, list);
|
||||||
|
AddEditMessageAction(menu, request, list);
|
||||||
|
}
|
||||||
|
|
||||||
void AddMessageActions(
|
void AddMessageActions(
|
||||||
not_null<Ui::PopupMenu*> menu,
|
not_null<Ui::PopupMenu*> menu,
|
||||||
const ContextMenuRequest &request,
|
const ContextMenuRequest &request,
|
||||||
not_null<ListWidget*> list) {
|
not_null<ListWidget*> list) {
|
||||||
AddEditMessageAction(menu, request, list);
|
|
||||||
AddPostLinkAction(menu, request);
|
AddPostLinkAction(menu, request);
|
||||||
AddForwardAction(menu, request, list);
|
AddForwardAction(menu, request, list);
|
||||||
AddSendNowAction(menu, request, list);
|
AddSendNowAction(menu, request, list);
|
||||||
|
@ -695,6 +725,7 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddTopMessageActions(result, request, list);
|
||||||
if (linkPhoto) {
|
if (linkPhoto) {
|
||||||
AddPhotoActions(result, photo);
|
AddPhotoActions(result, photo);
|
||||||
} else if (linkDocument) {
|
} else if (linkDocument) {
|
||||||
|
|
|
@ -2585,6 +2585,14 @@ void ListWidget::editMessageRequestNotify(FullMsgId item) {
|
||||||
_requestedToEditMessage.fire(std::move(item));
|
_requestedToEditMessage.fire(std::move(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<FullMsgId> ListWidget::replyToMessageRequested() const {
|
||||||
|
return _requestedToReplyToMessage.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::replyToMessageRequestNotify(FullMsgId item) {
|
||||||
|
_requestedToReplyToMessage.fire(std::move(item));
|
||||||
|
}
|
||||||
|
|
||||||
ListWidget::~ListWidget() = default;
|
ListWidget::~ListWidget() = default;
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -188,6 +188,8 @@ public:
|
||||||
|
|
||||||
rpl::producer<FullMsgId> editMessageRequested() const;
|
rpl::producer<FullMsgId> editMessageRequested() const;
|
||||||
void editMessageRequestNotify(FullMsgId item);
|
void editMessageRequestNotify(FullMsgId item);
|
||||||
|
rpl::producer<FullMsgId> replyToMessageRequested() const;
|
||||||
|
void replyToMessageRequestNotify(FullMsgId item);
|
||||||
|
|
||||||
// ElementDelegate interface.
|
// ElementDelegate interface.
|
||||||
Context elementContext() override;
|
Context elementContext() override;
|
||||||
|
@ -523,6 +525,7 @@ private:
|
||||||
base::Timer _highlightTimer;
|
base::Timer _highlightTimer;
|
||||||
|
|
||||||
rpl::event_stream<FullMsgId> _requestedToEditMessage;
|
rpl::event_stream<FullMsgId> _requestedToEditMessage;
|
||||||
|
rpl::event_stream<FullMsgId> _requestedToReplyToMessage;
|
||||||
|
|
||||||
rpl::lifetime _viewerLifetime;
|
rpl::lifetime _viewerLifetime;
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,11 @@ RepliesWidget::RepliesWidget(
|
||||||
}
|
}
|
||||||
}, _inner->lifetime());
|
}, _inner->lifetime());
|
||||||
|
|
||||||
|
_inner->replyToMessageRequested(
|
||||||
|
) | rpl::start_with_next([=](auto fullId) {
|
||||||
|
_composeControls->replyToMessage(fullId);
|
||||||
|
}, _inner->lifetime());
|
||||||
|
|
||||||
_history->session().changes().messageUpdates(
|
_history->session().changes().messageUpdates(
|
||||||
Data::MessageUpdate::Flag::Destroyed
|
Data::MessageUpdate::Flag::Destroyed
|
||||||
) | rpl::filter([=](const Data::MessageUpdate &update) {
|
) | rpl::filter([=](const Data::MessageUpdate &update) {
|
||||||
|
@ -390,6 +395,7 @@ bool RepliesWidget::confirmSendingFiles(
|
||||||
SendMenu::Type::Disabled); // #TODO replies schedule
|
SendMenu::Type::Disabled); // #TODO replies schedule
|
||||||
//_field->setTextWithTags({});
|
//_field->setTextWithTags({});
|
||||||
|
|
||||||
|
const auto replyTo = replyToId();
|
||||||
box->setConfirmedCallback(crl::guard(this, [=](
|
box->setConfirmedCallback(crl::guard(this, [=](
|
||||||
Storage::PreparedList &&list,
|
Storage::PreparedList &&list,
|
||||||
SendFilesWay way,
|
SendFilesWay way,
|
||||||
|
@ -409,7 +415,7 @@ bool RepliesWidget::confirmSendingFiles(
|
||||||
std::move(list),
|
std::move(list),
|
||||||
type,
|
type,
|
||||||
std::move(caption),
|
std::move(caption),
|
||||||
MsgId(_rootId),//replyToId(), // #TODO replies reply
|
replyTo,
|
||||||
options,
|
options,
|
||||||
album);
|
album);
|
||||||
}));
|
}));
|
||||||
|
@ -470,7 +476,7 @@ void RepliesWidget::uploadFilesAfterConfirmation(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto action = Api::SendAction(_history);
|
auto action = Api::SendAction(_history);
|
||||||
action.replyTo = _rootId;// replyTo;// #TODO replies reply
|
action.replyTo = replyTo ? replyTo : _rootId;
|
||||||
action.options = options;
|
action.options = options;
|
||||||
session().api().sendFiles(
|
session().api().sendFiles(
|
||||||
std::move(list),
|
std::move(list),
|
||||||
|
@ -536,7 +542,7 @@ void RepliesWidget::uploadFile(
|
||||||
SendMediaType type) {
|
SendMediaType type) {
|
||||||
// #TODO replies schedule
|
// #TODO replies schedule
|
||||||
auto action = Api::SendAction(_history);
|
auto action = Api::SendAction(_history);
|
||||||
action.replyTo = _rootId;// #TODO replies reply
|
action.replyTo = replyToId();
|
||||||
session().api().sendFile(fileContent, type, action);
|
session().api().sendFile(fileContent, type, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +601,7 @@ void RepliesWidget::send(Api::SendOptions options) {
|
||||||
auto message = ApiWrap::MessageToSend(_history);
|
auto message = ApiWrap::MessageToSend(_history);
|
||||||
message.textWithTags = _composeControls->getTextWithAppliedMarkdown();
|
message.textWithTags = _composeControls->getTextWithAppliedMarkdown();
|
||||||
message.action.options = options;
|
message.action.options = options;
|
||||||
message.action.replyTo = _rootId;// replyToId();// #TODO replies reply
|
message.action.replyTo = replyToId();
|
||||||
message.webPageId = webPageId;
|
message.webPageId = webPageId;
|
||||||
|
|
||||||
//const auto error = GetErrorTextForSending(
|
//const auto error = GetErrorTextForSending(
|
||||||
|
@ -717,7 +723,7 @@ bool RepliesWidget::sendExistingDocument(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message = Api::MessageToSend(_history);
|
auto message = Api::MessageToSend(_history);
|
||||||
message.action.replyTo = _rootId;// replyToId();// #TODO replies reply
|
message.action.replyTo = replyToId();
|
||||||
message.action.options = options;
|
message.action.options = options;
|
||||||
Api::SendExistingDocument(std::move(message), document);
|
Api::SendExistingDocument(std::move(message), document);
|
||||||
|
|
||||||
|
@ -729,6 +735,7 @@ bool RepliesWidget::sendExistingDocument(
|
||||||
// onCloudDraftSave(); // won't be needed if SendInlineBotResult will clear the cloud draft
|
// onCloudDraftSave(); // won't be needed if SendInlineBotResult will clear the cloud draft
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
_composeControls->cancelReplyMessage();
|
||||||
_composeControls->hidePanelsAnimated();
|
_composeControls->hidePanelsAnimated();
|
||||||
_composeControls->focus();
|
_composeControls->focus();
|
||||||
return true;
|
return true;
|
||||||
|
@ -757,10 +764,11 @@ bool RepliesWidget::sendExistingPhoto(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message = Api::MessageToSend(_history);
|
auto message = Api::MessageToSend(_history);
|
||||||
message.action.replyTo = _rootId;// replyToId();// #TODO replies reply
|
message.action.replyTo = replyToId();
|
||||||
message.action.options = options;
|
message.action.options = options;
|
||||||
Api::SendExistingPhoto(std::move(message), photo);
|
Api::SendExistingPhoto(std::move(message), photo);
|
||||||
|
|
||||||
|
_composeControls->cancelReplyMessage();
|
||||||
_composeControls->hidePanelsAnimated();
|
_composeControls->hidePanelsAnimated();
|
||||||
_composeControls->focus();
|
_composeControls->focus();
|
||||||
return true;
|
return true;
|
||||||
|
@ -788,7 +796,7 @@ void RepliesWidget::sendInlineResult(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
Api::SendOptions options) {
|
Api::SendOptions options) {
|
||||||
auto action = Api::SendAction(_history);
|
auto action = Api::SendAction(_history);
|
||||||
action.replyTo = _rootId;// replyToId();// #TODO replies reply
|
action.replyTo = replyToId();
|
||||||
action.options = options;
|
action.options = options;
|
||||||
action.generateLocal = true;
|
action.generateLocal = true;
|
||||||
session().api().sendInlineResult(bot, result, action);
|
session().api().sendInlineResult(bot, result, action);
|
||||||
|
@ -823,6 +831,11 @@ SendMenu::Type RepliesWidget::sendMenuType() const {
|
||||||
: SendMenu::Type::Scheduled;
|
: SendMenu::Type::Scheduled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MsgId RepliesWidget::replyToId() const {
|
||||||
|
const auto custom = _composeControls->replyingToMessage().msg;
|
||||||
|
return custom ? custom : _rootId;
|
||||||
|
}
|
||||||
|
|
||||||
void RepliesWidget::setupScrollDownButton() {
|
void RepliesWidget::setupScrollDownButton() {
|
||||||
_scrollDown->setClickedCallback([=] {
|
_scrollDown->setClickedCallback([=] {
|
||||||
scrollDownClicked();
|
scrollDownClicked();
|
||||||
|
@ -1188,6 +1201,9 @@ void RepliesWidget::listCancelRequest() {
|
||||||
if (_composeControls->isEditingMessage()) {
|
if (_composeControls->isEditingMessage()) {
|
||||||
_composeControls->cancelEditMessage();
|
_composeControls->cancelEditMessage();
|
||||||
return;
|
return;
|
||||||
|
} else if (_composeControls->replyingToMessage()) {
|
||||||
|
_composeControls->cancelReplyMessage();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
controller()->showBackFromStack();
|
controller()->showBackFromStack();
|
||||||
}
|
}
|
||||||
|
@ -1225,8 +1241,8 @@ void RepliesWidget::listSelectionChanged(SelectedItems &&items) {
|
||||||
if (item.canDelete) {
|
if (item.canDelete) {
|
||||||
++state.canDeleteCount;
|
++state.canDeleteCount;
|
||||||
}
|
}
|
||||||
if (item.canSendNow) {
|
if (item.canForward) {
|
||||||
++state.canSendNowCount;
|
++state.canForwardCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_topBar->showSelected(state);
|
_topBar->showSelected(state);
|
||||||
|
|
|
@ -166,6 +166,7 @@ private:
|
||||||
mtpRequestId *const saveEditMsgRequestId);
|
mtpRequestId *const saveEditMsgRequestId);
|
||||||
void chooseAttach();
|
void chooseAttach();
|
||||||
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
||||||
|
[[nodiscard]] MsgId replyToId() const;
|
||||||
|
|
||||||
void pushReplyReturn(not_null<HistoryItem*> item);
|
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||||
void computeCurrentReplyReturn();
|
void computeCurrentReplyReturn();
|
||||||
|
|
Loading…
Reference in New Issue