parent
d2b630bbca
commit
0eeeb18ecd
18 changed files with 988 additions and 55 deletions
|
|
@ -2620,4 +2620,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"ktg_settings_forward_chat_on_click" = "Open chat on click";
|
"ktg_settings_forward_chat_on_click" = "Open chat on click";
|
||||||
"ktg_settings_forward_chat_on_click_description" = "You can hold Ctrl to select multiple chats regardless of this option.";
|
"ktg_settings_forward_chat_on_click_description" = "You can hold Ctrl to select multiple chats regardless of this option.";
|
||||||
|
|
||||||
|
"ktg_forward_menu_quoted" = "Quoted";
|
||||||
|
"ktg_forward_menu_unquoted" = "Unquoted with captions";
|
||||||
|
"ktg_forward_menu_uncaptioned" = "Unquoted without captions";
|
||||||
|
|
||||||
|
"ktg_forward_menu_default_albums" = "Preserve albums";
|
||||||
|
"ktg_forward_menu_group_all_media" = "Group all media";
|
||||||
|
"ktg_forward_menu_separate_messages" = "Separate messages";
|
||||||
|
|
||||||
|
"ktg_forward_subtitle_unquoted" = "unquoted";
|
||||||
|
"ktg_forward_subtitle_uncaptioned" = "uncaptioned";
|
||||||
|
|
||||||
|
"ktg_forward_subtitle_group_all_media" = "as albums";
|
||||||
|
"ktg_forward_subtitle_separate_messages" = "one by one";
|
||||||
|
|
||||||
// Keys finished
|
// Keys finished
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "You can hold Ctrl to select multiple chats regardless of this option.",
|
"ktg_settings_forward_chat_on_click_description": "You can hold Ctrl to select multiple chats regardless of this option.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "Quoted",
|
||||||
|
"ktg_forward_menu_unquoted": "Unquoted with captions",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Unquoted without captions",
|
||||||
|
"ktg_forward_menu_default_albums": "Preserve albums",
|
||||||
|
"ktg_forward_menu_group_all_media": "Group all media",
|
||||||
|
"ktg_forward_menu_separate_messages": "Separate messages",
|
||||||
|
"ktg_forward_subtitle_unquoted": "unquoted",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "uncaptioned",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "as albums",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "one by one",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "Puoi tenere premuto Ctrl per selezionare più chat insieme indipendentemente da questa opzione.",
|
"ktg_settings_forward_chat_on_click_description": "Puoi tenere premuto Ctrl per selezionare più chat insieme indipendentemente da questa opzione.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "Quoted",
|
||||||
|
"ktg_forward_menu_unquoted": "Unquoted with captions",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Unquoted without captions",
|
||||||
|
"ktg_forward_menu_default_albums": "Preserve albums",
|
||||||
|
"ktg_forward_menu_group_all_media": "Group all media",
|
||||||
|
"ktg_forward_menu_separate_messages": "Separate messages",
|
||||||
|
"ktg_forward_subtitle_unquoted": "unquoted",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "uncaptioned",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "as albums",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "one by one",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "You can hold Ctrl to select multiple chats regardless of this option.",
|
"ktg_settings_forward_chat_on_click_description": "You can hold Ctrl to select multiple chats regardless of this option.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "Quoted",
|
||||||
|
"ktg_forward_menu_unquoted": "Unquoted with captions",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Unquoted without captions",
|
||||||
|
"ktg_forward_menu_default_albums": "Preserve albums",
|
||||||
|
"ktg_forward_menu_group_all_media": "Group all media",
|
||||||
|
"ktg_forward_menu_separate_messages": "Separate messages",
|
||||||
|
"ktg_forward_subtitle_unquoted": "unquoted",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "uncaptioned",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "as albums",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "one by one",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "Você pode pressionar Ctrl para selecionar vários chats, independentemente desta opção.",
|
"ktg_settings_forward_chat_on_click_description": "Você pode pressionar Ctrl para selecionar vários chats, independentemente desta opção.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "Quoted",
|
||||||
|
"ktg_forward_menu_unquoted": "Unquoted with captions",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Unquoted without captions",
|
||||||
|
"ktg_forward_menu_default_albums": "Preserve albums",
|
||||||
|
"ktg_forward_menu_group_all_media": "Group all media",
|
||||||
|
"ktg_forward_menu_separate_messages": "Separate messages",
|
||||||
|
"ktg_forward_subtitle_unquoted": "unquoted",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "uncaptioned",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "as albums",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "one by one",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "Удерживайте Ctrl для выбора нескольких чатов вне зависимости от этой настройки.",
|
"ktg_settings_forward_chat_on_click_description": "Удерживайте Ctrl для выбора нескольких чатов вне зависимости от этой настройки.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "С автором",
|
||||||
|
"ktg_forward_menu_unquoted": "Без автора с подписями",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Без автора и подписей",
|
||||||
|
"ktg_forward_menu_default_albums": "Оригинальные альбомы",
|
||||||
|
"ktg_forward_menu_group_all_media": "Объединить все медиа",
|
||||||
|
"ktg_forward_menu_separate_messages": "Отдельные сообщения",
|
||||||
|
"ktg_forward_subtitle_unquoted": "без автора",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "без подписей",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "альбомами",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "по одному",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "Ctrl tuşunu uzun tutarak birden fazla sohbet seçmek için, bu seçenek aktifligine rağmen.",
|
"ktg_settings_forward_chat_on_click_description": "Ctrl tuşunu uzun tutarak birden fazla sohbet seçmek için, bu seçenek aktifligine rağmen.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "Quoted",
|
||||||
|
"ktg_forward_menu_unquoted": "Unquoted with captions",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Unquoted without captions",
|
||||||
|
"ktg_forward_menu_default_albums": "Preserve albums",
|
||||||
|
"ktg_forward_menu_group_all_media": "Group all media",
|
||||||
|
"ktg_forward_menu_separate_messages": "Separate messages",
|
||||||
|
"ktg_forward_subtitle_unquoted": "unquoted",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "uncaptioned",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "as albums",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "one by one",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,16 @@
|
||||||
"ktg_settings_forward_chat_on_click_description": "Ви можете вибрати декілька чатів утримуючи Ctrl незалежно від цього параметра.",
|
"ktg_settings_forward_chat_on_click_description": "Ви можете вибрати декілька чатів утримуючи Ctrl незалежно від цього параметра.",
|
||||||
|
|
||||||
// New strings
|
// New strings
|
||||||
|
"ktg_forward_menu_quoted": "Quoted",
|
||||||
|
"ktg_forward_menu_unquoted": "Unquoted with captions",
|
||||||
|
"ktg_forward_menu_uncaptioned": "Unquoted without captions",
|
||||||
|
"ktg_forward_menu_default_albums": "Preserve albums",
|
||||||
|
"ktg_forward_menu_group_all_media": "Group all media",
|
||||||
|
"ktg_forward_menu_separate_messages": "Separate messages",
|
||||||
|
"ktg_forward_subtitle_unquoted": "unquoted",
|
||||||
|
"ktg_forward_subtitle_uncaptioned": "uncaptioned",
|
||||||
|
"ktg_forward_subtitle_group_all_media": "as albums",
|
||||||
|
"ktg_forward_subtitle_separate_messages": "one by one",
|
||||||
|
|
||||||
// This string should always be last for better work with Git.
|
// This string should always be last for better work with Git.
|
||||||
"dummy_last_string": ""
|
"dummy_last_string": ""
|
||||||
|
|
|
||||||
|
|
@ -3890,7 +3890,7 @@ void ApiWrap::forwardMessages(
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto count = int(items.size());
|
const auto count = int(items.size());
|
||||||
const auto genClientSideMessage = action.generateLocal && (count < 2);
|
const auto genClientSideMessage = action.generateLocal && (count < 2) && cForwardQuoted();
|
||||||
const auto history = action.history;
|
const auto history = action.history;
|
||||||
const auto peer = history->peer;
|
const auto peer = history->peer;
|
||||||
|
|
||||||
|
|
@ -3916,18 +3916,47 @@ void ApiWrap::forwardMessages(
|
||||||
|
|
||||||
auto forwardFrom = items.front()->history()->peer;
|
auto forwardFrom = items.front()->history()->peer;
|
||||||
auto currentGroupId = items.front()->groupId();
|
auto currentGroupId = items.front()->groupId();
|
||||||
|
auto isLastGrouped = false;
|
||||||
auto ids = QVector<MTPint>();
|
auto ids = QVector<MTPint>();
|
||||||
auto randomIds = QVector<MTPlong>();
|
auto randomIds = QVector<MTPlong>();
|
||||||
auto localIds = std::shared_ptr<base::flat_map<uint64, FullMsgId>>();
|
auto localIds = std::shared_ptr<base::flat_map<uint64, FullMsgId>>();
|
||||||
|
auto fromIter = items.begin();
|
||||||
|
auto toIter = items.begin();
|
||||||
|
|
||||||
const auto sendAccumulated = [&] {
|
const auto needNextGroup = [&] (not_null<HistoryItem *> item) {
|
||||||
|
if (cForwardAlbumsAsIs()) {
|
||||||
|
const auto newFrom = item->history()->peer;
|
||||||
|
const auto newGroupId = item->groupId();
|
||||||
|
return forwardFrom != newFrom
|
||||||
|
|| currentGroupId != newGroupId;
|
||||||
|
} else if (cForwardGrouped()) {
|
||||||
|
if (item->media() && item->media()->canBeGrouped()) {
|
||||||
|
return !isLastGrouped;
|
||||||
|
} else {
|
||||||
|
return isLastGrouped;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto isGrouped = [&] {
|
||||||
|
return (cForwardAlbumsAsIs()
|
||||||
|
&& currentGroupId != MessageGroupId())
|
||||||
|
|| (!cForwardAlbumsAsIs()
|
||||||
|
&& cForwardGrouped()
|
||||||
|
&& items.front()->media()
|
||||||
|
&& items.front()->media()->canBeGrouped());
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardQuoted = [&] {
|
||||||
if (shared) {
|
if (shared) {
|
||||||
++shared->requestsLeft;
|
++shared->requestsLeft;
|
||||||
}
|
}
|
||||||
const auto finalFlags = sendFlags
|
const auto finalFlags = sendFlags
|
||||||
| (currentGroupId == MessageGroupId()
|
| (isGrouped()
|
||||||
? MTPmessages_ForwardMessages::Flag(0)
|
? MTPmessages_ForwardMessages::Flag::f_grouped
|
||||||
: MTPmessages_ForwardMessages::Flag::f_grouped);
|
: MTPmessages_ForwardMessages::Flag(0));
|
||||||
const auto requestType = Data::Histories::RequestType::Send;
|
const auto requestType = Data::Histories::RequestType::Send;
|
||||||
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
history->sendRequestId = request(MTPmessages_ForwardMessages(
|
history->sendRequestId = request(MTPmessages_ForwardMessages(
|
||||||
|
|
@ -3957,6 +3986,308 @@ void ApiWrap::forwardMessages(
|
||||||
).send();
|
).send();
|
||||||
return history->sendRequestId;
|
return history->sendRequestId;
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardQuotedSingle = [&] (not_null<HistoryItem *> item) {
|
||||||
|
if (shared) {
|
||||||
|
++shared->requestsLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto currentIds = QVector<MTPint>();
|
||||||
|
currentIds.push_back(MTP_int(item->id));
|
||||||
|
|
||||||
|
auto currentRandomId = randomIds.takeFirst();
|
||||||
|
auto currentRandomIds = QVector<MTPlong>();
|
||||||
|
currentRandomIds.push_back(currentRandomId);
|
||||||
|
|
||||||
|
const auto requestType = Data::Histories::RequestType::Send;
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
history->sendRequestId = request(MTPmessages_ForwardMessages(
|
||||||
|
MTP_flags(sendFlags),
|
||||||
|
forwardFrom->input,
|
||||||
|
MTP_vector<MTPint>(currentIds),
|
||||||
|
MTP_vector<MTPlong>(currentRandomIds),
|
||||||
|
peer->input,
|
||||||
|
MTP_int(action.options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
applyUpdates(result);
|
||||||
|
if (shared && !--shared->requestsLeft) {
|
||||||
|
shared->callback();
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).fail([=, ids = localIds](const RPCError &error) {
|
||||||
|
auto found = false;
|
||||||
|
for (const auto &[randomId, itemId] : *ids) {
|
||||||
|
if (currentRandomId == MTP_long(randomId)) {
|
||||||
|
sendMessageFail(error, peer, randomId, itemId);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
sendMessageFail(error, peer);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).afterRequest(
|
||||||
|
history->sendRequestId
|
||||||
|
).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardAlbumUnquoted = [&] {
|
||||||
|
if (shared) {
|
||||||
|
++shared->requestsLeft;
|
||||||
|
}
|
||||||
|
auto medias = QVector<MTPInputSingleMedia>();
|
||||||
|
medias.reserve(ids.size());
|
||||||
|
|
||||||
|
for (auto i = fromIter, e = toIter; i != e; i++) {
|
||||||
|
const auto item = *i;
|
||||||
|
const auto media = item->media();
|
||||||
|
auto inputMedia = media->photo()
|
||||||
|
? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint())
|
||||||
|
: MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint());
|
||||||
|
auto caption = cForwardCaptioned()
|
||||||
|
? item->originalText()
|
||||||
|
: TextWithEntities();
|
||||||
|
auto sentEntities = Api::EntitiesToMTP(
|
||||||
|
_session,
|
||||||
|
caption.entities,
|
||||||
|
Api::ConvertOption::SkipLocal);
|
||||||
|
|
||||||
|
const auto flags = !sentEntities.v.isEmpty()
|
||||||
|
? MTPDinputSingleMedia::Flag::f_entities
|
||||||
|
: MTPDinputSingleMedia::Flag(0);
|
||||||
|
|
||||||
|
auto randomId = randomIds.takeFirst();
|
||||||
|
|
||||||
|
medias.push_back(MTP_inputSingleMedia(
|
||||||
|
MTP_flags(flags),
|
||||||
|
inputMedia,
|
||||||
|
randomId,
|
||||||
|
MTP_string(caption.text),
|
||||||
|
sentEntities));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto finalFlags = MTPmessages_SendMultiMedia::Flags(0)
|
||||||
|
| (action.options.silent
|
||||||
|
? MTPmessages_SendMultiMedia::Flag::f_silent
|
||||||
|
: MTPmessages_SendMultiMedia::Flag(0))
|
||||||
|
| (action.options.scheduled
|
||||||
|
? MTPmessages_SendMultiMedia::Flag::f_schedule_date
|
||||||
|
: MTPmessages_SendMultiMedia::Flag(0));
|
||||||
|
|
||||||
|
const auto requestType = Data::Histories::RequestType::Send;
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
history->sendRequestId = request(MTPmessages_SendMultiMedia(
|
||||||
|
MTP_flags(finalFlags),
|
||||||
|
peer->input,
|
||||||
|
MTPint(),
|
||||||
|
MTP_vector<MTPInputSingleMedia>(medias),
|
||||||
|
MTP_int(action.options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
applyUpdates(result);
|
||||||
|
if (shared && !--shared->requestsLeft) {
|
||||||
|
shared->callback();
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).fail([=, ids = localIds](const RPCError &error) {
|
||||||
|
if (ids) {
|
||||||
|
for (const auto &[randomId, itemId] : *ids) {
|
||||||
|
sendMessageFail(error, peer, randomId, itemId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendMessageFail(error, peer);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).afterRequest(
|
||||||
|
history->sendRequestId
|
||||||
|
).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardMediaUnquoted = [&] (not_null<HistoryItem *> item) {
|
||||||
|
if (shared) {
|
||||||
|
++shared->requestsLeft;
|
||||||
|
}
|
||||||
|
const auto media = item->media();
|
||||||
|
|
||||||
|
auto newSendFlags = MTPmessages_SendMedia::Flags(0)
|
||||||
|
| (action.options.silent
|
||||||
|
? MTPmessages_SendMedia::Flag::f_silent
|
||||||
|
: MTPmessages_SendMedia::Flag(0))
|
||||||
|
| (action.options.scheduled
|
||||||
|
? MTPmessages_SendMedia::Flag::f_schedule_date
|
||||||
|
: MTPmessages_SendMedia::Flag(0));
|
||||||
|
|
||||||
|
auto caption = (cForwardCaptioned()
|
||||||
|
&& !media->geoPoint()
|
||||||
|
&& !media->sharedContact())
|
||||||
|
? item->originalText()
|
||||||
|
: TextWithEntities();
|
||||||
|
|
||||||
|
auto sentEntities = Api::EntitiesToMTP(
|
||||||
|
_session,
|
||||||
|
caption.entities,
|
||||||
|
Api::ConvertOption::SkipLocal);
|
||||||
|
if (!sentEntities.v.isEmpty()) {
|
||||||
|
newSendFlags |= MTPmessages_SendMedia::Flag::f_entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto inputMedia = media->poll()
|
||||||
|
? PollDataToInputMedia(media->poll())
|
||||||
|
: media->geoPoint()
|
||||||
|
? MTP_inputMediaGeoPoint(
|
||||||
|
MTP_inputGeoPoint(
|
||||||
|
MTP_double(media->geoPoint()->lat()),
|
||||||
|
MTP_double(media->geoPoint()->lon())))
|
||||||
|
: media->sharedContact()
|
||||||
|
? MTP_inputMediaContact(
|
||||||
|
MTP_string(media->sharedContact()->phoneNumber),
|
||||||
|
MTP_string(media->sharedContact()->firstName),
|
||||||
|
MTP_string(media->sharedContact()->lastName),
|
||||||
|
MTPstring())
|
||||||
|
: media->photo()
|
||||||
|
? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint())
|
||||||
|
: MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint());
|
||||||
|
|
||||||
|
const auto requestType = Data::Histories::RequestType::Send;
|
||||||
|
const auto currentRandomId = randomIds.takeFirst();
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
history->sendRequestId = request(MTPmessages_SendMedia(
|
||||||
|
MTP_flags(newSendFlags),
|
||||||
|
peer->input,
|
||||||
|
MTPint(),
|
||||||
|
inputMedia,
|
||||||
|
MTP_string(caption.text),
|
||||||
|
currentRandomId,
|
||||||
|
MTPReplyMarkup(),
|
||||||
|
sentEntities,
|
||||||
|
MTP_int(action.options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
applyUpdates(result);
|
||||||
|
if (shared && !--shared->requestsLeft) {
|
||||||
|
shared->callback();
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).fail([=, ids = localIds](const RPCError &error) {
|
||||||
|
if (ids) {
|
||||||
|
auto found = false;
|
||||||
|
for (const auto &[randomId, itemId] : *ids) {
|
||||||
|
if (currentRandomId == MTP_long(randomId)) {
|
||||||
|
sendMessageFail(error, peer, randomId, itemId);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
sendMessageFail(error, peer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendMessageFail(error, peer);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).afterRequest(
|
||||||
|
history->sendRequestId
|
||||||
|
).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardMessageUnquoted = [&] (not_null<HistoryItem *> item) {
|
||||||
|
if (shared) {
|
||||||
|
++shared->requestsLeft;
|
||||||
|
}
|
||||||
|
const auto media = item->media();
|
||||||
|
|
||||||
|
auto newSendFlags = MTPmessages_SendMessage::Flag(0)
|
||||||
|
| (!media || !media->webpage()
|
||||||
|
? MTPmessages_SendMessage::Flag::f_no_webpage
|
||||||
|
: MTPmessages_SendMessage::Flag(0))
|
||||||
|
| (action.options.silent
|
||||||
|
? MTPmessages_SendMessage::Flag::f_silent
|
||||||
|
: MTPmessages_SendMessage::Flag(0))
|
||||||
|
| (action.options.scheduled
|
||||||
|
? MTPmessages_SendMessage::Flag::f_schedule_date
|
||||||
|
: MTPmessages_SendMessage::Flag(0));
|
||||||
|
|
||||||
|
auto sentEntities = Api::EntitiesToMTP(
|
||||||
|
_session,
|
||||||
|
item->originalText().entities,
|
||||||
|
Api::ConvertOption::SkipLocal);
|
||||||
|
if (!sentEntities.v.isEmpty()) {
|
||||||
|
newSendFlags |= MTPmessages_SendMessage::Flag::f_entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto requestType = Data::Histories::RequestType::Send;
|
||||||
|
const auto currentRandomId = randomIds.takeFirst();
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
history->sendRequestId = request(MTPmessages_SendMessage(
|
||||||
|
MTP_flags(newSendFlags),
|
||||||
|
peer->input,
|
||||||
|
MTPint(),
|
||||||
|
MTP_string(item->originalText().text),
|
||||||
|
currentRandomId,
|
||||||
|
MTPReplyMarkup(),
|
||||||
|
sentEntities,
|
||||||
|
MTP_int(action.options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
applyUpdates(result);
|
||||||
|
if (shared && !--shared->requestsLeft) {
|
||||||
|
shared->callback();
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).fail([=, ids = localIds](const RPCError &error) {
|
||||||
|
if (ids) {
|
||||||
|
auto found = false;
|
||||||
|
for (const auto &[randomId, itemId] : *ids) {
|
||||||
|
if (currentRandomId == MTP_long(randomId)) {
|
||||||
|
sendMessageFail(error, peer, randomId, itemId);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
sendMessageFail(error, peer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendMessageFail(error, peer);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).afterRequest(
|
||||||
|
history->sendRequestId
|
||||||
|
).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto sendAccumulated = [&] {
|
||||||
|
if (cForwardQuoted()) {
|
||||||
|
forwardQuoted();
|
||||||
|
} else if (isGrouped()) {
|
||||||
|
forwardAlbumUnquoted();
|
||||||
|
} else {
|
||||||
|
for (auto i = fromIter, e = toIter; i != e; i++) {
|
||||||
|
const auto item = *i;
|
||||||
|
const auto media = item->media();
|
||||||
|
|
||||||
|
if (media && !media->webpage()) {
|
||||||
|
if (media->poll()
|
||||||
|
|| media->geoPoint()
|
||||||
|
|| media->sharedContact()
|
||||||
|
|| media->photo()
|
||||||
|
|| media->document()) {
|
||||||
|
forwardMediaUnquoted(item);
|
||||||
|
} else {
|
||||||
|
forwardQuotedSingle(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
forwardMessageUnquoted(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ids.resize(0);
|
ids.resize(0);
|
||||||
randomIds.resize(0);
|
randomIds.resize(0);
|
||||||
|
|
@ -3965,7 +4296,8 @@ void ApiWrap::forwardMessages(
|
||||||
|
|
||||||
ids.reserve(count);
|
ids.reserve(count);
|
||||||
randomIds.reserve(count);
|
randomIds.reserve(count);
|
||||||
for (const auto item : items) {
|
for (auto i = items.begin(), e = items.end(); i != e; /* ++i is in the end */) {
|
||||||
|
const auto item = *i;
|
||||||
const auto randomId = rand_value<uint64>();
|
const auto randomId = rand_value<uint64>();
|
||||||
if (genClientSideMessage) {
|
if (genClientSideMessage) {
|
||||||
if (const auto message = item->toHistoryMessage()) {
|
if (const auto message = item->toHistoryMessage()) {
|
||||||
|
|
@ -3994,16 +4326,18 @@ void ApiWrap::forwardMessages(
|
||||||
localIds->emplace(randomId, newId);
|
localIds->emplace(randomId, newId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto newFrom = item->history()->peer;
|
if (needNextGroup(item)) {
|
||||||
const auto newGroupId = item->groupId();
|
|
||||||
if (forwardFrom != newFrom
|
|
||||||
|| currentGroupId != newGroupId) {
|
|
||||||
sendAccumulated();
|
sendAccumulated();
|
||||||
forwardFrom = newFrom;
|
forwardFrom = item->history()->peer;
|
||||||
currentGroupId = newGroupId;
|
currentGroupId = item->groupId();
|
||||||
|
fromIter = i;
|
||||||
}
|
}
|
||||||
ids.push_back(MTP_int(item->id));
|
ids.push_back(MTP_int(item->id));
|
||||||
randomIds.push_back(MTP_long(randomId));
|
randomIds.push_back(MTP_long(randomId));
|
||||||
|
if (item->media() && item->media()->canBeGrouped()) {
|
||||||
|
isLastGrouped = true;
|
||||||
|
}
|
||||||
|
toIter = ++i;
|
||||||
}
|
}
|
||||||
sendAccumulated();
|
sendAccumulated();
|
||||||
_session->data().sendHistoryChangeNotifications();
|
_session->data().sendHistoryChangeNotifications();
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "ui/widgets/dropdown_menu.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "ui/text_options.h"
|
#include "ui/text_options.h"
|
||||||
#include "chat_helpers/message_field.h"
|
#include "chat_helpers/message_field.h"
|
||||||
|
|
@ -41,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
class ShareBox::Inner final : public Ui::RpWidget, private base::Subscriber {
|
class ShareBox::Inner final : public Ui::RpWidget, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
|
|
@ -166,13 +168,15 @@ ShareBox::ShareBox(
|
||||||
CopyCallback &©Callback,
|
CopyCallback &©Callback,
|
||||||
SubmitCallback &&submitCallback,
|
SubmitCallback &&submitCallback,
|
||||||
FilterCallback &&filterCallback,
|
FilterCallback &&filterCallback,
|
||||||
GoToChatCallback &&goToChatCallback)
|
GoToChatCallback &&goToChatCallback,
|
||||||
|
bool hasMedia)
|
||||||
: _navigation(navigation)
|
: _navigation(navigation)
|
||||||
, _api(&_navigation->session().mtp())
|
, _api(&_navigation->session().mtp())
|
||||||
, _copyCallback(std::move(copyCallback))
|
, _copyCallback(std::move(copyCallback))
|
||||||
, _submitCallback(std::move(submitCallback))
|
, _submitCallback(std::move(submitCallback))
|
||||||
, _filterCallback(std::move(filterCallback))
|
, _filterCallback(std::move(filterCallback))
|
||||||
, _goToChatCallback(goToChatCallback ? std::move(goToChatCallback) : nullptr)
|
, _goToChatCallback(goToChatCallback ? std::move(goToChatCallback) : nullptr)
|
||||||
|
, _hasMediaMessages(hasMedia)
|
||||||
, _select(
|
, _select(
|
||||||
this,
|
this,
|
||||||
st::contactsMultiSelect,
|
st::contactsMultiSelect,
|
||||||
|
|
@ -226,6 +230,7 @@ void ShareBox::prepare() {
|
||||||
Ui::SendPendingMoveResizeEvents(_select);
|
Ui::SendPendingMoveResizeEvents(_select);
|
||||||
|
|
||||||
setTitle(tr::lng_selected_forward());
|
setTitle(tr::lng_selected_forward());
|
||||||
|
updateAdditionalTitle();
|
||||||
|
|
||||||
_inner = setInnerWidget(
|
_inner = setInnerWidget(
|
||||||
object_ptr<Inner>(
|
object_ptr<Inner>(
|
||||||
|
|
@ -447,6 +452,9 @@ SendMenu::Type ShareBox::sendMenuType() const {
|
||||||
|
|
||||||
void ShareBox::createButtons() {
|
void ShareBox::createButtons() {
|
||||||
clearButtons();
|
clearButtons();
|
||||||
|
const auto moreButton = addTopButton(st::infoTopBarMenu);
|
||||||
|
moreButton->setClickedCallback([=] { showMenu(moreButton.data()); });
|
||||||
|
|
||||||
if (_hasSelected) {
|
if (_hasSelected) {
|
||||||
if (_goToChatCallback && _inner->selected().size() == 1) {
|
if (_goToChatCallback && _inner->selected().size() == 1) {
|
||||||
const auto singleChat = _inner->selected().at(0);
|
const auto singleChat = _inner->selected().at(0);
|
||||||
|
|
@ -467,6 +475,109 @@ void ShareBox::createButtons() {
|
||||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShareBox::showMenu(not_null<Ui::IconButton*> button) {
|
||||||
|
if (_menu) {
|
||||||
|
_menu->hideAnimated(Ui::InnerDropdown::HideOption::IgnoreShow);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_menu = base::make_unique_q<Ui::DropdownMenu>(window());
|
||||||
|
const auto weak = _menu.get();
|
||||||
|
_menu->setHiddenCallback([=] {
|
||||||
|
weak->deleteLater();
|
||||||
|
if (_menu == weak) {
|
||||||
|
button->setForceRippled(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_menu->setShowStartCallback([=] {
|
||||||
|
if (_menu == weak) {
|
||||||
|
button->setForceRippled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_menu->setHideStartCallback([=] {
|
||||||
|
if (_menu == weak) {
|
||||||
|
button->setForceRippled(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
button->installEventFilter(_menu);
|
||||||
|
|
||||||
|
if (!cForwardQuoted()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_quoted(tr::now), [=] {
|
||||||
|
cSetForwardQuoted(true);
|
||||||
|
updateAdditionalTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardQuoted() || !cForwardCaptioned()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_unquoted(tr::now), [=] {
|
||||||
|
cSetForwardQuoted(false);
|
||||||
|
cSetForwardCaptioned(true);
|
||||||
|
updateAdditionalTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardQuoted() || cForwardCaptioned()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_uncaptioned(tr::now), [=] {
|
||||||
|
cSetForwardQuoted(false);
|
||||||
|
cSetForwardCaptioned(false);
|
||||||
|
updateAdditionalTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (_hasMediaMessages) {
|
||||||
|
_menu->addSeparator();
|
||||||
|
if (!cForwardAlbumsAsIs()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_default_albums(tr::now), [=] {
|
||||||
|
cSetForwardAlbumsAsIs(true);
|
||||||
|
updateAdditionalTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardAlbumsAsIs() || !cForwardGrouped()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_group_all_media(tr::now), [=] {
|
||||||
|
cSetForwardAlbumsAsIs(false);
|
||||||
|
cSetForwardGrouped(true);
|
||||||
|
updateAdditionalTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardAlbumsAsIs() || cForwardGrouped()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_separate_messages(tr::now), [=] {
|
||||||
|
cSetForwardAlbumsAsIs(false);
|
||||||
|
cSetForwardGrouped(false);
|
||||||
|
updateAdditionalTitle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto parentTopLeft = window()->mapToGlobal({ 0, 0 });
|
||||||
|
const auto buttonTopLeft = button->mapToGlobal({ 0, 0 });
|
||||||
|
const auto parentRect = QRect(parentTopLeft, window()->size());
|
||||||
|
const auto buttonRect = QRect(buttonTopLeft, button->size());
|
||||||
|
_menu->move(
|
||||||
|
buttonRect.x() + buttonRect.width() - _menu->width() - parentRect.x(),
|
||||||
|
buttonRect.y() + buttonRect.height() - parentRect.y() - style::ConvertScale(18));
|
||||||
|
_menu->showAnimated(Ui::PanelAnimation::Origin::TopRight);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShareBox::updateAdditionalTitle() {
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
if (!cForwardQuoted()) {
|
||||||
|
result += (cForwardCaptioned()
|
||||||
|
? tr::ktg_forward_subtitle_unquoted(tr::now)
|
||||||
|
: tr::ktg_forward_subtitle_uncaptioned(tr::now));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hasMediaMessages && !cForwardAlbumsAsIs()) {
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
result += ", ";
|
||||||
|
}
|
||||||
|
result += (cForwardGrouped()
|
||||||
|
? tr::ktg_forward_subtitle_group_all_media(tr::now)
|
||||||
|
: tr::ktg_forward_subtitle_separate_messages(tr::now));
|
||||||
|
}
|
||||||
|
|
||||||
|
setAdditionalTitle(rpl::single(result));
|
||||||
|
}
|
||||||
|
|
||||||
void ShareBox::applyFilterUpdate(const QString &query) {
|
void ShareBox::applyFilterUpdate(const QString &query) {
|
||||||
onScrollToY(0);
|
onScrollToY(0);
|
||||||
_inner->updateFilter(query);
|
_inner->updateFilter(query);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ class IndexedList;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MultiSelect;
|
class MultiSelect;
|
||||||
class InputField;
|
class InputField;
|
||||||
|
class DropdownMenu;
|
||||||
struct ScrollToRequest;
|
struct ScrollToRequest;
|
||||||
template <typename Widget>
|
template <typename Widget>
|
||||||
class SlideWrap;
|
class SlideWrap;
|
||||||
|
|
@ -67,7 +68,8 @@ public:
|
||||||
CopyCallback &©Callback,
|
CopyCallback &©Callback,
|
||||||
SubmitCallback &&submitCallback,
|
SubmitCallback &&submitCallback,
|
||||||
FilterCallback &&filterCallback,
|
FilterCallback &&filterCallback,
|
||||||
GoToChatCallback &&goToChatCallback = nullptr);
|
GoToChatCallback &&goToChatCallback = nullptr,
|
||||||
|
bool hasMedia = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
|
@ -94,6 +96,8 @@ private:
|
||||||
void applyFilterUpdate(const QString &query);
|
void applyFilterUpdate(const QString &query);
|
||||||
void selectedChanged();
|
void selectedChanged();
|
||||||
void createButtons();
|
void createButtons();
|
||||||
|
bool showMenu(not_null<Ui::IconButton*> button);
|
||||||
|
void updateAdditionalTitle();
|
||||||
int getTopScrollSkip() const;
|
int getTopScrollSkip() const;
|
||||||
int getBottomScrollSkip() const;
|
int getBottomScrollSkip() const;
|
||||||
int contentHeight() const;
|
int contentHeight() const;
|
||||||
|
|
@ -115,6 +119,8 @@ private:
|
||||||
FilterCallback _filterCallback;
|
FilterCallback _filterCallback;
|
||||||
GoToChatCallback _goToChatCallback;
|
GoToChatCallback _goToChatCallback;
|
||||||
|
|
||||||
|
bool _hasMediaMessages = false;
|
||||||
|
|
||||||
object_ptr<Ui::MultiSelect> _select;
|
object_ptr<Ui::MultiSelect> _select;
|
||||||
object_ptr<Ui::SlideWrap<Ui::InputField>> _comment;
|
object_ptr<Ui::SlideWrap<Ui::InputField>> _comment;
|
||||||
|
|
||||||
|
|
@ -136,4 +142,6 @@ private:
|
||||||
|
|
||||||
Ui::Animations::Simple _scrollAnimation;
|
Ui::Animations::Simple _scrollAnimation;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::DropdownMenu> _menu;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,10 @@ PollData *Media::poll() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LocationPoint *Media::geoPoint() const {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool Media::uploading() const {
|
bool Media::uploading() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -808,6 +812,10 @@ Data::CloudImage *MediaLocation::location() const {
|
||||||
return _location;
|
return _location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LocationPoint *MediaLocation::geoPoint() const {
|
||||||
|
return &_point;
|
||||||
|
}
|
||||||
|
|
||||||
QString MediaLocation::chatListText() const {
|
QString MediaLocation::chatListText() const {
|
||||||
return WithCaptionDialogsText(tr::lng_maps_point(tr::now), _title);
|
return WithCaptionDialogsText(tr::lng_maps_point(tr::now), _title);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ public:
|
||||||
virtual const Invoice *invoice() const;
|
virtual const Invoice *invoice() const;
|
||||||
virtual Data::CloudImage *location() const;
|
virtual Data::CloudImage *location() const;
|
||||||
virtual PollData *poll() const;
|
virtual PollData *poll() const;
|
||||||
|
virtual const LocationPoint *geoPoint() const;
|
||||||
|
|
||||||
virtual bool uploading() const;
|
virtual bool uploading() const;
|
||||||
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
|
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
|
||||||
|
|
@ -245,6 +246,7 @@ public:
|
||||||
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
|
||||||
|
|
||||||
Data::CloudImage *location() const override;
|
Data::CloudImage *location() const override;
|
||||||
|
const LocationPoint *geoPoint() const override;
|
||||||
QString chatListText() const override;
|
QString chatListText() const override;
|
||||||
QString notificationText() const override;
|
QString notificationText() const override;
|
||||||
QString pinnedTextSubstring() const override;
|
QString pinnedTextSubstring() const override;
|
||||||
|
|
|
||||||
|
|
@ -5172,6 +5172,9 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
updateField();
|
updateField();
|
||||||
} else if (_inReplyEditForward) {
|
} else if (_inReplyEditForward) {
|
||||||
if (readyToForward()) {
|
if (readyToForward()) {
|
||||||
|
if (e->button() != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto items = std::move(_toForward);
|
const auto items = std::move(_toForward);
|
||||||
session().data().cancelForwarding(_history);
|
session().data().cancelForwarding(_history);
|
||||||
auto list = ranges::view::all(
|
auto list = ranges::view::all(
|
||||||
|
|
@ -5189,6 +5192,92 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
|
if (_menu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto hasSecondLayer = (_editMsgId
|
||||||
|
|| _replyToId
|
||||||
|
|| readyToForward()
|
||||||
|
|| _kbReplyTo);
|
||||||
|
_replyForwardPressed = hasSecondLayer && QRect(
|
||||||
|
0,
|
||||||
|
_field->y() - st::historySendPadding - st::historyReplyHeight,
|
||||||
|
st::historyReplySkip,
|
||||||
|
st::historyReplyHeight).contains(e->pos());
|
||||||
|
if (_replyForwardPressed && !_fieldBarCancel->isHidden()) {
|
||||||
|
return;
|
||||||
|
} else if (_inReplyEditForward) {
|
||||||
|
if (readyToForward()) {
|
||||||
|
const auto count = int(_toForward.size());
|
||||||
|
auto hasMediaToGroup = false;
|
||||||
|
|
||||||
|
if (count > 1) {
|
||||||
|
auto grouppableMediaCount = 0;
|
||||||
|
for (const auto item : _toForward) {
|
||||||
|
if (item->media() && item->media()->canBeGrouped()) {
|
||||||
|
grouppableMediaCount++;
|
||||||
|
} else {
|
||||||
|
grouppableMediaCount = 0;
|
||||||
|
}
|
||||||
|
if (grouppableMediaCount > 1) {
|
||||||
|
hasMediaToGroup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_menu = base::make_unique_q<Ui::PopupMenu>(this);
|
||||||
|
|
||||||
|
if (!cForwardQuoted()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_quoted(tr::now), [=] {
|
||||||
|
cSetForwardQuoted(true);
|
||||||
|
updateForwardingTexts();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardQuoted() || !cForwardCaptioned()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_unquoted(tr::now), [=] {
|
||||||
|
cSetForwardQuoted(false);
|
||||||
|
cSetForwardCaptioned(true);
|
||||||
|
updateForwardingTexts();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardQuoted() || cForwardCaptioned()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_uncaptioned(tr::now), [=] {
|
||||||
|
cSetForwardQuoted(false);
|
||||||
|
cSetForwardCaptioned(false);
|
||||||
|
updateForwardingTexts();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (hasMediaToGroup && count > 1) {
|
||||||
|
_menu->addSeparator();
|
||||||
|
if (!cForwardAlbumsAsIs()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_default_albums(tr::now), [=] {
|
||||||
|
cSetForwardAlbumsAsIs(true);
|
||||||
|
updateForwardingTexts();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardAlbumsAsIs() || !cForwardGrouped()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_group_all_media(tr::now), [=] {
|
||||||
|
cSetForwardAlbumsAsIs(false);
|
||||||
|
cSetForwardGrouped(true);
|
||||||
|
updateForwardingTexts();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cForwardAlbumsAsIs() || cForwardGrouped()) {
|
||||||
|
_menu->addAction(tr::ktg_forward_menu_separate_messages(tr::now), [=] {
|
||||||
|
cSetForwardAlbumsAsIs(false);
|
||||||
|
cSetForwardGrouped(false);
|
||||||
|
updateForwardingTexts();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_menu->popup(QCursor::pos());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::keyPressEvent(QKeyEvent *e) {
|
void HistoryWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
if (!_history) return;
|
if (!_history) return;
|
||||||
|
|
||||||
|
|
@ -6319,6 +6408,8 @@ void HistoryWidget::updateForwardingTexts() {
|
||||||
auto insertedPeers = base::flat_set<not_null<PeerData*>>();
|
auto insertedPeers = base::flat_set<not_null<PeerData*>>();
|
||||||
auto insertedNames = base::flat_set<QString>();
|
auto insertedNames = base::flat_set<QString>();
|
||||||
auto fullname = QString();
|
auto fullname = QString();
|
||||||
|
auto hasMediaToGroup = false;
|
||||||
|
auto grouppableMediaCount = 0;
|
||||||
auto names = std::vector<QString>();
|
auto names = std::vector<QString>();
|
||||||
names.reserve(_toForward.size());
|
names.reserve(_toForward.size());
|
||||||
for (const auto item : _toForward) {
|
for (const auto item : _toForward) {
|
||||||
|
|
@ -6339,7 +6430,18 @@ void HistoryWidget::updateForwardingTexts() {
|
||||||
} else {
|
} else {
|
||||||
Unexpected("Corrupt forwarded information in message.");
|
Unexpected("Corrupt forwarded information in message.");
|
||||||
}
|
}
|
||||||
|
if (!hasMediaToGroup) {
|
||||||
|
if (item->media() && item->media()->canBeGrouped()) {
|
||||||
|
grouppableMediaCount++;
|
||||||
|
} else {
|
||||||
|
grouppableMediaCount = 0;
|
||||||
|
}
|
||||||
|
if (grouppableMediaCount > 1) {
|
||||||
|
hasMediaToGroup = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (names.size() > 2) {
|
if (names.size() > 2) {
|
||||||
from = tr::lng_forwarding_from(tr::now, lt_count, names.size() - 1, lt_user, names[0]);
|
from = tr::lng_forwarding_from(tr::now, lt_count, names.size() - 1, lt_user, names[0]);
|
||||||
} else if (names.size() < 2) {
|
} else if (names.size() < 2) {
|
||||||
|
|
@ -6348,10 +6450,20 @@ void HistoryWidget::updateForwardingTexts() {
|
||||||
from = tr::lng_forwarding_from_two(tr::now, lt_user, names[0], lt_second_user, names[1]);
|
from = tr::lng_forwarding_from_two(tr::now, lt_user, names[0], lt_second_user, names[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count < 2) {
|
if (count < 2 && cForwardQuoted()) {
|
||||||
text = _toForward.front()->inReplyText();
|
text = _toForward.front()->inReplyText();
|
||||||
} else {
|
} else {
|
||||||
text = textcmdLink(1, tr::lng_forward_messages(tr::now, lt_count, count));
|
text = textcmdLink(1, tr::lng_forward_messages(tr::now, lt_count, count)
|
||||||
|
+ (cForwardQuoted()
|
||||||
|
? QString()
|
||||||
|
: qsl(", ") + (cForwardCaptioned()
|
||||||
|
? tr::ktg_forward_subtitle_unquoted(tr::now)
|
||||||
|
: tr::ktg_forward_subtitle_uncaptioned(tr::now)))
|
||||||
|
+ (cForwardAlbumsAsIs() || !hasMediaToGroup
|
||||||
|
? QString()
|
||||||
|
: qsl(", ") + (cForwardGrouped()
|
||||||
|
? tr::ktg_forward_subtitle_group_all_media(tr::now)
|
||||||
|
: tr::ktg_forward_subtitle_separate_messages(tr::now))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_toForwardFrom.setText(st::msgNameStyle, from, Ui::NameTextOptions());
|
_toForwardFrom.setText(st::msgNameStyle, from, Ui::NameTextOptions());
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,7 @@ protected:
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
void keyPressEvent(QKeyEvent *e) override;
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void leaveEventHook(QEvent *e) override;
|
void leaveEventHook(QEvent *e) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
|
@ -769,4 +770,6 @@ private:
|
||||||
|
|
||||||
int _topDelta = 0;
|
int _topDelta = 0;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -219,3 +219,8 @@ QString gApiHash;
|
||||||
|
|
||||||
bool gUseEnvApi = true;
|
bool gUseEnvApi = true;
|
||||||
bool gApiFromStartParams = false;
|
bool gApiFromStartParams = false;
|
||||||
|
|
||||||
|
bool gForwardQuoted = true;
|
||||||
|
bool gForwardCaptioned = true;
|
||||||
|
bool gForwardAlbumsAsIs = true;
|
||||||
|
bool gForwardGrouped = false;
|
||||||
|
|
|
||||||
|
|
@ -129,3 +129,8 @@ DeclareSetting(int, ApiId);
|
||||||
DeclareSetting(QString, ApiHash);
|
DeclareSetting(QString, ApiHash);
|
||||||
DeclareSetting(bool, UseEnvApi);
|
DeclareSetting(bool, UseEnvApi);
|
||||||
DeclareSetting(bool, ApiFromStartParams);
|
DeclareSetting(bool, ApiFromStartParams);
|
||||||
|
|
||||||
|
DeclareSetting(bool, ForwardQuoted);
|
||||||
|
DeclareSetting(bool, ForwardCaptioned);
|
||||||
|
DeclareSetting(bool, ForwardAlbumsAsIs);
|
||||||
|
DeclareSetting(bool, ForwardGrouped);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "api/api_chat_filters.h"
|
#include "api/api_chat_filters.h"
|
||||||
|
#include "api/api_text_entities.h"
|
||||||
#include "mtproto/mtproto_config.h"
|
#include "mtproto/mtproto_config.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
|
@ -1045,6 +1046,15 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
FnMut<void()> submitCallback;
|
FnMut<void()> submitCallback;
|
||||||
};
|
};
|
||||||
struct MsgIdsGroup {
|
struct MsgIdsGroup {
|
||||||
|
MsgIdsGroup() = default;
|
||||||
|
MsgIdsGroup(not_null<HistoryItem*> item, MTPint fullId, bool isGrouped = false)
|
||||||
|
: grouped(isGrouped) {
|
||||||
|
add(item, fullId);
|
||||||
|
}
|
||||||
|
void add(not_null<HistoryItem*> item, MTPint fullId) {
|
||||||
|
items.push_back(item);
|
||||||
|
ids.push_back(fullId);
|
||||||
|
}
|
||||||
HistoryItemsList items;
|
HistoryItemsList items;
|
||||||
QVector<MTPint> ids;
|
QVector<MTPint> ids;
|
||||||
bool grouped = false;
|
bool grouped = false;
|
||||||
|
|
@ -1058,6 +1068,23 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
&& firstItem->media()
|
&& firstItem->media()
|
||||||
&& (firstItem->media()->game() != nullptr);
|
&& (firstItem->media()->game() != nullptr);
|
||||||
const auto canCopyLink = items.size() == 1 && (firstItem->hasDirectLink() || isGame);
|
const auto canCopyLink = items.size() == 1 && (firstItem->hasDirectLink() || isGame);
|
||||||
|
auto hasMediaForGrouping = false;
|
||||||
|
|
||||||
|
if (items.size() > 1) {
|
||||||
|
auto grouppableMediaCount = 0;
|
||||||
|
for (const auto item : history->owner().idsToItems(items)) {
|
||||||
|
if (item->media() && item->media()->canBeGrouped()) {
|
||||||
|
grouppableMediaCount++;
|
||||||
|
} else {
|
||||||
|
grouppableMediaCount = 0;
|
||||||
|
}
|
||||||
|
if (grouppableMediaCount > 1) {
|
||||||
|
hasMediaForGrouping = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto data = std::make_shared<ShareData>(history->peer, std::move(items), std::move(successCallback));
|
const auto data = std::make_shared<ShareData>(history->peer, std::move(items), std::move(successCallback));
|
||||||
|
|
||||||
auto copyCallback = [=]() {
|
auto copyCallback = [=]() {
|
||||||
|
|
@ -1128,37 +1155,261 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
: MTPmessages_ForwardMessages::Flag(0));
|
: MTPmessages_ForwardMessages::Flag(0));
|
||||||
const auto groupedSendFlags = sendFlags | MTPmessages_ForwardMessages::Flag::f_grouped;
|
const auto groupedSendFlags = sendFlags | MTPmessages_ForwardMessages::Flag::f_grouped;
|
||||||
|
|
||||||
|
// Regroup messages if needed
|
||||||
auto groupedMsgIds = QVector<MsgIdsGroup>();
|
auto groupedMsgIds = QVector<MsgIdsGroup>();
|
||||||
for (const auto fullId : data->msgIds) {
|
for (const auto fullId : data->msgIds) {
|
||||||
auto item = navigation->session().data().message(fullId);
|
const auto item = navigation->session().data().message(fullId);
|
||||||
auto group = owner->groups().find(item);
|
const auto group = owner->groups().find(item);
|
||||||
|
const auto canBeGrouped = hasMediaForGrouping && item->media() && item->media()->canBeGrouped();
|
||||||
|
|
||||||
if (groupedMsgIds.size()) {
|
if (groupedMsgIds.size() > 0) {
|
||||||
auto prevItem = groupedMsgIds.back().items.back();
|
auto lastGroup = &groupedMsgIds.back();
|
||||||
auto prevGroup = owner->groups().find(prevItem);
|
|
||||||
if (prevGroup == group) {
|
if (cForwardAlbumsAsIs()) {
|
||||||
groupedMsgIds.back().items.push_back(item);
|
if (owner->groups().find(lastGroup->items.back()) == group) {
|
||||||
groupedMsgIds.back().ids.push_back(MTP_int(fullId.msg));
|
lastGroup->add(item, MTP_int(fullId.msg));
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lastGroup->grouped) {
|
||||||
|
if (lastGroup->items.size() < 10 && canBeGrouped) {
|
||||||
|
lastGroup->add(item, MTP_int(fullId.msg));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!canBeGrouped) {
|
||||||
|
lastGroup->add(item, MTP_int(fullId.msg));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgIdsGroup msgIdGroupInst;
|
groupedMsgIds.push_back(MsgIdsGroup(
|
||||||
msgIdGroupInst.items.push_back(item);
|
item,
|
||||||
msgIdGroupInst.ids.push_back(MTP_int(fullId.msg));
|
MTP_int(fullId.msg),
|
||||||
msgIdGroupInst.grouped = (group != nullptr);
|
cForwardAlbumsAsIs()
|
||||||
groupedMsgIds.push_back(msgIdGroupInst);
|
? (group != nullptr)
|
||||||
|
: canBeGrouped
|
||||||
|
? cForwardGrouped()
|
||||||
|
: false));
|
||||||
}
|
}
|
||||||
auto generateRandom = [&] (int size) {
|
|
||||||
|
const auto generateRandom = [&] (int size) {
|
||||||
auto result = QVector<MTPlong>(size);
|
auto result = QVector<MTPlong>(size);
|
||||||
for (auto &value : result) {
|
for (auto &value : result) {
|
||||||
value = rand_value<MTPlong>();
|
value = rand_value<MTPlong>();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
const auto checkAndClose = [=] (mtpRequestId requestId) {
|
||||||
|
data->requests.remove(requestId);
|
||||||
|
if (data->requests.empty()) {
|
||||||
|
Ui::Toast::Show(tr::lng_share_done(tr::now));
|
||||||
|
Ui::hideLayer();
|
||||||
|
}
|
||||||
|
};
|
||||||
auto &api = owner->session().api();
|
auto &api = owner->session().api();
|
||||||
auto &histories = owner->histories();
|
auto &histories = owner->histories();
|
||||||
const auto requestType = Data::Histories::RequestType::Send;
|
const auto requestType = Data::Histories::RequestType::Send;
|
||||||
|
|
||||||
|
const auto forwardQuoted = [&] (
|
||||||
|
MsgIdsGroup &&group,
|
||||||
|
not_null<History*> history,
|
||||||
|
MTPmessages_ForwardMessages::Flags flags) {
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
auto &api = history->session().api();
|
||||||
|
history->sendRequestId = api.request(MTPmessages_ForwardMessages(
|
||||||
|
MTP_flags(flags),
|
||||||
|
data->peer->input,
|
||||||
|
MTP_vector<MTPint>(group.ids),
|
||||||
|
MTP_vector<MTPlong>(generateRandom(group.ids.size())),
|
||||||
|
history->peer->input,
|
||||||
|
MTP_int(options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
|
||||||
|
history->session().api().applyUpdates(updates);
|
||||||
|
checkAndClose(requestId);
|
||||||
|
finish();
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
finish();
|
||||||
|
}).afterRequest(history->sendRequestId).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
data->requests.insert(history->sendRequestId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardAlbumUnquoted = [&] (MsgIdsGroup &&group, not_null<History*> history) {
|
||||||
|
auto medias = QVector<MTPInputSingleMedia>();
|
||||||
|
medias.reserve(group.items.size());
|
||||||
|
|
||||||
|
auto randomIds = generateRandom(group.items.size());
|
||||||
|
|
||||||
|
for (const auto item : group.items) {
|
||||||
|
const auto media = item->media();
|
||||||
|
const auto inputMedia = media->photo()
|
||||||
|
? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint())
|
||||||
|
: MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint());
|
||||||
|
const auto caption = cForwardCaptioned()
|
||||||
|
? item->originalText()
|
||||||
|
: TextWithEntities();
|
||||||
|
const auto sentEntities = Api::EntitiesToMTP(
|
||||||
|
session,
|
||||||
|
caption.entities,
|
||||||
|
Api::ConvertOption::SkipLocal);
|
||||||
|
|
||||||
|
const auto flags = !sentEntities.v.isEmpty()
|
||||||
|
? MTPDinputSingleMedia::Flag::f_entities
|
||||||
|
: MTPDinputSingleMedia::Flag(0);
|
||||||
|
|
||||||
|
const auto randomId = randomIds.takeFirst();
|
||||||
|
|
||||||
|
medias.push_back(MTP_inputSingleMedia(
|
||||||
|
MTP_flags(flags),
|
||||||
|
inputMedia,
|
||||||
|
randomId,
|
||||||
|
MTP_string(caption.text),
|
||||||
|
sentEntities));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto flags = MTPmessages_SendMultiMedia::Flags(0)
|
||||||
|
| (options.silent
|
||||||
|
? MTPmessages_SendMultiMedia::Flag::f_silent
|
||||||
|
: MTPmessages_SendMultiMedia::Flag(0))
|
||||||
|
| (options.scheduled
|
||||||
|
? MTPmessages_SendMultiMedia::Flag::f_schedule_date
|
||||||
|
: MTPmessages_SendMultiMedia::Flag(0));
|
||||||
|
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
auto &api = history->session().api();
|
||||||
|
history->sendRequestId = api.request(MTPmessages_SendMultiMedia(
|
||||||
|
MTP_flags(flags),
|
||||||
|
history->peer->input,
|
||||||
|
MTPint(),
|
||||||
|
MTP_vector<MTPInputSingleMedia>(medias),
|
||||||
|
MTP_int(options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
|
||||||
|
history->session().api().applyUpdates(updates);
|
||||||
|
checkAndClose(requestId);
|
||||||
|
finish();
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
finish();
|
||||||
|
}).afterRequest(history->sendRequestId).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
data->requests.insert(history->sendRequestId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardMediaUnquoted = [&] (not_null<HistoryItem *> item, not_null<History*> history) {
|
||||||
|
const auto media = item->media();
|
||||||
|
|
||||||
|
auto newSendFlags = MTPmessages_SendMedia::Flags(0)
|
||||||
|
| (options.silent
|
||||||
|
? MTPmessages_SendMedia::Flag::f_silent
|
||||||
|
: MTPmessages_SendMedia::Flag(0))
|
||||||
|
| (options.scheduled
|
||||||
|
? MTPmessages_SendMedia::Flag::f_schedule_date
|
||||||
|
: MTPmessages_SendMedia::Flag(0));
|
||||||
|
|
||||||
|
const auto caption = (cForwardCaptioned()
|
||||||
|
&& !media->geoPoint()
|
||||||
|
&& !media->sharedContact())
|
||||||
|
? item->originalText()
|
||||||
|
: TextWithEntities();
|
||||||
|
|
||||||
|
const auto sentEntities = Api::EntitiesToMTP(
|
||||||
|
session,
|
||||||
|
caption.entities,
|
||||||
|
Api::ConvertOption::SkipLocal);
|
||||||
|
if (!sentEntities.v.isEmpty()) {
|
||||||
|
newSendFlags |= MTPmessages_SendMedia::Flag::f_entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto inputMedia = media->poll()
|
||||||
|
? PollDataToInputMedia(media->poll())
|
||||||
|
: media->geoPoint()
|
||||||
|
? MTP_inputMediaGeoPoint(
|
||||||
|
MTP_inputGeoPoint(
|
||||||
|
MTP_double(media->geoPoint()->lat()),
|
||||||
|
MTP_double(media->geoPoint()->lon())))
|
||||||
|
: media->sharedContact()
|
||||||
|
? MTP_inputMediaContact(
|
||||||
|
MTP_string(media->sharedContact()->phoneNumber),
|
||||||
|
MTP_string(media->sharedContact()->firstName),
|
||||||
|
MTP_string(media->sharedContact()->lastName),
|
||||||
|
MTPstring())
|
||||||
|
: media->photo()
|
||||||
|
? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint())
|
||||||
|
: MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint());
|
||||||
|
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
auto &api = history->session().api();
|
||||||
|
history->sendRequestId = api.request(MTPmessages_SendMedia(
|
||||||
|
MTP_flags(newSendFlags),
|
||||||
|
history->peer->input,
|
||||||
|
MTPint(),
|
||||||
|
inputMedia,
|
||||||
|
MTP_string(caption.text),
|
||||||
|
rand_value<MTPlong>(),
|
||||||
|
MTPReplyMarkup(),
|
||||||
|
sentEntities,
|
||||||
|
MTP_int(options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
|
||||||
|
history->session().api().applyUpdates(updates);
|
||||||
|
checkAndClose(requestId);
|
||||||
|
finish();
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
finish();
|
||||||
|
}).afterRequest(history->sendRequestId).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
data->requests.insert(history->sendRequestId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto forwardMessageUnquoted = [&] (not_null<HistoryItem *> item, not_null<History*> history) {
|
||||||
|
const auto media = item->media();
|
||||||
|
|
||||||
|
auto newSendFlags = MTPmessages_SendMessage::Flag(0)
|
||||||
|
| (!media || !media->webpage()
|
||||||
|
? MTPmessages_SendMessage::Flag::f_no_webpage
|
||||||
|
: MTPmessages_SendMessage::Flag(0))
|
||||||
|
| (options.silent
|
||||||
|
? MTPmessages_SendMessage::Flag::f_silent
|
||||||
|
: MTPmessages_SendMessage::Flag(0))
|
||||||
|
| (options.scheduled
|
||||||
|
? MTPmessages_SendMessage::Flag::f_schedule_date
|
||||||
|
: MTPmessages_SendMessage::Flag(0));
|
||||||
|
|
||||||
|
const auto sentEntities = Api::EntitiesToMTP(
|
||||||
|
session,
|
||||||
|
item->originalText().entities,
|
||||||
|
Api::ConvertOption::SkipLocal);
|
||||||
|
if (!sentEntities.v.isEmpty()) {
|
||||||
|
newSendFlags |= MTPmessages_SendMessage::Flag::f_entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||||
|
auto &api = history->session().api();
|
||||||
|
history->sendRequestId = api.request(MTPmessages_SendMessage(
|
||||||
|
MTP_flags(newSendFlags),
|
||||||
|
history->peer->input,
|
||||||
|
MTPint(),
|
||||||
|
MTP_string(item->originalText().text),
|
||||||
|
rand_value<MTPlong>(),
|
||||||
|
MTPReplyMarkup(),
|
||||||
|
sentEntities,
|
||||||
|
MTP_int(options.scheduled)
|
||||||
|
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
|
||||||
|
history->session().api().applyUpdates(updates);
|
||||||
|
checkAndClose(requestId);
|
||||||
|
finish();
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
finish();
|
||||||
|
}).afterRequest(history->sendRequestId).send();
|
||||||
|
return history->sendRequestId;
|
||||||
|
});
|
||||||
|
data->requests.insert(history->sendRequestId);
|
||||||
|
};
|
||||||
|
|
||||||
for (const auto peer : result) {
|
for (const auto peer : result) {
|
||||||
const auto history = owner->history(peer);
|
const auto history = owner->history(peer);
|
||||||
if (!comment.text.isEmpty()) {
|
if (!comment.text.isEmpty()) {
|
||||||
|
|
@ -1168,30 +1419,39 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
message.action.clearDraft = false;
|
message.action.clearDraft = false;
|
||||||
api.sendMessage(std::move(message));
|
api.sendMessage(std::move(message));
|
||||||
}
|
}
|
||||||
for (auto group : groupedMsgIds) {
|
for (auto &group : groupedMsgIds) {
|
||||||
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
if (cForwardQuoted()) {
|
||||||
auto &api = history->session().api();
|
// Forward regrouped messages as is
|
||||||
history->sendRequestId = api.request(MTPmessages_ForwardMessages(
|
const auto flags = group.grouped ? groupedSendFlags : sendFlags;
|
||||||
MTP_flags(group.grouped ? groupedSendFlags : sendFlags),
|
forwardQuoted(std::move(group), history, flags);
|
||||||
data->peer->input,
|
} else if (group.grouped) {
|
||||||
MTP_vector<MTPint>(group.ids),
|
// Sending albums without author
|
||||||
MTP_vector<MTPlong>(generateRandom(group.ids.size())),
|
forwardAlbumUnquoted(std::move(group), history);
|
||||||
peer->input,
|
} else {
|
||||||
MTP_int(options.scheduled)
|
for (const auto item : group.items) {
|
||||||
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
|
const auto media = item->media();
|
||||||
history->session().api().applyUpdates(updates);
|
|
||||||
data->requests.remove(requestId);
|
if (media && !media->webpage()) {
|
||||||
if (data->requests.empty()) {
|
if (media->poll()
|
||||||
Ui::Toast::Show(tr::lng_share_done(tr::now));
|
|| media->geoPoint()
|
||||||
Ui::hideLayer();
|
|| media->sharedContact()
|
||||||
|
|| media->photo()
|
||||||
|
|| media->document()) {
|
||||||
|
// Send media messages without author
|
||||||
|
forwardMediaUnquoted(item, history);
|
||||||
|
} else {
|
||||||
|
// Forward message if type doesn't support forwarding unquoted
|
||||||
|
forwardQuoted(
|
||||||
|
MsgIdsGroup(item, MTP_int(item->fullId().msg)),
|
||||||
|
history,
|
||||||
|
sendFlags);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Send messages without author
|
||||||
|
forwardMessageUnquoted(item, history);
|
||||||
}
|
}
|
||||||
finish();
|
}
|
||||||
}).fail([=](const RPCError &error) {
|
}
|
||||||
finish();
|
|
||||||
}).afterRequest(history->sendRequestId).send();
|
|
||||||
return history->sendRequestId;
|
|
||||||
});
|
|
||||||
data->requests.insert(history->sendRequestId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data->submitCallback && !cForwardRetainSelection()) {
|
if (data->submitCallback && !cForwardRetainSelection()) {
|
||||||
|
|
@ -1212,7 +1472,8 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
std::move(copyLinkCallback),
|
std::move(copyLinkCallback),
|
||||||
std::move(submitCallback),
|
std::move(submitCallback),
|
||||||
std::move(filterCallback),
|
std::move(filterCallback),
|
||||||
std::move(goToChatCallback)));
|
std::move(goToChatCallback),
|
||||||
|
hasMediaForGrouping));
|
||||||
return weak->data();
|
return weak->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue