mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 21:27:07 +02:00
Update API scheme to layer 167.
Support quote offset passing to API. Support simple phrases in giveaway results message.
This commit is contained in:
parent
f442d69cb6
commit
dcc326e17f
44 changed files with 389 additions and 303 deletions
|
@ -1667,6 +1667,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available.";
|
||||
"lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available.";
|
||||
"lng_action_giveaway_started" = "{from} just started a giveaway of Telegram Premium subscriptions to its followers.";
|
||||
"lng_action_giveaway_results#one" = "{count} winner of the giveaway was randomly selected by Telegram and received private messages with giftcodes.";
|
||||
"lng_action_giveaway_results#other" = "{count} winners of the giveaway were randomly selected by Telegram and received private messages with giftcodes.";
|
||||
"lng_action_giveaway_results_some" = "Some winners of the giveaway was randomly selected by Telegram and received private messages with giftcodes.";
|
||||
"lng_action_giveaway_results_none" = "No winners of the giveaway could be selected.";
|
||||
|
||||
"lng_premium_gift_duration_months#one" = "for {count} month";
|
||||
"lng_premium_gift_duration_months#other" = "for {count} months";
|
||||
|
|
|
@ -72,7 +72,7 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
| (external ? Flag::f_reply_to_peer_id : Flag())
|
||||
| (replyTo.quote.text.isEmpty()
|
||||
? Flag()
|
||||
: Flag::f_quote_text)
|
||||
: (Flag::f_quote_text | Flag::f_quote_offset))
|
||||
| (quoteEntities.v.isEmpty()
|
||||
? Flag()
|
||||
: Flag::f_quote_entities)),
|
||||
|
@ -82,7 +82,8 @@ MTPInputReplyTo ReplyToForMTP(
|
|||
? owner->peer(replyTo.messageId.peer)->input
|
||||
: MTPInputPeer()),
|
||||
MTP_string(replyTo.quote.text),
|
||||
quoteEntities);
|
||||
quoteEntities,
|
||||
MTP_int(replyTo.quoteOffset));
|
||||
}
|
||||
return MTPInputReplyTo();
|
||||
}
|
||||
|
@ -983,6 +984,7 @@ int Histories::sendPreparedMessage(
|
|||
.quote = replyTo.quote,
|
||||
.storyId = replyTo.storyId,
|
||||
.topicRootId = convertTopicReplyToId(history, replyTo.topicRootId),
|
||||
.quoteOffset = replyTo.quoteOffset,
|
||||
};
|
||||
return v::match(message(history, realReplyTo), [&](const auto &request) {
|
||||
const auto type = RequestType::Send;
|
||||
|
|
|
@ -161,6 +161,7 @@ struct FullReplyTo {
|
|||
TextWithEntities quote;
|
||||
FullStoryId storyId;
|
||||
MsgId topicRootId = 0;
|
||||
int quoteOffset = 0;
|
||||
|
||||
[[nodiscard]] bool valid() const {
|
||||
return messageId || (storyId && peerIsUser(storyId.peer));
|
||||
|
|
|
@ -1316,9 +1316,9 @@ ServiceAction ParseServiceAction(
|
|||
}, [&](const MTPDmessageActionSetChatWallPaper &data) {
|
||||
auto content = ActionSetChatWallPaper();
|
||||
// #TODO wallpapers
|
||||
content.same = data.is_same();
|
||||
content.both = data.is_for_both();
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionSetSameChatWallPaper &data) {
|
||||
result.content = ActionSetSameChatWallPaper();
|
||||
}, [&](const MTPDmessageActionRequestedPeer &data) {
|
||||
auto content = ActionRequestedPeer();
|
||||
content.peerId = ParsePeerId(data.vpeer());
|
||||
|
@ -1334,9 +1334,14 @@ ServiceAction ParseServiceAction(
|
|||
content.months = data.vmonths().v;
|
||||
content.code = data.vslug().v;
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionGiveawayLaunch &) {
|
||||
}, [&](const MTPDmessageActionGiveawayLaunch &data) {
|
||||
auto content = ActionGiveawayLaunch();
|
||||
result.content = content;
|
||||
}, [&](const MTPDmessageActionGiveawayResults &data) {
|
||||
auto content = ActionGiveawayResults();
|
||||
content.winners = data.vwinners_count().v;
|
||||
content.unclaimed = data.vunclaimed_count().v;
|
||||
result.content = content;
|
||||
}, [](const MTPDmessageActionEmpty &data) {});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -533,12 +533,11 @@ struct ActionSuggestProfilePhoto {
|
|||
};
|
||||
|
||||
struct ActionSetChatWallPaper {
|
||||
bool same = false;
|
||||
bool both = false;
|
||||
// #TODO wallpapers
|
||||
};
|
||||
|
||||
struct ActionSetSameChatWallPaper {
|
||||
};
|
||||
|
||||
struct ActionGiftCode {
|
||||
QByteArray code;
|
||||
PeerId boostPeerId = 0;
|
||||
|
@ -555,6 +554,11 @@ struct ActionRequestedPeer {
|
|||
struct ActionGiveawayLaunch {
|
||||
};
|
||||
|
||||
struct ActionGiveawayResults {
|
||||
int winners = 0;
|
||||
int unclaimed = 0;
|
||||
};
|
||||
|
||||
struct ServiceAction {
|
||||
std::variant<
|
||||
v::null_t,
|
||||
|
@ -593,9 +597,9 @@ struct ServiceAction {
|
|||
ActionSuggestProfilePhoto,
|
||||
ActionRequestedPeer,
|
||||
ActionSetChatWallPaper,
|
||||
ActionSetSameChatWallPaper,
|
||||
ActionGiftCode,
|
||||
ActionGiveawayLaunch> content;
|
||||
ActionGiveawayLaunch,
|
||||
ActionGiveawayResults> content;
|
||||
};
|
||||
|
||||
ServiceAction ParseServiceAction(
|
||||
|
|
|
@ -1273,12 +1273,12 @@ auto HtmlWriter::Wrap::pushMessage(
|
|||
}, [&](const ActionRequestedPeer &data) {
|
||||
return "requested: "_q/* + data.peerId*/;
|
||||
}, [&](const ActionSetChatWallPaper &data) {
|
||||
return serviceFrom + " set a new background for this chat";
|
||||
}, [&](const ActionSetSameChatWallPaper &data) {
|
||||
return serviceFrom
|
||||
+ " set "
|
||||
+ wrapReplyToLink("the same background")
|
||||
+ " for this chat";
|
||||
+ (data.same
|
||||
? (" set "
|
||||
+ wrapReplyToLink("the same background")
|
||||
+ " for this chat")
|
||||
: " set a new background for this chat");
|
||||
}, [&](const ActionGiftCode &data) {
|
||||
return data.unclaimed
|
||||
? ("This is an unclaimed Telegram Premium for "
|
||||
|
@ -1297,6 +1297,10 @@ auto HtmlWriter::Wrap::pushMessage(
|
|||
}, [&](const ActionGiveawayLaunch &data) {
|
||||
return serviceFrom + " just started a giveaway "
|
||||
"of Telegram Premium subscriptions to its followers.";
|
||||
}, [&](const ActionGiveawayResults &data) {
|
||||
return QByteArray::number(data.winners)
|
||||
+ " of the giveaway were randomly selected by Telegram "
|
||||
"and received private messages with giftcodes.";
|
||||
}, [](v::null_t) { return QByteArray(); });
|
||||
|
||||
if (!serviceText.isEmpty()) {
|
||||
|
|
|
@ -604,12 +604,15 @@ QByteArray SerializeMessage(
|
|||
push("via_giveaway", data.viaGiveaway);
|
||||
}, [&](const ActionGiveawayLaunch &data) {
|
||||
pushAction("giveaway_launch");
|
||||
}, [&](const ActionGiveawayResults &data) {
|
||||
pushAction("giveaway_results");
|
||||
push("winners", data.winners);
|
||||
push("unclaimed", data.unclaimed);
|
||||
}, [&](const ActionSetChatWallPaper &data) {
|
||||
pushActor();
|
||||
pushAction("set_chat_wallpaper");
|
||||
}, [&](const ActionSetSameChatWallPaper &data) {
|
||||
pushActor();
|
||||
pushAction("set_same_chat_wallpaper");
|
||||
pushAction(data.same
|
||||
? "set_same_chat_wallpaper"
|
||||
: "set_chat_wallpaper");
|
||||
pushReplyToMsgId("message_id");
|
||||
}, [](v::null_t) {});
|
||||
|
||||
|
|
|
@ -1144,7 +1144,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
} else if (item->isUnreadMention()
|
||||
&& !item->isUnreadMedia()) {
|
||||
readContents.insert(item);
|
||||
_widget->enqueueMessageHighlight(view, {});
|
||||
_widget->enqueueMessageHighlight({ item });
|
||||
}
|
||||
}
|
||||
session().data().reactions().poll(item, context.now);
|
||||
|
@ -2410,17 +2410,25 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
const auto replyToItem = selected.item ? selected.item : item;
|
||||
const auto itemId = replyToItem->fullId();
|
||||
const auto quote = selected.text;
|
||||
const auto quoteOffset = selected.offset;
|
||||
text.replace('&', u"&&"_q);
|
||||
_menu->addAction(text, [=] {
|
||||
if (canSendReply) {
|
||||
_widget->replyToMessage({ itemId, quote });
|
||||
_widget->replyToMessage({
|
||||
.messageId = itemId,
|
||||
.quote = quote,
|
||||
.quoteOffset = quoteOffset,
|
||||
});
|
||||
if (!quote.empty()) {
|
||||
_widget->clearSelected();
|
||||
}
|
||||
} else {
|
||||
HistoryView::Controls::ShowReplyToChatBox(
|
||||
controller->uiShow(),
|
||||
{ itemId, quote });
|
||||
const auto show = controller->uiShow();
|
||||
HistoryView::Controls::ShowReplyToChatBox(show, {
|
||||
.messageId = itemId,
|
||||
.quote = quote,
|
||||
.quoteOffset = quoteOffset,
|
||||
});
|
||||
}
|
||||
}, &st::menuIconReply);
|
||||
}
|
||||
|
|
|
@ -78,6 +78,20 @@ constexpr auto kPinnedMessageTextLimit = 16;
|
|||
|
||||
using ItemPreview = HistoryView::ItemPreview;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] PreparedServiceText PrepareEmptyText(const T &) {
|
||||
return PreparedServiceText();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] PreparedServiceText PrepareErrorText(const T &data) {
|
||||
if constexpr (!std::is_same_v<T, MTPDmessageActionEmpty>) {
|
||||
const auto name = QString::fromUtf8(typeid(data).name());
|
||||
LOG(("API Error: %1 received.").arg(name));
|
||||
}
|
||||
return PreparedServiceText{ { tr::lng_message_empty(tr::now) } };
|
||||
}
|
||||
|
||||
[[nodiscard]] TextWithEntities SpoilerLoginCode(TextWithEntities text) {
|
||||
const auto r = QRegularExpression(u"([\\d\\-]{5,7})"_q);
|
||||
const auto m = r.match(text.text);
|
||||
|
@ -449,7 +463,7 @@ HistoryItem::HistoryItem(
|
|||
const auto originalMedia = original->media();
|
||||
const auto dropForwardInfo = original->computeDropForwardedInfo();
|
||||
config.reply.messageId = config.reply.topMessageId = topicRootId;
|
||||
config.reply.topicPost = (topicRootId != 0);
|
||||
config.reply.topicPost = (topicRootId != 0) ? 1 : 0;
|
||||
if (const auto originalReply = original->Get<HistoryMessageReply>()) {
|
||||
if (originalReply->external()) {
|
||||
config.reply = originalReply->fields().clone(this);
|
||||
|
@ -3371,13 +3385,15 @@ void HistoryItem::createComponentsHelper(
|
|||
&& topic->rootId() != to->topicRootId()) {
|
||||
config.reply.externalPeerId = replyTo.messageId.peer;
|
||||
}
|
||||
config.reply.topicPost = config.reply.externalPeerId
|
||||
const auto topicPost = config.reply.externalPeerId
|
||||
? (replyTo.topicRootId
|
||||
&& (replyTo.topicRootId != Data::ForumTopic::kGeneralId))
|
||||
: (LookupReplyIsTopicPost(to)
|
||||
|| (to && to->Has<HistoryServiceTopicInfo>())
|
||||
|| (forum && forum->creating(config.reply.topMessageId)));
|
||||
config.reply.manualQuote = !replyTo.quote.empty();
|
||||
config.reply.topicPost = topicPost ? 1 : 0;
|
||||
config.reply.manualQuote = replyTo.quote.empty() ? 0 : 1;
|
||||
config.reply.quoteOffset = replyTo.quoteOffset;
|
||||
config.reply.quote = std::move(replyTo.quote);
|
||||
}
|
||||
config.markup = std::move(markup);
|
||||
|
@ -3696,8 +3712,12 @@ void HistoryItem::createServiceFromMtp(const MTPDmessageService &message) {
|
|||
}
|
||||
}, call->lifetime);
|
||||
}
|
||||
} else if (type == mtpc_messageActionSetSameChatWallPaper) {
|
||||
UpdateComponents(HistoryServiceSameBackground::Bit());
|
||||
} else if (type == mtpc_messageActionSetChatWallPaper) {
|
||||
if (action.c_messageActionSetChatWallPaper().is_same()) {
|
||||
UpdateComponents(HistoryServiceSameBackground::Bit());
|
||||
} else {
|
||||
RemoveComponents(HistoryServiceSameBackground::Bit());
|
||||
}
|
||||
}
|
||||
if (const auto replyTo = message.vreply_to()) {
|
||||
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
||||
|
@ -3877,7 +3897,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return result;
|
||||
};
|
||||
|
||||
auto prepareChatDeletePhoto = [this] {
|
||||
auto prepareChatDeletePhoto = [&](const MTPDmessageActionChatDeletePhoto &action) {
|
||||
auto result = PreparedServiceText();
|
||||
if (isPost()) {
|
||||
result.text = tr::lng_action_removed_photo_channel(
|
||||
|
@ -3956,7 +3976,23 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return result;
|
||||
};
|
||||
|
||||
auto prepareScreenshotTaken = [this] {
|
||||
auto preparePinMessage = [&](const MTPDmessageActionPinMessage &) {
|
||||
return preparePinnedText();
|
||||
};
|
||||
|
||||
auto prepareGameScore = [&](const MTPDmessageActionGameScore &) {
|
||||
return prepareGameScoreText();
|
||||
};
|
||||
|
||||
auto preparePhoneCall = [&](const MTPDmessageActionPhoneCall &) -> PreparedServiceText {
|
||||
Unexpected("PhoneCall type in setServiceMessageFromMtp.");
|
||||
};
|
||||
|
||||
auto preparePaymentSent = [&](const MTPDmessageActionPaymentSent &) {
|
||||
return preparePaymentSentText();
|
||||
};
|
||||
|
||||
auto prepareScreenshotTaken = [this](const MTPDmessageActionScreenshotTaken &) {
|
||||
auto result = PreparedServiceText();
|
||||
if (out()) {
|
||||
result.text = tr::lng_action_you_took_screenshot(
|
||||
|
@ -4055,7 +4091,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return result;
|
||||
};
|
||||
|
||||
auto prepareContactSignUp = [this] {
|
||||
auto prepareContactSignUp = [this](const MTPDmessageActionContactSignUp &data) {
|
||||
auto result = PreparedServiceText();
|
||||
result.links.push_back(fromLink());
|
||||
result.text = tr::lng_action_user_registered(
|
||||
|
@ -4258,6 +4294,10 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return result;
|
||||
};
|
||||
|
||||
auto prepareGroupCallScheduled = [&](const MTPDmessageActionGroupCallScheduled &data) {
|
||||
return prepareCallScheduledText(data.vschedule_date().v);
|
||||
};
|
||||
|
||||
auto prepareSetChatTheme = [this](const MTPDmessageActionSetChatTheme &action) {
|
||||
auto result = PreparedServiceText();
|
||||
const auto text = qs(action.vemoticon());
|
||||
|
@ -4459,28 +4499,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
auto prepareSetChatWallPaper = [&](
|
||||
const MTPDmessageActionSetChatWallPaper &action) {
|
||||
const auto isSelf = (_from->id == _from->session().userPeerId());
|
||||
const auto peer = isSelf ? history()->peer : _from;
|
||||
const auto user = peer->asUser();
|
||||
const auto name = (user && !user->firstName.isEmpty())
|
||||
? user->firstName
|
||||
: peer->name();
|
||||
auto result = PreparedServiceText{};
|
||||
result.links.push_back(peer->createOpenLink());
|
||||
result.text = isSelf
|
||||
? tr::lng_action_set_wallpaper_me(
|
||||
tr::now,
|
||||
Ui::Text::WithEntities)
|
||||
: tr::lng_action_set_wallpaper(
|
||||
tr::now,
|
||||
lt_user,
|
||||
Ui::Text::Link(name, 1), // Link 1.
|
||||
Ui::Text::WithEntities);
|
||||
return result;
|
||||
};
|
||||
|
||||
auto prepareSetSameChatWallPaper = [&](
|
||||
const MTPDmessageActionSetSameChatWallPaper &action) {
|
||||
const auto isSelf = (_from->id == _from->session().userPeerId());
|
||||
const auto same = action.is_same();
|
||||
const auto peer = isSelf ? history()->peer : _from;
|
||||
const auto user = peer->asUser();
|
||||
const auto name = (user && !user->firstName.isEmpty())
|
||||
|
@ -4491,14 +4510,18 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
result.links.push_back(peer->createOpenLink());
|
||||
}
|
||||
result.text = isSelf
|
||||
? tr::lng_action_set_same_wallpaper_me(
|
||||
tr::now,
|
||||
Ui::Text::WithEntities)
|
||||
: tr::lng_action_set_same_wallpaper(
|
||||
tr::now,
|
||||
lt_user,
|
||||
Ui::Text::Link(name, 1), // Link 1.
|
||||
Ui::Text::WithEntities);
|
||||
? (same
|
||||
? tr::lng_action_set_same_wallpaper_me
|
||||
: tr::lng_action_set_wallpaper_me)(
|
||||
tr::now,
|
||||
Ui::Text::WithEntities)
|
||||
: (same
|
||||
? tr::lng_action_set_same_wallpaper
|
||||
: tr::lng_action_set_wallpaper)(
|
||||
tr::now,
|
||||
lt_user,
|
||||
Ui::Text::Link(name, 1), // Link 1.
|
||||
Ui::Text::WithEntities);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
@ -4532,93 +4555,65 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
return result;
|
||||
};
|
||||
|
||||
setServiceText(action.match([&](
|
||||
const MTPDmessageActionChatAddUser &data) {
|
||||
return prepareChatAddUserText(data);
|
||||
}, [&](const MTPDmessageActionChatJoinedByLink &data) {
|
||||
return prepareChatJoinedByLink(data);
|
||||
}, [&](const MTPDmessageActionChatCreate &data) {
|
||||
return prepareChatCreate(data);
|
||||
}, [](const MTPDmessageActionChatMigrateTo &) {
|
||||
return PreparedServiceText();
|
||||
}, [](const MTPDmessageActionChannelMigrateFrom &) {
|
||||
return PreparedServiceText();
|
||||
}, [](const MTPDmessageActionHistoryClear &) {
|
||||
return PreparedServiceText();
|
||||
}, [&](const MTPDmessageActionChannelCreate &data) {
|
||||
return prepareChannelCreate(data);
|
||||
}, [&](const MTPDmessageActionChatDeletePhoto &) {
|
||||
return prepareChatDeletePhoto();
|
||||
}, [&](const MTPDmessageActionChatDeleteUser &data) {
|
||||
return prepareChatDeleteUser(data);
|
||||
}, [&](const MTPDmessageActionChatEditPhoto &data) {
|
||||
return prepareChatEditPhoto(data);
|
||||
}, [&](const MTPDmessageActionChatEditTitle &data) {
|
||||
return prepareChatEditTitle(data);
|
||||
}, [&](const MTPDmessageActionPinMessage &) {
|
||||
return preparePinnedText();
|
||||
}, [&](const MTPDmessageActionGameScore &) {
|
||||
return prepareGameScoreText();
|
||||
}, [&](const MTPDmessageActionPhoneCall &) -> PreparedServiceText {
|
||||
Unexpected("PhoneCall type in setServiceMessageFromMtp.");
|
||||
}, [&](const MTPDmessageActionPaymentSent &) {
|
||||
return preparePaymentSentText();
|
||||
}, [&](const MTPDmessageActionScreenshotTaken &) {
|
||||
return prepareScreenshotTaken();
|
||||
}, [&](const MTPDmessageActionCustomAction &data) {
|
||||
return prepareCustomAction(data);
|
||||
}, [&](const MTPDmessageActionBotAllowed &data) {
|
||||
return prepareBotAllowed(data);
|
||||
}, [&](const MTPDmessageActionSecureValuesSent &data) {
|
||||
return prepareSecureValuesSent(data);
|
||||
}, [&](const MTPDmessageActionContactSignUp &data) {
|
||||
return prepareContactSignUp();
|
||||
}, [&](const MTPDmessageActionGeoProximityReached &data) {
|
||||
return prepareProximityReached(data);
|
||||
}, [](const MTPDmessageActionPaymentSentMe &) {
|
||||
LOG(("API Error: messageActionPaymentSentMe received."));
|
||||
return PreparedServiceText{ { tr::lng_message_empty(tr::now) } };
|
||||
}, [](const MTPDmessageActionSecureValuesSentMe &) {
|
||||
LOG(("API Error: messageActionSecureValuesSentMe received."));
|
||||
return PreparedServiceText{ { tr::lng_message_empty(tr::now) } };
|
||||
}, [&](const MTPDmessageActionGroupCall &data) {
|
||||
return prepareGroupCall(data);
|
||||
}, [&](const MTPDmessageActionInviteToGroupCall &data) {
|
||||
return prepareInviteToGroupCall(data);
|
||||
}, [&](const MTPDmessageActionSetMessagesTTL &data) {
|
||||
return prepareSetMessagesTTL(data);
|
||||
}, [&](const MTPDmessageActionGroupCallScheduled &data) {
|
||||
return prepareCallScheduledText(data.vschedule_date().v);
|
||||
}, [&](const MTPDmessageActionSetChatTheme &data) {
|
||||
return prepareSetChatTheme(data);
|
||||
}, [&](const MTPDmessageActionChatJoinedByRequest &data) {
|
||||
return prepareChatJoinedByRequest(data);
|
||||
}, [&](const MTPDmessageActionWebViewDataSent &data) {
|
||||
return prepareWebViewDataSent(data);
|
||||
}, [&](const MTPDmessageActionGiftPremium &data) {
|
||||
return prepareGiftPremium(data);
|
||||
}, [&](const MTPDmessageActionTopicCreate &data) {
|
||||
return prepareTopicCreate(data);
|
||||
}, [&](const MTPDmessageActionTopicEdit &data) {
|
||||
return prepareTopicEdit(data);
|
||||
}, [&](const MTPDmessageActionWebViewDataSentMe &data) {
|
||||
LOG(("API Error: messageActionWebViewDataSentMe received."));
|
||||
return PreparedServiceText{ { tr::lng_message_empty(tr::now) } };
|
||||
}, [&](const MTPDmessageActionSuggestProfilePhoto &data) {
|
||||
return prepareSuggestProfilePhoto(data);
|
||||
}, [&](const MTPDmessageActionRequestedPeer &data) {
|
||||
return prepareRequestedPeer(data);
|
||||
}, [&](const MTPDmessageActionSetChatWallPaper &data) {
|
||||
return prepareSetChatWallPaper(data);
|
||||
}, [&](const MTPDmessageActionSetSameChatWallPaper &data) {
|
||||
return prepareSetSameChatWallPaper(data);
|
||||
}, [&](const MTPDmessageActionGiftCode &data) {
|
||||
return prepareGiftCode(data);
|
||||
}, [&](const MTPDmessageActionGiveawayLaunch &data) {
|
||||
return prepareGiveawayLaunch(data);
|
||||
}, [](const MTPDmessageActionEmpty &) {
|
||||
return PreparedServiceText{ { tr::lng_message_empty(tr::now) } };
|
||||
}));
|
||||
auto prepareGiveawayResults = [&](const MTPDmessageActionGiveawayResults &action) {
|
||||
auto result = PreparedServiceText();
|
||||
const auto winners = action.vwinners_count().v;
|
||||
const auto unclaimed = action.vunclaimed_count().v;
|
||||
result.text = {
|
||||
(!winners
|
||||
? tr::lng_action_giveaway_results_none(tr::now)
|
||||
: unclaimed
|
||||
? tr::lng_action_giveaway_results_some(tr::now)
|
||||
: tr::lng_action_giveaway_results(
|
||||
tr::now,
|
||||
lt_count,
|
||||
winners))
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
setServiceText(action.match(
|
||||
prepareChatAddUserText,
|
||||
prepareChatJoinedByLink,
|
||||
prepareChatCreate,
|
||||
PrepareEmptyText<MTPDmessageActionChatMigrateTo>,
|
||||
PrepareEmptyText<MTPDmessageActionChannelMigrateFrom>,
|
||||
PrepareEmptyText<MTPDmessageActionHistoryClear>,
|
||||
prepareChannelCreate,
|
||||
prepareChatDeletePhoto,
|
||||
prepareChatDeleteUser,
|
||||
prepareChatEditPhoto,
|
||||
prepareChatEditTitle,
|
||||
preparePinMessage,
|
||||
prepareGameScore,
|
||||
preparePhoneCall,
|
||||
preparePaymentSent,
|
||||
prepareScreenshotTaken,
|
||||
prepareCustomAction,
|
||||
prepareBotAllowed,
|
||||
prepareSecureValuesSent,
|
||||
prepareContactSignUp,
|
||||
prepareProximityReached,
|
||||
PrepareErrorText<MTPDmessageActionPaymentSentMe>,
|
||||
PrepareErrorText<MTPDmessageActionSecureValuesSentMe>,
|
||||
prepareGroupCall,
|
||||
prepareInviteToGroupCall,
|
||||
prepareSetMessagesTTL,
|
||||
prepareGroupCallScheduled,
|
||||
prepareSetChatTheme,
|
||||
prepareChatJoinedByRequest,
|
||||
prepareWebViewDataSent,
|
||||
prepareGiftPremium,
|
||||
prepareTopicCreate,
|
||||
prepareTopicEdit,
|
||||
PrepareErrorText<MTPDmessageActionWebViewDataSentMe>,
|
||||
prepareSuggestProfilePhoto,
|
||||
prepareRequestedPeer,
|
||||
prepareSetChatWallPaper,
|
||||
prepareGiftCode,
|
||||
prepareGiveawayLaunch,
|
||||
prepareGiveawayResults,
|
||||
PrepareErrorText<MTPDmessageActionEmpty>));
|
||||
|
||||
// Additional information.
|
||||
applyAction(action);
|
||||
|
@ -4680,10 +4675,13 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
|
|||
}, [](const MTPDphotoEmpty &) {
|
||||
});
|
||||
}, [&](const MTPDmessageActionSetChatWallPaper &data) {
|
||||
const auto session = &history()->session();
|
||||
const auto &attached = data.vwallpaper();
|
||||
if (const auto paper = Data::WallPaper::Create(session, attached)) {
|
||||
_media = std::make_unique<Data::MediaWallPaper>(this, *paper);
|
||||
if (!data.is_same()) {
|
||||
using namespace Data;
|
||||
const auto session = &history()->session();
|
||||
const auto &attached = data.vwallpaper();
|
||||
if (const auto paper = WallPaper::Create(session, attached)) {
|
||||
_media = std::make_unique<MediaWallPaper>(this, *paper);
|
||||
}
|
||||
}
|
||||
}, [&](const MTPDmessageActionGiftCode &data) {
|
||||
const auto boostedId = data.vboost_peer()
|
||||
|
|
|
@ -283,8 +283,9 @@ ReplyFields ReplyFields::clone(not_null<HistoryItem*> parent) const {
|
|||
.messageId = messageId,
|
||||
.topMessageId = topMessageId,
|
||||
.storyId = storyId,
|
||||
.topicPost = topicPost,
|
||||
.quoteOffset = quoteOffset,
|
||||
.manualQuote = manualQuote,
|
||||
.topicPost = topicPost,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -303,7 +304,7 @@ ReplyFields ReplyFieldsFromMTP(
|
|||
: id;
|
||||
result.topMessageId
|
||||
= data.vreply_to_top_id().value_or(id);
|
||||
result.topicPost = data.is_forum_topic();
|
||||
result.topicPost = data.is_forum_topic() ? 1 : 0;
|
||||
}
|
||||
if (const auto header = data.vreply_from()) {
|
||||
const auto &data = header->data();
|
||||
|
@ -324,7 +325,8 @@ ReplyFields ReplyFieldsFromMTP(
|
|||
&owner->session(),
|
||||
data.vquote_entities().value_or_empty()),
|
||||
};
|
||||
result.manualQuote = data.is_quote();
|
||||
result.quoteOffset = data.vquote_offset().value_or_empty();
|
||||
result.manualQuote = data.is_quote() ? 1 : 0;
|
||||
return result;
|
||||
}, [&](const MTPDmessageReplyStoryHeader &data) {
|
||||
return ReplyFields{
|
||||
|
@ -357,6 +359,7 @@ FullReplyTo ReplyToFromMTP(
|
|||
&history->session(),
|
||||
data.vquote_entities().value_or_empty()),
|
||||
};
|
||||
result.quoteOffset = data.vquote_offset().value_or_empty();
|
||||
return result;
|
||||
}, [&](const MTPDinputReplyToStory &data) {
|
||||
if (const auto parsed = Data::UserFromInputMTP(
|
||||
|
@ -461,7 +464,7 @@ void HistoryMessageReply::updateFields(
|
|||
MsgId messageId,
|
||||
MsgId topMessageId,
|
||||
bool topicPost) {
|
||||
_fields.topicPost = topicPost;
|
||||
_fields.topicPost = topicPost ? 1 : 0;
|
||||
if ((_fields.messageId != messageId)
|
||||
&& !IsServerMsgId(_fields.messageId)) {
|
||||
_fields.messageId = messageId;
|
||||
|
|
|
@ -233,7 +233,7 @@ private:
|
|||
};
|
||||
|
||||
struct ReplyFields {
|
||||
ReplyFields clone(not_null<HistoryItem*> parent) const;
|
||||
[[nodiscard]] ReplyFields clone(not_null<HistoryItem*> parent) const;
|
||||
|
||||
TextWithEntities quote;
|
||||
std::unique_ptr<Data::Media> externalMedia;
|
||||
|
@ -244,8 +244,9 @@ struct ReplyFields {
|
|||
MsgId messageId = 0;
|
||||
MsgId topMessageId = 0;
|
||||
StoryId storyId = 0;
|
||||
bool topicPost = false;
|
||||
bool manualQuote = false;
|
||||
uint32 quoteOffset : 30 = 0;
|
||||
uint32 manualQuote : 1 = 0;
|
||||
uint32 topicPost : 1 = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] ReplyFields ReplyFieldsFromMTP(
|
||||
|
|
|
@ -270,19 +270,22 @@ bool IsItemScheduledUntilOnline(not_null<const HistoryItem*> item) {
|
|||
ClickHandlerPtr JumpToMessageClickHandler(
|
||||
not_null<HistoryItem*> item,
|
||||
FullMsgId returnToId,
|
||||
TextWithEntities highlightPart) {
|
||||
TextWithEntities highlightPart,
|
||||
int highlightPartOffsetHint) {
|
||||
return JumpToMessageClickHandler(
|
||||
item->history()->peer,
|
||||
item->id,
|
||||
returnToId,
|
||||
std::move(highlightPart));
|
||||
std::move(highlightPart),
|
||||
highlightPartOffsetHint);
|
||||
}
|
||||
|
||||
ClickHandlerPtr JumpToMessageClickHandler(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId msgId,
|
||||
FullMsgId returnToId,
|
||||
TextWithEntities highlightPart) {
|
||||
TextWithEntities highlightPart,
|
||||
int highlightPartOffsetHint) {
|
||||
return std::make_shared<LambdaClickHandler>([=] {
|
||||
const auto separate = Core::App().separateWindowForPeer(peer);
|
||||
const auto controller = separate
|
||||
|
@ -293,6 +296,7 @@ ClickHandlerPtr JumpToMessageClickHandler(
|
|||
Window::SectionShow::Way::Forward
|
||||
};
|
||||
params.highlightPart = highlightPart;
|
||||
params.highlightPartOffsetHint = highlightPartOffsetHint;
|
||||
params.origin = Window::SectionShow::OriginMessage{
|
||||
returnToId
|
||||
};
|
||||
|
@ -392,8 +396,11 @@ MTPMessageReplyHeader NewMessageReplyHeader(const Api::SendAction &action) {
|
|||
MTP_flags(Flag::f_reply_to_msg_id
|
||||
| (replyToTop ? Flag::f_reply_to_top_id : Flag())
|
||||
| (externalPeerId ? Flag::f_reply_to_peer_id : Flag())
|
||||
| (replyTo.quote.empty() ? Flag() : Flag::f_quote)
|
||||
| (replyTo.quote.empty() ? Flag() : Flag::f_quote_text)
|
||||
| (replyTo.quote.empty()
|
||||
? Flag()
|
||||
: (Flag::f_quote
|
||||
| Flag::f_quote_text
|
||||
| Flag::f_quote_offset))
|
||||
| (quoteEntities.v.empty()
|
||||
? Flag()
|
||||
: Flag::f_quote_entities)),
|
||||
|
@ -403,7 +410,8 @@ MTPMessageReplyHeader NewMessageReplyHeader(const Api::SendAction &action) {
|
|||
MTPMessageMedia(), // reply_media
|
||||
MTP_int(replyToTop),
|
||||
MTP_string(replyTo.quote.text),
|
||||
quoteEntities);
|
||||
quoteEntities,
|
||||
MTP_int(replyTo.quoteOffset));
|
||||
}
|
||||
return MTPMessageReplyHeader();
|
||||
}
|
||||
|
|
|
@ -124,11 +124,13 @@ struct SendingErrorRequest {
|
|||
not_null<PeerData*> peer,
|
||||
MsgId msgId,
|
||||
FullMsgId returnToId = FullMsgId(),
|
||||
TextWithEntities highlightPart = {});
|
||||
TextWithEntities highlightPart = {},
|
||||
int highlightPartOffsetHint = 0);
|
||||
[[nodiscard]] ClickHandlerPtr JumpToMessageClickHandler(
|
||||
not_null<HistoryItem*> item,
|
||||
FullMsgId returnToId = FullMsgId(),
|
||||
TextWithEntities highlightPart = {});
|
||||
TextWithEntities highlightPart = {},
|
||||
int highlightPartOffsetHint = 0);
|
||||
[[nodiscard]] ClickHandlerPtr JumpToStoryClickHandler(
|
||||
not_null<Data::Story*> story);
|
||||
ClickHandlerPtr JumpToStoryClickHandler(
|
||||
|
|
|
@ -25,10 +25,8 @@ ElementHighlighter::ElementHighlighter(
|
|||
, _animation(*this) {
|
||||
}
|
||||
|
||||
void ElementHighlighter::enqueue(
|
||||
not_null<Element*> view,
|
||||
const TextWithEntities &part) {
|
||||
const auto data = computeHighlight(view, part);
|
||||
void ElementHighlighter::enqueue(const SelectedQuote "e) {
|
||||
const auto data = computeHighlight(quote);
|
||||
if (_queue.empty() && !_animation.animating()) {
|
||||
highlight(data);
|
||||
} else if (_highlighted != data && !base::contains(_queue, data)) {
|
||||
|
@ -37,10 +35,8 @@ void ElementHighlighter::enqueue(
|
|||
}
|
||||
}
|
||||
|
||||
void ElementHighlighter::highlight(
|
||||
not_null<Element*> view,
|
||||
const TextWithEntities &part) {
|
||||
highlight(computeHighlight(view, part));
|
||||
void ElementHighlighter::highlight(const SelectedQuote "e) {
|
||||
highlight(computeHighlight(quote));
|
||||
}
|
||||
|
||||
void ElementHighlighter::checkNextHighlight() {
|
||||
|
@ -75,9 +71,10 @@ Ui::ChatPaintHighlight ElementHighlighter::state(
|
|||
}
|
||||
|
||||
ElementHighlighter::Highlight ElementHighlighter::computeHighlight(
|
||||
not_null<const Element*> view,
|
||||
const TextWithEntities &part) {
|
||||
const auto item = view->data();
|
||||
const SelectedQuote "e) {
|
||||
Assert(quote.item != nullptr);
|
||||
|
||||
const auto item = not_null(quote.item);
|
||||
const auto owner = &item->history()->owner();
|
||||
if (const auto group = owner->groups().find(item)) {
|
||||
const auto leader = group->items.front();
|
||||
|
@ -85,20 +82,19 @@ ElementHighlighter::Highlight ElementHighlighter::computeHighlight(
|
|||
const auto i = ranges::find(group->items, item);
|
||||
if (i != end(group->items)) {
|
||||
const auto index = int(i - begin(group->items));
|
||||
if (part.empty()) {
|
||||
if (quote.text.empty()) {
|
||||
return { leaderId, AddGroupItemSelection({}, index) };
|
||||
} else if (const auto leaderView = _viewForItem(leader)) {
|
||||
return {
|
||||
leaderId,
|
||||
leaderView->selectionFromQuote(item, part),
|
||||
};
|
||||
return { leaderId, leaderView->selectionFromQuote(quote) };
|
||||
}
|
||||
}
|
||||
return { leaderId };
|
||||
} else if (part.empty()) {
|
||||
} else if (quote.text.empty()) {
|
||||
return { item->fullId() };
|
||||
} else if (const auto view = _viewForItem(item)) {
|
||||
return { item->fullId(), view->selectionFromQuote(quote) };
|
||||
}
|
||||
return { item->fullId(), view->selectionFromQuote(item, part) };
|
||||
return { item->fullId() };
|
||||
}
|
||||
|
||||
void ElementHighlighter::highlight(Highlight data) {
|
||||
|
|
|
@ -23,6 +23,7 @@ struct ChatPaintHighlight;
|
|||
namespace HistoryView {
|
||||
|
||||
class Element;
|
||||
struct SelectedQuote;
|
||||
|
||||
class ElementHighlighter final {
|
||||
public:
|
||||
|
@ -33,8 +34,8 @@ public:
|
|||
ViewForItem viewForItem,
|
||||
RepaintView repaintView);
|
||||
|
||||
void enqueue(not_null<Element*> view, const TextWithEntities &part);
|
||||
void highlight(not_null<Element*> view, const TextWithEntities &part);
|
||||
void enqueue(const SelectedQuote "e);
|
||||
void highlight(const SelectedQuote "e);
|
||||
void clear();
|
||||
|
||||
[[nodiscard]] Ui::ChatPaintHighlight state(
|
||||
|
@ -71,9 +72,7 @@ private:
|
|||
friend inline bool operator==(Highlight, Highlight) = default;
|
||||
};
|
||||
|
||||
[[nodiscard]] Highlight computeHighlight(
|
||||
not_null<const Element*> view,
|
||||
const TextWithEntities &part);
|
||||
[[nodiscard]] Highlight computeHighlight(const SelectedQuote "e);
|
||||
void highlight(Highlight data);
|
||||
void checkNextHighlight();
|
||||
void repaintHighlightedItem(not_null<const Element*> view);
|
||||
|
|
|
@ -1075,7 +1075,7 @@ void HistoryWidget::initTabbedSelector() {
|
|||
if (!data.recipientOverride) {
|
||||
return true;
|
||||
} else if (data.recipientOverride != _peer) {
|
||||
showHistory(data.recipientOverride->id, ShowAtTheEndMsgId, {});
|
||||
showHistory(data.recipientOverride->id, ShowAtTheEndMsgId);
|
||||
}
|
||||
return (data.recipientOverride == _peer);
|
||||
}) | rpl::start_with_next([=](ChatHelpers::InlineChosen data) {
|
||||
|
@ -1270,9 +1270,8 @@ void HistoryWidget::scrollToAnimationCallback(
|
|||
}
|
||||
|
||||
void HistoryWidget::enqueueMessageHighlight(
|
||||
not_null<HistoryView::Element*> view,
|
||||
const TextWithEntities &part) {
|
||||
_highlighter.enqueue(view, part);
|
||||
const HistoryView::SelectedQuote "e) {
|
||||
_highlighter.enqueue(quote);
|
||||
}
|
||||
|
||||
Ui::ChatPaintHighlight HistoryWidget::itemHighlight(
|
||||
|
@ -1973,10 +1972,12 @@ bool HistoryWidget::insideJumpToEndInsteadOfToUnread() const {
|
|||
void HistoryWidget::showHistory(
|
||||
const PeerId &peerId,
|
||||
MsgId showAtMsgId,
|
||||
const TextWithEntities &highlightPart) {
|
||||
const TextWithEntities &highlightPart,
|
||||
int highlightPartOffsetHint) {
|
||||
_pinnedClickedId = FullMsgId();
|
||||
_minPinnedId = std::nullopt;
|
||||
_showAtMsgHighlightPart = {};
|
||||
_showAtMsgHighlightPartOffsetHint = 0;
|
||||
|
||||
const auto wasDialogsEntryState = computeDialogsEntryState();
|
||||
const auto startBot = (showAtMsgId == ShowAndStartBotMsgId);
|
||||
|
@ -2024,10 +2025,16 @@ void HistoryWidget::showHistory(
|
|||
).arg(_history->inboxReadTillId().bare
|
||||
).arg(Logs::b(_history->loadedAtBottom())
|
||||
).arg(showAtMsgId.bare));
|
||||
delayedShowAt(showAtMsgId, highlightPart);
|
||||
delayedShowAt(
|
||||
showAtMsgId,
|
||||
highlightPart,
|
||||
highlightPartOffsetHint);
|
||||
} else if (_showAtMsgId != showAtMsgId) {
|
||||
clearAllLoadRequests();
|
||||
setMsgId(showAtMsgId, highlightPart);
|
||||
setMsgId(
|
||||
showAtMsgId,
|
||||
highlightPart,
|
||||
highlightPartOffsetHint);
|
||||
firstLoadMessages();
|
||||
doneShow();
|
||||
}
|
||||
|
@ -2047,7 +2054,10 @@ void HistoryWidget::showHistory(
|
|||
_cornerButtons.skipReplyReturn(skipId);
|
||||
}
|
||||
|
||||
setMsgId(showAtMsgId, highlightPart);
|
||||
setMsgId(
|
||||
showAtMsgId,
|
||||
highlightPart,
|
||||
highlightPartOffsetHint);
|
||||
if (_historyInited) {
|
||||
DEBUG_LOG(("JumpToEnd(%1, %2, %3): "
|
||||
"Showing instant at %4."
|
||||
|
@ -2151,6 +2161,7 @@ void HistoryWidget::showHistory(
|
|||
|
||||
_showAtMsgId = showAtMsgId;
|
||||
_showAtMsgHighlightPart = highlightPart;
|
||||
_showAtMsgHighlightPartOffsetHint = highlightPartOffsetHint;
|
||||
_historyInited = false;
|
||||
_contactStatus = nullptr;
|
||||
|
||||
|
@ -3305,7 +3316,10 @@ void HistoryWidget::messagesReceived(
|
|||
}
|
||||
|
||||
_delayedShowAtRequest = 0;
|
||||
setMsgId(_delayedShowAtMsgId, _delayedShowAtMsgHighlightPart);
|
||||
setMsgId(
|
||||
_delayedShowAtMsgId,
|
||||
_delayedShowAtMsgHighlightPart,
|
||||
_delayedShowAtMsgHighlightPartOffsetHint);
|
||||
historyLoaded();
|
||||
}
|
||||
if (session().supportMode()) {
|
||||
|
@ -3529,13 +3543,15 @@ void HistoryWidget::loadMessagesDown() {
|
|||
|
||||
void HistoryWidget::delayedShowAt(
|
||||
MsgId showAtMsgId,
|
||||
const TextWithEntities &highlightPart) {
|
||||
const TextWithEntities &highlightPart,
|
||||
int highlightPartOffsetHint) {
|
||||
if (!_history) {
|
||||
return;
|
||||
}
|
||||
if (_delayedShowAtMsgHighlightPart != highlightPart) {
|
||||
_delayedShowAtMsgHighlightPart = highlightPart;
|
||||
}
|
||||
_delayedShowAtMsgHighlightPartOffsetHint = highlightPartOffsetHint;
|
||||
if (_delayedShowAtRequest && _delayedShowAtMsgId == showAtMsgId) {
|
||||
return;
|
||||
}
|
||||
|
@ -4120,10 +4136,12 @@ PeerData *HistoryWidget::peer() const {
|
|||
// Sometimes _showAtMsgId is set directly.
|
||||
void HistoryWidget::setMsgId(
|
||||
MsgId showAtMsgId,
|
||||
const TextWithEntities &highlightPart) {
|
||||
const TextWithEntities &highlightPart,
|
||||
int highlightPartOffsetHint) {
|
||||
if (_showAtMsgHighlightPart != highlightPart) {
|
||||
_showAtMsgHighlightPart = highlightPart;
|
||||
}
|
||||
_showAtMsgHighlightPartOffsetHint = highlightPartOffsetHint;
|
||||
if (_showAtMsgId != showAtMsgId) {
|
||||
_showAtMsgId = showAtMsgId;
|
||||
if (_history) {
|
||||
|
@ -4244,11 +4262,11 @@ void HistoryWidget::cornerButtonsShowAtPosition(
|
|||
).arg(_history->peer->name()
|
||||
).arg(_history->inboxReadTillId().bare
|
||||
).arg(Logs::b(_history->loadedAtBottom())));
|
||||
showHistory(_peer->id, ShowAtUnreadMsgId, {});
|
||||
showHistory(_peer->id, ShowAtUnreadMsgId);
|
||||
} else if (_peer && position.fullId.peer == _peer->id) {
|
||||
showHistory(_peer->id, position.fullId.msg, {});
|
||||
showHistory(_peer->id, position.fullId.msg);
|
||||
} else if (_migrated && position.fullId.peer == _migrated->peer->id) {
|
||||
showHistory(_peer->id, -position.fullId.msg, {});
|
||||
showHistory(_peer->id, -position.fullId.msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5700,9 +5718,11 @@ int HistoryWidget::countInitialScrollTop() {
|
|||
const auto view = item->mainView();
|
||||
Assert(view != nullptr);
|
||||
|
||||
enqueueMessageHighlight(
|
||||
view,
|
||||
base::take(_showAtMsgHighlightPart));
|
||||
enqueueMessageHighlight({
|
||||
item,
|
||||
base::take(_showAtMsgHighlightPart),
|
||||
base::take(_showAtMsgHighlightPartOffsetHint),
|
||||
});
|
||||
const auto result = itemTopForHighlight(view);
|
||||
createUnreadBarIfBelowVisibleArea(result);
|
||||
return result;
|
||||
|
@ -6386,8 +6406,7 @@ void HistoryWidget::handlePeerMigration() {
|
|||
if (_peer != channel) {
|
||||
showHistory(
|
||||
channel->id,
|
||||
(_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId,
|
||||
{});
|
||||
(_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId);
|
||||
channel->session().api().chatParticipants().requestCountDelayed(
|
||||
channel);
|
||||
} else {
|
||||
|
@ -6483,7 +6502,7 @@ bool HistoryWidget::showSlowmodeError() {
|
|||
if (const auto item = _history->latestSendingMessage()) {
|
||||
if (const auto view = item->mainView()) {
|
||||
animatedScrollToItem(item->id);
|
||||
enqueueMessageHighlight(view, {});
|
||||
enqueueMessageHighlight({ item });
|
||||
}
|
||||
return tr::lng_slowmode_no_many(tr::now);
|
||||
}
|
||||
|
@ -7149,7 +7168,7 @@ void HistoryWidget::replyToMessage(
|
|||
if (isJoinChannel()) {
|
||||
return;
|
||||
}
|
||||
_processingReplyTo = { .messageId = item->fullId(), .quote = quote};
|
||||
_processingReplyTo = { .messageId = item->fullId(), .quote = quote };
|
||||
_processingReplyItem = item;
|
||||
processReply();
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ class Element;
|
|||
class PinnedTracker;
|
||||
class TranslateBar;
|
||||
class ComposeSearch;
|
||||
struct SelectedQuote;
|
||||
} // namespace HistoryView
|
||||
|
||||
namespace HistoryView::Controls {
|
||||
|
@ -149,7 +150,8 @@ public:
|
|||
void firstLoadMessages();
|
||||
void delayedShowAt(
|
||||
MsgId showAtMsgId,
|
||||
const TextWithEntities &highlightPart);
|
||||
const TextWithEntities &highlightPart,
|
||||
int highlightPartOffsetHint);
|
||||
|
||||
bool updateReplaceMediaButton();
|
||||
void updateFieldPlaceholder();
|
||||
|
@ -165,7 +167,8 @@ public:
|
|||
PeerData *peer() const;
|
||||
void setMsgId(
|
||||
MsgId showAtMsgId,
|
||||
const TextWithEntities &highlightPart = {});
|
||||
const TextWithEntities &highlightPart = {},
|
||||
int highlightPartOffsetHint = 0);
|
||||
MsgId msgId() const;
|
||||
|
||||
bool hasTopBarShadow() const {
|
||||
|
@ -182,9 +185,7 @@ public:
|
|||
|
||||
bool touchScroll(const QPoint &delta);
|
||||
|
||||
void enqueueMessageHighlight(
|
||||
not_null<HistoryView::Element*> view,
|
||||
const TextWithEntities &part);
|
||||
void enqueueMessageHighlight(const HistoryView::SelectedQuote "e);
|
||||
[[nodiscard]] Ui::ChatPaintHighlight itemHighlight(
|
||||
not_null<const HistoryItem*> item) const;
|
||||
|
||||
|
@ -228,7 +229,8 @@ public:
|
|||
void showHistory(
|
||||
const PeerId &peer,
|
||||
MsgId showAtMsgId,
|
||||
const TextWithEntities &highlightPart);
|
||||
const TextWithEntities &highlightPart = {},
|
||||
int highlightPartOffsetHint = 0);
|
||||
void setChooseReportMessagesDetails(
|
||||
Ui::ReportReason reason,
|
||||
Fn<void(MessageIdsList)> callback);
|
||||
|
@ -693,6 +695,7 @@ private:
|
|||
bool _canSendTexts = false;
|
||||
MsgId _showAtMsgId = ShowAtUnreadMsgId;
|
||||
TextWithEntities _showAtMsgHighlightPart;
|
||||
int _showAtMsgHighlightPartOffsetHint = 0;
|
||||
|
||||
int _firstLoadRequest = 0; // Not real mtpRequestId.
|
||||
int _preloadRequest = 0; // Not real mtpRequestId.
|
||||
|
@ -700,6 +703,7 @@ private:
|
|||
|
||||
MsgId _delayedShowAtMsgId = -1;
|
||||
TextWithEntities _delayedShowAtMsgHighlightPart;
|
||||
int _delayedShowAtMsgHighlightPartOffsetHint = 0;
|
||||
int _delayedShowAtRequest = 0; // Not real mtpRequestId.
|
||||
|
||||
History *_supportPreloadHistory = nullptr;
|
||||
|
|
|
@ -235,7 +235,7 @@ rpl::producer<SelectedQuote> PreviewWrap::showQuoteSelector(
|
|||
|
||||
initElement();
|
||||
|
||||
_selection = _element->selectionFromQuote(item, quote.text);
|
||||
_selection = _element->selectionFromQuote(quote);
|
||||
return _selection.value(
|
||||
) | rpl::map([=](TextSelection selection) {
|
||||
if (const auto result = _element->selectedQuote(selection)) {
|
||||
|
@ -643,6 +643,7 @@ void DraftOptionsBox(
|
|||
if (const auto current = state->quote.current()) {
|
||||
result.messageId = current.item->fullId();
|
||||
result.quote = current.text;
|
||||
result.quoteOffset = current.offset;
|
||||
} else {
|
||||
result.quote = {};
|
||||
}
|
||||
|
|
|
@ -581,7 +581,9 @@ bool AddReplyToMessageAction(
|
|||
const ContextMenuRequest &request,
|
||||
not_null<ListWidget*> list) {
|
||||
const auto context = list->elementContext();
|
||||
const auto item = request.quoteItem ? request.quoteItem : request.item;
|
||||
const auto item = request.quote.item
|
||||
? request.quote.item
|
||||
: request.item;
|
||||
const auto topic = item ? item->topic() : nullptr;
|
||||
const auto peer = item ? item->history()->peer.get() : nullptr;
|
||||
if (!item
|
||||
|
@ -598,7 +600,7 @@ bool AddReplyToMessageAction(
|
|||
}
|
||||
|
||||
const auto "e = request.quote;
|
||||
auto text = quote.empty()
|
||||
auto text = quote.text.empty()
|
||||
? tr::lng_context_reply_msg(tr::now)
|
||||
: tr::lng_context_quote_and_reply(tr::now);
|
||||
text.replace('&', u"&&"_q);
|
||||
|
@ -607,7 +609,11 @@ bool AddReplyToMessageAction(
|
|||
if (!item) {
|
||||
return;
|
||||
} else {
|
||||
list->replyToMessageRequestNotify({ itemId, quote });
|
||||
list->replyToMessageRequestNotify({
|
||||
.messageId = itemId,
|
||||
.quote = quote.text,
|
||||
.quoteOffset = quote.offset,
|
||||
});
|
||||
}
|
||||
}, &st::menuIconReply);
|
||||
return true;
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "base/unique_qptr.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
|
||||
namespace Data {
|
||||
struct ReactionId;
|
||||
|
@ -47,8 +48,7 @@ struct ContextMenuRequest {
|
|||
HistoryItem *item = nullptr;
|
||||
SelectedItems selectedItems;
|
||||
TextForMimeData selectedText;
|
||||
TextWithEntities quote;
|
||||
HistoryItem *quoteItem = nullptr;
|
||||
SelectedQuote quote;
|
||||
bool overSelection = false;
|
||||
PointState pointState = PointState();
|
||||
};
|
||||
|
|
|
@ -1647,29 +1647,30 @@ SelectedQuote Element::FindSelectedQuote(
|
|||
++i;
|
||||
}
|
||||
}
|
||||
return { item, result };
|
||||
return { item, result, modified.from };
|
||||
}
|
||||
|
||||
TextSelection Element::FindSelectionFromQuote(
|
||||
const Ui::Text::String &text,
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) {
|
||||
if (quote.empty()) {
|
||||
const SelectedQuote "e) {
|
||||
Expects(quote.item != nullptr);
|
||||
|
||||
if (quote.text.empty()) {
|
||||
return {};
|
||||
}
|
||||
const auto &original = item->originalText();
|
||||
const auto &original = quote.item->originalText();
|
||||
auto result = TextSelection();
|
||||
auto offset = 0;
|
||||
while (true) {
|
||||
const auto i = original.text.indexOf(quote.text, offset);
|
||||
const auto i = original.text.indexOf(quote.text.text, offset);
|
||||
if (i < 0) {
|
||||
return {};
|
||||
}
|
||||
auto selection = TextSelection{
|
||||
uint16(i),
|
||||
uint16(i + quote.text.size()),
|
||||
uint16(i + quote.text.text.size()),
|
||||
};
|
||||
if (CheckQuoteEntities(quote.entities, original, selection)) {
|
||||
if (CheckQuoteEntities(quote.text.entities, original, selection)) {
|
||||
result = selection;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -270,6 +270,7 @@ struct TopicButton {
|
|||
struct SelectedQuote {
|
||||
HistoryItem *item = nullptr;
|
||||
TextWithEntities text;
|
||||
int offset = 0;
|
||||
|
||||
explicit operator bool() const {
|
||||
return item && !text.empty();
|
||||
|
@ -401,8 +402,7 @@ public:
|
|||
virtual SelectedQuote selectedQuote(
|
||||
TextSelection selection) const = 0;
|
||||
virtual TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const = 0;
|
||||
const SelectedQuote "e) const = 0;
|
||||
[[nodiscard]] virtual TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const;
|
||||
|
@ -413,8 +413,7 @@ public:
|
|||
not_null<HistoryItem*> item);
|
||||
[[nodiscard]] static TextSelection FindSelectionFromQuote(
|
||||
const Ui::Text::String &text,
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e);
|
||||
const SelectedQuote "e);
|
||||
|
||||
[[nodiscard]] virtual auto reactionButtonParameters(
|
||||
QPoint position,
|
||||
|
|
|
@ -709,9 +709,10 @@ bool ListWidget::isBelowPosition(Data::MessagePosition position) const {
|
|||
|
||||
void ListWidget::highlightMessage(
|
||||
FullMsgId itemId,
|
||||
const TextWithEntities &part) {
|
||||
const TextWithEntities &part,
|
||||
int partOffsetHint) {
|
||||
if (const auto view = viewForItem(itemId)) {
|
||||
_highlighter.highlight(view, part);
|
||||
_highlighter.highlight({ view->data(), part, partOffsetHint });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -787,7 +788,10 @@ bool ListWidget::showAtPositionNow(
|
|||
computeScrollTo(*scrollTop, position, params.animated);
|
||||
if (position != Data::MaxMessagePosition
|
||||
&& position != Data::UnreadMessagePosition) {
|
||||
highlightMessage(position.fullId, params.highlightPart);
|
||||
highlightMessage(
|
||||
position.fullId,
|
||||
params.highlightPart,
|
||||
params.highlightPartOffsetHint);
|
||||
}
|
||||
if (done) {
|
||||
const auto found = !position.fullId.peer
|
||||
|
@ -2143,7 +2147,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
} else if (item->isUnreadMention()
|
||||
&& !item->isUnreadMedia()) {
|
||||
readContents.insert(item);
|
||||
_highlighter.enqueue(view, {});
|
||||
_highlighter.enqueue({ item });
|
||||
}
|
||||
}
|
||||
session->data().reactions().poll(item, context.now);
|
||||
|
@ -2603,12 +2607,10 @@ void ListWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
request.view = _overElement;
|
||||
request.item = overItem;
|
||||
request.pointState = _overState.pointState;
|
||||
const auto quote = (_overElement
|
||||
request.quote = (_overElement
|
||||
&& _selectedTextItem == _overElement->data())
|
||||
? _overElement->selectedQuote(_selectedTextRange)
|
||||
: SelectedQuote();
|
||||
request.quote = quote.text;
|
||||
request.quoteItem = quote.item;
|
||||
request.selectedText = _selectedText;
|
||||
request.selectedItems = collectSelectedItems();
|
||||
const auto hasSelection = !request.selectedItems.empty()
|
||||
|
|
|
@ -233,7 +233,8 @@ public:
|
|||
bool isBelowPosition(Data::MessagePosition position) const;
|
||||
void highlightMessage(
|
||||
FullMsgId itemId,
|
||||
const TextWithEntities &part);
|
||||
const TextWithEntities &part,
|
||||
int partOffsetHint);
|
||||
|
||||
void showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
|
|
|
@ -2684,11 +2684,13 @@ SelectedQuote Message::selectedQuote(TextSelection selection) const {
|
|||
}
|
||||
|
||||
TextSelection Message::selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
if (quote.empty()) {
|
||||
const SelectedQuote "e) const {
|
||||
Expects(quote.item != nullptr);
|
||||
|
||||
if (quote.text.empty()) {
|
||||
return {};
|
||||
}
|
||||
const auto item = quote.item;
|
||||
const auto &translated = item->translatedText();
|
||||
const auto &original = item->originalText();
|
||||
if (&translated != &original) {
|
||||
|
@ -2697,11 +2699,11 @@ TextSelection Message::selectionFromQuote(
|
|||
const auto media = this->media();
|
||||
const auto mediaDisplayed = media && media->isDisplayed();
|
||||
const auto mediaBefore = mediaDisplayed && invertMedia();
|
||||
const auto result = FindSelectionFromQuote(text(), item, quote);
|
||||
const auto result = FindSelectionFromQuote(text(), quote);
|
||||
return mediaBefore ? media->unskipSelection(result) : result;
|
||||
} else if (const auto media = this->media()) {
|
||||
if (media->isDisplayed() || isHiddenByGroup()) {
|
||||
return media->selectionFromQuote(item, quote);
|
||||
return media->selectionFromQuote(quote);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
|
|
@ -97,8 +97,7 @@ public:
|
|||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
SelectedQuote selectedQuote(TextSelection selection) const override;
|
||||
TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const override;
|
||||
const SelectedQuote "e) const override;
|
||||
TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
|
|
|
@ -130,11 +130,13 @@ RepliesMemento::RepliesMemento(
|
|||
not_null<History*> history,
|
||||
MsgId rootId,
|
||||
MsgId highlightId,
|
||||
const TextWithEntities &highlightPart)
|
||||
const TextWithEntities &highlightPart,
|
||||
int highlightPartOffsetHint)
|
||||
: _history(history)
|
||||
, _rootId(rootId)
|
||||
, _highlightId(highlightId)
|
||||
, _highlightPart(highlightPart) {
|
||||
, _highlightPart(highlightPart)
|
||||
, _highlightPartOffsetHint(highlightPartOffsetHint)
|
||||
, _highlightId(highlightId) {
|
||||
if (highlightId) {
|
||||
_list.setAroundPosition({
|
||||
.fullId = FullMsgId(_history->peer->id, highlightId),
|
||||
|
@ -2149,6 +2151,7 @@ void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
|
|||
Window::SectionShow::Way::Forward,
|
||||
anim::type::instant);
|
||||
params.highlightPart = memento->highlightPart();
|
||||
params.highlightPartOffsetHint = memento->highlightPartOffsetHint();
|
||||
showAtPosition(Data::MessagePosition{
|
||||
.fullId = FullMsgId(_history->peer->id, highlight),
|
||||
.date = TimeId(0),
|
||||
|
|
|
@ -381,7 +381,8 @@ public:
|
|||
not_null<History*> history,
|
||||
MsgId rootId,
|
||||
MsgId highlightId = 0,
|
||||
const TextWithEntities &highlightPart = {});
|
||||
const TextWithEntities &highlightPart = {},
|
||||
int highlightPartOffsetHint = 0);
|
||||
explicit RepliesMemento(
|
||||
not_null<HistoryItem*> commentsItem,
|
||||
MsgId commentId = 0);
|
||||
|
@ -431,14 +432,18 @@ public:
|
|||
[[nodiscard]] const TextWithEntities &highlightPart() const {
|
||||
return _highlightPart;
|
||||
}
|
||||
[[nodiscard]] int highlightPartOffsetHint() const {
|
||||
return _highlightPartOffsetHint;
|
||||
}
|
||||
|
||||
private:
|
||||
void setupTopicViewer();
|
||||
|
||||
const not_null<History*> _history;
|
||||
MsgId _rootId = 0;
|
||||
const MsgId _highlightId = 0;
|
||||
const TextWithEntities _highlightPart;
|
||||
const int _highlightPartOffsetHint = 0;
|
||||
const MsgId _highlightId = 0;
|
||||
ListMemento _list;
|
||||
std::shared_ptr<Data::RepliesList> _replies;
|
||||
QVector<FullMsgId> _replyReturns;
|
||||
|
|
|
@ -674,8 +674,7 @@ SelectedQuote Service::selectedQuote(TextSelection selection) const {
|
|||
}
|
||||
|
||||
TextSelection Service::selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
const SelectedQuote "e) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,7 @@ public:
|
|||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
SelectedQuote selectedQuote(TextSelection selection) const override;
|
||||
TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const override;
|
||||
const SelectedQuote "e) const override;
|
||||
TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
|
|
|
@ -1232,12 +1232,10 @@ SelectedQuote Document::selectedQuote(TextSelection selection) const {
|
|||
}
|
||||
|
||||
TextSelection Document::selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
const SelectedQuote "e) const {
|
||||
if (const auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
const auto result = Element::FindSelectionFromQuote(
|
||||
captioned->caption,
|
||||
item,
|
||||
quote);
|
||||
if (result.empty()) {
|
||||
return {};
|
||||
|
|
|
@ -48,8 +48,7 @@ public:
|
|||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
SelectedQuote selectedQuote(TextSelection selection) const override;
|
||||
TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const override;
|
||||
const SelectedQuote "e) const override;
|
||||
|
||||
bool uploading() const override;
|
||||
|
||||
|
|
|
@ -1205,10 +1205,8 @@ SelectedQuote Gif::selectedQuote(TextSelection selection) const {
|
|||
return Element::FindSelectedQuote(_caption, selection, _realParent);
|
||||
}
|
||||
|
||||
TextSelection Gif::selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
return Element::FindSelectionFromQuote(_caption, item, quote);
|
||||
TextSelection Gif::selectionFromQuote(const SelectedQuote "e) const {
|
||||
return Element::FindSelectionFromQuote(_caption, quote);
|
||||
}
|
||||
|
||||
bool Gif::fullFeaturedGrouped(RectParts sides) const {
|
||||
|
|
|
@ -71,8 +71,7 @@ public:
|
|||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
SelectedQuote selectedQuote(TextSelection selection) const override;
|
||||
TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const override;
|
||||
const SelectedQuote "e) const override;
|
||||
|
||||
bool uploading() const override;
|
||||
|
||||
|
|
|
@ -92,8 +92,7 @@ public:
|
|||
[[nodiscard]] virtual SelectedQuote selectedQuote(
|
||||
TextSelection selection) const;
|
||||
[[nodiscard]] virtual TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
const SelectedQuote "e) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -622,19 +622,20 @@ SelectedQuote GroupedMedia::selectedQuote(TextSelection selection) const {
|
|||
}
|
||||
|
||||
TextSelection GroupedMedia::selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
const SelectedQuote "e) const {
|
||||
Expects(quote.item != nullptr);
|
||||
|
||||
if (_mode != Mode::Column) {
|
||||
return (_captionItem == item)
|
||||
? Element::FindSelectionFromQuote(_caption, item, quote)
|
||||
return (_captionItem == quote.item)
|
||||
? Element::FindSelectionFromQuote(_caption, quote)
|
||||
: TextSelection();
|
||||
}
|
||||
const auto i = ranges::find(_parts, item, &Part::item);
|
||||
const auto i = ranges::find(_parts, not_null(quote.item), &Part::item);
|
||||
if (i == end(_parts)) {
|
||||
return {};
|
||||
}
|
||||
const auto index = int(i - begin(_parts));
|
||||
auto result = i->content->selectionFromQuote(item, quote);
|
||||
auto result = i->content->selectionFromQuote(quote);
|
||||
if (result.empty()) {
|
||||
return AddGroupItemSelection({}, index);
|
||||
}
|
||||
|
|
|
@ -57,8 +57,7 @@ public:
|
|||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
SelectedQuote selectedQuote(TextSelection selection) const override;
|
||||
TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const override;
|
||||
const SelectedQuote "e) const override;
|
||||
|
||||
std::vector<Ui::BubbleSelectionInterval> getBubbleSelectionIntervals(
|
||||
TextSelection selection) const override;
|
||||
|
|
|
@ -1098,10 +1098,8 @@ SelectedQuote Photo::selectedQuote(TextSelection selection) const {
|
|||
return Element::FindSelectedQuote(_caption, selection, _realParent);
|
||||
}
|
||||
|
||||
TextSelection Photo::selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const {
|
||||
return Element::FindSelectionFromQuote(_caption, item, quote);
|
||||
TextSelection Photo::selectionFromQuote(const SelectedQuote "e) const {
|
||||
return Element::FindSelectionFromQuote(_caption, quote);
|
||||
}
|
||||
|
||||
void Photo::hideSpoilers() {
|
||||
|
|
|
@ -59,8 +59,7 @@ public:
|
|||
TextForMimeData selectedText(TextSelection selection) const override;
|
||||
SelectedQuote selectedQuote(TextSelection selection) const override;
|
||||
TextSelection selectionFromQuote(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities "e) const override;
|
||||
const SelectedQuote "e) const override;
|
||||
|
||||
PhotoData *getPhoto() const override {
|
||||
return _data;
|
||||
|
|
|
@ -1411,7 +1411,11 @@ void MainWidget::showHistory(
|
|||
&& way != Way::Forward) {
|
||||
clearBotStartToken(_history->peer());
|
||||
}
|
||||
_history->showHistory(peerId, showAtMsgId, params.highlightPart);
|
||||
_history->showHistory(
|
||||
peerId,
|
||||
showAtMsgId,
|
||||
params.highlightPart,
|
||||
params.highlightPartOffsetHint);
|
||||
if (alreadyThatPeer && params.reapplyLocalDraft) {
|
||||
_history->applyDraft(HistoryWidget::FieldHistoryAction::NewEntry);
|
||||
}
|
||||
|
@ -1772,7 +1776,7 @@ void MainWidget::showNewSection(
|
|||
} else {
|
||||
_mainSection = std::move(newMainSection);
|
||||
_history->finishAnimating();
|
||||
_history->showHistory(0, 0, {});
|
||||
_history->showHistory(PeerId(), MsgId());
|
||||
|
||||
if (const auto entry = _mainSection->activeChat(); entry.key) {
|
||||
_controller->setActiveChatEntry(entry);
|
||||
|
|
|
@ -101,7 +101,7 @@ channel#1981ea7e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.
|
|||
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull;
|
||||
channelFull#723027bd flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories = ChatFull;
|
||||
channelFull#723027bd flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories = ChatFull;
|
||||
|
||||
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
|
||||
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
|
||||
|
@ -170,12 +170,12 @@ messageActionTopicCreate#d999256 flags:# title:string icon_color:int icon_emoji_
|
|||
messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags.1?long closed:flags.2?Bool hidden:flags.3?Bool = MessageAction;
|
||||
messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction;
|
||||
messageActionRequestedPeer#fe77345d button_id:int peer:Peer = MessageAction;
|
||||
messageActionSetChatWallPaper#bc44a927 wallpaper:WallPaper = MessageAction;
|
||||
messageActionSetSameChatWallPaper#c0787d6d wallpaper:WallPaper = MessageAction;
|
||||
messageActionSetChatWallPaper#5060a3f4 flags:# same:flags.0?true for_both:flags.1?true wallpaper:WallPaper = MessageAction;
|
||||
messageActionGiftCode#d2cfdb0e flags:# via_giveaway:flags.0?true unclaimed:flags.2?true boost_peer:flags.1?Peer months:int slug:string = MessageAction;
|
||||
messageActionGiveawayLaunch#332ba9ed = MessageAction;
|
||||
messageActionGiveawayResults#2a9fadc5 winners_count:int unclaimed_count:int = MessageAction;
|
||||
|
||||
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
|
||||
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
|
||||
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||
|
||||
photoEmpty#2331b22d id:long = Photo;
|
||||
|
@ -392,6 +392,9 @@ updateReadStories#f74e932b peer:Peer max_id:int = Update;
|
|||
updateStoryID#1bf335b9 id:int random_id:long = Update;
|
||||
updateStoriesStealthMode#2c084dc1 stealth_mode:StoriesStealthMode = Update;
|
||||
updateSentStoryReaction#7d627683 peer:Peer story_id:int reaction:Reaction = Update;
|
||||
updateBotChatBoost#904dd49c peer:Peer boost:Boost qts:int = Update;
|
||||
updateChannelViewForumAsMessages#7b68920 channel_id:long enabled:Bool = Update;
|
||||
updatePeerWallpaper#ae3f101d flags:# peer:Peer wallpaper:flags.0?WallPaper = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
|
@ -1232,7 +1235,7 @@ statsGraph#8ea464b6 flags:# json:DataJSON zoom_token:flags.0?string = StatsGraph
|
|||
|
||||
messageInteractionCounters#ad4fc9bd msg_id:int views:int forwards:int = MessageInteractionCounters;
|
||||
|
||||
stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph recent_message_interactions:Vector<MessageInteractionCounters> = stats.BroadcastStats;
|
||||
stats.broadcastStats#cb303962 period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph reactions_by_emotion_graph:StatsGraph story_interactions_graph:StatsGraph story_reactions_by_emotion_graph:StatsGraph recent_message_interactions:Vector<MessageInteractionCounters> = stats.BroadcastStats;
|
||||
|
||||
help.promoDataEmpty#98f6ac75 expires:int = help.PromoData;
|
||||
help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector<Chat> users:Vector<User> psa_type:flags.1?string psa_message:flags.2?string = help.PromoData;
|
||||
|
@ -1264,14 +1267,14 @@ 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 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;
|
||||
messageReplyHeader#afbc09db 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> quote_offset:flags.10?int = 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;
|
||||
|
||||
peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
|
||||
|
||||
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
|
||||
stats.messageStats#7fe91c14 views_graph:StatsGraph reactions_by_emotion_graph:StatsGraph = stats.MessageStats;
|
||||
|
||||
groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
|
||||
groupCall#d597650c flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true record_video_active:flags.11?true rtmp_stream:flags.12?true listeners_hidden:flags.13?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int = GroupCall;
|
||||
|
@ -1334,7 +1337,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
|
|||
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
|
||||
|
||||
sponsoredMessage#daafff6b flags:# recommended:flags.5?true show_peer_photo:flags.6?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string webpage:flags.9?SponsoredWebPage message:string entities:flags.1?Vector<MessageEntity> sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
|
||||
sponsoredMessage#ed5383f7 flags:# recommended:flags.5?true show_peer_photo:flags.6?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string webpage:flags.9?SponsoredWebPage app:flags.10?BotApp message:string entities:flags.1?Vector<MessageEntity> button_text:flags.11?string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
|
||||
|
||||
messages.sponsoredMessages#c9ee1d87 flags:# posts_between:flags.0?int messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
|
||||
messages.sponsoredMessagesEmpty#1839490f = messages.SponsoredMessages;
|
||||
|
@ -1544,7 +1547,7 @@ storyViews#8d595cd6 flags:# has_viewers:flags.1?true views_count:int forwards_co
|
|||
|
||||
storyItemDeleted#51e6ee4f id:int = StoryItem;
|
||||
storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem;
|
||||
storyItem#44c457ce flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true out:flags.16?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem;
|
||||
storyItem#af6365a1 flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true out:flags.16?true id:int date:int fwd_from:flags.17?StoryFwdHeader expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem;
|
||||
|
||||
stories.allStoriesNotModified#1158fe3e flags:# state:string stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
stories.allStories#6efc5e81 flags:# has_more:flags.0?true count:int state:string peer_stories:Vector<PeerStories> chats:Vector<Chat> users:Vector<User> stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
|
@ -1557,7 +1560,7 @@ stories.storyViewsList#46e9b9ec flags:# count:int reactions_count:int views:Vect
|
|||
|
||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||
|
||||
inputReplyToMessage#73ec805 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> = InputReplyTo;
|
||||
inputReplyToMessage#22c0f6d5 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int = InputReplyTo;
|
||||
inputReplyToStory#15b0f283 user_id:InputUser story_id:int = InputReplyTo;
|
||||
|
||||
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
||||
|
@ -1596,6 +1599,10 @@ premium.myBoosts#9ae228e2 my_boosts:Vector<MyBoost> chats:Vector<Chat> users:Vec
|
|||
|
||||
premium.boostsStatus#4959427a flags:# my_boost:flags.2?true level:int current_level_boosts:int boosts:int gift_boosts:flags.4?int next_level_boosts:flags.0?int premium_audience:flags.1?StatsPercentValue boost_url:string prepaid_giveaways:flags.3?Vector<PrepaidGiveaway> my_boost_slots:flags.2?Vector<int> = premium.BoostsStatus;
|
||||
|
||||
storyFwdHeader#b826e150 flags:# from:flags.0?Peer from_name:flags.1?string story_id:flags.2?int = StoryFwdHeader;
|
||||
|
||||
stats.storyStats#50cd067c views_graph:StatsGraph reactions_by_emotion_graph:StatsGraph = stats.StoryStats;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
|
@ -1936,7 +1943,8 @@ messages.searchCustomEmoji#2c11c0d7 emoticon:string hash:long = EmojiList;
|
|||
messages.togglePeerTranslations#e47cb579 flags:# disabled:flags.0?true peer:InputPeer = Bool;
|
||||
messages.getBotApp#34fdc5c3 app:InputBotApp hash:long = messages.BotApp;
|
||||
messages.requestAppWebView#8c5a3b3c flags:# write_allowed:flags.0?true peer:InputPeer app:InputBotApp start_param:flags.1?string theme_params:flags.2?DataJSON platform:string = AppWebViewResult;
|
||||
messages.setChatWallPaper#8ffacae1 flags:# peer:InputPeer wallpaper:flags.0?InputWallPaper settings:flags.2?WallPaperSettings id:flags.1?int = Updates;
|
||||
messages.setChatWallPaper#8ffacae1 flags:# for_both:flags.3?true revert:flags.4?true peer:InputPeer wallpaper:flags.0?InputWallPaper settings:flags.2?WallPaperSettings id:flags.1?int = Updates;
|
||||
messages.searchEmojiStickerSets#92b4494c flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
|
||||
|
@ -2038,6 +2046,8 @@ channels.reportAntiSpamFalsePositive#a850a693 channel:InputChannel msg_id:int =
|
|||
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
|
||||
channels.updateColor#621a201f flags:# channel:InputChannel color:int background_emoji_id:flags.0?long = Updates;
|
||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getChannelRecommendations#83b70d97 channel:InputChannel = messages.Chats;
|
||||
|
||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||
|
@ -2129,6 +2139,7 @@ stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph;
|
|||
stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel = stats.MegagroupStats;
|
||||
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
|
||||
stats.getStoryStats#374fef40 flags:# dark:flags.0?true peer:InputPeer id:int = stats.StoryStats;
|
||||
|
||||
chatlists.exportChatlistInvite#8472478e chatlist:InputChatlist title:string peers:Vector<InputPeer> = chatlists.ExportedChatlistInvite;
|
||||
chatlists.deleteExportedInvite#719c5c5e chatlist:InputChatlist slug:string = Bool;
|
||||
|
@ -2143,7 +2154,7 @@ chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector<P
|
|||
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = Updates;
|
||||
|
||||
stories.canSendStory#c7dfdfdd peer:InputPeer = Bool;
|
||||
stories.sendStory#bcb73644 flags:# pinned:flags.2?true noforwards:flags.4?true peer:InputPeer media:InputMedia media_areas:flags.5?Vector<MediaArea> caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> random_id:long period:flags.3?int = Updates;
|
||||
stories.sendStory#e4e6694b flags:# pinned:flags.2?true noforwards:flags.4?true peer:InputPeer media:InputMedia media_areas:flags.5?Vector<MediaArea> caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> random_id:long period:flags.3?int fwd_from_id:flags.6?InputPeer fwd_from_story:flags.6?int = Updates;
|
||||
stories.editStory#b583ba46 flags:# peer:InputPeer id:int media:flags.0?InputMedia media_areas:flags.3?Vector<MediaArea> caption:flags.1?string entities:flags.1?Vector<MessageEntity> privacy_rules:flags.2?Vector<InputPrivacyRule> = Updates;
|
||||
stories.deleteStories#ae59db5f peer:InputPeer id:Vector<int> = Vector<int>;
|
||||
stories.togglePinned#9a75a1ef peer:InputPeer id:Vector<int> pinned:Bool = Vector<int>;
|
||||
|
@ -2170,3 +2181,4 @@ premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:
|
|||
premium.getMyBoosts#be77b4a = premium.MyBoosts;
|
||||
premium.applyBoost#6b7da746 flags:# slots:flags.0?Vector<int> peer:InputPeer = premium.MyBoosts;
|
||||
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
|
||||
premium.getUserBoosts#39854d1f peer:InputPeer user_id:InputUser = premium.BoostsList;
|
||||
|
|
|
@ -1 +1 @@
|
|||
// LAYER 166
|
||||
// LAYER 167
|
||||
|
|
|
@ -806,7 +806,8 @@ void SessionNavigation::showRepliesForMessage(
|
|||
history,
|
||||
rootId,
|
||||
commentId,
|
||||
params.highlightPart);
|
||||
params.highlightPart,
|
||||
params.highlightPartOffsetHint);
|
||||
memento->setFromTopic(topic);
|
||||
showSection(std::move(memento), params);
|
||||
return;
|
||||
|
|
|
@ -168,6 +168,7 @@ struct SectionShow {
|
|||
}
|
||||
|
||||
TextWithEntities highlightPart;
|
||||
int highlightPartOffsetHint = 0;
|
||||
Way way = Way::Forward;
|
||||
anim::type animated = anim::type::normal;
|
||||
anim::activation activation = anim::activation::normal;
|
||||
|
|
Loading…
Add table
Reference in a new issue