mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-25 01:50:36 +00:00
Fix draft options edit, add to topics/replies.
This commit is contained in:
parent
a197ed9e95
commit
cc8408d11c
@ -6246,6 +6246,11 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||
return;
|
||||
} else if (_previewDrawPreview) {
|
||||
editDraftOptions();
|
||||
} else if (_editMsgId) {
|
||||
controller()->showPeerHistory(
|
||||
_peer,
|
||||
Window::SectionShow::Way::Forward,
|
||||
_editMsgId);
|
||||
} else if (isReadyToForward) {
|
||||
if (e->button() != Qt::LeftButton) {
|
||||
_forwardPanel->editToNextOption();
|
||||
@ -6259,11 +6264,6 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||
_kbReplyTo->history()->peer->id,
|
||||
Window::SectionShow::Way::Forward,
|
||||
_kbReplyTo->id);
|
||||
} else if (_editMsgId) {
|
||||
controller()->showPeerHistory(
|
||||
_peer,
|
||||
Window::SectionShow::Way::Forward,
|
||||
_editMsgId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,7 @@ public:
|
||||
[[nodiscard]] rpl::producer<FullMsgId> editMsgIdValue() const;
|
||||
[[nodiscard]] rpl::producer<FullMsgId> scrollToItemRequests() const;
|
||||
[[nodiscard]] rpl::producer<> editPhotoRequests() const;
|
||||
[[nodiscard]] rpl::producer<> editOptionsRequests() const;
|
||||
[[nodiscard]] MessageToEdit queryToEdit();
|
||||
|
||||
[[nodiscard]] FullReplyTo getDraftReply() const;
|
||||
@ -221,6 +222,7 @@ private:
|
||||
|
||||
rpl::event_stream<bool> _visibleChanged;
|
||||
rpl::event_stream<FullMsgId> _scrollToItemRequests;
|
||||
rpl::event_stream<> _editOptionsRequests;
|
||||
rpl::event_stream<> _editPhotoRequests;
|
||||
|
||||
};
|
||||
@ -333,7 +335,8 @@ void FieldHeader::init() {
|
||||
return (ranges::contains(kMouseEvents, type) || leaving)
|
||||
&& (isEditingMessage()
|
||||
|| readyToForward()
|
||||
|| replyingToMessage());
|
||||
|| replyingToMessage()
|
||||
|| _preview.parsed);
|
||||
}) | rpl::start_with_next([=](not_null<QEvent*> event) {
|
||||
const auto updateOver = [&](bool inClickable, bool inPhotoEdit) {
|
||||
if (_inClickable != inClickable) {
|
||||
@ -377,40 +380,14 @@ void FieldHeader::init() {
|
||||
_editPhotoRequests.fire({});
|
||||
} else if (isLeftButton && inPreviewRect) {
|
||||
const auto reply = replyingToMessage();
|
||||
if (!isEditingMessage() && readyToForward()) {
|
||||
if (_preview.parsed) {
|
||||
_editOptionsRequests.fire({});
|
||||
} else if (isEditingMessage()) {
|
||||
_scrollToItemRequests.fire(_editMsgId.current());
|
||||
} else if (readyToForward()) {
|
||||
_forwardPanel->editOptions(_show);
|
||||
} else if (!isEditingMessage() && reply) {
|
||||
//using namespace Controls;
|
||||
//const auto highlight = [=] {
|
||||
// _scrollToItemRequests.fire_copy(reply.messageId);
|
||||
//};
|
||||
//const auto history = _history;
|
||||
//const auto topicRootId = _topicRootId;
|
||||
//const auto done = [=](
|
||||
// FullReplyTo replyTo,
|
||||
// Data::WebPageDraft webpage) {
|
||||
// if (replyTo) {
|
||||
// replyToMessage(replyTo);
|
||||
// } else {
|
||||
// _replyCancelled.fire({});
|
||||
// }
|
||||
|
||||
//};
|
||||
//const auto clearOldReplyTo = [=, id = reply.messageId] {
|
||||
// ClearDraftReplyTo(history, topicRootId, id);
|
||||
//};
|
||||
//EditDraftOptions(
|
||||
// _show,
|
||||
// _history,
|
||||
// Data::Draft( reply,
|
||||
// done,
|
||||
// highlight,
|
||||
// clearOldReplyTo);
|
||||
} else {
|
||||
auto id = isEditingMessage()
|
||||
? _editMsgId.current()
|
||||
: replyingToMessage().messageId;
|
||||
_scrollToItemRequests.fire(std::move(id));
|
||||
} else if (reply) {
|
||||
_editOptionsRequests.fire({});
|
||||
}
|
||||
}
|
||||
} else if (type == QEvent::MouseButtonRelease) {
|
||||
@ -429,9 +406,12 @@ void FieldHeader::updateShownMessageText() {
|
||||
.session = &_data->session(),
|
||||
.customEmojiRepaint = [=] { customEmojiRepaint(); },
|
||||
};
|
||||
const auto reply = replyingToMessage();
|
||||
_shownMessageText.setMarkedText(
|
||||
st::messageTextStyle,
|
||||
_shownMessage->inReplyText(),
|
||||
((isEditingMessage() || reply.quote.empty())
|
||||
? _shownMessage->inReplyText()
|
||||
: reply.quote),
|
||||
Ui::DialogTextOptions(),
|
||||
context);
|
||||
}
|
||||
@ -779,6 +759,10 @@ rpl::producer<> FieldHeader::editPhotoRequests() const {
|
||||
return _editPhotoRequests.events();
|
||||
}
|
||||
|
||||
rpl::producer<> FieldHeader::editOptionsRequests() const {
|
||||
return _editOptionsRequests.events();
|
||||
}
|
||||
|
||||
MessageToEdit FieldHeader::queryToEdit() {
|
||||
const auto item = _data->message(_editMsgId.current());
|
||||
if (!isEditingMessage() || !item) {
|
||||
@ -1372,6 +1356,41 @@ void ComposeControls::init() {
|
||||
crl::guard(_wrap.get(), [=] { cancelEditMessage(); }));
|
||||
}, _wrap->lifetime());
|
||||
|
||||
_header->editOptionsRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto history = _history;
|
||||
const auto reply = _header->replyingToMessage();
|
||||
const auto webpage = _preview->draft();
|
||||
|
||||
const auto done = [=](
|
||||
FullReplyTo replyTo,
|
||||
Data::WebPageDraft webpage) {
|
||||
if (replyTo) {
|
||||
replyToMessage(replyTo);
|
||||
} else {
|
||||
cancelReplyMessage();
|
||||
}
|
||||
_preview->apply(webpage);
|
||||
};
|
||||
const auto replyToId = reply.messageId;
|
||||
const auto highlight = crl::guard(_wrap.get(), [=] {
|
||||
_scrollToItemRequests.fire_copy(replyToId);
|
||||
});
|
||||
|
||||
using namespace HistoryView::Controls;
|
||||
EditDraftOptions({
|
||||
.show = _show,
|
||||
.history = history,
|
||||
.draft = Data::Draft(_field, reply, _preview->draft()),
|
||||
.usedLink = _preview->link(),
|
||||
.links = _preview->links(),
|
||||
.resolver = _preview->resolver(),
|
||||
.done = done,
|
||||
.highlight = highlight,
|
||||
.clearOldDraft = [=] { ClearDraftReplyTo(history, replyToId); },
|
||||
});
|
||||
}, _wrap->lifetime());
|
||||
|
||||
_header->previewCancelled(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (_preview) {
|
||||
@ -2882,13 +2901,15 @@ Data::WebPageDraft ComposeControls::webPageDraft() const {
|
||||
}
|
||||
|
||||
rpl::producer<Data::MessagePosition> ComposeControls::scrollRequests() const {
|
||||
return _header->scrollToItemRequests(
|
||||
) | rpl::map([=](FullMsgId id) -> Data::MessagePosition {
|
||||
if (const auto item = session().data().message(id)) {
|
||||
return item->position();
|
||||
}
|
||||
return {};
|
||||
});
|
||||
return rpl::merge(
|
||||
_header->scrollToItemRequests(),
|
||||
_scrollToItemRequests.events()
|
||||
) | rpl::map([=](FullMsgId id) -> Data::MessagePosition {
|
||||
if (const auto item = session().data().message(id)) {
|
||||
return item->position();
|
||||
}
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
bool ComposeControls::isEditingMessage() const {
|
||||
|
@ -357,6 +357,7 @@ private:
|
||||
|
||||
const std::unique_ptr<Ui::RpWidget> _wrap;
|
||||
const std::unique_ptr<Ui::RpWidget> _writeRestricted;
|
||||
rpl::event_stream<FullMsgId> _scrollToItemRequests;
|
||||
|
||||
std::optional<Ui::RoundRect> _backgroundRect;
|
||||
|
||||
|
@ -247,10 +247,9 @@ PreviewWrap::~PreviewWrap() {
|
||||
rpl::producer<TextWithEntities> PreviewWrap::showQuoteSelector(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) {
|
||||
auto element = item->createView(_delegate.get());
|
||||
_selection.reset(element->selectionFromQuote(quote));
|
||||
_element = std::move(element);
|
||||
_selection.reset(TextSelection());
|
||||
|
||||
_element = item->createView(_delegate.get());
|
||||
_link = _pressedLink = nullptr;
|
||||
|
||||
if (const auto was = base::take(_draftItem)) {
|
||||
@ -266,6 +265,7 @@ rpl::producer<TextWithEntities> PreviewWrap::showQuoteSelector(
|
||||
|
||||
initElement();
|
||||
|
||||
_selection = _element->selectionFromQuote(quote);
|
||||
return _selection.value(
|
||||
) | rpl::map([=](TextSelection selection) {
|
||||
return _element->selectedQuote(selection);
|
||||
@ -596,7 +596,7 @@ auto PreviewDelegate::elementPathShiftGradient()
|
||||
}
|
||||
|
||||
Context PreviewDelegate::elementContext() {
|
||||
return Context::History;
|
||||
return Context::Replies;
|
||||
}
|
||||
|
||||
void AddFilledSkip(not_null<Ui::VerticalLayout*> container) {
|
||||
|
@ -605,13 +605,18 @@ bool AddReplyToMessageAction(
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto "e = request.quote;
|
||||
auto text = quote.empty()
|
||||
? tr::lng_context_reply_msg(tr::now)
|
||||
: tr::lng_context_quote_and_reply(tr::now);
|
||||
text.replace('&', u"&&"_q);
|
||||
const auto owner = &item->history()->owner();
|
||||
const auto itemId = item->fullId();
|
||||
menu->addAction(tr::lng_context_reply_msg(tr::now), [=] {
|
||||
menu->addAction(text, [=] {
|
||||
if (!item) {
|
||||
return;
|
||||
} else {
|
||||
list->replyToMessageRequestNotify({ itemId });
|
||||
list->replyToMessageRequestNotify({ itemId, quote });
|
||||
}
|
||||
}, &st::menuIconReply);
|
||||
return true;
|
||||
@ -936,7 +941,6 @@ void AddTopMessageActions(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
const ContextMenuRequest &request,
|
||||
not_null<ListWidget*> list) {
|
||||
AddReplyToMessageAction(menu, request, list);
|
||||
AddGoToMessageAction(menu, request, list);
|
||||
AddViewRepliesAction(menu, request, list);
|
||||
AddEditMessageAction(menu, request, list);
|
||||
@ -1008,6 +1012,8 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||
list,
|
||||
st::popupMenuWithIcons);
|
||||
|
||||
AddReplyToMessageAction(result, request, list);
|
||||
|
||||
if (request.overSelection
|
||||
&& !list->hasCopyRestrictionForSelected()
|
||||
&& !list->getSelectedText().empty()) {
|
||||
|
@ -47,6 +47,7 @@ struct ContextMenuRequest {
|
||||
HistoryItem *item = nullptr;
|
||||
SelectedItems selectedItems;
|
||||
TextForMimeData selectedText;
|
||||
TextWithEntities quote;
|
||||
bool overSelection = false;
|
||||
PointState pointState = PointState();
|
||||
};
|
||||
|
@ -802,7 +802,7 @@ auto Element::contextDependentServiceText() -> TextWithLinks {
|
||||
if (!info) {
|
||||
return {};
|
||||
}
|
||||
if (_delegate->elementContext() == Context::Replies) {
|
||||
if (_context == Context::Replies) {
|
||||
if (info->created()) {
|
||||
return { { tr::lng_action_topic_created_inside(tr::now) } };
|
||||
}
|
||||
|
@ -2576,6 +2576,7 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
: _overElement
|
||||
? _overElement->data().get()
|
||||
: nullptr;
|
||||
const auto overItemView = viewForItem(overItem);
|
||||
const auto clickedReaction = link
|
||||
? link->property(
|
||||
kReactionsCountEmojiProperty).value<Data::ReactionId>()
|
||||
@ -2602,6 +2603,9 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
request.view = _overElement;
|
||||
request.item = overItem;
|
||||
request.pointState = _overState.pointState;
|
||||
request.quote = (overItemView && _selectedTextItem == overItem)
|
||||
? overItemView->selectedQuote(_selectedTextRange)
|
||||
: TextWithEntities();
|
||||
request.selectedText = _selectedText;
|
||||
request.selectedItems = collectSelectedItems();
|
||||
const auto hasSelection = !request.selectedItems.empty()
|
||||
|
@ -94,7 +94,7 @@ const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_";
|
||||
const auto i = ranges::find(left, cut);
|
||||
if (i != left.end()) {
|
||||
left.erase(i);
|
||||
} else if (!ranges::contains(allowed, cut.type())) {
|
||||
} else if (ranges::contains(allowed, cut.type())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2615,7 +2615,8 @@ TextForMimeData Message::selectedText(TextSelection selection) const {
|
||||
const auto media = this->media();
|
||||
auto logEntryOriginalResult = TextForMimeData();
|
||||
const auto mediaDisplayed = (media && media->isDisplayed());
|
||||
const auto textSelection = (mediaDisplayed && invertMedia())
|
||||
const auto mediaBefore = mediaDisplayed && invertMedia();
|
||||
const auto textSelection = mediaBefore
|
||||
? media->skipSelection(selection)
|
||||
: selection;
|
||||
const auto mediaSelection = !invertMedia()
|
||||
@ -2628,19 +2629,15 @@ TextForMimeData Message::selectedText(TextSelection selection) const {
|
||||
? media->selectedText(mediaSelection)
|
||||
: TextForMimeData();
|
||||
if (auto entry = logEntryOriginal()) {
|
||||
const auto originalSelection = (mediaDisplayed && invertMedia())
|
||||
const auto originalSelection = mediaBefore
|
||||
? skipTextSelection(textSelection)
|
||||
: mediaDisplayed
|
||||
? media->skipSelection(mediaSelection)
|
||||
: skipTextSelection(selection);
|
||||
logEntryOriginalResult = entry->selectedText(originalSelection);
|
||||
}
|
||||
auto &first = (mediaDisplayed && invertMedia())
|
||||
? mediaResult
|
||||
: textResult;
|
||||
auto &second = (mediaDisplayed && invertMedia())
|
||||
? textResult
|
||||
: mediaResult;
|
||||
auto &first = mediaBefore ? mediaResult : textResult;
|
||||
auto &second = mediaBefore ? textResult : mediaResult;
|
||||
auto result = first;
|
||||
if (result.empty()) {
|
||||
result = std::move(second);
|
||||
@ -2664,7 +2661,13 @@ TextWithEntities Message::selectedQuote(TextSelection selection) const {
|
||||
|| selection == FullSelection) {
|
||||
return {};
|
||||
} else if (hasVisibleText()) {
|
||||
return selectedQuote(text(), selection);
|
||||
const auto media = this->media();
|
||||
const auto mediaDisplayed = media && media->isDisplayed();
|
||||
const auto mediaBefore = mediaDisplayed && invertMedia();
|
||||
const auto textSelection = mediaBefore
|
||||
? media->skipSelection(selection)
|
||||
: selection;
|
||||
return selectedQuote(text(), textSelection);
|
||||
} else if (const auto media = this->media()) {
|
||||
if (media->isDisplayed() || isHiddenByGroup()) {
|
||||
return media->selectedQuote(selection);
|
||||
@ -2737,7 +2740,11 @@ TextSelection Message::selectionFromQuote(
|
||||
if (&translated != &original || quote.empty()) {
|
||||
return {};
|
||||
} else if (hasVisibleText()) {
|
||||
return selectionFromQuote(text(), quote);
|
||||
const auto media = this->media();
|
||||
const auto mediaDisplayed = media && media->isDisplayed();
|
||||
const auto mediaBefore = mediaDisplayed && invertMedia();
|
||||
const auto result = selectionFromQuote(text(), quote);
|
||||
return mediaBefore ? media->unskipSelection(result) : result;
|
||||
} else if (const auto media = this->media()) {
|
||||
if (media->isDisplayed() || isHiddenByGroup()) {
|
||||
return media->selectionFromQuote(quote);
|
||||
@ -2793,43 +2800,53 @@ TextSelection Message::adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
const auto media = this->media();
|
||||
|
||||
auto result = hasVisibleText()
|
||||
? text().adjustSelection(selection, type)
|
||||
const auto mediaDisplayed = media && media->isDisplayed();
|
||||
const auto mediaBefore = mediaDisplayed && invertMedia();
|
||||
const auto textSelection = mediaBefore
|
||||
? media->skipSelection(selection)
|
||||
: selection;
|
||||
auto beforeMediaLength = visibleTextLength();
|
||||
if (selection.to <= beforeMediaLength) {
|
||||
return result;
|
||||
}
|
||||
auto mediaDisplayed = media && media->isDisplayed();
|
||||
auto textAdjusted = hasVisibleText()
|
||||
? text().adjustSelection(textSelection, type)
|
||||
: textSelection;
|
||||
auto textResult = mediaBefore
|
||||
? media->unskipSelection(textAdjusted)
|
||||
: textAdjusted;
|
||||
auto mediaResult = TextSelection();
|
||||
auto mediaSelection = mediaBefore
|
||||
? selection
|
||||
: skipTextSelection(selection);
|
||||
if (mediaDisplayed) {
|
||||
auto mediaSelection = unskipTextSelection(
|
||||
media->adjustSelection(skipTextSelection(selection), type));
|
||||
if (selection.from >= beforeMediaLength) {
|
||||
result = mediaSelection;
|
||||
} else {
|
||||
result.to = mediaSelection.to;
|
||||
}
|
||||
}
|
||||
auto beforeEntryLength = beforeMediaLength + visibleMediaTextLength();
|
||||
if (selection.to <= beforeEntryLength) {
|
||||
return result;
|
||||
auto mediaAdjusted = media->adjustSelection(mediaSelection, type);
|
||||
mediaResult = mediaBefore
|
||||
? mediaAdjusted
|
||||
: unskipTextSelection(mediaAdjusted);
|
||||
}
|
||||
auto entryResult = TextSelection();
|
||||
if (const auto entry = logEntryOriginal()) {
|
||||
auto entrySelection = mediaDisplayed
|
||||
? media->skipSelection(skipTextSelection(selection))
|
||||
: skipTextSelection(selection);
|
||||
auto logEntryOriginalSelection = entry->adjustSelection(entrySelection, type);
|
||||
auto entrySelection = !mediaDisplayed
|
||||
? skipTextSelection(selection)
|
||||
: mediaBefore
|
||||
? skipTextSelection(textSelection)
|
||||
: media->skipSelection(mediaSelection);
|
||||
auto entryAdjusted = entry->adjustSelection(entrySelection, type);
|
||||
entryResult = unskipTextSelection(entryAdjusted);
|
||||
if (mediaDisplayed) {
|
||||
logEntryOriginalSelection = media->unskipSelection(logEntryOriginalSelection);
|
||||
}
|
||||
logEntryOriginalSelection = unskipTextSelection(logEntryOriginalSelection);
|
||||
if (selection.from >= beforeEntryLength) {
|
||||
result = logEntryOriginalSelection;
|
||||
} else {
|
||||
result.to = logEntryOriginalSelection.to;
|
||||
entryResult = media->unskipSelection(entryResult);
|
||||
}
|
||||
}
|
||||
auto result = textResult;
|
||||
if (!mediaResult.empty()) {
|
||||
result = result.empty() ? mediaResult : TextSelection{
|
||||
std::min(result.from, mediaResult.from),
|
||||
std::max(result.to, mediaResult.to),
|
||||
};
|
||||
}
|
||||
if (!entryResult.empty()) {
|
||||
result = result.empty() ? entryResult : TextSelection{
|
||||
std::min(result.from, entryResult.from),
|
||||
std::max(result.to, entryResult.to),
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1264,7 +1264,7 @@ messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> use
|
||||
|
||||
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
||||
|
||||
messageReplyHeader#6eebcabd flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_from:flags.5?MessageFwdHeader reply_media:flags.8?MessageMedia reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> = MessageReplyHeader;
|
||||
messageReplyHeader#6eebcabd flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true quote:flags.9?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_from:flags.5?MessageFwdHeader reply_media:flags.8?MessageMedia reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> = MessageReplyHeader;
|
||||
messageReplyStoryHeader#9c98bfc1 user_id:long story_id:int = MessageReplyHeader;
|
||||
|
||||
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
||||
|
Loading…
Reference in New Issue
Block a user