mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
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:
commit
fe1babe437
133 changed files with 1105 additions and 726 deletions
|
@ -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
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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 = [&] {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
|
@ -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 {
|
|
@ -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(); }) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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; });
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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))
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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([=](
|
||||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue