mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-05-11 04:33:17 +00:00
Allow sending just webpage preview.
This commit is contained in:
parent
041ec1157f
commit
c035ec6917
@ -3607,7 +3607,13 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||||||
|
|
||||||
auto &histories = history->owner().histories();
|
auto &histories = history->owner().histories();
|
||||||
|
|
||||||
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
|
const auto exactWebPage = !message.webPage.url.isEmpty();
|
||||||
|
auto isFirst = true;
|
||||||
|
while (TextUtilities::CutPart(sending, left, MaxMessageSize)
|
||||||
|
|| (isFirst && exactWebPage)) {
|
||||||
|
TextUtilities::Trim(left);
|
||||||
|
const auto isLast = left.empty();
|
||||||
|
|
||||||
auto newId = FullMsgId(
|
auto newId = FullMsgId(
|
||||||
peer->id,
|
peer->id,
|
||||||
_session->data().nextLocalMessageId());
|
_session->data().nextLocalMessageId());
|
||||||
@ -3627,17 +3633,23 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||||||
sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to;
|
sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to;
|
||||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
mediaFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
||||||
}
|
}
|
||||||
|
const auto ignoreWebPage = message.webPage.removed
|
||||||
|
|| (exactWebPage && !isLast);
|
||||||
|
const auto manualWebPage = exactWebPage
|
||||||
|
&& !ignoreWebPage
|
||||||
|
&& (message.webPage.manual || (isLast && !isFirst));
|
||||||
const auto replyHeader = NewMessageReplyHeader(action);
|
const auto replyHeader = NewMessageReplyHeader(action);
|
||||||
MTPMessageMedia media = MTP_messageMediaEmpty();
|
MTPMessageMedia media = MTP_messageMediaEmpty();
|
||||||
if (message.webPage.removed) {
|
if (ignoreWebPage) {
|
||||||
sendFlags |= MTPmessages_SendMessage::Flag::f_no_webpage;
|
sendFlags |= MTPmessages_SendMessage::Flag::f_no_webpage;
|
||||||
} else if (const auto fields = message.webPage; fields.id) {
|
} else if (exactWebPage) {
|
||||||
using PageFlag = MTPDmessageMediaWebPage::Flag;
|
using PageFlag = MTPDmessageMediaWebPage::Flag;
|
||||||
using PendingFlag = MTPDwebPagePending::Flag;
|
using PendingFlag = MTPDwebPagePending::Flag;
|
||||||
|
const auto &fields = message.webPage;
|
||||||
const auto page = _session->data().webpage(fields.id);
|
const auto page = _session->data().webpage(fields.id);
|
||||||
media = MTP_messageMediaWebPage(
|
media = MTP_messageMediaWebPage(
|
||||||
MTP_flags(PageFlag()
|
MTP_flags(PageFlag()
|
||||||
| (fields.manual ? PageFlag::f_manual : PageFlag())
|
| (manualWebPage ? PageFlag::f_manual : PageFlag())
|
||||||
| (fields.forceLargeMedia
|
| (fields.forceLargeMedia
|
||||||
? PageFlag::f_force_large_media
|
? PageFlag::f_force_large_media
|
||||||
: PageFlag())
|
: PageFlag())
|
||||||
@ -3645,17 +3657,15 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||||||
? PageFlag::f_force_small_media
|
? PageFlag::f_force_small_media
|
||||||
: PageFlag())),
|
: PageFlag())),
|
||||||
MTP_webPagePending(
|
MTP_webPagePending(
|
||||||
MTP_flags(page->url.isEmpty()
|
MTP_flags(PendingFlag::f_url),
|
||||||
? PendingFlag()
|
MTP_long(fields.id),
|
||||||
: PendingFlag::f_url),
|
MTP_string(fields.url),
|
||||||
MTP_long(page->id),
|
|
||||||
MTP_string(page->url),
|
|
||||||
MTP_int(page->pendingTill)));
|
MTP_int(page->pendingTill)));
|
||||||
}
|
}
|
||||||
const auto anonymousPost = peer->amAnonymous();
|
const auto anonymousPost = peer->amAnonymous();
|
||||||
const auto silentPost = ShouldSendSilent(peer, action.options);
|
const auto silentPost = ShouldSendSilent(peer, action.options);
|
||||||
FillMessagePostFlags(action, peer, flags);
|
FillMessagePostFlags(action, peer, flags);
|
||||||
if (message.webPage.id && message.webPage.invert) {
|
if (exactWebPage && !ignoreWebPage && message.webPage.invert) {
|
||||||
flags |= MessageFlag::InvertMedia;
|
flags |= MessageFlag::InvertMedia;
|
||||||
sendFlags |= MTPmessages_SendMessage::Flag::f_invert_media;
|
sendFlags |= MTPmessages_SendMessage::Flag::f_invert_media;
|
||||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
mediaFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
||||||
@ -3732,9 +3742,9 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||||||
UnixtimeFromMsgId(response.outerMsgId));
|
UnixtimeFromMsgId(response.outerMsgId));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!message.webPage.removed
|
if (exactWebPage
|
||||||
&& (message.webPage.manual || sending.empty())
|
&& !ignoreWebPage
|
||||||
&& !message.webPage.url.isEmpty()) {
|
&& (manualWebPage || sending.empty())) {
|
||||||
histories.sendPreparedMessage(
|
histories.sendPreparedMessage(
|
||||||
history,
|
history,
|
||||||
action.replyTo,
|
action.replyTo,
|
||||||
@ -3743,7 +3753,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||||||
MTP_flags(mediaFlags),
|
MTP_flags(mediaFlags),
|
||||||
peer->input,
|
peer->input,
|
||||||
Data::Histories::ReplyToPlaceholder(),
|
Data::Histories::ReplyToPlaceholder(),
|
||||||
Data::WebPageForMTP(message.webPage),
|
Data::WebPageForMTP(message.webPage, true),
|
||||||
msgText,
|
msgText,
|
||||||
MTP_long(randomId),
|
MTP_long(randomId),
|
||||||
MTPReplyMarkup(),
|
MTPReplyMarkup(),
|
||||||
@ -3768,6 +3778,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||||
), done, fail);
|
), done, fail);
|
||||||
}
|
}
|
||||||
|
isFirst = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
finishForwarding(action);
|
finishForwarding(action);
|
||||||
|
@ -601,6 +601,12 @@ MessageLinksParser::MessageLinksParser(not_null<Ui::InputField*> field)
|
|||||||
_lifetime = _field->changes(
|
_lifetime = _field->changes(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
const auto length = _field->getTextWithTags().text.size();
|
const auto length = _field->getTextWithTags().text.size();
|
||||||
|
if (!length) {
|
||||||
|
_lastLength = 0;
|
||||||
|
_timer.cancel();
|
||||||
|
parse();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto timeout = (std::abs(length - _lastLength) > 2)
|
const auto timeout = (std::abs(length - _lastLength) > 2)
|
||||||
? 0
|
? 0
|
||||||
: kParseLinksTimeout;
|
: kParseLinksTimeout;
|
||||||
@ -652,6 +658,7 @@ void MessageLinksParser::parse() {
|
|||||||
const auto &tags = textWithTags.tags;
|
const auto &tags = textWithTags.tags;
|
||||||
const auto &markdownTags = _field->getMarkdownTags();
|
const auto &markdownTags = _field->getMarkdownTags();
|
||||||
if (_disabled || text.isEmpty()) {
|
if (_disabled || text.isEmpty()) {
|
||||||
|
_ranges = {};
|
||||||
_list = QStringList();
|
_list = QStringList();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -663,7 +670,7 @@ void MessageLinksParser::parse() {
|
|||||||
|| (tag == Ui::InputField::kTagSpoiler);
|
|| (tag == Ui::InputField::kTagSpoiler);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ranges = QVector<LinkRange>();
|
_ranges.clear();
|
||||||
|
|
||||||
auto tag = tags.begin();
|
auto tag = tags.begin();
|
||||||
const auto tagsEnd = tags.end();
|
const auto tagsEnd = tags.end();
|
||||||
@ -672,7 +679,7 @@ void MessageLinksParser::parse() {
|
|||||||
|
|
||||||
if (Ui::InputField::IsValidMarkdownLink(tag->id)
|
if (Ui::InputField::IsValidMarkdownLink(tag->id)
|
||||||
&& !TextUtilities::IsMentionLink(tag->id)) {
|
&& !TextUtilities::IsMentionLink(tag->id)) {
|
||||||
ranges.push_back({ tag->offset, tag->length, tag->id });
|
_ranges.push_back({ tag->offset, tag->length, tag->id });
|
||||||
}
|
}
|
||||||
++tag;
|
++tag;
|
||||||
};
|
};
|
||||||
@ -782,20 +789,18 @@ void MessageLinksParser::parse() {
|
|||||||
processTagsBefore(domainOffset);
|
processTagsBefore(domainOffset);
|
||||||
if (!hasTagsIntersection(range.start + range.length)) {
|
if (!hasTagsIntersection(range.start + range.length)) {
|
||||||
if (markdownTagsAllow(range.start, range.length)) {
|
if (markdownTagsAllow(range.start, range.length)) {
|
||||||
ranges.push_back(range);
|
_ranges.push_back(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset = matchOffset = p - start;
|
offset = matchOffset = p - start;
|
||||||
}
|
}
|
||||||
processTagsBefore(Ui::kQFixedMax);
|
processTagsBefore(Ui::kQFixedMax);
|
||||||
|
|
||||||
apply(text, ranges);
|
applyRanges(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLinksParser::apply(
|
void MessageLinksParser::applyRanges(const QString &text) {
|
||||||
const QString &text,
|
const auto count = int(_ranges.size());
|
||||||
const QVector<LinkRange> &ranges) {
|
|
||||||
const auto count = int(ranges.size());
|
|
||||||
const auto current = _list.current();
|
const auto current = _list.current();
|
||||||
const auto computeLink = [&](const LinkRange &range) {
|
const auto computeLink = [&](const LinkRange &range) {
|
||||||
return range.custom.isEmpty()
|
return range.custom.isEmpty()
|
||||||
@ -807,7 +812,7 @@ void MessageLinksParser::apply(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (auto i = 0; i != count; ++i) {
|
for (auto i = 0; i != count; ++i) {
|
||||||
if (computeLink(ranges[i]) != current[i]) {
|
if (computeLink(_ranges[i]) != current[i]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -818,7 +823,7 @@ void MessageLinksParser::apply(
|
|||||||
}
|
}
|
||||||
auto parsed = QStringList();
|
auto parsed = QStringList();
|
||||||
parsed.reserve(count);
|
parsed.reserve(count);
|
||||||
for (const auto &range : ranges) {
|
for (const auto &range : _ranges) {
|
||||||
parsed.push_back(computeLink(range).toString());
|
parsed.push_back(computeLink(range).toString());
|
||||||
}
|
}
|
||||||
_list = std::move(parsed);
|
_list = std::move(parsed);
|
||||||
|
@ -96,38 +96,38 @@ AutocompleteQuery ParseMentionHashtagBotCommandQuery(
|
|||||||
not_null<const Ui::InputField*> field,
|
not_null<const Ui::InputField*> field,
|
||||||
ChatHelpers::ComposeFeatures features);
|
ChatHelpers::ComposeFeatures features);
|
||||||
|
|
||||||
class MessageLinksParser : private QObject {
|
class MessageLinksParser final : private QObject {
|
||||||
public:
|
public:
|
||||||
MessageLinksParser(not_null<Ui::InputField*> field);
|
MessageLinksParser(not_null<Ui::InputField*> field);
|
||||||
|
|
||||||
void parseNow();
|
void parseNow();
|
||||||
void setDisabled(bool disabled);
|
void setDisabled(bool disabled);
|
||||||
|
|
||||||
[[nodiscard]] const rpl::variable<QStringList> &list() const;
|
struct LinkRange {
|
||||||
|
int start = 0;
|
||||||
|
int length = 0;
|
||||||
|
QString custom;
|
||||||
|
|
||||||
protected:
|
friend inline auto operator<=>(
|
||||||
bool eventFilter(QObject *object, QEvent *event) override;
|
const LinkRange&,
|
||||||
|
const LinkRange&) = default;
|
||||||
|
friend inline bool operator==(
|
||||||
|
const LinkRange&,
|
||||||
|
const LinkRange&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] const rpl::variable<QStringList> &list() const;
|
||||||
|
[[nodiscard]] const std::vector<LinkRange> &ranges() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct LinkRange {
|
bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
int start;
|
|
||||||
int length;
|
|
||||||
QString custom;
|
|
||||||
};
|
|
||||||
friend inline bool operator==(const LinkRange &a, const LinkRange &b) {
|
|
||||||
return (a.start == b.start)
|
|
||||||
&& (a.length == b.length)
|
|
||||||
&& (a.custom == b.custom);
|
|
||||||
}
|
|
||||||
friend inline bool operator!=(const LinkRange &a, const LinkRange &b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parse();
|
void parse();
|
||||||
void apply(const QString &text, const QVector<LinkRange> &ranges);
|
void applyRanges(const QString &text);
|
||||||
|
|
||||||
not_null<Ui::InputField*> _field;
|
not_null<Ui::InputField*> _field;
|
||||||
rpl::variable<QStringList> _list;
|
rpl::variable<QStringList> _list;
|
||||||
|
std::vector<LinkRange> _ranges;
|
||||||
int _lastLength = 0;
|
int _lastLength = 0;
|
||||||
bool _disabled = false;
|
bool _disabled = false;
|
||||||
base::Timer _timer;
|
base::Timer _timer;
|
||||||
|
@ -73,10 +73,12 @@ MTPInputReplyTo ReplyToForMTP(
|
|||||||
return MTPInputReplyTo();
|
return MTPInputReplyTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPInputMedia WebPageForMTP(const Data::WebPageDraft &draft) {
|
MTPInputMedia WebPageForMTP(
|
||||||
|
const Data::WebPageDraft &draft,
|
||||||
|
bool required) {
|
||||||
using Flag = MTPDinputMediaWebPage::Flag;
|
using Flag = MTPDinputMediaWebPage::Flag;
|
||||||
return MTP_inputMediaWebPage(
|
return MTP_inputMediaWebPage(
|
||||||
MTP_flags(Flag::f_optional
|
MTP_flags((required ? Flag() : Flag::f_optional)
|
||||||
| (draft.forceLargeMedia ? Flag::f_force_large_media : Flag())
|
| (draft.forceLargeMedia ? Flag::f_force_large_media : Flag())
|
||||||
| (draft.forceSmallMedia ? Flag::f_force_small_media : Flag())),
|
| (draft.forceSmallMedia ? Flag::f_force_small_media : Flag())),
|
||||||
MTP_string(draft.url));
|
MTP_string(draft.url));
|
||||||
|
@ -30,7 +30,9 @@ struct WebPageDraft;
|
|||||||
[[nodiscard]] MTPInputReplyTo ReplyToForMTP(
|
[[nodiscard]] MTPInputReplyTo ReplyToForMTP(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
FullReplyTo replyTo);
|
FullReplyTo replyTo);
|
||||||
[[nodiscard]] MTPInputMedia WebPageForMTP(const Data::WebPageDraft &draft);
|
[[nodiscard]] MTPInputMedia WebPageForMTP(
|
||||||
|
const Data::WebPageDraft &draft,
|
||||||
|
bool required = false);
|
||||||
|
|
||||||
class Histories final {
|
class Histories final {
|
||||||
public:
|
public:
|
||||||
|
@ -3941,6 +3941,9 @@ void HistoryWidget::send(Api::SendOptions options) {
|
|||||||
session().api().sendMessage(std::move(message));
|
session().api().sendMessage(std::move(message));
|
||||||
|
|
||||||
clearFieldText();
|
clearFieldText();
|
||||||
|
if (_preview) {
|
||||||
|
_preview->apply({ .removed = true });
|
||||||
|
}
|
||||||
_saveDraftText = true;
|
_saveDraftText = true;
|
||||||
_saveDraftStart = crl::now();
|
_saveDraftStart = crl::now();
|
||||||
saveDraft();
|
saveDraft();
|
||||||
|
@ -530,7 +530,7 @@ void FieldHeader::paintWebPage(Painter &p, not_null<PeerData*> context) {
|
|||||||
Expects(!!_preview.parsed);
|
Expects(!!_preview.parsed);
|
||||||
|
|
||||||
const auto textTop = st::msgReplyPadding.top();
|
const auto textTop = st::msgReplyPadding.top();
|
||||||
auto previewLeft = st::historyReplySkip + st::msgReplyBarSkip;
|
auto previewLeft = st::historyReplySkip;
|
||||||
|
|
||||||
const QRect to(
|
const QRect to(
|
||||||
previewLeft,
|
previewLeft,
|
||||||
@ -1204,6 +1204,9 @@ void ComposeControls::clear() {
|
|||||||
{},
|
{},
|
||||||
saveTextDraft ? TextUpdateEvent::SaveDraft : TextUpdateEvent());
|
saveTextDraft ? TextUpdateEvent::SaveDraft : TextUpdateEvent());
|
||||||
cancelReplyMessage();
|
cancelReplyMessage();
|
||||||
|
if (_preview) {
|
||||||
|
_preview->apply({ .removed = true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::setText(const TextWithTags &textWithTags) {
|
void ComposeControls::setText(const TextWithTags &textWithTags) {
|
||||||
@ -1755,8 +1758,8 @@ void ComposeControls::fieldChanged() {
|
|||||||
&& (_textUpdateEvents & TextUpdateEvent::SendTyping));
|
&& (_textUpdateEvents & TextUpdateEvent::SendTyping));
|
||||||
updateSendButtonType();
|
updateSendButtonType();
|
||||||
_hasSendText = HasSendText(_field);
|
_hasSendText = HasSendText(_field);
|
||||||
if (!_hasSendText.current() && _preview) {
|
if (!_hasSendText.current() && _preview && !_preview->draft().manual) {
|
||||||
_preview->apply({});
|
_preview->apply({ .removed = true });
|
||||||
}
|
}
|
||||||
if (updateBotCommandShown() || updateLikeShown()) {
|
if (updateBotCommandShown() || updateLikeShown()) {
|
||||||
updateControlsVisibility();
|
updateControlsVisibility();
|
||||||
|
@ -155,6 +155,9 @@ void WebpageProcessor::apply(Data::WebPageDraft draft, bool reparse) {
|
|||||||
_api.request(base::take(_requestId)).cancel();
|
_api.request(base::take(_requestId)).cancel();
|
||||||
if (draft.removed) {
|
if (draft.removed) {
|
||||||
_draft = draft;
|
_draft = draft;
|
||||||
|
if (_parsedLinks.empty()) {
|
||||||
|
_draft.removed = false;
|
||||||
|
}
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
_links = QStringList();
|
_links = QStringList();
|
||||||
_link = QString();
|
_link = QString();
|
||||||
@ -272,6 +275,9 @@ void WebpageProcessor::checkNow(bool force) {
|
|||||||
void WebpageProcessor::checkPreview() {
|
void WebpageProcessor::checkPreview() {
|
||||||
const auto previewRestricted = _history->peer
|
const auto previewRestricted = _history->peer
|
||||||
&& _history->peer->amRestricted(ChatRestriction::EmbedLinks);
|
&& _history->peer->amRestricted(ChatRestriction::EmbedLinks);
|
||||||
|
if (_parsedLinks.empty()) {
|
||||||
|
_draft.removed = false;
|
||||||
|
}
|
||||||
if (_draft.removed) {
|
if (_draft.removed) {
|
||||||
return;
|
return;
|
||||||
} else if (previewRestricted) {
|
} else if (previewRestricted) {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit b05f7eb915a86f67249904061d70f293066de618
|
Subproject commit 383b5b8f7e629475e5f22445167aaa7669c5cdd6
|
Loading…
Reference in New Issue
Block a user