Merge tag 'v4.16.8' into dev

# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/lib_ui
#	snap/snapcraft.yaml
This commit is contained in:
AlexeyZavar 2024-04-17 02:39:50 +03:00
commit fe1babe437
133 changed files with 1105 additions and 726 deletions

View file

@ -531,6 +531,10 @@ PRIVATE
data/business/data_business_info.h data/business/data_business_info.h
data/business/data_shortcut_messages.cpp data/business/data_shortcut_messages.cpp
data/business/data_shortcut_messages.h data/business/data_shortcut_messages.h
data/components/scheduled_messages.cpp
data/components/scheduled_messages.h
data/components/sponsored_messages.cpp
data/components/sponsored_messages.h
data/notify/data_notify_settings.cpp data/notify/data_notify_settings.cpp
data/notify/data_notify_settings.h data/notify/data_notify_settings.h
data/notify/data_peer_notify_settings.cpp data/notify/data_peer_notify_settings.cpp
@ -648,14 +652,10 @@ PRIVATE
data/data_send_action.h data/data_send_action.h
data/data_session.cpp data/data_session.cpp
data/data_session.h data/data_session.h
data/data_scheduled_messages.cpp
data/data_scheduled_messages.h
data/data_shared_media.cpp data/data_shared_media.cpp
data/data_shared_media.h data/data_shared_media.h
data/data_sparse_ids.cpp data/data_sparse_ids.cpp
data/data_sparse_ids.h data/data_sparse_ids.h
data/data_sponsored_messages.cpp
data/data_sponsored_messages.h
data/data_statistics.h data/data_statistics.h
data/data_stories.cpp data/data_stories.cpp
data/data_stories.h data/data_stories.h
@ -1530,8 +1530,6 @@ PRIVATE
ui/image/image_location.h ui/image/image_location.h
ui/image/image_location_factory.cpp ui/image/image_location_factory.cpp
ui/image/image_location_factory.h ui/image/image_location_factory.h
ui/widgets/level_meter.cpp
ui/widgets/level_meter.h
ui/countryinput.cpp ui/countryinput.cpp
ui/countryinput.h ui/countryinput.h
ui/dynamic_thumbnails.cpp ui/dynamic_thumbnails.cpp
@ -1547,6 +1545,8 @@ PRIVATE
ui/search_field_controller.h ui/search_field_controller.h
ui/text/format_song_document_name.cpp ui/text/format_song_document_name.cpp
ui/text/format_song_document_name.h ui/text/format_song_document_name.h
ui/widgets/label_with_custom_emoji.cpp
ui/widgets/label_with_custom_emoji.h
ui/unread_badge.cpp ui/unread_badge.cpp
ui/unread_badge.h ui/unread_badge.h
window/main_window.cpp window/main_window.cpp

View file

@ -309,7 +309,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_limit_reached#one" = "You've reached the message text limit. Please make the text shorter by {count} character."; "lng_edit_limit_reached#one" = "You've reached the message text limit. Please make the text shorter by {count} character.";
"lng_edit_limit_reached#other" = "You've reached the message text limit. Please make the text shorter by {count} characters."; "lng_edit_limit_reached#other" = "You've reached the message text limit. Please make the text shorter by {count} characters.";
"lng_edit_message" = "Edit message"; "lng_edit_message" = "Edit message";
"lng_edit_message_text" = "New message text..."; "lng_edit_message_text" = "Caption";
"lng_deleted" = "Deleted Account"; "lng_deleted" = "Deleted Account";
"lng_deleted_message" = "Deleted message"; "lng_deleted_message" = "Deleted message";
"lng_deleted_story" = "Deleted story"; "lng_deleted_story" = "Deleted story";
@ -734,6 +734,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_sensitive_disable_filtering" = "Disable filtering"; "lng_settings_sensitive_disable_filtering" = "Disable filtering";
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices."; "lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
"lng_settings_security_bots" = "Bots and websites"; "lng_settings_security_bots" = "Bots and websites";
"lng_settings_file_confirmations" = "File open confirmations";
"lng_settings_edit_extensions" = "Extensions whitelist";
"lng_settings_edit_extensions_about" = "Open files with the following extensions without additional confirmation.";
"lng_settings_edit_ip_confirm" = "IP reveal warning";
"lng_settings_edit_ip_confirm_about" = "Show confirmation when opening files that may reveal your IP address.";
"lng_settings_clear_payment_info" = "Clear Payment and Shipping Info"; "lng_settings_clear_payment_info" = "Clear Payment and Shipping Info";
"lng_settings_logged_in" = "Connected websites"; "lng_settings_logged_in" = "Connected websites";
"lng_settings_logged_in_title" = "Logged in with Telegram"; "lng_settings_logged_in_title" = "Logged in with Telegram";
@ -4480,10 +4485,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_translate_settings_about" = "The 'Translate' button will appear when you open a context menu on a text message."; "lng_translate_settings_about" = "The 'Translate' button will appear when you open a context menu on a text message.";
"lng_translate_settings_one" = "Please choose at least one language so that it can be used as the \"Translate to\" language."; "lng_translate_settings_one" = "Please choose at least one language so that it can be used as the \"Translate to\" language.";
"lng_launch_exe_warning" = "This file has a {extension} extension.\nAre you sure you want to run it?"; "lng_launch_exe_warning" = "This file has {extension} extension.\nAre you sure you want to run it?";
"lng_launch_other_warning" = "This file has {extension} extension.\nAre you sure you want to open it?";
"lng_launch_svg_warning" = "Opening this file can potentially expose your IP address to its sender. Continue?"; "lng_launch_svg_warning" = "Opening this file can potentially expose your IP address to its sender. Continue?";
"lng_launch_exe_sure" = "Run"; "lng_launch_exe_sure" = "Run";
"lng_launch_other_sure" = "Open";
"lng_launch_exe_dont_ask" = "Don't ask me again"; "lng_launch_exe_dont_ask" = "Don't ask me again";
"lng_launch_dont_ask" = "Remember for this file type";
"lng_launch_dont_ask_settings" = "You can later edit trusted file types in Settings > Privacy and Security > File open confirmations.";
"lng_polls_anonymous" = "Anonymous Poll"; "lng_polls_anonymous" = "Anonymous Poll";
"lng_polls_public" = "Poll"; "lng_polls_public" = "Poll";

View file

@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.16.6.0" /> Version="4.16.8.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName> <PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,16,6,0 FILEVERSION 4,16,8,0
PRODUCTVERSION 4,16,6,0 PRODUCTVERSION 4,16,8,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop" VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "4.16.6.0" VALUE "FileVersion", "4.16.8.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.16.6.0" VALUE "ProductVersion", "4.16.8.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,16,6,0 FILEVERSION 4,16,8,0
PRODUCTVERSION 4,16,6,0 PRODUCTVERSION 4,16,8,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater" VALUE "FileDescription", "AyuGram Desktop Updater"
VALUE "FileVersion", "4.16.6.0" VALUE "FileVersion", "4.16.8.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.16.6.0" VALUE "ProductVersion", "4.16.8.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -236,14 +236,14 @@ void SendBotCallbackDataWithPassword(
} else { } else {
return; return;
} }
const auto box = std::make_shared<QPointer<PasscodeBox>>();
auto fields = PasscodeBox::CloudFields::From(state); auto fields = PasscodeBox::CloudFields::From(state);
fields.customTitle = tr::lng_bots_password_confirm_title(); fields.customTitle = tr::lng_bots_password_confirm_title();
fields.customDescription fields.customDescription
= tr::lng_bots_password_confirm_description(tr::now); = tr::lng_bots_password_confirm_description(tr::now);
fields.customSubmitButton = tr::lng_passcode_submit(); fields.customSubmitButton = tr::lng_passcode_submit();
fields.customCheckCallback = [=]( fields.customCheckCallback = [=](
const Core::CloudPasswordResult &result) { const Core::CloudPasswordResult &result,
QPointer<PasscodeBox> box) {
if (const auto button = getButton()) { if (const auto button = getButton()) {
if (button->requestId) { if (button->requestId) {
return; return;
@ -257,18 +257,17 @@ void SendBotCallbackDataWithPassword(
return; return;
} }
SendBotCallbackData(strongController, item, row, column, result, [=] { SendBotCallbackData(strongController, item, row, column, result, [=] {
if (*box) { if (box) {
(*box)->closeBox(); box->closeBox();
} }
}, [=](const QString &error) { }, [=](const QString &error) {
if (*box) { if (box) {
(*box)->handleCustomCheckError(error); box->handleCustomCheckError(error);
} }
}); });
} }
}; };
auto object = Box<PasscodeBox>(session, fields); auto object = Box<PasscodeBox>(session, fields);
*box = Ui::MakeWeak(object.data());
show->showBox(std::move(object), Ui::LayerOption::CloseOther); show->showBox(std::move(object), Ui::LayerOption::CloseOther);
}, *lifetime); }, *lifetime);
} }

View file

@ -112,8 +112,8 @@ void ApplyLastList(
channel->mgInfo->lastAdmins.clear(); channel->mgInfo->lastAdmins.clear();
channel->mgInfo->lastRestricted.clear(); channel->mgInfo->lastRestricted.clear();
channel->mgInfo->lastParticipants.clear(); channel->mgInfo->lastParticipants.clear();
channel->mgInfo->lastParticipantsStatus = channel->mgInfo->lastParticipantsStatus
MegagroupInfo::LastParticipantsUpToDate = MegagroupInfo::LastParticipantsUpToDate
| MegagroupInfo::LastParticipantsOnceReceived; | MegagroupInfo::LastParticipantsOnceReceived;
auto botStatus = channel->mgInfo->botStatus; auto botStatus = channel->mgInfo->botStatus;

View file

@ -58,25 +58,33 @@ void HandleWithdrawalButton(
state->loading = false; state->loading = false;
auto fields = PasscodeBox::CloudFields::From(pass); auto fields = PasscodeBox::CloudFields::From(pass);
fields.customTitle = fields.customTitle
tr::lng_channel_earn_balance_password_title(); = tr::lng_channel_earn_balance_password_title();
fields.customDescription = fields.customDescription
tr::lng_channel_earn_balance_password_description(tr::now); = tr::lng_channel_earn_balance_password_description(tr::now);
fields.customSubmitButton = tr::lng_passcode_submit(); fields.customSubmitButton = tr::lng_passcode_submit();
fields.customCheckCallback = crl::guard(button, [=]( fields.customCheckCallback = crl::guard(button, [=](
const Core::CloudPasswordResult &result) { const Core::CloudPasswordResult &result,
QPointer<PasscodeBox> box) {
const auto done = [=](const QString &result) {
if (!result.isEmpty()) {
UrlClickHandler::Open(result);
if (box) {
box->closeBox();
}
}
};
const auto fail = [=](const QString &error) {
show->showToast(error);
};
session->api().request( session->api().request(
MTPstats_GetBroadcastRevenueWithdrawalUrl( MTPstats_GetBroadcastRevenueWithdrawalUrl(
channel->inputChannel, channel->inputChannel,
result.result result.result
)).done([=](const MTPstats_BroadcastRevenueWithdrawalUrl &r) { )).done([=](const MTPstats_BroadcastRevenueWithdrawalUrl &r) {
const auto url = qs(r.data().vurl()); done(qs(r.data().vurl()));
if (!url.isEmpty()) {
UrlClickHandler::Open(url);
}
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
show->showToast(error.type()); fail(error.type());
}).send(); }).send();
}); });
show->show(Box<PasscodeBox>(session, fields)); show->show(Box<PasscodeBox>(session, fields));

View file

@ -12,12 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_response.h" #include "mtproto/mtproto_response.h"
@ -29,20 +28,20 @@ namespace {
using namespace rpl::details; using namespace rpl::details;
template <typename T> template <typename T>
constexpr auto WithId = constexpr auto WithId
is_callable_plain_v<T, Fn<void()>, mtpRequestId>; = is_callable_plain_v<T, Fn<void()>, mtpRequestId>;
template <typename T> template <typename T>
constexpr auto WithoutId = constexpr auto WithoutId
is_callable_plain_v<T, Fn<void()>>; = is_callable_plain_v<T, Fn<void()>>;
template <typename T> template <typename T>
constexpr auto WithoutCallback = constexpr auto WithoutCallback
is_callable_plain_v<T>; = is_callable_plain_v<T>;
template <typename T> template <typename T>
constexpr auto ErrorWithId = constexpr auto ErrorWithId
is_callable_plain_v<T, QString, mtpRequestId>; = is_callable_plain_v<T, QString, mtpRequestId>;
template <typename T> template <typename T>
constexpr auto ErrorWithoutId = constexpr auto ErrorWithoutId
is_callable_plain_v<T, QString>; = is_callable_plain_v<T, QString>;
template <typename DoneCallback, typename FailCallback> template <typename DoneCallback, typename FailCallback>
mtpRequestId EditMessage( mtpRequestId EditMessage(
@ -95,7 +94,7 @@ mtpRequestId EditMessage(
: emptyFlag); : emptyFlag);
const auto id = item->isScheduled() const auto id = item->isScheduled()
? session->data().scheduledMessages().lookupId(item) ? session->scheduledMessages().lookupId(item)
: item->isBusinessShortcut() : item->isBusinessShortcut()
? session->data().shortcutMessages().lookupId(item) ? session->data().shortcutMessages().lookupId(item)
: item->id; : item->id;

View file

@ -860,6 +860,7 @@ void EarnStatistics::requestHistory(
.token = Data::EarnHistorySlice::OffsetToken(nextToken), .token = Data::EarnHistorySlice::OffsetToken(nextToken),
}); });
}).fail([=] { }).fail([=] {
done({});
_requestId = 0; _requestId = 0;
}).send(); }).send();
} }

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_config.h" #include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "data/data_saved_messages.h" #include "data/data_saved_messages.h"
@ -37,7 +38,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_scheduled_messages.h"
#include "data/data_send_action.h" #include "data/data_send_action.h"
#include "data/data_stories.h" #include "data/data_stories.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
@ -98,7 +98,7 @@ void ProcessScheduledMessageWithElapsedTime(
// Note that when a message is scheduled until online // Note that when a message is scheduled until online
// while the recipient is already online, the server sends // while the recipient is already online, the server sends
// an ordinary new message with skipped "from_scheduled" flag. // an ordinary new message with skipped "from_scheduled" flag.
session->data().scheduledMessages().checkEntitiesAndUpdate(data); session->scheduledMessages().checkEntitiesAndUpdate(data);
} }
} }
@ -1472,7 +1472,9 @@ void Updates::applyUpdates(
if (const auto id = owner.messageIdByRandomId(randomId)) { if (const auto id = owner.messageIdByRandomId(randomId)) {
const auto local = owner.message(id); const auto local = owner.message(id);
if (local && local->isScheduled()) { if (local && local->isScheduled()) {
owner.scheduledMessages().sendNowSimpleMessage(d, local); session().scheduledMessages().sendNowSimpleMessage(
d,
local);
} }
} }
const auto wasAlready = (lookupMessage() != nullptr); const auto wasAlready = (lookupMessage() != nullptr);
@ -1569,7 +1571,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
auto &owner = session().data(); auto &owner = session().data();
if (const auto local = owner.message(id)) { if (const auto local = owner.message(id)) {
if (local->isScheduled()) { if (local->isScheduled()) {
session().data().scheduledMessages().apply(d, local); session().scheduledMessages().apply(d, local);
} else if (local->isBusinessShortcut()) { } else if (local->isBusinessShortcut()) {
session().data().shortcutMessages().apply(d, local); session().data().shortcutMessages().apply(d, local);
} else { } else {
@ -1779,12 +1781,12 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateNewScheduledMessage: { case mtpc_updateNewScheduledMessage: {
const auto &d = update.c_updateNewScheduledMessage(); const auto &d = update.c_updateNewScheduledMessage();
session().data().scheduledMessages().apply(d); session().scheduledMessages().apply(d);
} break; } break;
case mtpc_updateDeleteScheduledMessages: { case mtpc_updateDeleteScheduledMessages: {
const auto &d = update.c_updateDeleteScheduledMessages(); const auto &d = update.c_updateDeleteScheduledMessages();
session().data().scheduledMessages().apply(d); session().scheduledMessages().apply(d);
} break; } break;
case mtpc_updateQuickReplies: { case mtpc_updateQuickReplies: {

View file

@ -307,8 +307,8 @@ void UserPrivacy::reload(Key key) {
} }
void UserPrivacy::pushPrivacy(Key key, const TLRules &rules) { void UserPrivacy::pushPrivacy(Key key, const TLRules &rules) {
const auto &saved = (_privacyValues[key] = const auto &saved
TLToRules(rules, _session->data())); = (_privacyValues[key] = TLToRules(rules, _session->data()));
const auto i = _privacyChanges.find(key); const auto i = _privacyChanges.find(key);
if (i != end(_privacyChanges)) { if (i != end(_privacyChanges)) {
i->second.fire_copy(saved); i->second.fire_copy(saved);

View file

@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_user_names.h" #include "api/api_user_names.h"
#include "api/api_websites.h" #include "api/api_websites.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
@ -43,7 +44,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_saved_sublist.h" #include "data/data_saved_sublist.h"
#include "data/data_search_controller.h" #include "data/data_search_controller.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
@ -559,7 +559,7 @@ void ApiWrap::sendMessageFail(
} }
} }
} else if (error == u"SCHEDULE_STATUS_PRIVATE"_q) { } else if (error == u"SCHEDULE_STATUS_PRIVATE"_q) {
auto &scheduled = _session->data().scheduledMessages(); auto &scheduled = _session->scheduledMessages();
Assert(peer->isUser()); Assert(peer->isUser());
if (const auto item = scheduled.lookupItem(peer->id, itemId.msg)) { if (const auto item = scheduled.lookupItem(peer->id, itemId.msg)) {
scheduled.removeSending(item); scheduled.removeSending(item);
@ -1573,8 +1573,8 @@ void ApiWrap::saveStickerSets(
writeRecent = true; writeRecent = true;
} }
const auto isAttached = const auto isAttached
(removedSetId == Data::Stickers::CloudRecentAttachedSetId); = (removedSetId == Data::Stickers::CloudRecentAttachedSetId);
const auto flags = isAttached const auto flags = isAttached
? MTPmessages_ClearRecentStickers::Flag::f_attached ? MTPmessages_ClearRecentStickers::Flag::f_attached
: MTPmessages_ClearRecentStickers::Flags(0); : MTPmessages_ClearRecentStickers::Flags(0);
@ -2480,8 +2480,8 @@ void ApiWrap::refreshFileReference(
_session->data().peer(storyId.peer)->input, _session->data().peer(storyId.peer)->input,
MTP_vector<MTPint>(1, MTP_int(storyId.story)))); MTP_vector<MTPint>(1, MTP_int(storyId.story))));
} else if (item->isScheduled()) { } else if (item->isScheduled()) {
const auto &scheduled = _session->data().scheduledMessages(); const auto realId = _session->scheduledMessages().lookupId(
const auto realId = scheduled.lookupId(item); item);
request(MTPmessages_GetScheduledMessages( request(MTPmessages_GetScheduledMessages(
item->history()->peer->input, item->history()->peer->input,
MTP_vector<MTPint>(1, MTP_int(realId)))); MTP_vector<MTPint>(1, MTP_int(realId))));
@ -2527,8 +2527,8 @@ void ApiWrap::refreshFileReference(
}, [&](Data::FileOriginPeerPhoto data) { }, [&](Data::FileOriginPeerPhoto data) {
fail(); fail();
}, [&](Data::FileOriginStickerSet data) { }, [&](Data::FileOriginStickerSet data) {
const auto isRecentAttached = const auto isRecentAttached
(data.setId == Data::Stickers::CloudRecentAttachedSetId); = (data.setId == Data::Stickers::CloudRecentAttachedSetId);
if (data.setId == Data::Stickers::CloudRecentSetId if (data.setId == Data::Stickers::CloudRecentSetId
|| data.setId == Data::Stickers::RecentSetId || data.setId == Data::Stickers::RecentSetId
|| isRecentAttached) { || isRecentAttached) {

View file

@ -605,8 +605,8 @@ void GroupInfoBox::prepare() {
_navigation->session().api().selfDestruct().reload(); _navigation->session().api().selfDestruct().reload();
const auto top = addTopButton(st::infoTopBarMenu); const auto top = addTopButton(st::infoTopBarMenu);
const auto menu = const auto menu
top->lifetime().make_state<base::unique_qptr<Ui::PopupMenu>>(); = top->lifetime().make_state<base::unique_qptr<Ui::PopupMenu>>();
top->setClickedCallback([=] { top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>( *menu = base::make_unique_q<Ui::PopupMenu>(
top, top,
@ -1306,8 +1306,8 @@ void SetupChannelBox::handleChange() {
&& (ch < 'a' || ch > 'z') && (ch < 'a' || ch > 'z')
&& (ch < '0' || ch > '9') && (ch < '0' || ch > '9')
&& ch != '_') { && ch != '_') {
const auto badSymbols = const auto badSymbols
tr::lng_create_channel_link_bad_symbols(tr::now); = tr::lng_create_channel_link_bad_symbols(tr::now);
if (_errorText != badSymbols) { if (_errorText != badSymbols) {
_errorText = badSymbols; _errorText = badSymbols;
update(); update();
@ -1317,8 +1317,8 @@ void SetupChannelBox::handleChange() {
} }
} }
if (name.size() < Ui::EditPeer::kMinUsernameLength) { if (name.size() < Ui::EditPeer::kMinUsernameLength) {
const auto tooShort = const auto tooShort
tr::lng_create_channel_link_too_short(tr::now); = tr::lng_create_channel_link_too_short(tr::now);
if (_errorText != tooShort) { if (_errorText != tooShort) {
_errorText = tooShort; _errorText = tooShort;
update(); update();

View file

@ -232,8 +232,8 @@ void DeleteMessagesBox::prepare() {
if (hasScheduledMessages()) { if (hasScheduledMessages()) {
} else if (auto revoke = revokeText(peer)) { } else if (auto revoke = revokeText(peer)) {
const auto &settings = Core::App().settings(); const auto &settings = Core::App().settings();
const auto revokeByDefault = const auto revokeByDefault
!settings.rememberedDeleteMessageOnlyForYou(); = !settings.rememberedDeleteMessageOnlyForYou();
_revoke.create( _revoke.create(
this, this,
revoke->checkbox, revoke->checkbox,

View file

@ -16,7 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/prepare_short_info_box.h" #include "boxes/peers/prepare_short_info_box.h"
#include "boxes/peers/replace_boost_box.h" // BoostsForGift. #include "boxes/peers/replace_boost_box.h" // BoostsForGift.
#include "boxes/premium_preview_box.h" // ShowPremiumPreviewBox. #include "boxes/premium_preview_box.h" // ShowPremiumPreviewBox.
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "data/data_boosts.h" #include "data/data_boosts.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_channel.h" #include "data/data_channel.h"
@ -48,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/gradient_round_button.h" #include "ui/widgets/gradient_round_button.h"
#include "ui/widgets/label_with_custom_emoji.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/wrap/table_layout.h" #include "ui/wrap/table_layout.h"
@ -319,21 +319,20 @@ void GiftBox(
std::move(titleLabel)), std::move(titleLabel)),
st::premiumGiftTitlePadding); st::premiumGiftTitlePadding);
auto textLabel = object_ptr<Ui::FlatLabel>(box, st::premiumPreviewAbout); auto textLabel = Ui::CreateLabelWithCustomEmoji(
tr::lng_premium_gift_about( box,
lt_user, tr::lng_premium_gift_about(
user->session().changes().peerFlagsValue( lt_user,
user, user->session().changes().peerFlagsValue(
Data::PeerUpdate::Flag::Name user,
) | rpl::map([=] { return TextWithEntities{ user->firstName }; }), Data::PeerUpdate::Flag::Name
Ui::Text::RichLangValue ) | rpl::map([=] { return TextWithEntities{ user->firstName }; }),
) | rpl::map( Ui::Text::RichLangValue
BoostsForGiftText({ user }) ) | rpl::map(
) | rpl::start_with_next([ BoostsForGiftText({ user })
raw = textLabel.data(), ),
session = &user->session()](const TextWithEntities &t) { { .session = &user->session() },
raw->setMarkedText(t, Core::MarkedTextContext{ .session = session }); st::premiumPreviewAbout);
}, textLabel->lifetime());
textLabel->setTextColorOverride(stTitle.textFg->c); textLabel->setTextColorOverride(stTitle.textFg->c);
textLabel->resizeToWidth(available); textLabel->resizeToWidth(available);
box->addRow( box->addRow(
@ -536,14 +535,12 @@ void GiftsBox(
const auto label = box->addRow( const auto label = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>( object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box, box,
object_ptr<Ui::FlatLabel>(box, st::premiumPreviewAbout)), Ui::CreateLabelWithCustomEmoji(
box,
std::move(text),
{ .session = session },
st::premiumPreviewAbout)),
padding)->entity(); padding)->entity();
std::move(
text
) | rpl::start_with_next([=](const TextWithEntities &t) {
using namespace Core;
label->setMarkedText(t, MarkedTextContext{ .session = session });
}, label->lifetime());
label->setTextColorOverride(stTitle.textFg->c); label->setTextColorOverride(stTitle.textFg->c);
label->resizeToWidth(available); label->resizeToWidth(available);
} }

View file

@ -740,7 +740,7 @@ void PasscodeBox::submitOnlyCheckCloudPassword(const QString &oldPassword) {
void PasscodeBox::sendOnlyCheckCloudPassword(const QString &oldPassword) { void PasscodeBox::sendOnlyCheckCloudPassword(const QString &oldPassword) {
checkPassword(oldPassword, [=](const Core::CloudPasswordResult &check) { checkPassword(oldPassword, [=](const Core::CloudPasswordResult &check) {
if (const auto onstack = _cloudFields.customCheckCallback) { if (const auto onstack = _cloudFields.customCheckCallback) {
onstack(check); onstack(check, Ui::MakeWeak(this));
} else { } else {
Assert(_cloudFields.turningOff); Assert(_cloudFields.turningOff);
sendClearCloudPassword(check); sendClearCloudPassword(check);

View file

@ -51,7 +51,10 @@ public:
TimeId pendingResetDate = 0; TimeId pendingResetDate = 0;
// Check cloud password for some action. // Check cloud password for some action.
Fn<void(const Core::CloudPasswordResult &)> customCheckCallback; using CustomCheck = Fn<void(
const Core::CloudPasswordResult &,
QPointer<PasscodeBox>)>;
CustomCheck customCheckCallback;
rpl::producer<QString> customTitle; rpl::producer<QString> customTitle;
std::optional<QString> customDescription; std::optional<QString> customDescription;
rpl::producer<QString> customSubmitButton; rpl::producer<QString> customSubmitButton;

View file

@ -598,19 +598,17 @@ void EditAdminBox::requestTransferPassword(not_null<ChannelData*> channel) {
) | rpl::take( ) | rpl::take(
1 1
) | rpl::start_with_next([=](const Core::CloudPasswordState &state) { ) | rpl::start_with_next([=](const Core::CloudPasswordState &state) {
const auto box = std::make_shared<QPointer<PasscodeBox>>();
auto fields = PasscodeBox::CloudFields::From(state); auto fields = PasscodeBox::CloudFields::From(state);
fields.customTitle = tr::lng_rights_transfer_password_title(); fields.customTitle = tr::lng_rights_transfer_password_title();
fields.customDescription fields.customDescription
= tr::lng_rights_transfer_password_description(tr::now); = tr::lng_rights_transfer_password_description(tr::now);
fields.customSubmitButton = tr::lng_passcode_submit(); fields.customSubmitButton = tr::lng_passcode_submit();
fields.customCheckCallback = crl::guard(this, [=]( fields.customCheckCallback = crl::guard(this, [=](
const Core::CloudPasswordResult &result) { const Core::CloudPasswordResult &result,
sendTransferRequestFrom(*box, channel, result); QPointer<PasscodeBox> box) {
sendTransferRequestFrom(box, channel, result);
}); });
*box = getDelegate()->show(Box<PasscodeBox>( getDelegate()->show(Box<PasscodeBox>(&channel->session(), fields));
&channel->session(),
fields));
}, lifetime()); }, lifetime());
} }

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "ui/layers/generic_box.h" #include "ui/layers/generic_box.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -23,6 +24,17 @@ void EditPeerHistoryVisibilityBox(
Ui::RadioenumGroup<HistoryVisibility> Ui::RadioenumGroup<HistoryVisibility>
>(historyVisibilitySavedValue); >(historyVisibilitySavedValue);
const auto addButton = [=](
not_null<Ui::RpWidget*> inner,
HistoryVisibility v) {
const auto button = Ui::CreateChild<Ui::AbstractButton>(inner.get());
inner->sizeValue(
) | rpl::start_with_next([=](const QSize &s) {
button->resize(s);
}, button->lifetime());
button->setClickedCallback([=] { historyVisibility->setValue(v); });
};
box->setTitle(tr::lng_manage_history_visibility_title()); box->setTitle(tr::lng_manage_history_visibility_title());
box->addButton(tr::lng_settings_save(), [=] { box->addButton(tr::lng_settings_save(), [=] {
savedCallback(historyVisibility->current()); savedCallback(historyVisibility->current());
@ -31,32 +43,36 @@ void EditPeerHistoryVisibilityBox(
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
box->addSkip(st::editPeerHistoryVisibilityTopSkip); box->addSkip(st::editPeerHistoryVisibilityTopSkip);
box->addRow(object_ptr<Ui::Radioenum<HistoryVisibility>>( const auto visible = box->addRow(object_ptr<Ui::VerticalLayout>(box));
visible->add(object_ptr<Ui::Radioenum<HistoryVisibility>>(
box, box,
historyVisibility, historyVisibility,
HistoryVisibility::Visible, HistoryVisibility::Visible,
tr::lng_manage_history_visibility_shown(tr::now), tr::lng_manage_history_visibility_shown(tr::now),
st::defaultBoxCheckbox)); st::defaultBoxCheckbox));
box->addRow( visible->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
box, box,
tr::lng_manage_history_visibility_shown_about(), tr::lng_manage_history_visibility_shown_about(),
st::editPeerPrivacyLabel), st::editPeerPrivacyLabel),
st::editPeerPreHistoryLabelMargins + st::boxRowPadding); st::editPeerPreHistoryLabelMargins);
addButton(visible, HistoryVisibility::Visible);
box->addSkip(st::editPeerHistoryVisibilityTopSkip); box->addSkip(st::editPeerHistoryVisibilityTopSkip);
box->addRow(object_ptr<Ui::Radioenum<HistoryVisibility>>( const auto hidden = box->addRow(object_ptr<Ui::VerticalLayout>(box));
hidden->add(object_ptr<Ui::Radioenum<HistoryVisibility>>(
box, box,
historyVisibility, historyVisibility,
HistoryVisibility::Hidden, HistoryVisibility::Hidden,
tr::lng_manage_history_visibility_hidden(tr::now), tr::lng_manage_history_visibility_hidden(tr::now),
st::defaultBoxCheckbox)); st::defaultBoxCheckbox));
box->addRow( hidden->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
box, box,
(isLegacy (isLegacy
? tr::lng_manage_history_visibility_hidden_legacy ? tr::lng_manage_history_visibility_hidden_legacy
: tr::lng_manage_history_visibility_hidden_about)(), : tr::lng_manage_history_visibility_hidden_about)(),
st::editPeerPrivacyLabel), st::editPeerPrivacyLabel),
st::editPeerPreHistoryLabelMargins + st::boxRowPadding); st::editPeerPreHistoryLabelMargins);
addButton(hidden, HistoryVisibility::Hidden);
} }

View file

@ -983,8 +983,8 @@ void Controller::fillHistoryVisibilityButton() {
: HistoryVisibility::Visible; : HistoryVisibility::Visible;
_channelHasLocationOriginalValue = channel && channel->hasLocation(); _channelHasLocationOriginalValue = channel && channel->hasLocation();
const auto updateHistoryVisibility = const auto updateHistoryVisibility
std::make_shared<rpl::event_stream<HistoryVisibility>>(); = std::make_shared<rpl::event_stream<HistoryVisibility>>();
const auto boxCallback = crl::guard(this, [=](HistoryVisibility checked) { const auto boxCallback = crl::guard(this, [=](HistoryVisibility checked) {
updateHistoryVisibility->fire(std::move(checked)); updateHistoryVisibility->fire(std::move(checked));
@ -1698,8 +1698,8 @@ void Controller::saveUsernamesOrder() {
channel->setUsernames(ranges::views::all( channel->setUsernames(ranges::views::all(
newUsernames newUsernames
) | ranges::views::transform([&](QString username) { ) | ranges::views::transform([&](QString username) {
const auto editable = const auto editable
(channel->editableUsername() == username); = (channel->editableUsername() == username);
return Data::Username{ return Data::Username{
.username = std::move(username), .username = std::move(username),
.active = true, .active = true,

View file

@ -227,9 +227,9 @@ QImage QrExact(const Qr::Data &data, int pixel, QColor color) {
p.drawImage( p.drawImage(
skip, skip,
skip, skip,
Intro::details::TelegramLogoImage().scaled( Window::LogoNoMargin().scaled(
logoSize * style::DevicePixelRatio(), logoSize,
logoSize * style::DevicePixelRatio(), logoSize,
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation)); Qt::SmoothTransformation));
} }

View file

@ -1240,8 +1240,8 @@ void DecorateListPromoBox(
box->setStyle(st::premiumPreviewDoubledLimitsBox); box->setStyle(st::premiumPreviewDoubledLimitsBox);
box->widthValue( box->widthValue(
) | rpl::start_with_next([=](int width) { ) | rpl::start_with_next([=](int width) {
const auto &padding = const auto &padding
st::premiumPreviewDoubledLimitsBox.buttonPadding; = st::premiumPreviewDoubledLimitsBox.buttonPadding;
button->resizeToWidth(width button->resizeToWidth(width
- padding.left() - padding.left()
- padding.right()); - padding.right());

View file

@ -90,7 +90,7 @@ QString ExtractRingtoneName(not_null<DocumentData*> document) {
} }
const auto name = document->filename(); const auto name = document->filename();
if (!name.isEmpty()) { if (!name.isEmpty()) {
const auto extension = Data::FileExtension(name); const auto extension = Core::FileExtension(name);
if (extension.isEmpty()) { if (extension.isEmpty()) {
return name; return name;
} else if (name.size() > extension.size() + 1) { } else if (name.size() > extension.size() + 1) {

View file

@ -611,8 +611,8 @@ void StickerSetBox::updateButtons() {
if (!_inner->shortName().isEmpty()) { if (!_inner->shortName().isEmpty()) {
const auto top = addTopButton(st::infoTopBarMenu); const auto top = addTopButton(st::infoTopBarMenu);
const auto menu = const auto menu
std::make_shared<base::unique_qptr<Ui::PopupMenu>>(); = std::make_shared<base::unique_qptr<Ui::PopupMenu>>();
top->setClickedCallback([=] { top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>( *menu = base::make_unique_q<Ui::PopupMenu>(
top, top,
@ -656,8 +656,8 @@ void StickerSetBox::updateButtons() {
_show->showBox(std::move(box)); _show->showBox(std::move(box));
} }
}; };
const auto menu = const auto menu
std::make_shared<base::unique_qptr<Ui::PopupMenu>>(); = std::make_shared<base::unique_qptr<Ui::PopupMenu>>();
top->setClickedCallback([=] { top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>( *menu = base::make_unique_q<Ui::PopupMenu>(
top, top,

View file

@ -945,8 +945,8 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
tgcalls::Descriptor descriptor = { tgcalls::Descriptor descriptor = {
.version = versionString, .version = versionString,
.config = tgcalls::Config{ .config = tgcalls::Config{
.initializationTimeout = .initializationTimeout
serverConfig.callConnectTimeoutMs / 1000., = serverConfig.callConnectTimeoutMs / 1000.,
.receiveTimeout = serverConfig.callPacketTimeoutMs / 1000., .receiveTimeout = serverConfig.callPacketTimeoutMs / 1000.,
.dataSaving = tgcalls::DataSaving::Never, .dataSaving = tgcalls::DataSaving::Never,
.enableP2P = call.is_p2p_allowed(), .enableP2P = call.is_p2p_allowed(),

View file

@ -277,11 +277,11 @@ private:
MTP::Sender _api; MTP::Sender _api;
Type _type = Type::Outgoing; Type _type = Type::Outgoing;
rpl::variable<State> _state = State::Starting; rpl::variable<State> _state = State::Starting;
rpl::variable<RemoteAudioState> _remoteAudioState = rpl::variable<RemoteAudioState> _remoteAudioState
RemoteAudioState::Active; = RemoteAudioState::Active;
rpl::variable<Webrtc::VideoState> _remoteVideoState; rpl::variable<Webrtc::VideoState> _remoteVideoState;
rpl::variable<RemoteBatteryState> _remoteBatteryState = rpl::variable<RemoteBatteryState> _remoteBatteryState
RemoteBatteryState::Normal; = RemoteBatteryState::Normal;
rpl::event_stream<Error> _errors; rpl::event_stream<Error> _errors;
FinishType _finishAfterRequestingCall = FinishType::None; FinishType _finishAfterRequestingCall = FinishType::None;
bool _answerAfterDhConfigReceived = false; bool _answerAfterDhConfigReceived = false;

View file

@ -162,8 +162,8 @@ private:
object_ptr<Ui::FlatLabel> _status; object_ptr<Ui::FlatLabel> _status;
object_ptr<Ui::RpWidget> _fingerprint = { nullptr }; object_ptr<Ui::RpWidget> _fingerprint = { nullptr };
object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _remoteAudioMute = { nullptr }; object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _remoteAudioMute = { nullptr };
object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _remoteLowBattery = object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _remoteLowBattery
{ nullptr }; = { nullptr };
std::unique_ptr<Userpic> _userpic; std::unique_ptr<Userpic> _userpic;
std::unique_ptr<VideoBubble> _outgoingVideoBubble; std::unique_ptr<VideoBubble> _outgoingVideoBubble;
QPixmap _bottomShadow; QPixmap _bottomShadow;

View file

@ -25,8 +25,8 @@ const auto kSpeakerThreshold = std::vector<float>{
50.0f / kMaxVolumePercent, 50.0f / kMaxVolumePercent,
150.0f / kMaxVolumePercent }; 150.0f / kMaxVolumePercent };
constexpr auto kVolumeStickedValues = constexpr auto kVolumeStickedValues
std::array<std::pair<float64, float64>, 7>{{ = std::array<std::pair<float64, float64>, 7>{{
{ 25. / kMaxVolumePercent, 2. / kMaxVolumePercent }, { 25. / kMaxVolumePercent, 2. / kMaxVolumePercent },
{ 50. / kMaxVolumePercent, 2. / kMaxVolumePercent }, { 50. / kMaxVolumePercent, 2. / kMaxVolumePercent },
{ 75. / kMaxVolumePercent, 2. / kMaxVolumePercent }, { 75. / kMaxVolumePercent, 2. / kMaxVolumePercent },
@ -93,8 +93,8 @@ MenuVolumeItem::MenuVolumeItem(
const auto volume = _localMuted const auto volume = _localMuted
? 0 ? 0
: base::SafeRound(_slider->value() * kMaxVolumePercent); : base::SafeRound(_slider->value() * kMaxVolumePercent);
const auto muteProgress = const auto muteProgress
_crossLineAnimation.value((!volume) ? 1. : 0.); = _crossLineAnimation.value((!volume) ? 1. : 0.);
const auto selected = isSelected(); const auto selected = isSelected();
p.fillRect(clip, selected ? st.itemBgOver : st.itemBg); p.fillRect(clip, selected ? st.itemBgOver : st.itemBg);
@ -174,8 +174,8 @@ MenuVolumeItem::MenuVolumeItem(
return; return;
} }
if (_waitingForUpdateVolume) { if (_waitingForUpdateVolume) {
const auto localVolume = const auto localVolume
base::SafeRound(_slider->value() * _maxVolume); = base::SafeRound(_slider->value() * _maxVolume);
if ((localVolume != newVolume) if ((localVolume != newVolume)
&& (_cloudVolume == newVolume)) { && (_cloudVolume == newVolume)) {
_changeVolumeRequests.fire(int(localVolume)); _changeVolumeRequests.fire(int(localVolume));

View file

@ -437,8 +437,8 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
auto filterNotPassedByUsername = [this](UserData *user) -> bool { auto filterNotPassedByUsername = [this](UserData *user) -> bool {
if (PrimaryUsername(user).startsWith(_filter, Qt::CaseInsensitive)) { if (PrimaryUsername(user).startsWith(_filter, Qt::CaseInsensitive)) {
const auto exactUsername = const auto exactUsername
(PrimaryUsername(user).size() == _filter.size()); = (PrimaryUsername(user).size() == _filter.size());
return exactUsername; return exactUsername;
} }
return true; return true;
@ -446,8 +446,9 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
auto filterNotPassedByName = [&](UserData *user) -> bool { auto filterNotPassedByName = [&](UserData *user) -> bool {
for (const auto &nameWord : user->nameWords()) { for (const auto &nameWord : user->nameWords()) {
if (nameWord.startsWith(_filter, Qt::CaseInsensitive)) { if (nameWord.startsWith(_filter, Qt::CaseInsensitive)) {
const auto exactUsername = const auto exactUsername = PrimaryUsername(user).compare(
(PrimaryUsername(user).compare(_filter, Qt::CaseInsensitive) == 0); _filter,
Qt::CaseInsensitive) == 0;
return exactUsername; return exactUsername;
} }
} }

View file

@ -933,8 +933,8 @@ void Application::handleAppDeactivated() {
} }
rpl::producer<bool> Application::appDeactivatedValue() const { rpl::producer<bool> Application::appDeactivatedValue() const {
const auto &app = const auto &app
static_cast<QGuiApplication*>(QCoreApplication::instance()); = static_cast<QGuiApplication*>(QCoreApplication::instance());
return rpl::single( return rpl::single(
app->applicationState() app->applicationState()
) | rpl::then( ) | rpl::then(

View file

@ -313,8 +313,8 @@ CloudPasswordState ParseCloudPasswordState(
ParseCloudPasswordAlgo(data.vnew_algo())); ParseCloudPasswordAlgo(data.vnew_algo()));
result.mtp.newSecureSecret = ValidateNewSecureSecretAlgo( result.mtp.newSecureSecret = ValidateNewSecureSecretAlgo(
ParseSecureSecretAlgo(data.vnew_secure_algo())); ParseSecureSecretAlgo(data.vnew_secure_algo()));
result.unconfirmedPattern = result.unconfirmedPattern = qs(
qs(data.vemail_unconfirmed_pattern().value_or_empty()); data.vemail_unconfirmed_pattern().value_or_empty());
result.pendingResetDate = data.vpending_reset_date().value_or_empty(); result.pendingResetDate = data.vpending_reset_date().value_or_empty();
result.outdatedClient = [&] { result.outdatedClient = [&] {

View file

@ -160,6 +160,10 @@ QByteArray Settings::serialize() const {
const auto &recentEmojiPreloadData = _recentEmojiPreload.empty() const auto &recentEmojiPreloadData = _recentEmojiPreload.empty()
? recentEmojiPreloadGenerated ? recentEmojiPreloadGenerated
: _recentEmojiPreload; : _recentEmojiPreload;
const auto noWarningExtensions = QStringList(
begin(_noWarningExtensions),
end(_noWarningExtensions)
).join(' ');
auto size = Serialize::bytearraySize(themesAccentColors) auto size = Serialize::bytearraySize(themesAccentColors)
+ sizeof(qint32) * 5 + sizeof(qint32) * 5
@ -216,7 +220,8 @@ QByteArray Settings::serialize() const {
+ Serialize::stringSize(_captureDeviceId.current()) + Serialize::stringSize(_captureDeviceId.current())
+ Serialize::stringSize(_callPlaybackDeviceId.current()) + Serialize::stringSize(_callPlaybackDeviceId.current())
+ Serialize::stringSize(_callCaptureDeviceId.current()) + Serialize::stringSize(_callCaptureDeviceId.current())
+ Serialize::bytearraySize(ivPosition); + Serialize::bytearraySize(ivPosition)
+ Serialize::stringSize(noWarningExtensions);
auto result = QByteArray(); auto result = QByteArray();
result.reserve(size); result.reserve(size);
@ -256,7 +261,7 @@ QByteArray Settings::serialize() const {
<< qint32(_sendSubmitWay) << qint32(_sendSubmitWay)
<< qint32(_includeMutedCounter ? 1 : 0) << qint32(_includeMutedCounter ? 1 : 0)
<< qint32(_countUnreadMessages ? 1 : 0) << qint32(_countUnreadMessages ? 1 : 0)
<< qint32(_exeLaunchWarning ? 1 : 0) << qint32(1) // legacy exe launch warning
<< qint32(_notifyAboutPinned.current() ? 1 : 0) << qint32(_notifyAboutPinned.current() ? 1 : 0)
<< qint32(_loopAnimatedStickers ? 1 : 0) << qint32(_loopAnimatedStickers ? 1 : 0)
<< qint32(_largeEmoji.current() ? 1 : 0) << qint32(_largeEmoji.current() ? 1 : 0)
@ -361,7 +366,8 @@ QByteArray Settings::serialize() const {
<< _captureDeviceId.current() << _captureDeviceId.current()
<< _callPlaybackDeviceId.current() << _callPlaybackDeviceId.current()
<< _callCaptureDeviceId.current() << _callCaptureDeviceId.current()
<< ivPosition; << ivPosition
<< noWarningExtensions;
} }
Ensures(result.size() == size); Ensures(result.size() == size);
@ -412,7 +418,8 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 sendSubmitWay = static_cast<qint32>(_sendSubmitWay); qint32 sendSubmitWay = static_cast<qint32>(_sendSubmitWay);
qint32 includeMutedCounter = _includeMutedCounter ? 1 : 0; qint32 includeMutedCounter = _includeMutedCounter ? 1 : 0;
qint32 countUnreadMessages = _countUnreadMessages ? 1 : 0; qint32 countUnreadMessages = _countUnreadMessages ? 1 : 0;
qint32 exeLaunchWarning = _exeLaunchWarning ? 1 : 0; std::optional<QString> noWarningExtensions;
qint32 legacyExeLaunchWarning = 1;
qint32 notifyAboutPinned = _notifyAboutPinned.current() ? 1 : 0; qint32 notifyAboutPinned = _notifyAboutPinned.current() ? 1 : 0;
qint32 loopAnimatedStickers = _loopAnimatedStickers ? 1 : 0; qint32 loopAnimatedStickers = _loopAnimatedStickers ? 1 : 0;
qint32 largeEmoji = _largeEmoji.current() ? 1 : 0; qint32 largeEmoji = _largeEmoji.current() ? 1 : 0;
@ -519,7 +526,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
>> sendSubmitWay >> sendSubmitWay
>> includeMutedCounter >> includeMutedCounter
>> countUnreadMessages >> countUnreadMessages
>> exeLaunchWarning >> legacyExeLaunchWarning
>> notifyAboutPinned >> notifyAboutPinned
>> loopAnimatedStickers >> loopAnimatedStickers
>> largeEmoji >> largeEmoji
@ -761,6 +768,10 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) { if (!stream.atEnd()) {
stream >> ivPosition; stream >> ivPosition;
} }
if (!stream.atEnd()) {
noWarningExtensions = QString();
stream >> *noWarningExtensions;
}
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("App Error: " LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()")); "Bad data for Core::Settings::constructFromSerialized()"));
@ -824,7 +835,12 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
} }
_includeMutedCounter = (includeMutedCounter == 1); _includeMutedCounter = (includeMutedCounter == 1);
_countUnreadMessages = (countUnreadMessages == 1); _countUnreadMessages = (countUnreadMessages == 1);
_exeLaunchWarning = (exeLaunchWarning == 1); if (noWarningExtensions) {
const auto list = noWarningExtensions->mid(0, 10240)
.split(' ', Qt::SkipEmptyParts)
.mid(0, 1024);
_noWarningExtensions = base::flat_set<QString>(list.begin(), list.end());
}
_ipRevealWarning = (ipRevealWarning == 1); _ipRevealWarning = (ipRevealWarning == 1);
_notifyAboutPinned = (notifyAboutPinned == 1); _notifyAboutPinned = (notifyAboutPinned == 1);
_loopAnimatedStickers = (loopAnimatedStickers == 1); _loopAnimatedStickers = (loopAnimatedStickers == 1);
@ -1290,7 +1306,7 @@ void Settings::resetOnLastLogout() {
//_sendSubmitWay = Ui::InputSubmitSettings::Enter; //_sendSubmitWay = Ui::InputSubmitSettings::Enter;
_soundOverrides = {}; _soundOverrides = {};
_exeLaunchWarning = true; _noWarningExtensions.clear();
_ipRevealWarning = true; _ipRevealWarning = true;
_loopAnimatedStickers = true; _loopAnimatedStickers = true;
_largeEmoji = true; _largeEmoji = true;

View file

@ -404,11 +404,12 @@ public:
} }
[[nodiscard]] QString getSoundPath(const QString &key) const; [[nodiscard]] QString getSoundPath(const QString &key) const;
[[nodiscard]] bool exeLaunchWarning() const { [[nodiscard]] auto noWarningExtensions() const
return _exeLaunchWarning; -> const base::flat_set<QString> & {
return _noWarningExtensions;
} }
void setExeLaunchWarning(bool warning) { void setNoWarningExtensions(base::flat_set<QString> extensions) {
_exeLaunchWarning = warning; _noWarningExtensions = std::move(extensions);
} }
[[nodiscard]] bool ipRevealWarning() const { [[nodiscard]] bool ipRevealWarning() const {
return _ipRevealWarning; return _ipRevealWarning;
@ -939,7 +940,7 @@ private:
Ui::SendFilesWay _sendFilesWay = Ui::SendFilesWay(); Ui::SendFilesWay _sendFilesWay = Ui::SendFilesWay();
Ui::InputSubmitSettings _sendSubmitWay = Ui::InputSubmitSettings(); Ui::InputSubmitSettings _sendSubmitWay = Ui::InputSubmitSettings();
base::flat_map<QString, QString> _soundOverrides; base::flat_map<QString, QString> _soundOverrides;
bool _exeLaunchWarning = true; base::flat_set<QString> _noWarningExtensions;
bool _ipRevealWarning = true; bool _ipRevealWarning = true;
bool _loopAnimatedStickers = true; bool _loopAnimatedStickers = true;
rpl::variable<bool> _largeEmoji = true; rpl::variable<bool> _largeEmoji = true;
@ -990,8 +991,8 @@ private:
#else // Q_OS_MAC #else // Q_OS_MAC
bool _hardwareAcceleratedVideo = false; bool _hardwareAcceleratedVideo = false;
#endif // Q_OS_MAC #endif // Q_OS_MAC
HistoryView::DoubleClickQuickAction _chatQuickAction = HistoryView::DoubleClickQuickAction _chatQuickAction
HistoryView::DoubleClickQuickAction(); = HistoryView::DoubleClickQuickAction();
bool _translateButtonEnabled = false; bool _translateButtonEnabled = false;
rpl::variable<bool> _translateChatEnabled = true; rpl::variable<bool> _translateChatEnabled = true;
rpl::variable<int> _translateToRaw = 0; rpl::variable<int> _translateToRaw = 0;

View file

@ -37,6 +37,12 @@ namespace {
&& data->hasImage(); && data->hasImage();
} }
[[nodiscard]] base::flat_set<QString> SplitExtensions(
const QString &joined) {
const auto list = joined.split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}
} // namespace } // namespace
MimeType::MimeType(const QMimeType &type) : _typeStruct(type) { MimeType::MimeType(const QMimeType &type) : _typeStruct(type) {
@ -162,22 +168,9 @@ bool IsMimeAcceptedForPhotoVideoAlbum(const QString &mime) {
} }
bool FileIsImage(const QString &name, const QString &mime) { bool FileIsImage(const QString &name, const QString &mime) {
QString lowermime = mime.toLower(), namelower = name.toLower(); return name.isEmpty()
if (lowermime.startsWith(u"image/"_q)) { ? mime.toLower().startsWith(u"image/"_q)
return true; : (DetectNameType(name) == NameType::Image);
} else if (namelower.endsWith(u".bmp"_q)
|| namelower.endsWith(u".jpg"_q)
|| namelower.endsWith(u".jpeg"_q)
|| namelower.endsWith(u".gif"_q)
|| namelower.endsWith(u".webp"_q)
|| namelower.endsWith(u".tga"_q)
|| namelower.endsWith(u".tiff"_q)
|| namelower.endsWith(u".tif"_q)
|| namelower.endsWith(u".psd"_q)
|| namelower.endsWith(u".png"_q)) {
return true;
}
return false;
} }
std::shared_ptr<QMimeData> ShareMimeMediaData( std::shared_ptr<QMimeData> ShareMimeMediaData(
@ -194,10 +187,10 @@ std::shared_ptr<QMimeData> ShareMimeMediaData(
result->setData(u"application/x-td-use-jpeg"_q, "1"); result->setData(u"application/x-td-use-jpeg"_q, "1");
result->setData(u"image/jpeg"_q, original->data(u"image/jpeg"_q)); result->setData(u"image/jpeg"_q, original->data(u"image/jpeg"_q));
} }
if (auto list = Core::ReadMimeUrls(original); !list.isEmpty()) { if (auto list = ReadMimeUrls(original); !list.isEmpty()) {
result->setUrls(std::move(list)); result->setUrls(std::move(list));
} }
result->setText(Core::ReadMimeText(original)); result->setText(ReadMimeText(original));
return result; return result;
} }
@ -240,4 +233,116 @@ bool CanSendFiles(not_null<const QMimeData*> data) {
return false; return false;
} }
QString FileExtension(const QString &filepath) {
const auto reversed = ranges::views::reverse(filepath);
const auto last = ranges::find_first_of(reversed, ".\\/");
if (last == reversed.end() || *last != '.') {
return QString();
}
return QString(last.base(), last - reversed.begin());
}
NameType DetectNameType(const QString &filepath) {
static const auto kImage = SplitExtensions(u"\
afdesign ai avif bmp dng gif heic icns ico jfif jpeg jpg jpg-large nef png \
png-large psd raw sketch svg tga tif tiff webp"_q);
static const auto kVideo = SplitExtensions(u"\
3g2 3gp 3gpp aep avi flv h264 m4s m4v mkv mov mp4 mpeg mpg ogv srt tgs tgv \
vob webm wmv"_q);
static const auto kAudio = SplitExtensions(u"\
aac ac3 aif amr caf cda cue flac m4a m4b mid midi mp3 ogg opus wav wma"_q);
static const auto kDocument = SplitExtensions(u"\
pdf doc docx ppt pptx pps ppsx xls xlsx txt rtf odt ods odp csv text log tl \
tex xspf xml djvu diag ps ost kml pub epub mobi cbr cbz fb2 prc ris pem p7b \
m3u m3u8 wpd wpl htm html xhtml key"_q);
static const auto kArchive = SplitExtensions(u"\
7z arj bz2 gz rar tar xz z zip zst"_q);
static const auto kThemeFile = SplitExtensions(u"\
tdesktop-theme tdesktop-palette tgios-theme attheme"_q);
static const auto kOtherBenign = SplitExtensions(u"\
c cc cpp cxx h m mm swift cs ts class java css ninja cmake patch diff plist \
gyp gitignore strings asoundrc torrent csr json xaml md keylayout sql \
sln xib mk \
\
dmg img iso vcd \
\
pdb eot ics ips ipa core mem pcap ovpn part pcapng dmp pkpass dat zxp crash \
file bak gbr plain dlc fon fnt otf ttc ttf gpx db rss cur \
\
tdesktop-endpoints"_q);
static const auto kExecutable = SplitExtensions(
#ifdef Q_OS_WIN
u"\
ad ade adp ahk app application appref-ms asp aspx asx bas bat bin cab cdxml \
cer cfg cgi chi chm cmd cnt com conf cpl crt csh der diagcab dll drv eml \
exe fon fxp gadget grp hlp hpj hta htt inf ini ins inx isp isu its jar jnlp \
job js jse jsp key ksh lexe library-ms lnk local lua mad maf mag mam \
manifest maq mar mas mat mau mav maw mcf mda mdb mde mdt mdw mdz mht mhtml \
mjs mmc mof msc msg msh msh1 msh2 msh1xml msh2xml mshxml msi msp mst ops \
osd paf pcd phar php php3 php4 php5 php7 phps php-s pht phtml pif pl plg pm \
pod prf prg ps1 ps2 ps1xml ps2xml psc1 psc2 psd1 psm1 pssc pst py py3 pyc \
pyd pyi pyo pyw pyzw pyz rb reg rgs scf scr sct search-ms settingcontent-ms \
sh shb shs slk sys swf t tmp u3p url vb vbe vbp vbs vbscript vdx vsmacros \
vsd vsdm vsdx vss vssm vssx vst vstm vstx vsw vsx vtx website wlua ws wsc \
wsf wsh xbap xll xlsm xnk xs"_q
#elif defined Q_OS_MAC // Q_OS_MAC
u"\
applescript action app bin command csh osx workflow terminal url caction \
mpkg pkg scpt scptd xhtm xhtml webarchive"_q
#else // Q_OS_WIN || Q_OS_MAC
u"bin csh deb desktop ksh out pet pkg pup rpm run sh shar slp zsh"_q
#endif // !Q_OS_WIN && !Q_OS_MAC
);
const auto extension = FileExtension(filepath).toLower();
if (kExecutable.contains(extension)) {
return NameType::Executable;
} else if (kImage.contains(extension)) {
return NameType::Image;
} else if (kVideo.contains(extension)) {
return NameType::Video;
} else if (kAudio.contains(extension)) {
return NameType::Audio;
} else if (kDocument.contains(extension)) {
return NameType::Document;
} else if (kArchive.contains(extension)) {
return NameType::Archive;
} else if (kThemeFile.contains(extension)) {
return NameType::ThemeFile;
} else if (kOtherBenign.contains(extension)) {
return NameType::OtherBenign;
}
return NameType::Unknown;
}
bool NameTypeAllowsThumbnail(NameType type) {
return type == NameType::Image
|| type == NameType::Video
|| type == NameType::Audio
|| type == NameType::Document
|| type == NameType::ThemeFile;
}
bool IsIpRevealingPath(const QString &filepath) {
static const auto kExtensions = [] {
const auto joined = u"htm html svg m4v m3u8 xhtml"_q;
const auto list = joined.split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}();
static const auto kMimeTypes = [] {
const auto joined = u"text/html image/svg+xml"_q;
const auto list = joined.split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}();
return ranges::binary_search(
kExtensions,
FileExtension(filepath).toLower()
) || ranges::binary_search(
kMimeTypes,
QMimeDatabase().mimeTypeForFile(QFileInfo(filepath)).name()
);
}
} // namespace Core } // namespace Core

View file

@ -69,4 +69,21 @@ struct MimeImageData {
[[nodiscard]] QList<QUrl> ReadMimeUrls(not_null<const QMimeData*> data); [[nodiscard]] QList<QUrl> ReadMimeUrls(not_null<const QMimeData*> data);
[[nodiscard]] bool CanSendFiles(not_null<const QMimeData*> data); [[nodiscard]] bool CanSendFiles(not_null<const QMimeData*> data);
enum class NameType : uchar {
Unknown,
Executable,
Image,
Video,
Audio,
Document,
Archive,
ThemeFile,
OtherBenign,
};
[[nodiscard]] QString FileExtension(const QString &filepath);
[[nodiscard]] NameType DetectNameType(const QString &filepath);
[[nodiscard]] bool NameTypeAllowsThumbnail(NameType type);
[[nodiscard]] bool IsIpRevealingPath(const QString &filepath);
} // namespace Core } // namespace Core

View file

@ -82,7 +82,6 @@ bool Sandbox::QuitOnStartRequested = false;
Sandbox::Sandbox(int &argc, char **argv) Sandbox::Sandbox(int &argc, char **argv)
: QApplication(argc, argv) : QApplication(argc, argv)
, _mainThreadId(QThread::currentThreadId()) { , _mainThreadId(QThread::currentThreadId()) {
setQuitOnLastWindowClosed(false);
} }
int Sandbox::start() { int Sandbox::start() {

View file

@ -107,6 +107,7 @@ private:
void readClients(); void readClients();
void removeClients(); void removeClients();
QEventLoopLocker _eventLoopLocker;
const Qt::HANDLE _mainThreadId = nullptr; const Qt::HANDLE _mainThreadId = nullptr;
int _eventNestingLevel = 0; int _eventNestingLevel = 0;
int _loopNestingLevel = 0; int _loopNestingLevel = 0;

View file

@ -230,8 +230,24 @@ void WriteDefaultCustomFile() {
const auto path = CustomFilePath(); const auto path = CustomFilePath();
auto input = QFile(":/misc/default_shortcuts-custom.json"); auto input = QFile(":/misc/default_shortcuts-custom.json");
auto output = QFile(path); auto output = QFile(path);
if (input.open(QIODevice::ReadOnly) && output.open(QIODevice::WriteOnly)) { if (input.open(QIODevice::ReadOnly)
&& output.open(QIODevice::WriteOnly)) {
#ifdef Q_OS_MAC
auto text = qs(input.readAll());
const auto note = R"(
// Note:
// On Apple platforms, reference to "ctrl" corresponds to the Command keys )"
+ QByteArray()
+ R"(on the Macintosh keyboard.
// On Apple platforms, reference to "meta" corresponds to the Control keys.
[
)";
text.replace(u"\n\n["_q, QString(note));
output.write(text.toUtf8());
#else
output.write(input.readAll()); output.write(input.readAll());
#endif // !Q_OS_MAC
} }
} }

View file

@ -13,9 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/sandbox.h" #include "core/sandbox.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "data/components/sponsored_messages.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "iv/iv_instance.h" #include "iv/iv_instance.h"
#include "ui/text/text_custom_emoji.h" #include "ui/text/text_custom_emoji.h"
#include "ui/basic_click_handlers.h" #include "ui/basic_click_handlers.h"
@ -303,7 +303,7 @@ bool UiIntegration::allowClickHandlerActivation(
const ClickContext &context) { const ClickContext &context) {
const auto my = context.other.value<ClickHandlerContext>(); const auto my = context.other.value<ClickHandlerContext>();
if (const auto window = my.sessionWindow.get()) { if (const auto window = my.sessionWindow.get()) {
window->session().data().sponsoredMessages().clicked(my.itemId); window->session().sponsoredMessages().clicked(my.itemId);
} }
return true; return true;
} }

View file

@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
constexpr auto AppNameOld = "AyuGram for Windows"_cs; constexpr auto AppNameOld = "AyuGram for Windows"_cs;
constexpr auto AppName = "AyuGram Desktop"_cs; constexpr auto AppName = "AyuGram Desktop"_cs;
constexpr auto AppFile = "AyuGram"_cs; constexpr auto AppFile = "AyuGram"_cs;
constexpr auto AppVersion = 4016006; constexpr auto AppVersion = 4016008;
constexpr auto AppVersionStr = "4.16.6"; constexpr auto AppVersionStr = "4.16.8";
constexpr auto AppBetaVersion = false; constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "data/data_scheduled_messages.h" #include "data/components/scheduled_messages.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
@ -101,10 +101,10 @@ bool IsScheduledMsgId(MsgId id) {
return (id > ServerMaxMsgId) && (id < ScheduledMaxMsgId); return (id > ServerMaxMsgId) && (id < ScheduledMaxMsgId);
} }
ScheduledMessages::ScheduledMessages(not_null<Session*> owner) ScheduledMessages::ScheduledMessages(not_null<Main::Session*> session)
: _session(&owner->session()) : _session(session)
, _clearTimer([=] { clearOldRequests(); }) { , _clearTimer([=] { clearOldRequests(); }) {
owner->itemRemoved( _session->data().itemRemoved(
) | rpl::filter([](not_null<const HistoryItem*> item) { ) | rpl::filter([](not_null<const HistoryItem*> item) {
return item->isScheduled(); return item->isScheduled();
}) | rpl::start_with_next([=](not_null<const HistoryItem*> item) { }) | rpl::start_with_next([=](not_null<const HistoryItem*> item) {
@ -113,9 +113,16 @@ ScheduledMessages::ScheduledMessages(not_null<Session*> owner)
} }
ScheduledMessages::~ScheduledMessages() { ScheduledMessages::~ScheduledMessages() {
for (const auto &request : _requests) { Expects(_data.empty());
Expects(_requests.empty());
}
void ScheduledMessages::clear() {
_lifetime.destroy();
for (const auto &request : base::take(_requests)) {
_session->api().request(request.second.requestId).cancel(); _session->api().request(request.second.requestId).cancel();
} }
base::take(_data);
} }
void ScheduledMessages::clearOldRequests() { void ScheduledMessages::clearOldRequests() {

View file

@ -18,14 +18,13 @@ class Session;
namespace Data { namespace Data {
class Session;
struct MessagesSlice; struct MessagesSlice;
[[nodiscard]] bool IsScheduledMsgId(MsgId id); [[nodiscard]] bool IsScheduledMsgId(MsgId id);
class ScheduledMessages final { class ScheduledMessages final {
public: public:
explicit ScheduledMessages(not_null<Session*> owner); explicit ScheduledMessages(not_null<Main::Session*> session);
ScheduledMessages(const ScheduledMessages &other) = delete; ScheduledMessages(const ScheduledMessages &other) = delete;
ScheduledMessages &operator=(const ScheduledMessages &other) = delete; ScheduledMessages &operator=(const ScheduledMessages &other) = delete;
~ScheduledMessages(); ~ScheduledMessages();
@ -56,6 +55,8 @@ public:
[[nodiscard]] Data::MessagesSlice list( [[nodiscard]] Data::MessagesSlice list(
not_null<const Data::ForumTopic*> topic) const; not_null<const Data::ForumTopic*> topic) const;
void clear();
private: private:
using OwnedItem = std::unique_ptr<HistoryItem, HistoryItem::Destroyer>; using OwnedItem = std::unique_ptr<HistoryItem, HistoryItem::Destroyer>;
struct List { struct List {

View file

@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "data/data_sponsored_messages.h" #include "data/components/sponsored_messages.h"
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -34,8 +34,8 @@ constexpr auto kRequestTimeLimit = 5 * 60 * crl::time(1000);
} // namespace } // namespace
SponsoredMessages::SponsoredMessages(not_null<Session*> owner) SponsoredMessages::SponsoredMessages(not_null<Main::Session*> session)
: _session(&owner->session()) : _session(session)
, _clearTimer([=] { clearOldRequests(); }) { , _clearTimer([=] { clearOldRequests(); }) {
} }

View file

@ -20,8 +20,6 @@ class Session;
namespace Data { namespace Data {
class Session;
struct SponsoredReportResult final { struct SponsoredReportResult final {
using Id = QByteArray; using Id = QByteArray;
struct Option final { struct Option final {
@ -89,7 +87,7 @@ public:
bool canReport = false; bool canReport = false;
}; };
using RandomId = QByteArray; using RandomId = QByteArray;
explicit SponsoredMessages(not_null<Session*> owner); explicit SponsoredMessages(not_null<Main::Session*> session);
SponsoredMessages(const SponsoredMessages &other) = delete; SponsoredMessages(const SponsoredMessages &other) = delete;
SponsoredMessages &operator=(const SponsoredMessages &other) = delete; SponsoredMessages &operator=(const SponsoredMessages &other) = delete;
~SponsoredMessages(); ~SponsoredMessages();

View file

@ -22,6 +22,14 @@ CloudFile::~CloudFile() {
base::take(loader); base::take(loader);
} }
void CloudFile::clear() {
location = {};
base::take(loader);
byteSize = 0;
progressivePartSize = 0;
flags = {};
}
CloudImage::CloudImage() = default; CloudImage::CloudImage() = default;
CloudImage::CloudImage( CloudImage::CloudImage(

View file

@ -37,6 +37,8 @@ struct CloudFile final {
~CloudFile(); ~CloudFile();
void clear();
ImageLocation location; ImageLocation location;
std::unique_ptr<FileLoader> loader; std::unique_ptr<FileLoader> loader;
int byteSize = 0; int byteSize = 0;

View file

@ -478,6 +478,31 @@ void DocumentData::setattributes(
_additional = nullptr; _additional = nullptr;
} }
if (!_filename.isEmpty()) {
using Type = Core::NameType;
if (type == VideoDocument
|| type == AnimatedDocument
|| type == RoundVideoDocument
|| isAnimation()) {
if (!enforceNameType(Type::Video)) {
type = FileDocument;
_additional = nullptr;
}
}
if (type == SongDocument || type == VoiceDocument || isAudioFile()) {
if (!enforceNameType(Type::Audio)) {
type = FileDocument;
_additional = nullptr;
}
}
if (!Core::NameTypeAllowsThumbnail(_nameType)) {
_inlineThumbnailBytes = {};
_flags &= ~Flag::InlineThumbnailIsPath;
_thumbnail.clear();
_videoThumbnail.clear();
}
}
if (isAudioFile() if (isAudioFile()
|| isAnimation() || isAnimation()
|| isVoiceMessage() || isVoiceMessage()
@ -530,6 +555,10 @@ void DocumentData::updateThumbnails(
const ImageWithLocation &thumbnail, const ImageWithLocation &thumbnail,
const ImageWithLocation &videoThumbnail, const ImageWithLocation &videoThumbnail,
bool isPremiumSticker) { bool isPremiumSticker) {
if (!_filename.isEmpty()
&& !Core::NameTypeAllowsThumbnail(Core::DetectNameType(_filename))) {
return;
}
if (!inlineThumbnail.bytes.isEmpty() if (!inlineThumbnail.bytes.isEmpty()
&& _inlineThumbnailBytes.isEmpty()) { && _inlineThumbnailBytes.isEmpty()) {
_inlineThumbnailBytes = inlineThumbnail.bytes; _inlineThumbnailBytes = inlineThumbnail.bytes;
@ -919,6 +948,25 @@ void DocumentData::setFileName(const QString &remoteFileName) {
for (const auto &ch : controls) { for (const auto &ch : controls) {
_filename = std::move(_filename).replace(ch, "_"); _filename = std::move(_filename).replace(ch, "_");
} }
_nameType = Core::DetectNameType(_filename);
}
bool DocumentData::enforceNameType(Core::NameType nameType) {
if (_nameType == nameType) {
return true;
}
const auto base = _filename.isEmpty() ? u"file"_q : _filename;
const auto mime = Core::MimeTypeForName(mimeString());
const auto patterns = mime.globPatterns();
for (const auto &pattern : mime.globPatterns()) {
const auto now = base + QString(pattern).replace('*', QString());
if (Core::DetectNameType(now) == nameType) {
_filename = now;
_nameType = nameType;
return true;
}
}
return false;
} }
void DocumentData::setLoadedInMediaCacheLocation() { void DocumentData::setLoadedInMediaCacheLocation() {
@ -1460,6 +1508,10 @@ QString DocumentData::filename() const {
return _filename; return _filename;
} }
Core::NameType DocumentData::nameType() const {
return _nameType;
}
QString DocumentData::mimeString() const { QString DocumentData::mimeString() const {
return _mimeString; return _mimeString;
} }
@ -1527,7 +1579,10 @@ bool DocumentData::isVideoMessage() const {
bool DocumentData::isAnimation() const { bool DocumentData::isAnimation() const {
return (type == AnimatedDocument) return (type == AnimatedDocument)
|| isVideoMessage() || isVideoMessage()
|| (hasMimeType(u"image/gif"_q) || ((_filename.isEmpty()
|| _nameType == Core::NameType::Image
|| _nameType == Core::NameType::Video)
&& hasMimeType(u"image/gif"_q)
&& !(_flags & Flag::StreamingPlaybackFailed)); && !(_flags & Flag::StreamingPlaybackFailed));
} }
@ -1537,9 +1592,11 @@ bool DocumentData::isGifv() const {
} }
bool DocumentData::isTheme() const { bool DocumentData::isTheme() const {
return hasMimeType(u"application/x-tgtheme-tdesktop"_q) return _filename.endsWith(u".tdesktop-theme"_q, Qt::CaseInsensitive)
|| _filename.endsWith(u".tdesktop-theme"_q, Qt::CaseInsensitive) || _filename.endsWith(u".tdesktop-palette"_q, Qt::CaseInsensitive)
|| _filename.endsWith(u".tdesktop-palette"_q, Qt::CaseInsensitive); || (hasMimeType(u"application/x-tgtheme-tdesktop"_q)
&& (_filename.isEmpty()
|| _nameType == Core::NameType::ThemeFile));
} }
bool DocumentData::isSong() const { bool DocumentData::isSong() const {
@ -1562,6 +1619,10 @@ bool DocumentData::isAudioFile() const {
return true; return true;
} }
return false; return false;
} else if (!_filename.isEmpty()
&& _nameType != Core::NameType::Audio
&& _nameType != Core::NameType::Video) {
return false;
} }
const auto left = _mimeString.mid(prefix.size()); const auto left = _mimeString.mid(prefix.size());
const auto types = { u"x-wav"_q, u"wav"_q, u"mp4"_q }; const auto types = { u"x-wav"_q, u"wav"_q, u"mp4"_q };

View file

@ -20,6 +20,10 @@ namespace Images {
class Source; class Source;
} // namespace Images } // namespace Images
namespace Core {
enum class NameType : uchar;
} // namespace Core
namespace Storage { namespace Storage {
namespace Cache { namespace Cache {
struct Key; struct Key;
@ -255,6 +259,7 @@ public:
void collectLocalData(not_null<DocumentData*> local); void collectLocalData(not_null<DocumentData*> local);
[[nodiscard]] QString filename() const; [[nodiscard]] QString filename() const;
[[nodiscard]] Core::NameType nameType() const;
[[nodiscard]] QString mimeString() const; [[nodiscard]] QString mimeString() const;
[[nodiscard]] bool hasMimeType(const QString &mime) const; [[nodiscard]] bool hasMimeType(const QString &mime) const;
void setMimeString(const QString &mime); void setMimeString(const QString &mime);
@ -340,6 +345,7 @@ private:
void setMaybeSupportsStreaming(bool supports); void setMaybeSupportsStreaming(bool supports);
void setLoadedInMediaCacheLocation(); void setLoadedInMediaCacheLocation();
void setFileName(const QString &remoteFileName); void setFileName(const QString &remoteFileName);
bool enforceNameType(Core::NameType nameType);
void finishLoad(); void finishLoad();
void handleLoaderUpdates(); void handleLoaderUpdates();
@ -373,6 +379,7 @@ private:
std::unique_ptr<DocumentAdditionalData> _additional; std::unique_ptr<DocumentAdditionalData> _additional;
mutable Flags _flags = kStreamingSupportedUnknown; mutable Flags _flags = kStreamingSupportedUnknown;
GoodThumbnailState _goodThumbnailState = GoodThumbnailState(); GoodThumbnailState _goodThumbnailState = GoodThumbnailState();
Core::NameType _nameType = Core::NameType();
std::unique_ptr<FileLoader> _loader; std::unique_ptr<FileLoader> _loader;
}; };

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_theme_preview.h" #include "window/themes/window_theme_preview.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "core/application.h" #include "core/application.h"
#include "core/mime_type.h"
#include "storage/file_download.h" #include "storage/file_download.h"
#include "ui/chat/attach/attach_prepare.h" #include "ui/chat/attach/attach_prepare.h"
@ -295,10 +296,12 @@ void DocumentMedia::automaticLoad(
// No automatic download in this case. // No automatic download in this case.
return; return;
} }
const auto indata = _owner->filename();
const auto filename = toCache const auto filename = toCache
? QString() ? QString()
: DocumentFileNameForSave(_owner); : DocumentFileNameForSave(_owner);
const auto shouldLoadFromCloud = !Data::IsExecutableName(filename) const auto shouldLoadFromCloud = (indata.isEmpty()
|| Core::DetectNameType(indata) != Core::NameType::Executable)
&& (item && (item
? Data::AutoDownload::Should( ? Data::AutoDownload::Should(
_owner->session().settings().autoDownload(), _owner->session().settings().autoDownload(),

View file

@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/wrap/slide_wrap.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -46,11 +47,12 @@ base::options::toggle OptionExternalVideoPlayer({
void ConfirmDontWarnBox( void ConfirmDontWarnBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
rpl::producer<TextWithEntities> &&text, rpl::producer<TextWithEntities> &&text,
rpl::producer<QString> &&check,
rpl::producer<QString> &&confirm, rpl::producer<QString> &&confirm,
Fn<void(bool)> callback) { Fn<void(bool)> callback) {
auto checkbox = object_ptr<Ui::Checkbox>( auto checkbox = object_ptr<Ui::Checkbox>(
box.get(), box.get(),
tr::lng_launch_exe_dont_ask(), std::move(check),
false, false,
st::defaultBoxCheckbox); st::defaultBoxCheckbox);
const auto weak = Ui::MakeWeak(checkbox.data()); const auto weak = Ui::MakeWeak(checkbox.data());
@ -67,29 +69,43 @@ void ConfirmDontWarnBox(
auto padding = st::boxPadding; auto padding = st::boxPadding;
padding.setTop(padding.bottom()); padding.setTop(padding.bottom());
box->addRow(std::move(checkbox), std::move(padding)); box->addRow(std::move(checkbox), std::move(padding));
box->addRow(object_ptr<Ui::SlideWrap<Ui::FlatLabel>>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_launch_dont_ask_settings(),
st::boxLabel)
))->toggleOn(weak->checkedValue());
} }
void LaunchWithWarning( void LaunchWithWarning(
// not_null<Window::Controller*> controller, // not_null<Window::Controller*> controller,
const QString &name, const QString &name,
HistoryItem *item) { HistoryItem *item) {
const auto isExecutable = Data::IsExecutableName(name); const auto nameType = Core::DetectNameType(name);
const auto isIpReveal = Data::IsIpRevealingName(name); const auto isIpReveal = (nameType != Core::NameType::Executable)
&& Core::IsIpRevealingPath(name);
const auto extension = Core::FileExtension(name).toLower();
auto &app = Core::App(); auto &app = Core::App();
auto &settings = app.settings();
const auto warn = [&] { const auto warn = [&] {
if (item && item->history()->peer->isVerified()) { if (item && item->history()->peer->isVerified()) {
return false; return false;
} }
return (isExecutable && app.settings().exeLaunchWarning()) return (isIpReveal && settings.ipRevealWarning())
|| (isIpReveal && app.settings().ipRevealWarning()); || ((nameType == Core::NameType::Executable
|| nameType == Core::NameType::Unknown)
&& !settings.noWarningExtensions().contains(extension));
}(); }();
const auto extension = '.' + Data::FileExtension(name); if (extension.isEmpty()) {
if (Platform::IsWindows() && extension == u"."_q) {
// If you launch a file without extension, like "test", in case // If you launch a file without extension, like "test", in case
// there is an executable file with the same name in this folder, // there is an executable file with the same name in this folder,
// like "test.bat", the executable file will be launched. // like "test.bat", the executable file will be launched.
// //
// Now we always force an Open With dialog box for such files. // Now we always force an Open With dialog box for such files.
//
// Let's force it for all platforms for files without extension.
crl::on_main([=] { crl::on_main([=] {
Platform::File::UnsafeShowOpenWith(name); Platform::File::UnsafeShowOpenWith(name);
}); });
@ -98,27 +114,38 @@ void LaunchWithWarning(
File::Launch(name); File::Launch(name);
return; return;
} }
const auto callback = [=, &app](bool checked) { const auto callback = [=, &app, &settings](bool checked) {
if (checked) { if (checked) {
if (isExecutable) { if (isIpReveal) {
app.settings().setExeLaunchWarning(false); settings.setIpRevealWarning(false);
} else if (isIpReveal) { } else {
app.settings().setIpRevealWarning(false); auto copy = settings.noWarningExtensions();
copy.emplace(extension);
settings.setNoWarningExtensions(std::move(copy));
} }
app.saveSettingsDelayed(); app.saveSettingsDelayed();
} }
File::Launch(name); File::Launch(name);
}; };
auto text = isExecutable auto text = isIpReveal
? tr::lng_launch_exe_warning( ? tr::lng_launch_svg_warning(Ui::Text::WithEntities)
lt_extension, : ((nameType == Core::NameType::Executable)
rpl::single(Ui::Text::Bold(extension)), ? tr::lng_launch_exe_warning
Ui::Text::WithEntities) : tr::lng_launch_other_warning)(
: tr::lng_launch_svg_warning(Ui::Text::WithEntities); lt_extension,
rpl::single(Ui::Text::Bold('.' + extension)),
Ui::Text::WithEntities);
auto check = (isIpReveal
? tr::lng_launch_exe_dont_ask
: tr::lng_launch_dont_ask)();
auto confirm = ((nameType == Core::NameType::Executable)
? tr::lng_launch_exe_sure
: tr::lng_launch_other_sure)();
Ui::show(Box( Ui::show(Box(
ConfirmDontWarnBox, ConfirmDontWarnBox,
std::move(text), std::move(text),
(isExecutable ? tr::lng_launch_exe_sure : tr::lng_continue)(), std::move(check),
std::move(confirm),
callback)); callback));
} }
@ -126,91 +153,6 @@ void LaunchWithWarning(
const char kOptionExternalVideoPlayer[] = "external-video-player"; const char kOptionExternalVideoPlayer[] = "external-video-player";
QString FileExtension(const QString &filepath) {
const auto reversed = ranges::views::reverse(filepath);
const auto last = ranges::find_first_of(reversed, ".\\/");
if (last == reversed.end() || *last != '.') {
return QString();
}
return QString(last.base(), last - reversed.begin());
}
#if 0
bool IsValidMediaFile(const QString &filepath) {
static const auto kExtensions = [] {
const auto list = qsl("\
16svx 2sf 3g2 3gp 8svx aac aaf aif aifc aiff amr amv ape asf ast au aup \
avchd avi brstm bwf cam cdda cust dat divx drc dsh dsf dts dtshd dtsma \
dvr-ms dwd evo f4a f4b f4p f4v fla flac flr flv gif gifv gsf gsm gym iff \
ifo it jam la ly m1v m2p m2ts m2v m4a m4p m4v mcf mid mk3d mka mks mkv mng \
mov mp1 mp2 mp3 mp4 minipsf mod mpc mpe mpeg mpg mpv mscz mt2 mus mxf mxl \
niff nsf nsv off ofr ofs ogg ogv opus ots pac ps psf psf2 psflib ptb qsf \
qt ra raw rka rm rmj rmvb roq s3m shn sib sid smi smp sol spc spx ssf svi \
swa swf tak ts tta txm usf vgm vob voc vox vqf wav webm wma wmv wrap wtv \
wv xm xml ym yuv").split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}();
return ranges::binary_search(
kExtensions,
FileExtension(filepath).toLower());
}
#endif
bool IsExecutableName(const QString &filepath) {
static const auto kExtensions = [] {
const auto joined =
#ifdef Q_OS_WIN
u"\
ad ade adp app application appref-ms asp asx bas bat bin cab cdxml cer cfg \
chi chm cmd cnt com cpl crt csh der diagcab dll drv eml exe fon fxp gadget \
grp hlp hpj hta htt inf ini ins inx isp isu its jar jnlp job js jse key ksh \
lnk local lua mad maf mag mam manifest maq mar mas mat mau mav maw mcf mda \
mdb mde mdt mdw mdz mht mhtml mjs mmc mof msc msg msh msh1 msh2 msh1xml \
msh2xml mshxml msi msp mst ops osd paf pcd phar php php3 php4 php5 php7 phps \
php-s pht phtml pif pl plg pm pod prf prg ps1 ps2 ps1xml ps2xml psc1 psc2 \
psd1 psm1 pssc pst py py3 pyc pyd pyi pyo pyw pywz pyz rb reg rgs scf scr \
sct search-ms settingcontent-ms sh shb shs slk sys t tmp u3p url vb vbe vbp \
vbs vbscript vdx vsmacros vsd vsdm vsdx vss vssm vssx vst vstm vstx vsw vsx \
vtx website ws wsc wsf wsh xbap xll xnk xs"_q;
#elif defined Q_OS_MAC // Q_OS_MAC
u"\
applescript action app bin command csh osx workflow terminal url caction \
mpkg pkg scpt scptd xhtm webarchive"_q;
#else // Q_OS_WIN || Q_OS_MAC
u"bin csh deb desktop ksh out pet pkg pup rpm run sh shar \
slp zsh"_q;
#endif // !Q_OS_WIN && !Q_OS_MAC
const auto list = joined.split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}();
return ranges::binary_search(
kExtensions,
FileExtension(filepath).toLower());
}
bool IsIpRevealingName(const QString &filepath) {
static const auto kExtensions = [] {
const auto joined = u"htm html svg m4v m3u8"_q;
const auto list = joined.split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}();
static const auto kMimeTypes = [] {
const auto joined = u"text/html image/svg+xml"_q;
const auto list = joined.split(' ');
return base::flat_set<QString>(list.begin(), list.end());
}();
return ranges::binary_search(
kExtensions,
FileExtension(filepath).toLower()
) || ranges::binary_search(
kMimeTypes,
QMimeDatabase().mimeTypeForFile(QFileInfo(filepath)).name()
);
}
base::binary_guard ReadBackgroundImageAsync( base::binary_guard ReadBackgroundImageAsync(
not_null<Data::DocumentMedia*> media, not_null<Data::DocumentMedia*> media,
FnMut<QImage(QImage)> postprocess, FnMut<QImage(QImage)> postprocess,

View file

@ -22,10 +22,6 @@ class DocumentMedia;
extern const char kOptionExternalVideoPlayer[]; extern const char kOptionExternalVideoPlayer[];
[[nodiscard]] QString FileExtension(const QString &filepath);
// [[nodiscard]] bool IsValidMediaFile(const QString &filepath);
[[nodiscard]] bool IsExecutableName(const QString &filepath);
[[nodiscard]] bool IsIpRevealingName(const QString &filepath);
base::binary_guard ReadBackgroundImageAsync( base::binary_guard ReadBackgroundImageAsync(
not_null<Data::DocumentMedia*> media, not_null<Data::DocumentMedia*> media,
FnMut<QImage(QImage)> postprocess, FnMut<QImage(QImage)> postprocess,

View file

@ -9,13 +9,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_scheduled_messages.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/random.h" #include "base/random.h"
@ -846,11 +846,12 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) {
if (item->isScheduled()) { if (item->isScheduled()) {
const auto wasOnServer = !item->isSending() const auto wasOnServer = !item->isSending()
&& !item->hasFailed(); && !item->hasFailed();
auto &scheduled = _owner->session().scheduledMessages();
if (wasOnServer) { if (wasOnServer) {
scheduledIdsByPeer[history->peer].push_back(MTP_int( scheduledIdsByPeer[history->peer].push_back(
_owner->scheduledMessages().lookupId(item))); MTP_int(scheduled.lookupId(item)));
} else { } else {
_owner->scheduledMessages().removeSending(item); scheduled.removeSending(item);
} }
continue; continue;
} else if (item->isBusinessShortcut()) { } else if (item->isBusinessShortcut()) {

View file

@ -121,8 +121,8 @@ bool PollData::applyResults(const MTPPollResults &results) {
return results.match([&](const MTPDpollResults &results) { return results.match([&](const MTPDpollResults &results) {
_lastResultsUpdate = crl::now(); _lastResultsUpdate = crl::now();
const auto newTotalVoters = const auto newTotalVoters
results.vtotal_voters().value_or(totalVoters); = results.vtotal_voters().value_or(totalVoters);
auto changed = (newTotalVoters != totalVoters); auto changed = (newTotalVoters != totalVoters);
if (const auto list = results.vresults()) { if (const auto list = results.vresults()) {
for (const auto &result : list->v) { for (const auto &result : list->v) {

View file

@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/business/data_business_chatbots.h" #include "data/business/data_business_chatbots.h"
#include "data/business/data_business_info.h" #include "data/business/data_business_info.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/data_bot_app.h" #include "data/data_bot_app.h"
@ -56,9 +57,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_poll.h" #include "data/data_poll.h"
#include "data/data_replies_list.h" #include "data/data_replies_list.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_scheduled_messages.h"
#include "data/data_send_action.h" #include "data/data_send_action.h"
#include "data/data_sponsored_messages.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
#include "data/data_emoji_statuses.h" #include "data/data_emoji_statuses.h"
#include "data/data_forum_icons.h" #include "data/data_forum_icons.h"
@ -278,9 +277,7 @@ Session::Session(not_null<Main::Session*> session)
, _savedMessages(std::make_unique<SavedMessages>(this)) , _savedMessages(std::make_unique<SavedMessages>(this))
, _chatbots(std::make_unique<Chatbots>(this)) , _chatbots(std::make_unique<Chatbots>(this))
, _businessInfo(std::make_unique<BusinessInfo>(this)) , _businessInfo(std::make_unique<BusinessInfo>(this))
, _scheduledMessages(std::make_unique<ScheduledMessages>(this)) , _shortcutMessages(std::make_unique<ShortcutMessages>(this)) {
, _shortcutMessages(std::make_unique<ShortcutMessages>(this))
, _sponsoredMessages(std::make_unique<SponsoredMessages>(this)) {
_cache->open(_session->local().cacheKey()); _cache->open(_session->local().cacheKey());
_bigFileCache->open(_session->local().cacheBigFileKey()); _bigFileCache->open(_session->local().cacheBigFileKey());
@ -407,9 +404,8 @@ void Session::clear() {
_sendActionManager->clear(); _sendActionManager->clear();
_histories->unloadAll(); _histories->unloadAll();
_scheduledMessages = nullptr;
_shortcutMessages = nullptr; _shortcutMessages = nullptr;
_sponsoredMessages = nullptr; _session->scheduledMessages().clear();
_dependentMessages.clear(); _dependentMessages.clear();
base::take(_messages); base::take(_messages);
base::take(_nonChannelMessages); base::take(_nonChannelMessages);

View file

@ -47,10 +47,8 @@ namespace Data {
class Folder; class Folder;
class LocationPoint; class LocationPoint;
class WallPaper; class WallPaper;
class ScheduledMessages;
class ShortcutMessages; class ShortcutMessages;
class SendActionManager; class SendActionManager;
class SponsoredMessages;
class Reactions; class Reactions;
class EmojiStatuses; class EmojiStatuses;
class ForumIcons; class ForumIcons;
@ -104,9 +102,6 @@ public:
[[nodiscard]] ChatFilters &chatsFilters() const { [[nodiscard]] ChatFilters &chatsFilters() const {
return *_chatsFilters; return *_chatsFilters;
} }
[[nodiscard]] ScheduledMessages &scheduledMessages() const {
return *_scheduledMessages;
}
[[nodiscard]] ShortcutMessages &shortcutMessages() const { [[nodiscard]] ShortcutMessages &shortcutMessages() const {
return *_shortcutMessages; return *_shortcutMessages;
} }
@ -128,9 +123,6 @@ public:
[[nodiscard]] Stickers &stickers() const { [[nodiscard]] Stickers &stickers() const {
return *_stickers; return *_stickers;
} }
[[nodiscard]] SponsoredMessages &sponsoredMessages() const {
return *_sponsoredMessages;
}
[[nodiscard]] Reactions &reactions() const { [[nodiscard]] Reactions &reactions() const {
return *_reactions; return *_reactions;
} }
@ -1084,9 +1076,7 @@ private:
const std::unique_ptr<SavedMessages> _savedMessages; const std::unique_ptr<SavedMessages> _savedMessages;
const std::unique_ptr<Chatbots> _chatbots; const std::unique_ptr<Chatbots> _chatbots;
const std::unique_ptr<BusinessInfo> _businessInfo; const std::unique_ptr<BusinessInfo> _businessInfo;
std::unique_ptr<ScheduledMessages> _scheduledMessages;
std::unique_ptr<ShortcutMessages> _shortcutMessages; std::unique_ptr<ShortcutMessages> _shortcutMessages;
std::unique_ptr<SponsoredMessages> _sponsoredMessages;
MsgId _nonHistoryEntryId = ShortcutMaxMsgId; MsgId _nonHistoryEntryId = ShortcutMaxMsgId;

View file

@ -13,10 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_facade.h" #include "storage/storage_facade.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "data/components/scheduled_messages.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
#include "data/data_photo.h" #include "data/data_photo.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "core/crash_reports.h" #include "core/crash_reports.h"
@ -193,9 +193,9 @@ rpl::producer<SparseIdsMergedSlice> SharedScheduledMediaViewer(
const auto history = session->data().history(key.mergedKey.peerId); const auto history = session->data().history(key.mergedKey.peerId);
return rpl::single(rpl::empty) | rpl::then( return rpl::single(rpl::empty) | rpl::then(
session->data().scheduledMessages().updates(history) session->scheduledMessages().updates(history)
) | rpl::map([=] { ) | rpl::map([=] {
const auto list = session->data().scheduledMessages().list(history); const auto list = session->scheduledMessages().list(history);
auto items = ranges::views::all( auto items = ranges::views::all(
list.ids list.ids

View file

@ -30,14 +30,15 @@ struct StatisticalChart {
[[nodiscard]] int findIndex(int left, int right, float64 v) const; [[nodiscard]] int findIndex(int left, int right, float64 v) const;
struct Line final { struct Line final {
std::vector<int> y; std::vector<Statistic::ChartValue> y;
Statistic::SegmentTree segmentTree; Statistic::SegmentTree segmentTree;
int id = 0; int id = 0;
QString idString; QString idString;
QString name; QString name;
int maxValue = 0; Statistic::ChartValue maxValue = 0;
int minValue = std::numeric_limits<int>::max(); Statistic::ChartValue minValue
= std::numeric_limits<Statistic::ChartValue>::max();
QString colorKey; QString colorKey;
QColor color; QColor color;
QColor colorDark; QColor colorDark;
@ -55,8 +56,9 @@ struct StatisticalChart {
float64 max = 0.; float64 max = 0.;
} defaultZoomXIndex; } defaultZoomXIndex;
int maxValue = 0; Statistic::ChartValue maxValue = 0;
int minValue = std::numeric_limits<int>::max(); Statistic::ChartValue minValue
= std::numeric_limits<Statistic::ChartValue>::max();
float64 oneDayPercentage = 0.; float64 oneDayPercentage = 0.;

View file

@ -775,8 +775,8 @@ void Widget::updateScrollUpPosition() {
_scrollToTop->moveToRight( _scrollToTop->moveToRight(
st::historyToDownPosition.x(), st::historyToDownPosition.x(),
_scroll->height() - top); _scroll->height() - top);
const auto shouldBeHidden = const auto shouldBeHidden
!_scrollToTopIsShown && !_scrollToTopShown.animating(); = !_scrollToTopIsShown && !_scrollToTopShown.animating();
if (shouldBeHidden != _scrollToTop->isHidden()) { if (shouldBeHidden != _scrollToTop->isHidden()) {
_scrollToTop->setVisible(!shouldBeHidden); _scrollToTop->setVisible(!shouldBeHidden);
} }

View file

@ -48,8 +48,8 @@ PhotoEditorContent::PhotoEditorContent(
return; return;
} }
const auto imageSizeF = [&] { const auto imageSizeF = [&] {
const auto rotatedSize = const auto rotatedSize
FlipSizeByRotation(size, mods.angle); = FlipSizeByRotation(size, mods.angle);
const auto m = _crop->cropMargins(); const auto m = _crop->cropMargins();
const auto sizeForCrop = rotatedSize const auto sizeForCrop = rotatedSize
- QSize(m.left() + m.right(), m.top() + m.bottom()); - QSize(m.left() + m.right(), m.top() + m.bottom());

View file

@ -541,8 +541,8 @@ void ApiWrap::requestDialogsCount() {
Expects(_startProcess != nullptr); Expects(_startProcess != nullptr);
if (_settings->onlySinglePeer()) { if (_settings->onlySinglePeer()) {
_startProcess->info.dialogsCount = _startProcess->info.dialogsCount
(_settings->singlePeer.type() == mtpc_inputPeerChannel = (_settings->singlePeer.type() == mtpc_inputPeerChannel
? 1 ? 1
: _splits.size()); : _splits.size());
sendNextStartRequest(); sendNextStartRequest();

View file

@ -738,8 +738,8 @@ void GenerateItems(
using LogPromote = MTPDchannelAdminLogEventActionParticipantToggleAdmin; using LogPromote = MTPDchannelAdminLogEventActionParticipantToggleAdmin;
using LogSticker = MTPDchannelAdminLogEventActionChangeStickerSet; using LogSticker = MTPDchannelAdminLogEventActionChangeStickerSet;
using LogEmoji = MTPDchannelAdminLogEventActionChangeEmojiStickerSet; using LogEmoji = MTPDchannelAdminLogEventActionChangeEmojiStickerSet;
using LogPreHistory = using LogPreHistory
MTPDchannelAdminLogEventActionTogglePreHistoryHidden; = MTPDchannelAdminLogEventActionTogglePreHistoryHidden;
using LogPermissions = MTPDchannelAdminLogEventActionDefaultBannedRights; using LogPermissions = MTPDchannelAdminLogEventActionDefaultBannedRights;
using LogPoll = MTPDchannelAdminLogEventActionStopPoll; using LogPoll = MTPDchannelAdminLogEventActionStopPoll;
using LogDiscussion = MTPDchannelAdminLogEventActionChangeLinkedChat; using LogDiscussion = MTPDchannelAdminLogEventActionChangeLinkedChat;
@ -749,19 +749,19 @@ void GenerateItems(
using LogDiscardCall = MTPDchannelAdminLogEventActionDiscardGroupCall; using LogDiscardCall = MTPDchannelAdminLogEventActionDiscardGroupCall;
using LogMute = MTPDchannelAdminLogEventActionParticipantMute; using LogMute = MTPDchannelAdminLogEventActionParticipantMute;
using LogUnmute = MTPDchannelAdminLogEventActionParticipantUnmute; using LogUnmute = MTPDchannelAdminLogEventActionParticipantUnmute;
using LogCallSetting = using LogCallSetting
MTPDchannelAdminLogEventActionToggleGroupCallSetting; = MTPDchannelAdminLogEventActionToggleGroupCallSetting;
using LogJoinByInvite = using LogJoinByInvite
MTPDchannelAdminLogEventActionParticipantJoinByInvite; = MTPDchannelAdminLogEventActionParticipantJoinByInvite;
using LogInviteDelete = using LogInviteDelete
MTPDchannelAdminLogEventActionExportedInviteDelete; = MTPDchannelAdminLogEventActionExportedInviteDelete;
using LogInviteRevoke = using LogInviteRevoke
MTPDchannelAdminLogEventActionExportedInviteRevoke; = MTPDchannelAdminLogEventActionExportedInviteRevoke;
using LogInviteEdit = MTPDchannelAdminLogEventActionExportedInviteEdit; using LogInviteEdit = MTPDchannelAdminLogEventActionExportedInviteEdit;
using LogVolume = MTPDchannelAdminLogEventActionParticipantVolume; using LogVolume = MTPDchannelAdminLogEventActionParticipantVolume;
using LogTTL = MTPDchannelAdminLogEventActionChangeHistoryTTL; using LogTTL = MTPDchannelAdminLogEventActionChangeHistoryTTL;
using LogJoinByRequest = using LogJoinByRequest
MTPDchannelAdminLogEventActionParticipantJoinByRequest; = MTPDchannelAdminLogEventActionParticipantJoinByRequest;
using LogNoForwards = MTPDchannelAdminLogEventActionToggleNoForwards; using LogNoForwards = MTPDchannelAdminLogEventActionToggleNoForwards;
using LogSendMessage = MTPDchannelAdminLogEventActionSendMessage; using LogSendMessage = MTPDchannelAdminLogEventActionSendMessage;
using LogChangeAvailableReactions = MTPDchannelAdminLogEventActionChangeAvailableReactions; using LogChangeAvailableReactions = MTPDchannelAdminLogEventActionChangeAvailableReactions;

View file

@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_unread_things.h" #include "history/history_unread_things.h"
#include "dialogs/ui/dialogs_layout.h" #include "dialogs/ui/dialogs_layout.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/components/sponsored_messages.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
@ -28,8 +30,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel_admins.h" #include "data/data_channel_admins.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_scheduled_messages.h"
#include "data/data_sponsored_messages.h"
#include "data/data_send_action.h" #include "data/data_send_action.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_forum.h" #include "data/data_forum.h"
@ -598,7 +598,7 @@ not_null<HistoryItem*> History::addNewItem(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
bool unread) { bool unread) {
if (item->isScheduled()) { if (item->isScheduled()) {
owner().scheduledMessages().appendSending(item); session().scheduledMessages().appendSending(item);
return item; return item;
} else if (item->isBusinessShortcut()) { } else if (item->isBusinessShortcut()) {
owner().shortcutMessages().appendSending(item); owner().shortcutMessages().appendSending(item);

View file

@ -25,10 +25,6 @@ struct HistoryMessageMarkupData;
class HistoryMainElementDelegateMixin; class HistoryMainElementDelegateMixin;
struct LanguageId; struct LanguageId;
namespace Main {
class Session;
} // namespace Main
namespace Data { namespace Data {
struct Draft; struct Draft;
class Session; class Session;

View file

@ -52,8 +52,8 @@ DragArea::Areas DragArea::SetupDragAreaToContainer(
auto &lifetime = container->lifetime(); auto &lifetime = container->lifetime();
container->setAcceptDrops(true); container->setAcceptDrops(true);
const auto attachDragDocument = const auto attachDragDocument
Ui::CreateChild<DragArea>(container.get()); = Ui::CreateChild<DragArea>(container.get());
const auto attachDragPhoto = Ui::CreateChild<DragArea>(container.get()); const auto attachDragPhoto = Ui::CreateChild<DragArea>(container.get());
attachDragDocument->hide(); attachDragDocument->hide();
@ -62,8 +62,8 @@ DragArea::Areas DragArea::SetupDragAreaToContainer(
attachDragDocument->raise(); attachDragDocument->raise();
attachDragPhoto->raise(); attachDragPhoto->raise();
const auto attachDragState = const auto attachDragState
lifetime.make_state<DragState>(DragState::None); = lifetime.make_state<DragState>(DragState::None);
const auto width = [=] { const auto width = [=] {
return container->width(); return container->width();

View file

@ -23,8 +23,8 @@ public:
DragArea *photo; DragArea *photo;
}; };
using CallbackComputeState = using CallbackComputeState
Fn<Storage::MimeDataState(const QMimeData *data)>; = Fn<Storage::MimeDataState(const QMimeData *data)>;
static Areas SetupDragAreaToContainer( static Areas SetupDragAreaToContainer(
not_null<Ui::RpWidget*> container, not_null<Ui::RpWidget*> container,

View file

@ -68,6 +68,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_who_reacted.h" #include "api/api_who_reacted.h"
#include "api/api_views.h" #include "api/api_views.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_channel.h" #include "data/data_channel.h"
@ -79,7 +80,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_click_handler.h" #include "data/data_file_click_handler.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_sponsored_messages.h"
#include "dialogs/ui/dialogs_video_userpic.h" #include "dialogs/ui/dialogs_video_userpic.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
@ -123,7 +123,7 @@ void FillSponsoredMessagesMenu(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
FullMsgId itemId, FullMsgId itemId,
not_null<Ui::PopupMenu*> menu) { not_null<Ui::PopupMenu*> menu) {
const auto &data = controller->session().data().sponsoredMessages(); const auto &data = controller->session().sponsoredMessages();
const auto info = data.lookupDetails(itemId).info; const auto info = data.lookupDetails(itemId).info;
const auto show = controller->uiShow(); const auto show = controller->uiShow();
if (!info.empty()) { if (!info.empty()) {
@ -984,7 +984,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
: yShown(top + height / 2); : yShown(top + height / 2);
if (markShown) { if (markShown) {
if (isSponsored) { if (isSponsored) {
session().data().sponsoredMessages().view(item->fullId()); session().sponsoredMessages().view(item->fullId());
} else if (isUnread) { } else if (isUnread) {
readTill = item; readTill = item;
} }

View file

@ -40,11 +40,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer_rpl.h" #include "base/timer_rpl.h"
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "api/api_updates.h" #include "api/api_updates.h"
#include "data/components/scheduled_messages.h"
#include "data/components/sponsored_messages.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/data_bot_app.h" #include "data/data_bot_app.h"
#include "data/data_saved_messages.h" #include "data/data_saved_messages.h"
#include "data/data_saved_sublist.h" #include "data/data_saved_sublist.h"
#include "data/data_scheduled_messages.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
@ -57,7 +58,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_group_call.h" // Data::GroupCall::id(). #include "data/data_group_call.h" // Data::GroupCall::id().
#include "data/data_poll.h" // PollData::publicVotes. #include "data/data_poll.h" // PollData::publicVotes.
#include "data/data_sponsored_messages.h"
#include "data/data_stories.h" #include "data/data_stories.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
#include "chat_helpers/stickers_gift_box_pack.h" #include "chat_helpers/stickers_gift_box_pack.h"

View file

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
@ -42,7 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
#include "data/data_file_click_handler.h" #include "data/data_file_click_handler.h"
#include "data/data_scheduled_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_stories.h" #include "data/data_stories.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -301,7 +301,7 @@ ReplyFields ReplyFieldsFromMTP(
const auto owner = &item->history()->owner(); const auto owner = &item->history()->owner();
if (const auto id = data.vreply_to_msg_id().value_or_empty()) { if (const auto id = data.vreply_to_msg_id().value_or_empty()) {
result.messageId = data.is_reply_to_scheduled() result.messageId = data.is_reply_to_scheduled()
? owner->scheduledMessages().localMessageId(id) ? owner->session().scheduledMessages().localMessageId(id)
: item->shortcutId() : item->shortcutId()
? owner->shortcutMessages().localMessageId(id) ? owner->shortcutMessages().localMessageId(id)
: id; : id;

View file

@ -54,6 +54,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "data/business/data_shortcut_messages.h" #include "data/business/data_shortcut_messages.h"
#include "data/components/scheduled_messages.h"
#include "data/components/sponsored_messages.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
@ -68,8 +70,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_scheduled_messages.h"
#include "data/data_sponsored_messages.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_group_call.h" #include "data/data_group_call.h"
@ -319,7 +319,7 @@ HistoryWidget::HistoryWidget(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
if (_history if (_history
&& _history->loadedAtBottom() && _history->loadedAtBottom()
&& session().data().sponsoredMessages().append(_history)) { && session().sponsoredMessages().append(_history)) {
_scroll->contentAdded(); _scroll->contentAdded();
} }
}, lifetime()); }, lifetime());
@ -2241,7 +2241,7 @@ void HistoryWidget::showHistory(
return; return;
} else { } else {
_sponsoredMessagesStateKnown = false; _sponsoredMessagesStateKnown = false;
session().data().sponsoredMessages().clearItems(_history); session().sponsoredMessages().clearItems(_history);
session().data().hideShownSpoilers(); session().data().hideShownSpoilers();
_composeSearch = nullptr; _composeSearch = nullptr;
} }
@ -2491,20 +2491,18 @@ void HistoryWidget::showHistory(
if (history != _history) { if (history != _history) {
return; return;
} }
auto &sponsored = session().data().sponsoredMessages();
using State = Data::SponsoredMessages::State; using State = Data::SponsoredMessages::State;
const auto state = sponsored.state(_history); const auto state = session().sponsoredMessages().state(
_history);
_sponsoredMessagesStateKnown = (state != State::None); _sponsoredMessagesStateKnown = (state != State::None);
if (state == State::AppendToEnd) { if (state == State::AppendToEnd) {
_scroll->setTrackingContent( _scroll->setTrackingContent(
sponsored.canHaveFor(_history)); session().sponsoredMessages().canHaveFor(_history));
} else if (state == State::InjectToMiddle) { } else if (state == State::InjectToMiddle) {
injectSponsoredMessages(); injectSponsoredMessages();
} }
}); });
session().data().sponsoredMessages().request( session().sponsoredMessages().request(_history, checkState);
_history,
checkState);
checkState(); checkState();
} }
} else { } else {
@ -2608,7 +2606,7 @@ void HistoryWidget::setupPreview() {
} }
void HistoryWidget::injectSponsoredMessages() const { void HistoryWidget::injectSponsoredMessages() const {
session().data().sponsoredMessages().inject( session().sponsoredMessages().inject(
_history, _history,
_showAtMsgId, _showAtMsgId,
_scroll->height() * 2, _scroll->height() * 2,
@ -2799,9 +2797,9 @@ void HistoryWidget::setupScheduledToggle() {
controller()->activeChatValue( controller()->activeChatValue(
) | rpl::map([=](Dialogs::Key key) -> rpl::producer<> { ) | rpl::map([=](Dialogs::Key key) -> rpl::producer<> {
if (const auto history = key.history()) { if (const auto history = key.history()) {
return session().data().scheduledMessages().updates(history); return session().scheduledMessages().updates(history);
} else if (const auto topic = key.topic()) { } else if (const auto topic = key.topic()) {
return session().data().scheduledMessages().updates( return session().scheduledMessages().updates(
topic->owningHistory()); topic->owningHistory());
} }
return rpl::never<rpl::empty_value>(); return rpl::never<rpl::empty_value>();
@ -2816,7 +2814,7 @@ void HistoryWidget::setupScheduledToggle() {
void HistoryWidget::refreshScheduledToggle() { void HistoryWidget::refreshScheduledToggle() {
const auto has = _history const auto has = _history
&& _canSendMessages && _canSendMessages
&& (session().data().scheduledMessages().count(_history) > 0); && (session().scheduledMessages().count(_history) > 0);
if (!_scheduled && has) { if (!_scheduled && has) {
_scheduled.create(this, st::historyScheduledToggle); _scheduled.create(this, st::historyScheduledToggle);
_scheduled->show(); _scheduled->show();
@ -3659,7 +3657,7 @@ void HistoryWidget::loadMessagesDown() {
auto from = loadMigrated ? _migrated : _history; auto from = loadMigrated ? _migrated : _history;
if (from->loadedAtBottom()) { if (from->loadedAtBottom()) {
if (_sponsoredMessagesStateKnown) { if (_sponsoredMessagesStateKnown) {
session().data().sponsoredMessages().request(_history, nullptr); session().sponsoredMessages().request(_history, nullptr);
} }
return; return;
} }

View file

@ -377,8 +377,8 @@ TTLButton::TTLButton(
return (r.left() + r.width() > parentWidget()->width()); return (r.left() + r.width() > parentWidget()->width());
}) | rpl::distinct_until_changed( }) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool toHide) { ) | rpl::start_with_next([=](bool toHide) {
const auto isFirstTooltip = const auto isFirstTooltip
!Core::App().settings().ttlVoiceClickTooltipHidden(); = !Core::App().settings().ttlVoiceClickTooltipHidden();
if (isFirstTooltip || (!isFirstTooltip && toHide)) { if (isFirstTooltip || (!isFirstTooltip && toHide)) {
_tooltip->toggleAnimated(!toHide); _tooltip->toggleAnimated(!toHide);
} }

View file

@ -39,10 +39,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/item_text_options.h" #include "ui/item_text_options.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_sponsored_messages.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -1125,7 +1125,7 @@ ClickHandlerPtr Element::fromLink() const {
} }
const auto my = context.other.value<ClickHandlerContext>(); const auto my = context.other.value<ClickHandlerContext>();
if (const auto window = ContextOrSessionWindow(my, session)) { if (const auto window = ContextOrSessionWindow(my, session)) {
auto &sponsored = session->data().sponsoredMessages(); auto &sponsored = session->sponsoredMessages();
const auto itemId = my.itemId ? my.itemId : item->fullId(); const auto itemId = my.itemId ? my.itemId : item->fullId();
const auto details = sponsored.lookupDetails(itemId); const auto details = sponsored.lookupDetails(itemId);
if (!details.externalLink.isEmpty()) { if (!details.externalLink.isEmpty()) {

View file

@ -56,8 +56,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/premium_preview_box.h" #include "boxes/premium_preview_box.h"
#include "boxes/peers/edit_participant_box.h" #include "boxes/peers/edit_participant_box.h"
#include "core/crash_reports.h" #include "core/crash_reports.h"
#include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
@ -2138,8 +2138,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
: yShown(top + height / 2); : yShown(top + height / 2);
if (markShown) { if (markShown) {
if (isSponsored) { if (isSponsored) {
session->data().sponsoredMessages().view( session->sponsoredMessages().view(item->fullId());
item->fullId());
} else if (isUnread) { } else if (isUnread) {
readTill = item; readTill = item;
} }
@ -3898,8 +3897,8 @@ bool ListWidget::lastMessageEditRequestNotify() const {
if (it == end(list)) { if (it == end(list)) {
return false; return false;
} else { } else {
const auto item = const auto item
session().data().groups().findItemToEdit((*it)->data()).get(); = session().data().groups().findItemToEdit((*it)->data()).get();
editMessageRequestNotify(item->fullId()); editMessageRequestNotify(item->fullId());
return true; return true;
} }

View file

@ -27,12 +27,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/round_rect.h" #include "ui/round_rect.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/power_saving.h" #include "ui/power_saving.h"
#include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
#include "data/data_sponsored_messages.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -440,8 +440,9 @@ Message::Message(
} }
} }
if (data->isSponsored()) { if (data->isSponsored()) {
const auto &messages = data->history()->owner().sponsoredMessages(); const auto &session = data->history()->session();
const auto details = messages.lookupDetails(data->fullId()); const auto details = session.sponsoredMessages().lookupDetails(
data->fullId());
if (details.canReport) { if (details.canReport) {
_rightAction = std::make_unique<RightAction>(); _rightAction = std::make_unique<RightAction>();
_rightAction->second = std::make_unique<SecondRightAction>(); _rightAction->second = std::make_unique<SecondRightAction>();
@ -1867,27 +1868,27 @@ void Message::clickHandlerPressedChanged(
Element::clickHandlerPressedChanged(handler, pressed); Element::clickHandlerPressedChanged(handler, pressed);
if (!handler) { if (!handler) {
return; return;
} else if (_rightAction) { } else if (_rightAction && (handler == _rightAction->link)) {
if (_rightAction->second && (handler == _rightAction->second->link)) { toggleRightActionRipple(pressed);
const auto rightSize = rightActionSize(); } else if (_rightAction
Assert(rightSize != std::nullopt); && _rightAction->second
if (pressed) { && (handler == _rightAction->second->link)) {
if (!_rightAction->second->ripple) { const auto rightSize = rightActionSize();
// Create a ripple. Assert(rightSize != std::nullopt);
_rightAction->second->ripple = if (pressed) {
std::make_unique<Ui::RippleAnimation>( if (!_rightAction->second->ripple) {
st::defaultRippleAnimation, // Create a ripple.
Ui::RippleAnimation::RoundRectMask( _rightAction->second->ripple
Size(rightSize->width()), = std::make_unique<Ui::RippleAnimation>(
rightSize->width() / 2), st::defaultRippleAnimation,
[=] { repaint(); }); Ui::RippleAnimation::RoundRectMask(
} Size(rightSize->width()),
_rightAction->second->ripple->add(_rightAction->lastPoint); rightSize->width() / 2),
} else if (_rightAction->second->ripple) { [=] { repaint(); });
_rightAction->second->ripple->lastStop();
} }
} else if (handler == _rightAction->link) { _rightAction->second->ripple->add(_rightAction->lastPoint);
toggleRightActionRipple(pressed); } else if (_rightAction->second->ripple) {
_rightAction->second->ripple->lastStop();
} }
} else if (_comments && (handler == _comments->link)) { } else if (_comments && (handler == _comments->link)) {
toggleCommentsButtonRipple(pressed); toggleCommentsButtonRipple(pressed);

View file

@ -52,6 +52,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/mime_type.h" #include "core/mime_type.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_session_settings.h" #include "main/main_session_settings.h"
#include "data/components/scheduled_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat.h" #include "data/data_chat.h"
@ -63,7 +64,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_shared_media.h" #include "data/data_shared_media.h"
#include "data/data_send_action.h" #include "data/data_send_action.h"
#include "data/data_scheduled_messages.h"
#include "data/data_premium_limits.h" #include "data/data_premium_limits.h"
#include "storage/storage_media_prepare.h" #include "storage/storage_media_prepare.h"
#include "storage/storage_account.h" #include "storage/storage_account.h"
@ -234,10 +234,9 @@ RepliesWidget::RepliesWidget(
.stickerOrEmojiChosen = controller->stickerOrEmojiChosen(), .stickerOrEmojiChosen = controller->stickerOrEmojiChosen(),
.scheduledToggleValue = _topic .scheduledToggleValue = _topic
? rpl::single(rpl::empty_value()) | rpl::then( ? rpl::single(rpl::empty_value()) | rpl::then(
session().data().scheduledMessages().updates( session().scheduledMessages().updates(_topic->owningHistory())
_topic->owningHistory())
) | rpl::map([=] { ) | rpl::map([=] {
return session().data().scheduledMessages().hasFor(_topic); return session().scheduledMessages().hasFor(_topic);
}) | rpl::type_erased() }) | rpl::type_erased()
: rpl::single(false), : rpl::single(false),
})) }))

View file

@ -33,11 +33,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/mime_type.h" #include "core/mime_type.h"
#include "chat_helpers/tabbed_selector.h" #include "chat_helpers/tabbed_selector.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "data/components/scheduled_messages.h"
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_scheduled_messages.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
@ -62,7 +62,7 @@ namespace HistoryView {
ScheduledMemento::ScheduledMemento(not_null<History*> history) ScheduledMemento::ScheduledMemento(not_null<History*> history)
: _history(history) : _history(history)
, _forumTopic(nullptr) { , _forumTopic(nullptr) {
const auto list = _history->owner().scheduledMessages().list(_history); const auto list = _history->session().scheduledMessages().list(_history);
if (!list.ids.empty()) { if (!list.ids.empty()) {
_list.setScrollTopState({ .item = { .fullId = list.ids.front() } }); _list.setScrollTopState({ .item = { .fullId = list.ids.front() } });
} }
@ -71,7 +71,8 @@ ScheduledMemento::ScheduledMemento(not_null<History*> history)
ScheduledMemento::ScheduledMemento(not_null<Data::ForumTopic*> forumTopic) ScheduledMemento::ScheduledMemento(not_null<Data::ForumTopic*> forumTopic)
: _history(forumTopic->owningHistory()) : _history(forumTopic->owningHistory())
, _forumTopic(forumTopic) { , _forumTopic(forumTopic) {
const auto list = _history->owner().scheduledMessages().list(_forumTopic); const auto list = _history->session().scheduledMessages().list(
_forumTopic);
if (!list.ids.empty()) { if (!list.ids.empty()) {
_list.setScrollTopState({ .item = { .fullId = list.ids.front() } }); _list.setScrollTopState({ .item = { .fullId = list.ids.front() } });
} }
@ -1201,13 +1202,13 @@ rpl::producer<Data::MessagesSlice> ScheduledWidget::listSource(
Data::MessagePosition aroundId, Data::MessagePosition aroundId,
int limitBefore, int limitBefore,
int limitAfter) { int limitAfter) {
const auto data = &controller()->session().data(); const auto session = &controller()->session();
return rpl::single(rpl::empty) | rpl::then( return rpl::single(rpl::empty) | rpl::then(
data->scheduledMessages().updates(_history) session->scheduledMessages().updates(_history)
) | rpl::map([=] { ) | rpl::map([=] {
return _forumTopic return _forumTopic
? data->scheduledMessages().list(_forumTopic) ? session->scheduledMessages().list(_forumTopic)
: data->scheduledMessages().list(_history); : session->scheduledMessages().list(_history);
}) | rpl::after_next([=](const Data::MessagesSlice &slice) { }) | rpl::after_next([=](const Data::MessagesSlice &slice) {
highlightSingleNewMessage(slice); highlightSingleNewMessage(slice);
}); });

View file

@ -150,8 +150,8 @@ bool SendActionPainter::paint(
const auto extraAnimationWidth = _animationLeft const auto extraAnimationWidth = _animationLeft
? animationWidth * 2 ? animationWidth * 2
: 0; : 0;
const auto left = const auto left
(availableWidth < _animationLeft + extraAnimationWidth) = (availableWidth < _animationLeft + extraAnimationWidth)
? 0 ? 0
: _animationLeft; : _animationLeft;
_sendActionAnimation.paint( _sendActionAnimation.paint(

View file

@ -10,8 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_chat_invite.h" #include "api/api_chat_invite.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -37,8 +37,8 @@ ClickHandlerPtr SponsoredLink(const QString &externalLink) {
if (!controller) { if (!controller) {
return; return;
} }
const auto &data = controller->session().data(); const auto &session = controller->session();
const auto details = data.sponsoredMessages().lookupDetails( const auto details = session.sponsoredMessages().lookupDetails(
my.itemId); my.itemId);
if (!details.externalLink.isEmpty()) { if (!details.externalLink.isEmpty()) {
File::OpenUrl(details.externalLink); File::OpenUrl(details.externalLink);

View file

@ -387,12 +387,9 @@ void Document::createComponents(bool caption) {
mask |= HistoryDocumentVoice::Bit(); mask |= HistoryDocumentVoice::Bit();
} else { } else {
mask |= HistoryDocumentNamed::Bit(); mask |= HistoryDocumentNamed::Bit();
if (_data->hasThumbnail()) { if (_data->hasThumbnail() && !_data->isSong()) {
if (!_data->isSong() _data->loadThumbnail(_realParent->fullId());
&& !Data::IsExecutableName(_data->filename())) { mask |= HistoryDocumentThumbed::Bit();
_data->loadThumbnail(_realParent->fullId());
mask |= HistoryDocumentThumbed::Bit();
}
} }
} }
if (caption) { if (caption) {

View file

@ -13,11 +13,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "iv/iv_instance.h" #include "iv/iv_instance.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "core/ui_integration.h" #include "core/ui_integration.h"
#include "data/components/sponsored_messages.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "data/data_file_click_handler.h" #include "data/data_file_click_handler.h"
#include "data/data_photo_media.h" #include "data/data_photo_media.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
@ -231,8 +231,8 @@ WebPage::WebPage(
if (!(flags & MediaWebPageFlag::Sponsored)) { if (!(flags & MediaWebPageFlag::Sponsored)) {
return std::nullopt; return std::nullopt;
} }
const auto &data = _parent->data()->history()->owner(); const auto &session = _parent->data()->history()->session();
const auto details = data.sponsoredMessages().lookupDetails( const auto details = session.sponsoredMessages().lookupDetails(
_parent->data()->fullId()); _parent->data()->fullId());
auto result = std::make_optional<SponsoredData>(); auto result = std::make_optional<SponsoredData>();
result->buttonText = details.buttonText; result->buttonText = details.buttonText;
@ -500,8 +500,8 @@ QSize WebPage::countOptimalSize() {
minHeight = resizeGetHeight(maxWidth); minHeight = resizeGetHeight(maxWidth);
} }
if (_sponsoredData && _sponsoredData->canReport) { if (_sponsoredData && _sponsoredData->canReport) {
_sponsoredData->widthBeforeHint = _sponsoredData->widthBeforeHint
st::webPageTitleStyle.font->width(siteName); = st::webPageTitleStyle.font->width(siteName);
const auto &font = st::webPageSponsoredHintFont; const auto &font = st::webPageSponsoredHintFont;
_sponsoredData->hintSize = QSize( _sponsoredData->hintSize = QSize(
font->width(tr::lng_sponsored_message_revenue_button(tr::now)) font->width(tr::lng_sponsored_message_revenue_button(tr::now))

View file

@ -48,8 +48,11 @@ QString MinorPart(EarnInt value) {
QString ToUsd(EarnInt value, float64 rate) { QString ToUsd(EarnInt value, float64 rate) {
constexpr auto kApproximately = QChar(0x2248); constexpr auto kApproximately = QChar(0x2248);
const auto multiplier = EarnInt(rate * Data::kEarnMultiplier);
const auto result = (value * multiplier) / Data::kEarnMultiplier; const auto result = value
/ float64(Data::kEarnMultiplier)
* rate
* Data::kEarnMultiplier;
return QString(kApproximately) return QString(kApproximately)
+ QChar('$') + QChar('$')
+ MajorPart(result) + MajorPart(result)

View file

@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge. #include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge.
#include "chat_helpers/stickers_emoji_pack.h" #include "chat_helpers/stickers_emoji_pack.h"
#include "core/application.h" #include "core/application.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_premium_limits.h" #include "data/data_premium_limits.h"
#include "data/data_session.h" #include "data/data_session.h"
@ -31,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "statistics/chart_widget.h" #include "statistics/chart_widget.h"
#include "ui/basic_click_handlers.h" #include "ui/basic_click_handlers.h"
#include "ui/widgets/label_with_custom_emoji.h"
#include "ui/boxes/boost_box.h" #include "ui/boxes/boost_box.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
#include "ui/effects/animation_value_f.h" #include "ui/effects/animation_value_f.h"
@ -334,23 +334,21 @@ void InnerWidget::fill() {
st::channelEarnLearnArrowMargins, st::channelEarnLearnArrowMargins,
false)); false));
const auto addAboutWithLearn = [&](const tr::phrase<lngtag_link> &text) { const auto addAboutWithLearn = [&](const tr::phrase<lngtag_link> &text) {
auto label = object_ptr<Ui::FlatLabel>( auto label = Ui::CreateLabelWithCustomEmoji(
container, container,
st::boxDividerLabel); text(
const auto raw = label.data(); lt_link,
text( tr::lng_channel_earn_about_link(
lt_link, lt_emoji,
tr::lng_channel_earn_about_link( rpl::single(arrow),
lt_emoji, Ui::Text::RichLangValue
rpl::single(arrow), ) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(std::move(text), 1);
}),
Ui::Text::RichLangValue Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) { ),
return Ui::Text::Link(std::move(text), 1); { .session = session },
}), st::boxDividerLabel);
Ui::Text::RichLangValue
) | rpl::start_with_next([=](const TextWithEntities &text) {
raw->setMarkedText(text, makeContext(raw));
}, label->lifetime());
label->setLink(1, std::make_shared<LambdaClickHandler>([=] { label->setLink(1, std::make_shared<LambdaClickHandler>([=] {
_show->showBox(Box([=](not_null<Ui::GenericBox*> box) { _show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
box->setNoContentMargin(true); box->setNoContentMargin(true);
@ -454,17 +452,16 @@ void InnerWidget::fill() {
const auto l = box->addRow( const auto l = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>( object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
content, content,
object_ptr<Ui::FlatLabel>( Ui::CreateLabelWithCustomEmoji(
content, content,
tr::lng_channel_earn_learn_coin_title(
lt_emoji,
rpl::single(
Ui::Text::Link(bigCurrencyIcon, 1)),
Ui::Text::RichLangValue
),
{ .session = session },
st::boxTitle)))->entity(); st::boxTitle)))->entity();
tr::lng_channel_earn_learn_coin_title(
lt_emoji,
rpl::single(
Ui::Text::Link(bigCurrencyIcon, 1)),
Ui::Text::RichLangValue
) | rpl::start_with_next([=](TextWithEntities t) {
l->setMarkedText(std::move(t), makeContext(l));
}, l->lifetime());
const auto diamonds = l->lifetime().make_state<int>(0); const auto diamonds = l->lifetime().make_state<int>(0);
l->setLink(1, std::make_shared<LambdaClickHandler>([=] { l->setLink(1, std::make_shared<LambdaClickHandler>([=] {
const auto count = (*diamonds); const auto count = (*diamonds);
@ -480,25 +477,23 @@ void InnerWidget::fill() {
Ui::AddSkip(content); Ui::AddSkip(content);
{ {
const auto label = box->addRow( const auto label = box->addRow(
object_ptr<Ui::FlatLabel>( Ui::CreateLabelWithCustomEmoji(
content, content,
tr::lng_channel_earn_learn_coin_about(
lt_link,
tr::lng_channel_earn_about_link(
lt_emoji,
rpl::single(arrow),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(std::move(text), 1);
}),
Ui::Text::RichLangValue
),
{ .session = session },
st::channelEarnLearnDescription)); st::channelEarnLearnDescription));
tr::lng_channel_earn_learn_coin_about( label->resizeToWidth(box->width()
lt_link, - rect::m::sum::h(st::boxRowPadding));
tr::lng_channel_earn_about_link(
lt_emoji,
rpl::single(arrow),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(std::move(text), 1);
}),
Ui::Text::RichLangValue
) | rpl::start_with_next([=, l = label](
TextWithEntities t) {
l->setMarkedText(std::move(t), makeContext(l));
l->resizeToWidth(box->width()
- rect::m::sum::h(st::boxRowPadding));
}, label->lifetime());
label->setLink( label->setLink(
1, 1,
LearnMoreCurrencyLink( LearnMoreCurrencyLink(

View file

@ -693,13 +693,13 @@ void TopBar::createSelectionControls() {
_selectionActionRequests, _selectionActionRequests,
_cancelSelection->lifetime()); _cancelSelection->lifetime());
_delete->entity()->setVisible(_canDelete); _delete->entity()->setVisible(_canDelete);
const auto archive = const auto archive = _toggleStoryPin = wrap(
_toggleStoryPin = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>( Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
this,
object_ptr<Ui::IconButton>(
this, this,
_storiesArchive ? _st.storiesSave : _st.storiesArchive), object_ptr<Ui::IconButton>(
st::infoTopBarScale)); this,
_storiesArchive ? _st.storiesSave : _st.storiesArchive),
st::infoTopBarScale));
registerToggleControlCallback( registerToggleControlCallback(
_toggleStoryPin.data(), _toggleStoryPin.data(),
[this] { return selectionMode() && _canToggleStoryPin; }); [this] { return selectionMode() && _canToggleStoryPin; });

View file

@ -814,8 +814,8 @@ void ListWidget::paintEvent(QPaintEvent *e) {
} }
if (_dateBadge->goodType && clip.intersects(_dateBadge->rect)) { if (_dateBadge->goodType && clip.intersects(_dateBadge->rect)) {
const auto scrollDateOpacity = const auto scrollDateOpacity
_dateBadge->opacity.value(_dateBadge->shown ? 1. : 0.); = _dateBadge->opacity.value(_dateBadge->shown ? 1. : 0.);
if (scrollDateOpacity > 0.) { if (scrollDateOpacity > 0.) {
p.setOpacity(scrollDateOpacity); p.setOpacity(scrollDateOpacity);
if (_dateBadge->corners.p[0].isNull()) { if (_dateBadge->corners.p[0].isNull()) {

View file

@ -349,12 +349,14 @@ void FillOverview(
const auto diffText = diffAbs > kTooMuchDiff const auto diffText = diffAbs > kTooMuchDiff
? Lang::FormatCountToShort(std::abs(diff)).string ? Lang::FormatCountToShort(std::abs(diff)).string
: QString::number(diffAbs); : QString::number(diffAbs);
const auto percentage = std::abs(v.growthRatePercentage);
const auto precision = (percentage == int(percentage)) ? 0 : 1;
return { return {
(diff < 0 ? st::menuIconAttentionColor : st::settingsIconBg2)->c, (diff < 0 ? st::menuIconAttentionColor : st::settingsIconBg2)->c,
QString("%1%2 (%3%)") QString("%1%2 (%3%)")
.arg((diff < 0) ? QChar(0x2212) : QChar(0x002B)) .arg((diff < 0) ? QChar(0x2212) : QChar(0x002B))
.arg(diffText) .arg(diffText)
.arg(std::abs(std::round(v.growthRatePercentage * 10.) / 10.)) .arg(QString::number(percentage, 'f', precision))
}; };
}; };

View file

@ -28,6 +28,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/file_upload.h" #include "storage/file_upload.h"
#include "storage/storage_account.h" #include "storage/storage_account.h"
#include "storage/storage_facade.h" #include "storage/storage_facade.h"
#include "data/components/scheduled_messages.h"
#include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_user.h" #include "data/data_user.h"
@ -100,6 +102,8 @@ Session::Session(
, _giftBoxStickersPacks(std::make_unique<Stickers::GiftBoxPack>(this)) , _giftBoxStickersPacks(std::make_unique<Stickers::GiftBoxPack>(this))
, _sendAsPeers(std::make_unique<SendAsPeers>(this)) , _sendAsPeers(std::make_unique<SendAsPeers>(this))
, _attachWebView(std::make_unique<InlineBots::AttachWebView>(this)) , _attachWebView(std::make_unique<InlineBots::AttachWebView>(this))
, _scheduledMessages(std::make_unique<Data::ScheduledMessages>(this))
, _sponsoredMessages(std::make_unique<Data::SponsoredMessages>(this))
, _supportHelper(Support::Helper::Create(this)) , _supportHelper(Support::Helper::Create(this))
, _saveSettingsTimer([=] { saveSettings(); }) { , _saveSettingsTimer([=] { saveSettings(); }) {
Expects(_settings != nullptr); Expects(_settings != nullptr);

View file

@ -31,6 +31,8 @@ class Templates;
namespace Data { namespace Data {
class Session; class Session;
class Changes; class Changes;
class ScheduledMessages;
class SponsoredMessages;
} // namespace Data } // namespace Data
namespace Storage { namespace Storage {
@ -104,6 +106,12 @@ public:
[[nodiscard]] Data::Changes &changes() const { [[nodiscard]] Data::Changes &changes() const {
return *_changes; return *_changes;
} }
[[nodiscard]] Data::SponsoredMessages &sponsoredMessages() const {
return *_sponsoredMessages;
}
[[nodiscard]] Data::ScheduledMessages &scheduledMessages() const {
return *_scheduledMessages;
}
[[nodiscard]] Api::Updates &updates() const { [[nodiscard]] Api::Updates &updates() const {
return *_updates; return *_updates;
} }
@ -224,6 +232,8 @@ private:
const std::unique_ptr<Stickers::GiftBoxPack> _giftBoxStickersPacks; const std::unique_ptr<Stickers::GiftBoxPack> _giftBoxStickersPacks;
const std::unique_ptr<SendAsPeers> _sendAsPeers; const std::unique_ptr<SendAsPeers> _sendAsPeers;
const std::unique_ptr<InlineBots::AttachWebView> _attachWebView; const std::unique_ptr<InlineBots::AttachWebView> _attachWebView;
const std::unique_ptr<Data::ScheduledMessages> _scheduledMessages;
const std::unique_ptr<Data::SponsoredMessages> _sponsoredMessages;
const std::unique_ptr<Support::Helper> _supportHelper; const std::unique_ptr<Support::Helper> _supportHelper;

View file

@ -140,7 +140,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
qint32 supportChatsTimeSlice = _supportChatsTimeSlice.current(); qint32 supportChatsTimeSlice = _supportChatsTimeSlice.current();
qint32 appIncludeMutedCounter = app.includeMutedCounter() ? 1 : 0; qint32 appIncludeMutedCounter = app.includeMutedCounter() ? 1 : 0;
qint32 appCountUnreadMessages = app.countUnreadMessages() ? 1 : 0; qint32 appCountUnreadMessages = app.countUnreadMessages() ? 1 : 0;
qint32 appExeLaunchWarning = app.exeLaunchWarning() ? 1 : 0; qint32 legacyAppExeLaunchWarning = 1;
QByteArray autoDownload; QByteArray autoDownload;
qint32 supportAllSearchResults = _supportAllSearchResults.current() ? 1 : 0; qint32 supportAllSearchResults = _supportAllSearchResults.current() ? 1 : 0;
qint32 archiveCollapsed = _archiveCollapsed.current() ? 1 : 0; qint32 archiveCollapsed = _archiveCollapsed.current() ? 1 : 0;
@ -262,7 +262,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
stream >> appCountUnreadMessages; stream >> appCountUnreadMessages;
} }
if (!stream.atEnd()) { if (!stream.atEnd()) {
stream >> appExeLaunchWarning; stream >> legacyAppExeLaunchWarning;
} }
} }
if (!stream.atEnd()) { if (!stream.atEnd()) {
@ -509,7 +509,6 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
} }
app.setIncludeMutedCounter(appIncludeMutedCounter == 1); app.setIncludeMutedCounter(appIncludeMutedCounter == 1);
app.setCountUnreadMessages(appCountUnreadMessages == 1); app.setCountUnreadMessages(appCountUnreadMessages == 1);
app.setExeLaunchWarning(appExeLaunchWarning == 1);
app.setNotifyAboutPinned(appNotifyAboutPinned == 1); app.setNotifyAboutPinned(appNotifyAboutPinned == 1);
app.setLoopAnimatedStickers(appLoopAnimatedStickers == 1); app.setLoopAnimatedStickers(appLoopAnimatedStickers == 1);
app.setLargeEmoji(appLargeEmoji == 1); app.setLargeEmoji(appLargeEmoji == 1);

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_updates.h" #include "api/api_updates.h"
#include "api/api_views.h" #include "api/api_views.h"
#include "data/components/scheduled_messages.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/data_document_resolver.h" #include "data/data_document_resolver.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
@ -22,7 +23,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_scheduled_messages.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
@ -811,6 +811,13 @@ void MainWidget::createPlayer() {
}); });
_player->entity()->setShowItemCallback([=]( _player->entity()->setShowItemCallback([=](
not_null<const HistoryItem*> item) { not_null<const HistoryItem*> item) {
const auto peer = item->history()->peer;
if (const auto window = Core::App().windowFor(peer)) {
if (const auto controller = window->sessionController()) {
controller->showMessage(item);
return;
}
}
_controller->showMessage(item); _controller->showMessage(item);
}); });

View file

@ -77,8 +77,8 @@ base::options::toggle AutoScrollInactiveChat({
} // namespace } // namespace
const char kOptionAutoScrollInactiveChat[] = const char kOptionAutoScrollInactiveChat[]
"auto-scroll-inactive-chat"; = "auto-scroll-inactive-chat";
MainWindow::MainWindow(not_null<Window::Controller*> controller) MainWindow::MainWindow(not_null<Window::Controller*> controller)
: Platform::MainWindow(controller) { : Platform::MainWindow(controller) {

View file

@ -35,8 +35,8 @@ constexpr auto kSpeedDebounceTimeout = crl::time(600);
return base::SafeRound(speed * 10) / 10.; return base::SafeRound(speed * 10) / 10.;
} }
constexpr auto kSpeedStickedValues = constexpr auto kSpeedStickedValues
std::array<std::pair<float64, float64>, 7>{{ = std::array<std::pair<float64, float64>, 7>{{
{ 0.8, 0.05 }, { 0.8, 0.05 },
{ 1.0, 0.05 }, { 1.0, 0.05 },
{ 1.2, 0.05 }, { 1.2, 0.05 },

View file

@ -44,8 +44,8 @@ bool SystemMediaControlsManager::Supported() {
SystemMediaControlsManager::SystemMediaControlsManager() SystemMediaControlsManager::SystemMediaControlsManager()
: _controls(std::make_unique<base::Platform::SystemMediaControls>()) { : _controls(std::make_unique<base::Platform::SystemMediaControls>()) {
using PlaybackStatus = using PlaybackStatus
base::Platform::SystemMediaControls::PlaybackStatus; = base::Platform::SystemMediaControls::PlaybackStatus;
using Command = base::Platform::SystemMediaControls::Command; using Command = base::Platform::SystemMediaControls::Command;
_controls->setApplicationName(AppName.utf16()); _controls->setApplicationName(AppName.utf16());

View file

@ -9,10 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/premium_preview_box.h" #include "boxes/premium_preview_box.h"
#include "chat_helpers/compose/compose_show.h" #include "chat_helpers/compose/compose_show.h"
#include "core/ui_integration.h" // Core::MarkedTextContext. #include "data/components/sponsored_messages.h"
#include "data/data_premium_limits.h" #include "data/data_premium_limits.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "history/history.h" #include "history/history.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -25,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/vertical_list.h" #include "ui/vertical_list.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/label_with_custom_emoji.h"
#include "styles/style_channel_earn.h" #include "styles/style_channel_earn.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -169,31 +169,23 @@ void AboutBox(
st::topicButtonArrow, st::topicButtonArrow,
st::channelEarnLearnArrowMargins, st::channelEarnLearnArrowMargins,
false)); false));
const auto label = box->addRow( const auto available = box->width()
object_ptr<Ui::FlatLabel>( - rect::m::sum::h(st::boxRowPadding);
box->addRow(
Ui::CreateLabelWithCustomEmoji(
content, content,
st::channelEarnLearnDescription)); tr::lng_sponsored_revenued_footer_description(
tr::lng_sponsored_revenued_footer_description( lt_link,
lt_link, tr::lng_channel_earn_about_link(
tr::lng_channel_earn_about_link( lt_emoji,
lt_emoji, rpl::single(arrow),
rpl::single(arrow), Ui::Text::RichLangValue
Ui::Text::RichLangValue ) | rpl::map([=](TextWithEntities text) {
) | rpl::map([=](TextWithEntities text) { return Ui::Text::Link(std::move(text), kUrl.utf16());
return Ui::Text::Link(std::move(text), kUrl.utf16()); }),
}), Ui::Text::RichLangValue),
Ui::Text::RichLangValue { .session = session },
) | rpl::start_with_next([=, l = label]( st::channelEarnLearnDescription))->resizeToWidth(available);
TextWithEntities t) {
l->setMarkedText(
std::move(t),
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { l->update(); },
});
l->resizeToWidth(box->width()
- rect::m::sum::h(st::boxRowPadding));
}, label->lifetime());
} }
Ui::AddSkip(content); Ui::AddSkip(content);
Ui::AddSkip(content); Ui::AddSkip(content);
@ -217,7 +209,7 @@ void ShowReportSponsoredBox(
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
not_null<HistoryItem*> item) { not_null<HistoryItem*> item) {
const auto peer = item->history()->peer; const auto peer = item->history()->peer;
auto &sponsoredMessages = peer->session().data().sponsoredMessages(); auto &sponsoredMessages = peer->session().sponsoredMessages();
const auto fullId = item->fullId(); const auto fullId = item->fullId();
const auto report = sponsoredMessages.createReportCallback(fullId); const auto report = sponsoredMessages.createReportCallback(fullId);
const auto guideLink = Ui::Text::Link( const auto guideLink = Ui::Text::Link(

View file

@ -1514,9 +1514,7 @@ bool Document::iconAnimated() const {
} }
bool Document::withThumb() const { bool Document::withThumb() const {
return !songLayout() return !songLayout() && _data->hasThumbnail();
&& _data->hasThumbnail()
&& !Data::IsExecutableName(_data->filename());
} }
bool Document::updateStatusText() { bool Document::updateStatusText() {

View file

@ -2686,8 +2686,8 @@ bool FormController::applyPassword(const MTPDaccount_password &result) {
settings.notEmptyPassport = result.is_has_secure_values(); settings.notEmptyPassport = result.is_has_secure_values();
settings.request = Core::ParseCloudPasswordCheckRequest(result); settings.request = Core::ParseCloudPasswordCheckRequest(result);
settings.unknownAlgo = result.vcurrent_algo() && !settings.request; settings.unknownAlgo = result.vcurrent_algo() && !settings.request;
settings.unconfirmedPattern = settings.unconfirmedPattern = qs(
qs(result.vemail_unconfirmed_pattern().value_or_empty()); result.vemail_unconfirmed_pattern().value_or_empty());
settings.newAlgo = Core::ValidateNewCloudPasswordAlgo( settings.newAlgo = Core::ValidateNewCloudPasswordAlgo(
Core::ParseCloudPasswordAlgo(result.vnew_algo())); Core::ParseCloudPasswordAlgo(result.vnew_algo()));
settings.newSecureAlgo = Core::ValidateNewSecureSecretAlgo( settings.newSecureAlgo = Core::ValidateNewSecureSecretAlgo(

View file

@ -26,8 +26,8 @@ struct EditContactScheme;
enum class ReadScanError; enum class ReadScanError;
using preferredLangCallback = using preferredLangCallback
Fn<rpl::producer<EditDocumentCountry>(const QString &)>; = Fn<rpl::producer<EditDocumentCountry>(const QString &)>;
EditDocumentScheme GetDocumentScheme( EditDocumentScheme GetDocumentScheme(
Scope::Type type, Scope::Type type,
std::optional<Value::Type> scansType, std::optional<Value::Type> scansType,

View file

@ -766,12 +766,12 @@ void CheckoutProcess::requestPassword() {
(index < list.size()) ? list[index].title : QString()); (index < list.size()) ? list[index].title : QString());
fields.customSubmitButton = tr::lng_payments_password_submit(); fields.customSubmitButton = tr::lng_payments_password_submit();
fields.customCheckCallback = [=]( fields.customCheckCallback = [=](
const Core::CloudPasswordResult &result) { const Core::CloudPasswordResult &result,
QPointer<PasscodeBox> box) {
_enterPasswordBox = box;
_form->submit(result); _form->submit(result);
}; };
auto owned = Box<PasscodeBox>(_session, fields); _panel->showBox(Box<PasscodeBox>(_session, fields));
_enterPasswordBox = owned.data();
_panel->showBox(std::move(owned));
}); });
} }

View file

@ -99,42 +99,6 @@ void XCBSkipTaskbar(QWindow *window, bool skip) {
| XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
reinterpret_cast<const char*>(&xev)); reinterpret_cast<const char*>(&xev));
} }
void XCBSetDesktopFileName(QWindow *window) {
const auto connection = base::Platform::XCB::GetConnectionFromQt();
if (!connection) {
return;
}
const auto utf8Atom = base::Platform::XCB::GetAtom(
connection,
"UTF8_STRING");
if (!utf8Atom.has_value()) {
return;
}
const auto filenameAtoms = {
base::Platform::XCB::GetAtom(connection, "_GTK_APPLICATION_ID"),
base::Platform::XCB::GetAtom(connection, "_KDE_NET_WM_DESKTOP_FILE"),
};
const auto filename = QGuiApplication::desktopFileName().toUtf8();
for (const auto atom : filenameAtoms) {
if (atom.has_value()) {
xcb_change_property(
connection,
XCB_PROP_MODE_REPLACE,
window->winId(),
*atom,
*utf8Atom,
8,
filename.size(),
filename.data());
}
}
}
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
void SkipTaskbar(QWindow *window, bool skip) { void SkipTaskbar(QWindow *window, bool skip) {
@ -206,10 +170,6 @@ void MainWindow::initHook() {
} }
return base::EventFilterResult::Continue; return base::EventFilterResult::Continue;
}); });
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
XCBSetDesktopFileName(windowHandle());
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
} }
void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) {

View file

@ -315,19 +315,19 @@ bool NotificationData::init(
_actions.push_back("inline-reply"); _actions.push_back("inline-reply");
_actions.push_back(tr::lng_notification_reply(tr::now).toStdString()); _actions.push_back(tr::lng_notification_reply(tr::now).toStdString());
_notificationRepliedSignalId = _notificationRepliedSignalId
_interface.signal_notification_replied().connect([=]( = _interface.signal_notification_replied().connect([=](
XdgNotifications::Notifications, XdgNotifications::Notifications,
uint id, uint id,
std::string text) { std::string text) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] { Core::Sandbox::Instance().customEnterFromEventLoop([&] {
if (id == _notificationId) { if (id == _notificationId) {
_manager->notificationReplied( _manager->notificationReplied(
_id, _id,
{ QString::fromStdString(text), {} }); { QString::fromStdString(text), {} });
} }
});
}); });
});
} }
_actionInvokedSignalId = _interface.signal_action_invoked().connect([=]( _actionInvokedSignalId = _interface.signal_action_invoked().connect([=](

View file

@ -551,13 +551,11 @@ NSRect PeerRectByIndex(int index) {
const auto processOnline = [=](const auto &pin) { const auto processOnline = [=](const auto &pin) {
// TODO: this should be replaced // TODO: this should be replaced
// with the global application timer for online statuses. // with the global application timer for online statuses.
const auto onlineChanges = const auto onlineChanges
peerChangedLifetime->make_state<rpl::event_stream<PeerData*>>(); = peerChangedLifetime->make_state<rpl::event_stream<PeerData*>>();
const auto peer = pin->peer; const auto peer = pin->peer;
const auto onlineTimer = const auto onlineTimer = peerChangedLifetime->make_state<base::Timer>(
peerChangedLifetime->make_state<base::Timer>([=] { [=] { onlineChanges->fire_copy({ peer }); });
onlineChanges->fire_copy({ peer });
});
const auto callTimer = [=](const auto &pin) { const auto callTimer = [=](const auto &pin) {
onlineTimer->cancel(); onlineTimer->cancel();

Some files were not shown because too many files have changed in this diff Show more