Updated to 6.0.3.

Esse commit está contido em:
23rd
2025-08-22 20:30:52 +03:00
294 arquivos alterados com 5206 adições e 3551 exclusões
+2 -2
Ver Arquivo
@@ -4,8 +4,8 @@ on:
push:
paths-ignore:
- 'docs/**'
- '!docs/building-win*.md'
- '**.md'
- '!docs/building-win*.md'
- 'changelog.txt'
- 'LEGAL'
- 'LICENSE'
@@ -23,8 +23,8 @@ on:
pull_request:
paths-ignore:
- 'docs/**'
- '!docs/building-win*.md'
- '**.md'
- '!docs/building-win*.md'
- 'changelog.txt'
- 'LEGAL'
- 'LICENSE'
+12 -6
Ver Arquivo
@@ -529,6 +529,8 @@ PRIVATE
data/notify/data_notify_settings.h
data/notify/data_peer_notify_settings.cpp
data/notify/data_peer_notify_settings.h
data/notify/data_peer_notify_volume.cpp
data/notify/data_peer_notify_volume.h
data/stickers/data_custom_emoji.cpp
data/stickers/data_custom_emoji.h
data/stickers/data_stickers_set.cpp
@@ -886,6 +888,8 @@ PRIVATE
history/view/history_view_fake_items.h
history/view/history_view_group_call_bar.cpp
history/view/history_view_group_call_bar.h
history/view/history_view_group_members_widget.cpp
history/view/history_view_group_members_widget.h
history/view/history_view_item_preview.h
history/view/history_view_list_widget.cpp
history/view/history_view_list_widget.h
@@ -1129,6 +1133,8 @@ PRIVATE
inline_bots/inline_results_widget.h
intro/intro_code.cpp
intro/intro_code.h
intro/intro_email.cpp
intro/intro_email.h
intro/intro_password_check.cpp
intro/intro_password_check.h
intro/intro_phone.cpp
@@ -1284,6 +1290,8 @@ PRIVATE
menu/menu_antispam_validator.h
menu/menu_item_download_files.cpp
menu/menu_item_download_files.h
menu/menu_item_rate_transcribe_session.cpp
menu/menu_item_rate_transcribe_session.h
menu/menu_mute.cpp
menu/menu_mute.h
menu/menu_send.cpp
@@ -1317,6 +1325,8 @@ PRIVATE
mtproto/special_config_request.cpp
mtproto/special_config_request.h
mtproto/type_utils.h
overview/overview_checkbox.cpp
overview/overview_checkbox.h
overview/overview_layout.cpp
overview/overview_layout.h
overview/overview_layout_delegate.h
@@ -1437,10 +1447,6 @@ PRIVATE
platform/platform_window_title.h
profile/profile_back_button.cpp
profile/profile_back_button.h
profile/profile_block_group_members.cpp
profile/profile_block_group_members.h
profile/profile_block_peer_list.cpp
profile/profile_block_peer_list.h
profile/profile_block_widget.cpp
profile/profile_block_widget.h
profile/profile_cover_drop_area.cpp
@@ -1637,8 +1643,6 @@ PRIVATE
ui/text/format_song_document_name.h
ui/widgets/expandable_peer_list.cpp
ui/widgets/expandable_peer_list.h
ui/widgets/label_with_custom_emoji.cpp
ui/widgets/label_with_custom_emoji.h
ui/widgets/chat_filters_tabs_strip.cpp
ui/widgets/chat_filters_tabs_strip.h
ui/widgets/peer_bubble.cpp
@@ -1671,6 +1675,8 @@ PRIVATE
window/window_adaptive.h
window/window_chat_preview.cpp
window/window_chat_preview.h
window/window_chat_switch_process.cpp
window/window_chat_switch_process.h
window/window_connecting_widget.cpp
window/window_connecting_widget.h
window/window_controller.cpp
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / Mini / mini_ton_bold</title>
<g id="Icon-/-Mini-/-mini_ton_bold" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M12.5980305,2.7875 C13.2201476,2.7875 13.7244732,3.29182558 13.7244732,3.9139427 C13.7244732,4.11165014 13.6724374,4.30587532 13.5735947,4.47710133 L9.21676388,12.0244744 C8.80179975,12.7433201 7.88266529,12.9896647 7.16381961,12.5747006 C6.92829269,12.4387393 6.73407151,12.2414175 6.60185728,12.0037668 L2.40584723,4.46158062 C2.10339516,3.91793325 2.29892259,3.23203413 2.84256996,2.92958206 C3.01005587,2.83640316 3.19854713,2.7875 3.39020787,2.7875 L12.5980305,2.7875 Z M7.24956057,4.2875 L4.025,4.2875 L7.24956057,10.0835 L7.24956057,4.2875 Z M11.95,4.2875 L8.74956057,4.2875 L8.74956057,9.8255 L11.95,4.2875 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

Depois

Largura:  |  Altura:  |  Tamanho: 1.0 KiB

+32 -3
Ver Arquivo
@@ -380,6 +380,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_intro_fragment_about" = "Get the code for {phone_number} in the Anonymous Numbers section on Fragment.";
"lng_intro_fragment_button" = "Open Fragment";
"lng_intro_email_setup_title" = "Choose a login email";
"lng_intro_email_confirm_subtitle" = "Please check your email {email} (don't forget the spam folder) and enter the code we just sent you.";
"lng_phone_title" = "Your Phone Number";
"lng_phone_desc" = "Please confirm your country code\nand enter your phone number.";
"lng_phone_to_qr" = "Quick log in using QR code";
@@ -547,6 +550,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_notify_global" = "Global settings";
"lng_settings_notify_title" = "Notifications for chats";
"lng_settings_desktop_notify" = "Desktop notifications";
"lng_settings_master_volume_notifications" = "Volume";
"lng_settings_native_title" = "System integration";
"lng_settings_use_windows" = "Use Windows notifications";
"lng_settings_skip_in_focus" = "Respect system Focus mode";
@@ -587,12 +591,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_notification_title_private_chats" = "Notifications for private chats";
"lng_notification_about_private_chats#one" = "Please note that **{count} chat** is listed as an exception and won't be affected by this change.";
"lng_notification_about_private_chats#other" = "Please note that **{count} chats** are listed as exceptions and won't be affected by this change.";
"lng_notification_volume_private_chats" = "Notifications volume for private chats";
"lng_notification_title_groups" = "Notifications for groups";
"lng_notification_about_groups#one" = "Please note that **{count} group** is listed as an exception and won't be affected by this change.";
"lng_notification_about_groups#other" = "Please note that **{count} groups** are listed as exceptions and won't be affected by this change.";
"lng_notification_volume_groups" = "Notifications volume for groups";
"lng_notification_title_channels" = "Notifications for channels";
"lng_notification_about_channels#one" = "Please note that **{count} channel** is listed as an exception and won't be affected by this change.";
"lng_notification_about_channels#other" = "Please note that **{count} channels** are listed as exceptions and won't be affected by this change.";
"lng_notification_volume_channel" = "Notifications volume for channels";
"lng_notification_exceptions_view" = "View exceptions";
"lng_notification_enable" = "Enable notifications";
"lng_notification_sound" = "Sound";
@@ -722,6 +729,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_shortcuts_media_fullscreen" = "Toggle video fullscreen";
"lng_shortcuts_show_chat_menu" = "Show chat menu";
"lng_shortcuts_show_chat_preview" = "Show chat preview";
"lng_shortcuts_record_voice_message" = "Record Voice Message";
"lng_shortcuts_record_round_message" = "Record Round Message";
"lng_settings_chat_reactions_title" = "Quick Reaction";
"lng_settings_chat_reactions_subtitle" = "Choose your favorite reaction";
@@ -1273,6 +1282,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_quick_dialog_action_toast_archive_success" = "The chat has been archived.";
"lng_quick_dialog_action_toast_unarchive_success" = "The chat has been unarchived.";
"lng_archive_hint_title" = "This is your Archive";
"lng_archive_hint_about" = "Archived chats will remain in the Archive when you receive a new message. {link}";
"lng_archive_hint_about_unmuted" = "When you receive a new message, muted chats will remain in the Archive, while unmuted chats will be moved to Chats. {link}";
"lng_archive_hint_about_link" = "Tap to change {emoji}";
"lng_archive_hint_section_1" = "Archived Chats";
"lng_archive_hint_section_1_info" = "Move any chat into your Archive and back by swiping on it.";
"lng_archive_hint_section_2" = "Hiding Archive";
"lng_archive_hint_section_2_info" = "Hide the Archive from your Main screen by swiping on it.";
"lng_archive_hint_section_3" = "Stories";
"lng_archive_hint_section_3_info" = "Archive Stories from your contacts separately from chats with them.";
"lng_archive_hint_button" = "Got it";
"lng_settings_generic_subscribe" = "Subscribe to {link} to use this setting.";
"lng_settings_generic_subscribe_link" = "Telegram Premium";
@@ -2090,6 +2111,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sure_delete_contact" = "Are you sure you want to delete {contact} from your contact list?";
"lng_sure_delete_history" = "Are you sure you want to delete all message history with {contact}?\n\nThis action cannot be undone.";
"lng_sure_delete_group_history" = "Are you sure you want to delete all messages in \"{group}\"?\n\nThis action cannot be undone.";
"lng_sure_delete_channel_history" = "Are you sure you want to delete all messages in \"{channel}\"?\n\n**This action cannot be undone.**";
"lng_sure_delete_and_exit" = "Are you sure you want to delete all message history and leave «{group}»?\n\nThis action cannot be undone.";
"lng_sure_leave_channel" = "Are you sure you want to leave\nthis channel?";
"lng_sure_delete_channel" = "Are you sure you want to delete this channel? All subscribers will be removed and all messages will be lost.";
@@ -2937,6 +2959,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_box_history_entry_ads" = "Ads Platform";
"lng_credits_box_history_entry_premium_bot" = "Stars Top-Up";
"lng_credits_box_history_entry_currency_in" = "TON Top-Up";
"lng_credits_box_history_entry_posts_search" = "Posts Search";
"lng_credits_box_history_entry_api" = "Paid Broadcast";
"lng_credits_box_history_entry_floodskip_about#one" = "{count} Message";
"lng_credits_box_history_entry_floodskip_about#other" = "{count} Messages";
@@ -3645,8 +3668,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_hidden_hint_channel" = "This gift is hidden from visitors of your channel.";
"lng_gift_visible_hint_channel" = "This gift is visible in your channel's Gifts.";
"lng_gift_in_blockchain" = "This gift is in TON blockchain. {link}";
"lng_gift_in_blockchain_link" = "View >";
"lng_gift_visible_hide" = "Hide >";
"lng_gift_in_blockchain_link_arrow" = "View {arrow}";
"lng_gift_visible_hide_arrow" = "Hide {arrow}";
"lng_gift_visible_show_arrow" = "Show {arrow}";
"lng_gift_show_on_page" = "Display on my Page";
"lng_gift_show_on_channel" = "Display in channel's Gifts";
"lng_gift_availability" = "Availability";
@@ -3665,7 +3689,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_unique_address_copied" = "Address copied to clipboard.";
"lng_gift_unique_status" = "Status";
"lng_gift_unique_status_non" = "Non-Unique";
"lng_gift_unique_status_upgrade" = "upgrade";
"lng_gift_unique_upgrade" = "Upgrade";
"lng_gift_unique_number" = "Collectible #{index}";
"lng_gift_unique_number_by" = "Collectible #{index} by {name}";
"lng_gift_unique_model" = "Model";
@@ -4324,6 +4348,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_archive_to_list" = "Move to chat list";
"lng_context_archive_to_menu_info" = "Archive moved to the main menu!\nRight click the archive button to return the Archive to your chat list.";
"lng_context_archive_settings" = "Archive settings";
"lng_context_archive_how_does_it_work" = "How does it work?";
"lng_context_mute" = "Mute notifications";
"lng_context_unmute" = "Unmute";
@@ -4335,6 +4360,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_remove_from_group" = "Remove from group";
"lng_context_add_to_group" = "Add to group";
"lng_context_rate_transcription" = "Rate transcription";
"lng_toast_sent_rate_transcription" = "Thank you for your feedback!";
"lng_context_copy_link" = "Copy Link";
"lng_context_copy_message_link" = "Copy Message Link";
"lng_context_copy_post_link" = "Copy Post Link";
@@ -6372,6 +6400,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_ringtones_box_title" = "Notification Sound";
"lng_ringtones_box_cloud_subtitle" = "Choose your tone";
"lng_ringtones_box_volume" = "Volume";
"lng_ringtones_box_upload_choose" = "Choose a tone";
"lng_ringtones_box_upload_button" = "Upload Sound";
"lng_ringtones_box_about" = "Right click on any short voice note or MP3 file in chat and select \"Save for Notifications\". It will appear here.";
+2 -2
Ver Arquivo
@@ -51,8 +51,8 @@ var LocationPicker = {
},
init: function (params) {
mapboxgl.accessToken = params.token;
if (params.protocol) {
mapboxgl.config.API_URL = params.protocol + '://domain/api.mapbox.com';
if (location.hostname != 'desktop-app-resource') {
mapboxgl.config.API_URL = location.protocol + '//' + location.host + '/api.mapbox.com';
}
var options = { container: 'map', config: {
+1 -1
Ver Arquivo
@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="6.0.2.0" />
Version="6.0.3.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
+4 -4
Ver Arquivo
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 6,0,2,0
PRODUCTVERSION 6,0,2,0
FILEVERSION 6,0,3,0
PRODUCTVERSION 6,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", ""
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "6.0.2.0"
VALUE "FileVersion", "6.0.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "6.0.2.0"
VALUE "ProductVersion", "6.0.3.0"
END
END
BLOCK "VarFileInfo"
+4 -4
Ver Arquivo
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 6,0,2,0
PRODUCTVERSION 6,0,2,0
FILEVERSION 6,0,3,0
PRODUCTVERSION 6,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", ""
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "6.0.2.0"
VALUE "FileVersion", "6.0.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "6.0.2.0"
VALUE "ProductVersion", "6.0.3.0"
END
END
BLOCK "VarFileInfo"
+1 -5
Ver Arquivo
@@ -217,11 +217,7 @@ void Authorizations::toggleCallsDisabled(uint64 hash, bool disabled) {
MTP_bool(disabled)
)).done([=] {
_toggleCallsDisabledRequests.remove(hash);
}).fail([=](const MTP::Error &error) {
LOG(("API Error: toggle calls %1. Hash: %2. %3.")
.arg(disabled ? u"disabled"_q : u"enabled"_q)
.arg(hash)
.arg(error.type()));
}).fail([=] {
_toggleCallsDisabledRequests.remove(hash);
}).send();
_toggleCallsDisabledRequests.emplace(hash, id);
+35 -39
Ver Arquivo
@@ -142,13 +142,12 @@ void ConfirmSubscriptionBox(
const auto content = box->verticalLayout();
Ui::AddSkip(content, st::confirmInvitePhotoTop);
const auto userpicWrap = content->add(
object_ptr<Ui::CenterWrap<>>(
content,
object_ptr<Ui::RpWidget>(content)));
const auto userpic = userpicWrap->entity();
const auto userpic = content->add(
object_ptr<Ui::RpWidget>(content),
style::al_top);
const auto photoSize = st::confirmInvitePhotoSize;
userpic->resize(Size(photoSize));
userpic->setNaturalWidth(photoSize);
const auto creditsIconSize = photoSize / 3;
const auto creditsIconCallback =
Ui::PaintOutlinedColoredCreditsIconCallback(
@@ -188,8 +187,8 @@ void ConfirmSubscriptionBox(
}
auto p = QPainter(userpic);
p.drawImage(0, 0, state->frame);
}, userpicWrap->lifetime());
userpicWrap->setAttribute(Qt::WA_TransparentForMouseEvents);
}, userpic->lifetime());
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
if (photo) {
state->photoMedia = photo->createMediaView();
state->photoMedia->wanted(Data::PhotoSize::Small, Data::FileOrigin());
@@ -197,7 +196,7 @@ void ConfirmSubscriptionBox(
session->downloaderTaskFinished(
) | rpl::start_with_next([=] {
userpic->update();
}, userpicWrap->entity()->lifetime());
}, userpic->lifetime());
}
} else {
state->photoEmpty = std::make_unique<Ui::EmptyUserpic>(
@@ -215,43 +214,40 @@ void ConfirmSubscriptionBox(
2.);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_channel_invite_subscription_title(),
st::inviteLinkSubscribeBoxTitle)));
tr::lng_channel_invite_subscription_title(),
st::inviteLinkSubscribeBoxTitle),
style::al_top);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_channel_invite_subscription_about(
lt_channel,
rpl::single(Ui::Text::Bold(name)),
lt_price,
tr::lng_credits_summary_options_credits(
lt_count,
rpl::single(amount) | tr::to_count(),
Ui::Text::Bold),
Ui::Text::WithEntities),
st::inviteLinkSubscribeBoxAbout)));
tr::lng_channel_invite_subscription_about(
lt_channel,
rpl::single(Ui::Text::Bold(name)),
lt_price,
tr::lng_credits_summary_options_credits(
lt_count,
rpl::single(amount) | tr::to_count(),
Ui::Text::Bold),
Ui::Text::WithEntities),
st::inviteLinkSubscribeBoxAbout),
style::al_top);
Ui::AddSkip(content);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_channel_invite_subscription_terms(
lt_link,
rpl::combine(
tr::lng_paid_react_agree_link(),
tr::lng_group_invite_subscription_about_url()
) | rpl::map([](const QString &text, const QString &url) {
return Ui::Text::Link(text, url);
}),
Ui::Text::RichLangValue),
st::inviteLinkSubscribeBoxTerms)));
tr::lng_channel_invite_subscription_terms(
lt_link,
rpl::combine(
tr::lng_paid_react_agree_link(),
tr::lng_group_invite_subscription_about_url()
) | rpl::map([](const QString &text, const QString &url) {
return Ui::Text::Link(text, url);
}),
Ui::Text::RichLangValue),
st::inviteLinkSubscribeBoxTerms),
style::al_top);
{
const auto balance = Settings::AddBalanceWidget(
@@ -153,6 +153,7 @@ Data::CreditsHistoryEntry CreditsHistoryEntryFromTL(
.floodSkip = int(tl.data().vfloodskip_number().value_or(0)),
.converted = stargift && incoming,
.stargift = stargift.has_value(),
.postsSearch = tl.data().is_posts_search(),
.giftUpgraded = tl.data().is_stargift_upgrade(),
.giftResale = tl.data().is_stargift_resale(),
.reaction = tl.data().is_reaction(),
+21 -14
Ver Arquivo
@@ -45,15 +45,17 @@ namespace {
auto options = PremiumSubscriptionOptionsFromTL(tlOptions);
for (auto i = 0; i < options.size(); i++) {
const auto &tlOption = tlOptions[i].data();
const auto currency = qs(tlOption.vcurrency());
const auto perUserText = Ui::FillAmountAndCurrency(
tlOption.vamount().v / float64(tlOption.vusers().v),
qs(tlOption.vcurrency()),
currency,
false);
options[i].costPerMonth = perUserText
+ ' '
+ QChar(0x00D7)
+ ' '
+ QString::number(tlOption.vusers().v);
options[i].currency = currency;
}
return options;
}
@@ -613,24 +615,32 @@ std::vector<GiftOptionData> PremiumGiftCodeOptions::optionsForPeer() const {
return result;
}
Data::PremiumSubscriptionOptions PremiumGiftCodeOptions::options(int amount) {
const auto it = _subscriptionOptions.find(amount);
Data::PremiumSubscriptionOptions PremiumGiftCodeOptions::optionsForGiveaway(
int usersCount) {
const auto skipForStars = [&](Data::PremiumSubscriptionOptions options) {
const auto proj = &Data::PremiumSubscriptionOption::currency;
options.erase(
ranges::remove(options, Ui::kCreditsCurrency, proj),
end(options));
return options;
};
const auto it = _subscriptionOptions.find(usersCount);
if (it != end(_subscriptionOptions)) {
return it->second;
return skipForStars(it->second);
} else {
auto tlOptions = QVector<MTPPremiumGiftCodeOption>();
for (auto i = 0; i < _optionsForOnePerson.months.size(); i++) {
tlOptions.push_back(MTP_premiumGiftCodeOption(
MTP_flags(MTPDpremiumGiftCodeOption::Flags(0)),
MTP_int(amount),
MTP_int(usersCount),
MTP_int(_optionsForOnePerson.months[i]),
MTPstring(),
MTPint(),
MTP_string(_optionsForOnePerson.currencies[i]),
MTP_long(_optionsForOnePerson.totalCosts[i] * amount)));
MTP_long(_optionsForOnePerson.totalCosts[i] * usersCount)));
}
_subscriptionOptions[amount] = GiftCodesFromTL(tlOptions);
return _subscriptionOptions[amount];
_subscriptionOptions[usersCount] = GiftCodesFromTL(tlOptions);
return skipForStars(_subscriptionOptions[usersCount]);
}
}
@@ -950,12 +960,9 @@ std::optional<Data::SavedStarGift> FromTL(
| ranges::to_vector)
: std::vector<int>()),
.message = (data.vmessage()
? TextWithEntities{
.text = qs(data.vmessage()->data().vtext()),
.entities = Api::EntitiesFromMTP(
session,
data.vmessage()->data().ventities().v),
}
? Api::ParseTextWithEntities(
session,
*data.vmessage())
: TextWithEntities()),
.starsConverted = int64(data.vconvert_stars().value_or_empty()),
.starsUpgradedBySender = int64(
+2 -1
Ver Arquivo
@@ -180,7 +180,8 @@ public:
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
[[nodiscard]] std::vector<GiftOptionData> optionsForPeer() const;
[[nodiscard]] Data::PremiumSubscriptionOptions options(int amount);
[[nodiscard]] Data::PremiumSubscriptionOptions optionsForGiveaway(
int usersCount);
[[nodiscard]] const std::vector<int> &availablePresets() const;
[[nodiscard]] int monthsFromPreset(int monthsIndex);
[[nodiscard]] Payments::InvoicePremiumGiftCode invoice(
+27
Ver Arquivo
@@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_helpers.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
namespace Api {
@@ -25,6 +26,32 @@ Transcribes::Transcribes(not_null<ApiWrap*> api)
, _api(&api->instance()) {
}
bool Transcribes::isRated(not_null<HistoryItem*> item) const {
const auto fullId = item->fullId();
for (const auto &[transcribeId, id] : _ids) {
if (id == fullId) {
return _session->settings().isTranscriptionRated(transcribeId);
}
}
return false;
}
void Transcribes::rate(not_null<HistoryItem*> item, bool isGood) {
const auto fullId = item->fullId();
for (const auto &[transcribeId, id] : _ids) {
if (id == fullId) {
_api.request(MTPmessages_RateTranscribedAudio(
item->history()->peer->input,
MTP_int(item->id),
MTP_long(transcribeId),
MTP_bool(isGood))).send();
_session->settings().markTranscriptionAsRated(transcribeId);
_session->saveSettings();
return;
}
}
}
bool Transcribes::freeFor(not_null<HistoryItem*> item) const {
if (const auto channel = item->history()->peer->asMegagroup()) {
const auto owner = &channel->owner();
+2
Ver Arquivo
@@ -37,6 +37,8 @@ public:
void apply(const MTPDupdateTranscribedAudio &update);
[[nodiscard]] bool freeFor(not_null<HistoryItem*> item) const;
[[nodiscard]] bool isRated(not_null<HistoryItem*> item) const;
void rate(not_null<HistoryItem*> item, bool isGood);
[[nodiscard]] bool trialsSupport();
[[nodiscard]] TimeId trialsRefreshAt();
+10 -1
Ver Arquivo
@@ -2458,7 +2458,16 @@ void ApiWrap::refreshFileReference(
v::match(origin.data, [&](Data::FileOriginMessage data) {
if (const auto item = _session->data().message(data)) {
const auto media = item->media();
const auto storyId = media ? media->storyId() : FullStoryId();
const auto mediaStory = media ? media->storyId() : FullStoryId();
const auto storyId = mediaStory
? mediaStory
: FullStoryId(
(IsStoryMsgId(item->id)
? item->history()->peer->id
: PeerId()),
(IsStoryMsgId(item->id)
? StoryIdFromMsgId(item->id)
: StoryId()));
if (storyId) {
request(MTPstories_GetStoriesByID(
_session->data().peer(storyId.peer)->input,
+1 -1
Ver Arquivo
@@ -28,7 +28,7 @@ namespace Data {
struct UpdatedFileReferences;
class WallPaper;
struct ResolvedForwardDraft;
enum class DefaultNotify;
enum class DefaultNotify : uint8_t;
enum class StickersType : uchar;
class Forum;
class ForumTopic;
+156
Ver Arquivo
@@ -13,12 +13,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/update_checker.h"
#include "lang/lang_keys.h"
#include "ui/boxes/confirm_box.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_channel_earn.h"
#include "styles/style_chat.h"
#include "styles/style_dialogs.h"
#include "styles/style_menu_icons.h"
#include "styles/style_premium.h"
#include "styles/style_settings.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
@@ -160,3 +168,151 @@ QString currentVersionText() {
#endif
return result;
}
void ArchiveHintBox(
not_null<Ui::GenericBox*> box,
bool unarchiveOnNewMessage,
Fn<void()> onUnarchive) {
box->setNoContentMargin(true);
const auto content = box->verticalLayout().get();
Ui::AddSkip(content);
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto &icon = st::dialogsArchiveUserpic;
const auto rect = Rect(icon.size() * 2);
auto owned = object_ptr<Ui::RpWidget>(content);
owned->resize(rect.size());
owned->setNaturalWidth(rect.width());
const auto widget = box->addRow(std::move(owned), style::al_top);
widget->paintRequest(
) | rpl::start_with_next([=] {
auto p = Painter(widget);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::activeButtonBg);
p.drawEllipse(rect);
icon.paintInCenter(p, rect);
}, widget->lifetime());
}
Ui::AddSkip(content);
Ui::AddSkip(content);
box->addRow(
object_ptr<Ui::FlatLabel>(
content,
tr::lng_archive_hint_title(),
st::boxTitle),
style::al_top);
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto label = box->addRow(
object_ptr<Ui::FlatLabel>(
content,
(unarchiveOnNewMessage
? tr::lng_archive_hint_about_unmuted
: tr::lng_archive_hint_about)(
lt_link,
tr::lng_archive_hint_about_link(
lt_emoji,
rpl::single(
Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(std::move(text), 1);
}),
Ui::Text::RichLangValue),
st::channelEarnHistoryRecipientLabel));
label->resizeToWidth(box->width()
- rect::m::sum::h(st::boxRowPadding));
label->setLink(
1,
std::make_shared<GenericClickHandler>([=](ClickContext context) {
if (context.button == Qt::LeftButton) {
onUnarchive();
}
}));
}
Ui::AddSkip(content);
Ui::AddSkip(content);
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto padding = QMargins(
st::settingsButton.padding.left(),
st::boxRowPadding.top(),
st::boxRowPadding.right(),
st::boxRowPadding.bottom());
const auto addEntry = [&](
rpl::producer<QString> title,
rpl::producer<QString> about,
const style::icon &icon) {
const auto top = content->add(
object_ptr<Ui::FlatLabel>(
content,
std::move(title),
st::channelEarnSemiboldLabel),
padding);
Ui::AddSkip(content, st::channelEarnHistoryThreeSkip);
content->add(
object_ptr<Ui::FlatLabel>(
content,
std::move(about),
st::channelEarnHistoryRecipientLabel),
padding);
const auto left = Ui::CreateChild<Ui::RpWidget>(
box->verticalLayout().get());
left->paintRequest(
) | rpl::start_with_next([=] {
auto p = Painter(left);
icon.paint(p, 0, 0, left->width());
}, left->lifetime());
left->resize(icon.size());
top->geometryValue(
) | rpl::start_with_next([=](const QRect &g) {
left->moveToLeft(
(g.left() - left->width()) / 2,
g.top() + st::channelEarnHistoryThreeSkip);
}, left->lifetime());
};
addEntry(
tr::lng_archive_hint_section_1(),
tr::lng_archive_hint_section_1_info(),
st::menuIconArchive);
Ui::AddSkip(content);
Ui::AddSkip(content);
addEntry(
tr::lng_archive_hint_section_2(),
tr::lng_archive_hint_section_2_info(),
st::menuIconStealth);
Ui::AddSkip(content);
Ui::AddSkip(content);
addEntry(
tr::lng_archive_hint_section_3(),
tr::lng_archive_hint_section_3_info(),
st::menuIconStoriesSavedSection);
Ui::AddSkip(content);
Ui::AddSkip(content);
}
Ui::AddSkip(content);
Ui::AddSkip(content);
Ui::AddSkip(content);
{
const auto &st = st::premiumPreviewDoubledLimitsBox;
box->setStyle(st);
auto button = object_ptr<Ui::RoundButton>(
box,
tr::lng_archive_hint_button(),
st::defaultActiveButton);
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
button->setClickedCallback([=] { box->closeBox(); });
box->addButton(std::move(button));
}
}
+4
Ver Arquivo
@@ -10,6 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
void AboutBox(not_null<Ui::GenericBox*> box);
void ArchiveHintBox(
not_null<Ui::GenericBox*> box,
bool unarchiveOnNewMessage,
Fn<void()> onUnarchive);
QString telegramFaqLink();
QString currentVersionText();
+10 -2
Ver Arquivo
@@ -1116,8 +1116,16 @@ moderateBoxExpandInnerSkip: 2px;
moderateBoxExpandFont: font(11px);
moderateBoxExpandToggleSize: 4px;
moderateBoxExpandToggleFourStrokes: 3px;
moderateBoxExpandIcon: icon{{ "info/edit/expand_arrow_small-flip_vertical", windowActiveTextFg }};
moderateBoxExpandIconDown: icon{{ "info/edit/expand_arrow_small", windowActiveTextFg }};
moderateBoxExpandIcon: IconEmoji{
icon: icon{{ "info/edit/expand_arrow_small-flip_vertical", windowActiveTextFg }};
padding: margins(-2px, -1px, 0px, 0px);
useIconColor: true;
}
moderateBoxExpandIconDown: IconEmoji{
icon: icon{{ "info/edit/expand_arrow_small", windowActiveTextFg }};
padding: margins(-2px, -1px, 0px, 0px);
useIconColor: true;
}
moderateBoxDividerLabel: FlatLabel(boxDividerLabel) {
palette: TextPalette(defaultTextPalette) {
selectLinkFg: windowActiveTextFg;
+13 -12
Ver Arquivo
@@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/rect.h"
#include "ui/wrap/slide_wrap.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@@ -111,16 +112,12 @@ void DeleteMessagesBox::prepare() {
Ui::Text::RichLangValue);
deleteStyle = &st::attentionBoxButton;
} else if (_wipeHistoryJustClear) {
const auto isChannel = peer->isBroadcast();
const auto isPublicGroup = peer->isMegagroup()
&& peer->asChannel()->isPublic();
if (isChannel || isPublicGroup) {
canDelete = false;
}
details.text = isChannel
? tr::lng_no_clear_history_channel(tr::now)
: isPublicGroup
? tr::lng_no_clear_history_group(tr::now)
_revokeJustClearForChannel = true;
details.text = (peer->isChannel() && !peer->isMegagroup())
? tr::lng_sure_delete_channel_history(
tr::now,
lt_channel,
peer->name())
: peer->isSelf()
? tr::lng_sure_delete_saved_messages(tr::now)
: peer->isUser()
@@ -156,7 +153,8 @@ void DeleteMessagesBox::prepare() {
}
deleteStyle = &st::attentionBoxButton;
}
if (auto revoke = revokeText(peer)) {
if (_revokeJustClearForChannel) {
} else if (auto revoke = revokeText(peer)) {
_revoke.create(
this,
revoke->checkbox,
@@ -285,6 +283,7 @@ void DeleteMessagesBox::prepare() {
}
}
_text.create(this, rpl::single(std::move(details)), st::boxLabel);
_text->resizeToWidth(st::boxWidth - rect::m::sum::h(st::boxPadding));
if (_wipeHistoryJustClear && _wipeHistoryPeer) {
const auto validator = TTLMenu::TTLValidator(
@@ -554,7 +553,9 @@ void DeleteMessagesBox::deleteAndClear() {
!_revoke->checked());
Core::App().saveSettingsDelayed();
}
const auto revoke = _revoke ? _revoke->checked() : _revokeForBot;
const auto revoke = _revoke
? _revoke->checked()
: (_revokeForBot || _revokeJustClearForChannel);
const auto session = _session;
const auto invokeCallbackAndClose = [&] {
// deleteMessages can initiate closing of the current section,
@@ -75,6 +75,7 @@ private:
bool _moderateDeleteAll = false;
bool _revokeForBot = false;
bool _revokeJustClearForChannel = false;
object_ptr<Ui::FlatLabel> _text = { nullptr };
object_ptr<Ui::Checkbox> _revoke = { nullptr };
+1 -1
Ver Arquivo
@@ -1293,7 +1293,7 @@ void EditDirectMessagesPriceBox(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
box,
object_ptr<Ui::VerticalLayout>(box)),
{});
style::margins());
wrap->toggle(savedValue.has_value(), anim::type::instant);
wrap->toggleOn(toggle->toggledChanges());
@@ -538,25 +538,24 @@ void LinkController::addHeader(not_null<Ui::VerticalLayout*> container) {
const auto isStatic = _filterTitle.isStatic;
verticalLayout->add(
object_ptr<Ui::CenterWrap<>>(
object_ptr<Ui::FlatLabel>(
verticalLayout,
object_ptr<Ui::FlatLabel>(
verticalLayout,
(_data.url.isEmpty()
? tr::lng_filters_link_no_about(Ui::Text::WithEntities)
: tr::lng_filters_link_share_about(
lt_folder,
rpl::single(Ui::Text::Wrapped(
_filterTitle.text,
EntityType::Bold)),
Ui::Text::WithEntities)),
st::settingsFilterDividerLabel,
st::defaultPopupMenu,
Core::TextContext({
.session = &_window->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}))),
st::filterLinkDividerLabelPadding);
(_data.url.isEmpty()
? tr::lng_filters_link_no_about(Ui::Text::WithEntities)
: tr::lng_filters_link_share_about(
lt_folder,
rpl::single(Ui::Text::Wrapped(
_filterTitle.text,
EntityType::Bold)),
Ui::Text::WithEntities)),
st::settingsFilterDividerLabel,
st::defaultPopupMenu,
Core::TextContext({
.session = &_window->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
})),
st::filterLinkDividerLabelPadding,
style::al_top)->setTryMakeSimilarLines(true);
verticalLayout->geometryValue(
) | rpl::start_with_next([=](const QRect &r) {
+12 -16
Ver Arquivo
@@ -24,7 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rect.h"
#include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "ui/widgets/label_with_custom_emoji.h"
#include "window/window_session_controller.h"
#include "styles/style_boxes.h"
#include "styles/style_channel_earn.h"
@@ -53,9 +52,8 @@ void GiftCreditsBox(
Ui::AddSkip(content);
const auto &stUser = st::premiumGiftsUserpicButton;
const auto userpicWrap = content->add(
object_ptr<Ui::CenterWrap<>>(
content,
object_ptr<Ui::UserpicButton>(content, peer, stUser)));
object_ptr<Ui::UserpicButton>(content, peer, stUser),
style::al_top);
userpicWrap->setAttribute(Qt::WA_TransparentForMouseEvents);
Ui::AddSkip(content);
Ui::AddSkip(content);
@@ -78,19 +76,17 @@ void GiftCreditsBox(
u"internal:stars_examples"_q);
});
content->add(
object_ptr<Ui::CenterWrap<>>(
object_ptr<Ui::FlatLabel>(
content,
Ui::CreateLabelWithCustomEmoji(
content,
tr::lng_credits_box_history_entry_gift_out_about(
lt_user,
rpl::single(TextWithEntities{ peer->shortName() }),
lt_link,
std::move(link),
Ui::Text::RichLangValue),
Core::TextContext({ .session = &peer->session() }),
st::creditsBoxAbout)),
st::boxRowPadding);
tr::lng_credits_box_history_entry_gift_out_about(
lt_user,
rpl::single(TextWithEntities{ peer->shortName() }),
lt_link,
std::move(link),
Ui::Text::RichLangValue),
st::creditsBoxAbout),
st::boxRowPadding,
style::al_top);
}
Ui::AddSkip(content);
Ui::AddSkip(box->verticalLayout());
+17 -39
Ver Arquivo
@@ -466,8 +466,7 @@ void AddTableRow(
}
[[nodiscard]] object_ptr<Ui::RpWidget> MakeNonUniqueStatusTableValue(
not_null<Ui::TableLayout*> table,
Fn<void()> startUpgrade) {
not_null<Ui::TableLayout*> table) {
auto result = object_ptr<Ui::RpWidget>(table);
const auto raw = result.data();
@@ -477,34 +476,10 @@ void AddTableRow(
table->st().defaultValue,
st::defaultPopupMenu);
const auto upgrade = startUpgrade
? Ui::CreateChild<Ui::RoundButton>(
raw,
tr::lng_gift_unique_status_upgrade(),
table->st().smallButton)
: (Ui::RoundButton*)(nullptr);
if (upgrade) {
using namespace Ui;
upgrade->setTextTransform(RoundButton::TextTransform::NoTransform);
upgrade->setClickedCallback(startUpgrade);
}
rpl::combine(
raw->widthValue(),
upgrade ? upgrade->widthValue() : rpl::single(0)
) | rpl::start_with_next([=](int width, int toggleWidth) {
const auto toggleSkip = toggleWidth
? (st::normalFont->spacew + toggleWidth)
: 0;
label->resizeToNaturalWidth(width - toggleSkip);
raw->widthValue(
) | rpl::start_with_next([=](int width) {
label->resizeToNaturalWidth(width);
label->moveToLeft(0, 0, width);
if (upgrade) {
upgrade->moveToLeft(
label->width() + st::normalFont->spacew,
(table->st().defaultValue.style.font->ascent
- table->st().smallButton.style.font->ascent),
width);
}
}, label->lifetime());
label->heightValue() | rpl::start_with_next([=](int height) {
@@ -766,7 +741,8 @@ void GiftCodeBox(
std::move(shareLink),
Ui::Text::WithEntities)),
st::giveawayGiftCodeFooter),
st::giveawayGiftCodeFooterMargin);
st::giveawayGiftCodeFooterMargin,
style::al_top);
footer->setClickHandlerFilter([=](const auto &...) {
ShareWithFriend(controller, slug);
return false;
@@ -908,7 +884,8 @@ void GiftCodePendingBox(
box,
tr::lng_gift_link_pending_footer(),
st::giveawayGiftCodeFooter),
st::giveawayGiftCodeFooterMargin);
st::giveawayGiftCodeFooterMargin,
style::al_top);
const auto close = Ui::CreateChild<Ui::IconButton>(
box.get(),
@@ -1013,12 +990,11 @@ void GiveawayInfoBox(
label->setTextColorOverride(st::windowActiveTextFg->c);
}
const auto result = box->addRow(
object_ptr<Ui::PaddingWrap<Ui::CenterWrap<Ui::FlatLabel>>>(
object_ptr<Ui::PaddingWrap<Ui::FlatLabel>>(
box.get(),
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box.get(),
std::move(label)),
QMargins(0, skip, 0, skip)));
std::move(label),
QMargins(0, skip, 0, skip)),
style::al_justify);
result->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(result);
p.setPen(Qt::NoPen);
@@ -1211,7 +1187,8 @@ void GiveawayInfoBox(
: tr::lng_prizes_cancelled()),
st::giveawayRefundedLabel),
st::giveawayRefundedPadding),
{ padding.left(), 0, padding.right(), padding.bottom() });
{ padding.left(), 0, padding.right(), padding.bottom() },
style::al_top);
const auto bg = wrap->lifetime().make_state<Ui::RoundRect>(
st::boxRadius,
st::attentionBoxButton.textBgOver);
@@ -1525,7 +1502,7 @@ void AddStarGiftTable(
AddTableRow(
table,
tr::lng_gift_unique_status(),
MakeNonUniqueStatusTableValue(table, std::move(startUpgrade)),
MakeNonUniqueStatusTableValue(table),
marginWithButton);
}
if (unique) {
@@ -1674,7 +1651,8 @@ void AddCreditsHistoryEntryTable(
show,
peerId);
}
if (actorId || (!entry.starrefCommission && peerId)) {
if (!entry.postsSearch
&& (actorId || (!entry.starrefCommission && peerId))) {
auto text = entry.starrefCommission
? tr::lng_credits_box_history_entry_referred()
: entry.in
@@ -403,22 +403,10 @@ void CreateModerateMessagesBox(
const auto container = wrap->entity();
wrap->toggle(false, anim::type::instant);
const auto session = &participants.front()->session();
const auto emojiMargin = QMargins(
-st::moderateBoxExpandInnerSkip,
-st::moderateBoxExpandInnerSkip / 2,
0,
0);
const auto emojiUp = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIcon,
emojiMargin,
false));
const auto emojiDown = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIconDown,
emojiMargin,
false));
const auto emojiUp = Ui::Text::IconEmoji(
&st::moderateBoxExpandIcon);
const auto emojiDown = Ui::Text::IconEmoji(
&st::moderateBoxExpandIconDown);
auto label = object_ptr<Ui::FlatLabel>(
inner,
@@ -463,9 +451,7 @@ void CreateModerateMessagesBox(
Ui::Text::WithEntities);
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const TextWithEntities &text) {
raw->setMarkedText(
Ui::Text::Link(text, u"internal:"_q),
Core::TextContext({ .session = session }));
raw->setMarkedText(Ui::Text::Link(text, u"internal:"_q));
}, label->lifetime());
Ui::AddSkip(inner);
@@ -233,7 +233,8 @@ void FillUpgradeToPremiumCover(
container,
rpl::single(text),
st::inviteForbiddenInfo),
st::inviteForbiddenInfoPadding);
st::inviteForbiddenInfoPadding,
style::al_top);
}
void SimpleForbiddenBox(
@@ -511,7 +512,8 @@ void InviteForbiddenController::setComplexCover() {
if (_can) {
container->add(
MakeShowOrLabel(container, tr::lng_invite_upgrade_or()),
st::inviteForbiddenOrLabelPadding);
st::inviteForbiddenOrLabelPadding,
style::al_justify);
}
container->add(
object_ptr<Ui::FlatLabel>(
@@ -520,7 +522,8 @@ void InviteForbiddenController::setComplexCover() {
? tr::lng_invite_upgrade_via_title()
: tr::lng_via_link_cant()),
st::inviteForbiddenTitle),
st::inviteForbiddenTitlePadding);
st::inviteForbiddenTitlePadding,
style::al_top);
const auto about = _can
? (_peer->isBroadcast()
@@ -544,7 +547,8 @@ void InviteForbiddenController::setComplexCover() {
container,
rpl::single(about),
st::inviteForbiddenInfo),
st::inviteForbiddenInfoPadding);
st::inviteForbiddenInfoPadding,
style::al_top);
}
delegate()->peerListSetAboveWidget(std::move(cover));
}
@@ -77,7 +77,9 @@ DefaultIconEmoji::DefaultIconEmoji(
std::move(value) | rpl::start_with_next([=](DefaultIcon value) {
_icon = value;
_image = QImage();
repaint();
if (repaint) {
repaint();
}
}, _lifetime);
}
@@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/background_box.h"
#include "boxes/stickers_box.h"
#include "chat_helpers/compose/compose_show.h"
#include "core/ui_integration.h" // TextContext
#include "data/stickers/data_custom_emoji.h"
#include "data/stickers/data_stickers.h"
#include "data/data_changes.h"
@@ -82,7 +81,6 @@ public:
bool selected);
[[nodiscard]] uint8 index() const;
int naturalWidth() const override;
void setSelected(bool selected);
@@ -164,7 +162,6 @@ private:
void updateText();
const uint32 _level;
const TextWithEntities _icon;
const Ui::Text::MarkedContext _context;
Ui::Text::String _text;
bool _minimal = false;
@@ -183,6 +180,15 @@ ColorSample::ColorSample(
colorIndex
) | rpl::start_with_next([=](uint8 index) {
_index = index;
setNaturalWidth([&] {
if (_name.isEmpty() || _style->colorPatternIndex(_index)) {
return st::settingsColorSampleSize;
}
const auto padding = st::settingsColorSamplePadding;
return std::max(
padding.left() + _name.maxWidth() + padding.right(),
padding.top() + st::semiboldFont->height + padding.bottom());
}());
update();
}, lifetime());
}
@@ -197,6 +203,7 @@ ColorSample::ColorSample(
, _index(colorIndex)
, _selected(selected)
, _simple(true) {
setNaturalWidth(st::settingsColorSampleSize);
}
void ColorSample::setSelected(bool selected) {
@@ -278,16 +285,6 @@ uint8 ColorSample::index() const {
return _index;
}
int ColorSample::naturalWidth() const {
if (_name.isEmpty() || _style->colorPatternIndex(_index)) {
return st::settingsColorSampleSize;
}
const auto padding = st::settingsColorSamplePadding;
return std::max(
padding.left() + _name.maxWidth() + padding.right(),
padding.top() + st::semiboldFont->height + padding.bottom());
}
PreviewWrap::PreviewWrap(
not_null<Ui::GenericBox*> box,
std::shared_ptr<Ui::ChatStyle> style,
@@ -460,22 +457,12 @@ LevelBadge::LevelBadge(
uint32 level,
not_null<Main::Session*> session)
: Ui::RpWidget(parent)
, _level(level)
, _icon(Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::settingsLevelBadgeLock,
QMargins(0, st::settingsLevelBadgeLockSkip, 0, 0),
false)))
, _context(Core::TextContext({
.session = session,
.repaint = [this] { update(); },
})) {
, _level(level) {
updateText();
}
void LevelBadge::updateText() {
auto text = _icon;
text.append(' ');
auto text = Ui::Text::IconEmoji(&st::settingsLevelBadgeLock).append(' ');
if (!_minimal) {
text.append(tr::lng_boost_level(
tr::now,
@@ -490,7 +477,7 @@ void LevelBadge::updateText() {
st,
text,
kMarkupTextOptions,
_context);
Ui::Text::MarkedContext{ .repaint = [=] { update(); } });
const auto &padding = st::settingsColorSamplePadding;
QWidget::resize(
_text.maxWidth() + rect::m::sum::h(padding),
@@ -1213,7 +1200,7 @@ void EditPeerColorBox(
peer,
state->index.value(),
state->emojiId.value()
), {});
), style::margins());
auto indices = peer->session().api().peerColors().suggestedValue();
const auto margin = st::settingsColorRadioMargin;
@@ -1257,7 +1257,7 @@ void Controller::fillAutoTranslateButton() {
_navigation->uiShow(),
_peer,
[=](int level) {
if (const auto strong = weak.get()) {
if (weak.get()) {
state->isLocked = (level < requiredLevel);
}
return (level < requiredLevel)
@@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_item_helpers.h" // GetErrorForSending.
#include "history/view/history_view_group_call_bar.h" // GenerateUserpics...
#include "info/channel_statistics/earn/earn_icons.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "qr/qr_generate.h"
@@ -42,6 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/controls/userpic_button.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
@@ -247,6 +249,9 @@ private:
const Role _role = Role::Joined;
rpl::variable<LinkData> _data;
Ui::Text::CustomEmojiHelper _emojiHelper;
TextWithEntities _creditsEmoji;
base::unique_qptr<Ui::PopupMenu> _menu;
rpl::event_stream<Processed> _processed;
@@ -408,6 +413,8 @@ Controller::Controller(
const auto current = _data.current();
_link = current.link;
_revoked = current.revoked;
_creditsEmoji = _emojiHelper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
}
rpl::producer<LinkData> Controller::dataValue() const {
@@ -725,7 +732,7 @@ void Controller::setupAboveJoinedWidget() {
? tr::lng_group_invite_subscription_info_title(
tr::now,
lt_emoji,
session().data().customEmojiManager().creditsEmoji(),
_creditsEmoji,
lt_price,
{ QString::number(current.subscription.credits) },
lt_multiplier,
@@ -736,15 +743,12 @@ void Controller::setupAboveJoinedWidget() {
: tr::lng_group_invite_subscription_info_title_none(
tr::now,
lt_emoji,
session().data().customEmojiManager().creditsEmoji(),
_creditsEmoji,
lt_price,
{ QString::number(current.subscription.credits) },
Ui::Text::WithEntities),
kMarkupTextOptions,
Core::TextContext({
.session = &session(),
.repaint = [=] { widget->update(); },
}));
_emojiHelper.context([=] { widget->update(); }));
auto &lifetime = widget->lifetime();
const auto rateValue = lifetime.make_state<rpl::variable<float64>>(
session().credits().rateValue(_peer));
@@ -965,43 +969,41 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
const auto photoSize = st::boostReplaceUserpic.photoSize;
const auto session = &row->peer()->session();
content->add(object_ptr<Ui::CenterWrap<>>(
content,
Settings::SubscriptionUserpic(content, channel, photoSize)));
content->add(
Settings::SubscriptionUserpic(content, channel, photoSize),
style::al_top);
Ui::AddSkip(content);
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_credits_box_subscription_title(),
st::creditsBoxAboutTitle)));
st::creditsBoxAboutTitle),
style::al_top);
Ui::AddSkip(content);
const auto subtitle1 = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
st::creditsTopupPrice)))->entity();
st::creditsTopupPrice),
style::al_top);
subtitle1->setMarkedText(
tr::lng_credits_subscription_subtitle(
tr::now,
lt_emoji,
session->data().customEmojiManager().creditsEmoji(),
_creditsEmoji,
lt_cost,
{ QString::number(data.subscription.credits) },
Ui::Text::WithEntities),
Core::TextContext({ .session = session }));
_emojiHelper.context());
const auto subtitle2 = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
st::creditsTopupPrice)))->entity();
st::creditsTopupPrice),
style::al_top);
session->credits().rateValue(
channel
) | rpl::start_with_next([=, currency = u"USD"_q](float64 rate) {
@@ -1023,8 +1025,7 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
Ui::AddSkip(content);
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
tr::lng_credits_box_out_about(
@@ -1033,7 +1034,8 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
) | Ui::Text::ToLink(
tr::lng_credits_box_out_about_link(tr::now)),
Ui::Text::WithEntities),
st::creditsBoxAboutDivider)));
st::creditsBoxAboutDivider),
style::al_top);
const auto button = box->addButton(tr::lng_box_ok(), [=] {
box->closeBox();
@@ -886,32 +886,18 @@ rpl::producer<int> AddSlowmodeSlider(
return secondsCount->value();
}
void AddBoostsUnrestrictLabels(
not_null<Ui::VerticalLayout*> container,
not_null<Main::Session*> session) {
void AddBoostsUnrestrictLabels(not_null<Ui::VerticalLayout*> container) {
const auto labels = container->add(
object_ptr<Ui::FixedHeightWidget>(container, st::normalFont->height),
st::slowmodeLabelsMargin);
const auto manager = &session->data().customEmojiManager();
const auto one = Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
st::boostMessageIcon,
st::boostMessageIconPadding));
const auto many = Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
st::boostsMessageIcon,
st::boostsMessageIconPadding));
const auto context = Core::TextContext({
.session = session,
.customEmojiLoopLimit = 1,
});
const auto one = Ui::Text::IconEmoji(&st::boostMessageIcon);
const auto many = Ui::Text::IconEmoji(&st::boostsMessageIcon);
for (auto i = 0; i != kBoostsUnrestrictValues; ++i) {
const auto label = Ui::CreateChild<Ui::FlatLabel>(
labels,
st::boostsUnrestrictLabel);
label->setMarkedText(
TextWithEntities(i ? many : one).append(QString::number(i + 1)),
context);
TextWithEntities(i ? many : one).append(QString::number(i + 1)));
rpl::combine(
labels->widthValue(),
label->widthValue()
@@ -977,7 +963,7 @@ rpl::producer<int> AddBoostsUnrestrictSlider(
const auto inner = outer->entity();
AddBoostsUnrestrictLabels(inner, &peer->session());
AddBoostsUnrestrictLabels(inner);
const auto slider = inner->add(
object_ptr<Ui::MediaSlider>(inner, st::localStorageLimitSlider),
@@ -221,7 +221,8 @@ void Controller::prepare() {
Ui::Text::RichLangValue),
Ui::Text::RichLangValue),
st::boostReassignText),
st::boxRowPadding);
st::boxRowPadding,
style::al_top);
delegate()->peerListSetAboveWidget(std::move(above));
const auto now = base::unixtime::now();
@@ -585,14 +585,14 @@ void ChannelsLimitBox(
const auto content = box->addRow(
object_ptr<PeerListContent>(box, controller),
{});
style::margins());
delegate->setContent(content);
controller->setDelegate(delegate);
const auto count = 100;
const auto placeholder = box->addRow(
object_ptr<PeerListDummy>(box, count, st::defaultPeerList),
{});
style::margins());
using namespace rpl::mappers;
controller->countValue(
@@ -676,14 +676,14 @@ void PublicLinksLimitBox(
const auto content = box->addRow(
object_ptr<PeerListContent>(box, controller),
{});
style::margins());
delegate->setContent(content);
controller->setDelegate(delegate);
const auto count = defaultLimit;
const auto placeholder = box->addRow(
object_ptr<PeerListDummy>(box, count, st::defaultPeerList),
{});
style::margins());
using namespace rpl::mappers;
controller->countValue(
+13 -18
Ver Arquivo
@@ -902,7 +902,7 @@ void PreviewBox(
const auto outer = box->addRow(
ChatBackPreview(box, size.height(), back),
{});
style::margins());
struct Hiding {
not_null<Ui::RpWidget*> widget;
@@ -1079,26 +1079,21 @@ void PreviewBox(
auto text = state->selected.value(
) | rpl::map(SectionAbout) | rpl::flatten_latest();
const auto padding = st::premiumPreviewAboutPadding;
const auto available = size.width() - padding.left() - padding.right();
auto titleLabel = object_ptr<Ui::FlatLabel>(
box,
std::move(title),
st::premiumPreviewAboutTitle);
titleLabel->resizeToWidth(available);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
std::move(titleLabel)),
st::premiumPreviewAboutTitlePadding);
auto textLabel = object_ptr<Ui::FlatLabel>(
box,
std::move(text),
st::premiumPreviewAbout);
textLabel->resizeToWidth(available);
std::move(title),
st::premiumPreviewAboutTitle),
st::premiumPreviewAboutTitlePadding,
style::al_top);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(box, std::move(textLabel)),
padding);
object_ptr<Ui::FlatLabel>(
box,
std::move(text),
st::premiumPreviewAbout),
st::premiumPreviewAboutPadding,
style::al_top
)->setTryMakeSimilarLines(true);
box->addRow(
CreateSwitch(box->verticalLayout(), &state->selected, state->order),
st::premiumDotsMargin);
+48 -4
Ver Arquivo
@@ -7,8 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/ringtones_box.h"
#include "data/notify/data_peer_notify_volume.h"
#include "data/notify/data_peer_notify_settings.h"
#include "api/api_ringtones.h"
#include "apiwrap.h"
#include "ui/widgets/continuous_sliders.h"
#include "base/call_delayed.h"
#include "base/event_filter.h"
#include "base/timer_rpl.h"
@@ -21,11 +24,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h"
#include "data/data_document_resolver.h"
#include "data/data_thread.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/notify/data_notify_settings.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "media/audio/media_audio.h"
#include "ui/wrap/slide_wrap.h"
#include "platform/platform_notifications_manager.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h"
@@ -111,7 +117,8 @@ void RingtonesBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session,
Data::NotifySound selected,
Fn<void(Data::NotifySound)> save) {
Fn<void(Data::NotifySound)> save,
Data::VolumeController volumeController) {
box->setTitle(tr::lng_ringtones_box_title());
const auto container = box->verticalLayout();
@@ -128,12 +135,17 @@ void RingtonesBox(
QPointer<Ui::Radiobutton> defaultButton;
QPointer<Ui::Radiobutton> chosenButton;
std::vector<QPointer<Ui::Radiobutton>> buttons;
ushort presavedVolume = 0;
};
const auto state = container->lifetime().make_state<State>(State{
.group = std::make_shared<Ui::RadiobuttonGroup>(),
.chosen = selected,
});
const auto volumeOverride = [volume = volumeController.volume] {
return volume ? (0.01 * volume()) : -1;
};
const auto addToGroup = [=](
not_null<Ui::VerticalLayout*> verticalLayout,
int value,
@@ -156,7 +168,10 @@ void RingtonesBox(
if (value == kDefaultValue) {
state->defaultButton = button;
button->setClickedCallback([=] {
Core::App().notifications().playSound(session, 0);
Core::App().notifications().playSound(
session,
0,
volumeOverride());
});
}
if (value < 0) {
@@ -170,7 +185,8 @@ void RingtonesBox(
if (media->loaded()) {
Core::App().notifications().playSound(
session,
media->owner()->id);
media->owner()->id,
volumeOverride());
}
});
base::install_event_filter(button, [=](not_null<QEvent*> e) {
@@ -320,6 +336,31 @@ void RingtonesBox(
}));
});
if (volumeController.volume && volumeController.saveVolume) {
auto saveAndTestVolume = [=](ushort currentVolume) {
state->presavedVolume = currentVolume;
const auto value = state->group->current();
if (value != kNoSoundValue) {
Core::App().notifications().playSound(
session,
(value == kDefaultValue)
? 0
: state->medias[value]->owner()->id,
0.01 * currentVolume);
}
};
Ui::AddRingtonesVolumeSlider(
container,
state->group->value() | rpl::map([=](int value) {
return value != kNoSoundValue;
}),
tr::lng_ringtones_box_volume(),
Data::VolumeController{
base::take(volumeController.volume),
std::move(saveAndTestVolume),
});
}
box->addSkip(st::ringtonesBoxSkip);
Ui::AddDividerText(container, tr::lng_ringtones_box_about());
@@ -333,6 +374,9 @@ void RingtonesBox(
: (value == kNoSoundValue)
? Data::NotifySound{ .none = true }
: Data::NotifySound{ .id = state->medias[value]->owner()->id };
if (state->presavedVolume) {
volumeController.saveVolume(state->presavedVolume);
}
save(sound);
box->closeBox();
});
@@ -345,5 +389,5 @@ void ThreadRingtonesBox(
const auto now = thread->owner().notifySettings().sound(thread);
RingtonesBox(box, &thread->session(), now, [=](Data::NotifySound sound) {
thread->owner().notifySettings().update(thread, {}, {}, sound);
});
}, Data::ThreadRingtonesVolumeController(thread));
}
+4 -1
Ver Arquivo
@@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data {
struct NotifySound;
class Thread;
enum class DefaultNotify : uint8_t;
struct VolumeController;
} // namespace Data
namespace Main {
@@ -28,7 +30,8 @@ void RingtonesBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session,
Data::NotifySound selected,
Fn<void(Data::NotifySound)> save);
Fn<void(Data::NotifySound)> save,
Data::VolumeController volumeController);
void ThreadRingtonesBox(
not_null<Ui::GenericBox*> box,
+16 -20
Ver Arquivo
@@ -348,9 +348,9 @@ void SendCreditsBox(
}, ministarsContainer->lifetime());
}
const auto thumb = box->addRow(object_ptr<Ui::CenterWrap<>>(
content,
SendCreditsThumbnail(content, session, form.get(), photoSize)));
const auto thumb = box->addRow(
SendCreditsThumbnail(content, session, form.get(), photoSize),
style::al_top);
thumb->setAttribute(Qt::WA_TransparentForMouseEvents);
if (form->invoice.subscriptionPeriod) {
const auto badge = SendCreditsBadge(content, form->invoice.amount);
@@ -364,31 +364,30 @@ void SendCreditsBox(
}
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
form->invoice.subscriptionPeriod
? rpl::single(form->title)
: tr::lng_credits_box_out_title(),
st::settingsPremiumUserTitle)));
st::settingsPremiumUserTitle),
style::al_top);
if (form->invoice.subscriptionPeriod && form->botId && form->photo) {
Ui::AddSkip(content);
Ui::AddSkip(content);
const auto bot = session->data().user(form->botId);
box->addRow(
object_ptr<Ui::CenterWrap<>>(
box,
Ui::CreatePeerBubble(box, bot)));
Ui::CreatePeerBubble(box, bot),
style::al_top);
Ui::AddSkip(content);
}
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
SendCreditsConfirmText(session, form.get()),
st::creditsBoxAbout)));
st::creditsBoxAbout),
style::al_top);
Ui::AddSkip(content);
Ui::AddSkip(content);
@@ -455,7 +454,7 @@ void SendCreditsBox(
lt_count,
rpl::single(form->invoice.amount) | tr::to_count(),
lt_emoji,
rpl::single(CreditsEmojiSmall(session)),
rpl::single(CreditsEmojiSmall()),
Ui::Text::RichLangValue),
state->confirmButtonBusy.value()
) | rpl::map([](TextWithEntities &&text, bool busy) {
@@ -502,16 +501,13 @@ void SendCreditsBox(
}
}
TextWithEntities CreditsEmoji(not_null<Main::Session*> session) {
return Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::settingsPremiumIconStar,
QMargins{ 0, -st::moderateBoxExpandInnerSkip, 0, 0 },
true),
TextWithEntities CreditsEmoji() {
return Ui::Text::IconEmoji(
&st::starIconEmojiLarge,
QString(QChar(0x2B50)));
}
TextWithEntities CreditsEmojiSmall(not_null<Main::Session*> session) {
TextWithEntities CreditsEmojiSmall() {
return Ui::Text::IconEmoji(
&st::starIconEmoji,
QString(QChar(0x2B50)));
+2 -4
Ver Arquivo
@@ -32,11 +32,9 @@ void SendCreditsBox(
std::shared_ptr<Payments::CreditsFormData> data,
Fn<void()> sent);
[[nodiscard]] TextWithEntities CreditsEmoji(
not_null<Main::Session*> session);
[[nodiscard]] TextWithEntities CreditsEmoji();
[[nodiscard]] TextWithEntities CreditsEmojiSmall(
not_null<Main::Session*> session);
[[nodiscard]] TextWithEntities CreditsEmojiSmall();
not_null<FlatLabel*> SetButtonMarkedLabel(
not_null<RpWidget*> button,
+5 -6
Ver Arquivo
@@ -843,9 +843,8 @@ void SendFilesBox::refreshPriceTag() {
QPainter(raw).drawImage(0, 0, _priceTagBg);
}, raw->lifetime());
const auto session = &_show->session();
auto price = _price.value() | rpl::map([=](uint64 amount) {
auto result = Ui::Text::Colorized(Ui::CreditsEmoji(session));
auto result = Ui::Text::Colorized(Ui::CreditsEmoji());
result.append(Lang::FormatCountDecimal(amount));
return result;
});
@@ -857,10 +856,10 @@ void SendFilesBox::refreshPriceTag() {
raw,
QString(),
st::paidTagLabel);
std::move(text) | rpl::start_with_next([=](TextWithEntities &&text) {
label->setMarkedText(text, Core::TextContext({
.session = session,
}));
std::move(
text
) | rpl::start_with_next([=](const TextWithEntities &text) {
label->setMarkedText(text);
}, label->lifetime());
label->show();
label->sizeValue() | rpl::start_with_next([=](QSize size) {
+51 -48
Ver Arquivo
@@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "info/channel_statistics/earn/earn_icons.h"
#include "info/peer_gifts/info_peer_gifts_common.h"
#include "info/profile/info_profile_icon.h"
#include "lang/lang_keys.h"
@@ -82,6 +83,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/new_badges.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
@@ -1194,8 +1196,9 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
}
[[nodiscard]] Text::String TabTextForPrice(
not_null<Main::Session*> session,
int price) {
int price,
TextWithEntities creditsIcon,
Ui::Text::MarkedContext context) {
const auto simple = [](const QString &text) {
return Text::String(st::semiboldTextStyle, text);
};
@@ -1210,13 +1213,12 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
} else if (price == kPriceTabResale) {
return simple(tr::lng_gift_stars_tabs_resale(tr::now));
}
auto &manager = session->data().customEmojiManager();
auto result = Text::String();
result.setMarkedText(
st::semiboldTextStyle,
manager.creditsEmoji().append(QString::number(price)),
creditsIcon.append(QString::number(price)),
kMarkupTextOptions,
Core::TextContext({ .session = session }));
context);
return result;
}
@@ -1636,7 +1638,6 @@ struct GiftPriceTabs {
object_ptr<RpWidget> widget;
};
[[nodiscard]] GiftPriceTabs MakeGiftsPriceTabs(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
rpl::producer<std::vector<GiftTypeStars>> gifts,
bool hasMyUnique) {
@@ -1745,7 +1746,6 @@ struct GiftPriceTabs {
state->priceTab = state->buttons[index].price;
};
const auto session = &peer->session();
state->prices.value(
) | rpl::start_with_next([=](const std::vector<int> &prices) {
auto x = st::giftBoxTabsMargin.left();
@@ -1759,12 +1759,18 @@ struct GiftPriceTabs {
currentPrice = kPriceTabAll;
}
state->active = -1;
auto helper = Ui::Text::CustomEmojiHelper();
const auto creditsIcon = helper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
for (auto i = 0, count = int(prices.size()); i != count; ++i) {
const auto price = prices[i];
auto &button = state->buttons[i];
if (button.text.isEmpty() || button.price != price) {
button.price = price;
button.text = TabTextForPrice(session, price);
button.text = TabTextForPrice(
price,
creditsIcon,
helper.context());
}
button.active = (price == currentPrice);
if (button.active) {
@@ -2177,7 +2183,6 @@ void SoldOutBox(
void AddUpgradeButton(
not_null<Ui::VerticalLayout*> container,
not_null<Main::Session*> session,
int cost,
not_null<PeerData*> peer,
Fn<void(bool)> toggled,
@@ -2190,7 +2195,8 @@ void AddUpgradeButton(
button->toggleOn(rpl::single(false))->toggledValue(
) | rpl::start_with_next(toggled, button->lifetime());
auto star = session->data().customEmojiManager().creditsEmoji();
auto helper = Ui::Text::CustomEmojiHelper();
auto star = helper.paletteDependent(Ui::Earn::IconCreditsEmoji());
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
tr::lng_gift_send_unique(
@@ -2201,7 +2207,7 @@ void AddUpgradeButton(
Text::WithEntities),
st::boxLabel,
st::defaultPopupMenu,
Core::TextContext({ .session = session }));
helper.context());
label->show();
label->setAttribute(Qt::WA_TransparentForMouseEvents);
button->widthValue() | rpl::start_with_next([=](int outer) {
@@ -2355,7 +2361,7 @@ void SendGiftBox(
});
auto cost = state->details.value(
) | rpl::map([session](const GiftDetails &details) {
) | rpl::map([](const GiftDetails &details) {
return v::match(details.descriptor, [&](const GiftTypePremium &data) {
const auto stars = (details.byStars && data.stars)
? data.stars
@@ -2363,7 +2369,7 @@ void SendGiftBox(
? data.cost
: 0;
if (stars) {
return CreditsEmojiSmall(session).append(
return CreditsEmojiSmall().append(
Lang::FormatCountDecimal(std::abs(stars)));
}
return TextWithEntities{
@@ -2372,7 +2378,7 @@ void SendGiftBox(
}, [&](const GiftTypeStars &data) {
const auto amount = std::abs(data.info.stars)
+ (details.upgraded ? data.info.starsToUpgrade : 0);
return CreditsEmojiSmall(session).append(
return CreditsEmojiSmall().append(
Lang::FormatCountDecimal(amount));
});
});
@@ -2448,8 +2454,7 @@ void SendGiftBox(
const auto showing = std::make_shared<bool>();
AddDivider(container);
AddSkip(container);
AddUpgradeButton(container, session, costToUpgrade, peer, [=](
bool on) {
AddUpgradeButton(container, costToUpgrade, peer, [=](bool on) {
auto now = state->details.current();
now.upgraded = on;
state->details = std::move(now);
@@ -2976,13 +2981,15 @@ void AddBlock(
content,
std::move(args.subtitle),
st::giftBoxSubtitle),
st::giftBoxSubtitleMargin);
st::giftBoxSubtitleMargin,
style::al_top);
const auto about = content->add(
object_ptr<FlatLabel>(
content,
std::move(args.about),
st::giftBoxAbout),
st::giftBoxAboutMargin);
st::giftBoxAboutMargin,
style::al_top);
about->setClickHandlerFilter(std::move(args.aboutFilter));
content->add(std::move(args.content));
}
@@ -3027,7 +3034,6 @@ void AddBlock(
state->gifts = GiftsStars(&window->session(), peer);
auto tabs = MakeGiftsPriceTabs(
window,
peer,
state->gifts.value(),
!state->my.list.empty() && !peer->isSelf());
@@ -3145,10 +3151,9 @@ void GiftBox(
&& uniqueDisallowed;
content->add(
object_ptr<CenterWrap<UserpicButton>>(
content,
object_ptr<UserpicButton>(content, peer, stUser))
)->entity()->setClickedCallback([=] { window->showPeerInfo(peer); });
object_ptr<UserpicButton>(content, peer, stUser),
style::al_top
)->setClickedCallback([=] { window->showPeerInfo(peer); });
AddSkip(content);
AddSkip(content);
@@ -4377,13 +4382,15 @@ void ShowUniqueGiftWearBox(
lt_name,
rpl::single(UniqueGiftName(gift))),
st.title ? *st.title : st::uniqueGiftTitle),
st::settingsPremiumRowTitlePadding);
st::settingsPremiumRowTitlePadding,
style::al_top);
content->add(
object_ptr<Ui::FlatLabel>(
content,
tr::lng_gift_wear_about(),
st.subtitle ? *st.subtitle : st::uniqueGiftSubtitle),
st::settingsPremiumRowAboutPadding);
st::settingsPremiumRowAboutPadding,
style::al_top);
infoRow(
tr::lng_gift_wear_badge_title(),
(channel
@@ -4445,11 +4452,7 @@ void ShowUniqueGiftWearBox(
u"wear_collectibles"_q);
}
});
const auto lock = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::historySendDisabledIcon,
st::giftBoxLockMargins,
true));
const auto lock = Ui::Text::IconEmoji(&st::giftBoxLock);
auto label = rpl::combine(
tr::lng_gift_wear_start(),
Data::AmPremiumValue(&show->session())
@@ -4915,19 +4918,18 @@ void UpgradeBox(
object_ptr<PlainShadow>(container),
st::boxRowPadding + QMargins(0, skip, 0, skip));
const auto checkbox = container->add(
object_ptr<CenterWrap<Checkbox>>(
object_ptr<Checkbox>(
container,
object_ptr<Checkbox>(
container,
(args.canAddComment
? tr::lng_gift_upgrade_add_comment(tr::now)
: args.canAddSender
? tr::lng_gift_upgrade_add_sender(tr::now)
: args.canAddMyComment
? tr::lng_gift_upgrade_add_my_comment(tr::now)
: tr::lng_gift_upgrade_add_my(tr::now)),
args.addDetailsDefault)),
st::defaultCheckbox.margin)->entity();
(args.canAddComment
? tr::lng_gift_upgrade_add_comment(tr::now)
: args.canAddSender
? tr::lng_gift_upgrade_add_sender(tr::now)
: args.canAddMyComment
? tr::lng_gift_upgrade_add_my_comment(tr::now)
: tr::lng_gift_upgrade_add_my(tr::now)),
args.addDetailsDefault),
st::defaultCheckbox.margin,
style::al_top);
checkbox->checkedChanges() | rpl::start_with_next([=](bool checked) {
state->preserveDetails = checked;
}, checkbox->lifetime());
@@ -4936,7 +4938,6 @@ void UpgradeBox(
box->setStyle(preview ? st::giftBox : st::upgradeGiftBox);
const auto cost = args.cost;
const auto session = &controller->session();
auto buttonText = preview ? tr::lng_box_ok() : rpl::single(QString());
const auto button = box->addButton(std::move(buttonText), [=] {
if (preview) {
@@ -4961,18 +4962,20 @@ void UpgradeBox(
UpgradeGift(controller, args.savedId, keepDetails, cost, done);
});
if (!preview) {
auto star = session->data().customEmojiManager().creditsEmoji();
auto helper = Ui::Text::CustomEmojiHelper();
auto star = helper.paletteDependent(Ui::Earn::IconCreditsEmoji());
SetButtonMarkedLabel(
button,
(cost
? tr::lng_gift_upgrade_button(
lt_price,
rpl::single(star.append(
' ' + Lang::FormatCreditsAmountDecimal(
CreditsAmount{ cost }))),
rpl::single(Ui::Text::IconEmoji(
&st::starIconEmoji
).append(' ').append(Lang::FormatCreditsAmountDecimal(
CreditsAmount{ cost }))),
Ui::Text::WithEntities)
: tr::lng_gift_upgrade_confirm(Ui::Text::WithEntities)),
&controller->session(),
helper.context(),
st::creditsBoxButtonLabel,
&st::giftBox.button.textFg);
}
+2 -11
Ver Arquivo
@@ -641,20 +641,11 @@ void ChangeSetNameBox(
const auto it = sets.find(input.id);
return (it == sets.end()) ? QString() : it->second->title;
}();
const auto wrap = box->addRow(object_ptr<Ui::FixedHeightWidget>(
const auto field = box->addRow(object_ptr<Ui::InputField>(
box,
st::editStickerSetNameField.heightMin));
auto owned = object_ptr<Ui::InputField>(
wrap,
st::editStickerSetNameField,
tr::lng_stickers_context_edit_name(),
wasName);
const auto field = owned.data();
wrap->widthValue() | rpl::start_with_next([=](int width) {
field->move(0, 0);
field->resize(width, field->height());
wrap->resize(width, field->height());
}, wrap->lifetime());
wasName));
field->selectAll();
constexpr auto kMaxSetNameLength = 50;
field->setMaxLength(kMaxSetNameLength);
+3 -6
Ver Arquivo
@@ -248,12 +248,9 @@ void TranslateBox(
showText(
Ui::Text::Italic(tr::lng_translate_box_error(tr::now)));
} else {
showText(TextWithEntities{
.text = qs(list.front().data().vtext()),
.entities = Api::EntitiesFromMTP(
&peer->session(),
list.front().data().ventities().v),
});
showText(Api::ParseTextWithEntities(
&peer->session(),
list.front()));
}
}).fail([=](const MTP::Error &error) {
showText(
+2 -2
Ver Arquivo
@@ -324,7 +324,7 @@ void UsernamesBox(
const auto editor = box->addRow(
object_ptr<UsernameEditor>(box, peer),
{});
style::margins());
editor->setEnabled(!isBot);
box->setFocusCallback([=] { editor->setInnerFocus(); });
@@ -366,7 +366,7 @@ void UsernamesBox(
!isBot
? [=] { box->scrollToY(0); editor->setInnerFocus(); }
: Fn<void()>(nullptr)),
{});
style::margins());
const auto finish = [=] {
list->save(
@@ -825,7 +825,7 @@ void ShowCallsBox(not_null<::Window::SessionController*> window) {
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
box,
object_ptr<Ui::VerticalLayout>(box)),
{});
style::margins());
groupCalls->hide(anim::type::instant);
groupCalls->toggleOn(state->groupCallsController.shownValue());
@@ -833,8 +833,7 @@ void ShowCallsBox(not_null<::Window::SessionController*> window) {
groupCalls->entity(),
tr::lng_call_box_groupcalls_subtitle());
state->groupCallsDelegate.setContent(groupCalls->entity()->add(
object_ptr<PeerListContent>(box, &state->groupCallsController),
{}));
object_ptr<PeerListContent>(box, &state->groupCallsController)));
state->groupCallsController.setDelegate(&state->groupCallsDelegate);
Ui::AddSkip(groupCalls->entity());
Ui::AddDivider(groupCalls->entity());
@@ -853,7 +852,7 @@ void ShowCallsBox(not_null<::Window::SessionController*> window) {
const auto content = box->addRow(
object_ptr<PeerListContent>(box, &state->callsController),
{});
style::margins());
state->callsDelegate.setContent(content);
state->callsController.setDelegate(&state->callsDelegate);
@@ -3982,7 +3982,7 @@ void GroupCall::inviteUsers(
}
};
if (const auto call = _conferenceCall.get()) {
if (_conferenceCall.get()) {
for (const auto &request : requests) {
inviteToConference(request, [=] {
return &state->result;
@@ -116,13 +116,12 @@ void ConferenceCallJoinConfirm(
st::boxRowPadding + st::confcallLinkHeaderIconPadding);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_confcall_join_title(),
st::boxTitle)),
st::boxRowPadding + st::confcallLinkTitlePadding);
tr::lng_confcall_join_title(),
st::boxTitle),
st::boxRowPadding + st::confcallLinkTitlePadding,
style::al_top);
const auto wrapName = [&](not_null<PeerData*> peer) {
return rpl::single(Ui::Text::Bold(peer->shortName()));
};
@@ -136,7 +135,8 @@ void ConferenceCallJoinConfirm(
Ui::Text::RichLangValue)
: tr::lng_confcall_join_text(Ui::Text::RichLangValue)),
st::confcallLinkCenteredText),
st::boxRowPadding
st::boxRowPadding,
style::al_top
)->setTryMakeSimilarLines(true);
const auto &participants = call->participants();
@@ -209,7 +209,8 @@ void ConferenceCallJoinConfirm(
box,
std::move(text),
st::confcallLinkCenteredText),
st::boxRowPadding
st::boxRowPadding,
style::al_top
)->setTryMakeSimilarLines(true);
}
const auto joinAndClose = [=] {
@@ -321,13 +322,12 @@ void ShowConferenceCallLinkBox(
Info::BotStarRef::CreateLinkHeaderIcon(box, &call->session()),
st::boxRowPadding + st::confcallLinkHeaderIconPadding);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_confcall_link_title(),
st.box ? st.box->title : st::boxTitle)),
st::boxRowPadding + st::confcallLinkTitlePadding);
tr::lng_confcall_link_title(),
st.box ? st.box->title : st::boxTitle),
st::boxRowPadding + st::confcallLinkTitlePadding,
style::al_top);
box->addRow(
object_ptr<Ui::FlatLabel>(
box,
@@ -335,7 +335,8 @@ void ShowConferenceCallLinkBox(
(st.centerLabel
? *st.centerLabel
: st::confcallLinkCenteredText)),
st::boxRowPadding
st::boxRowPadding,
style::al_top
)->setTryMakeSimilarLines(true);
Ui::AddSkip(box->verticalLayout(), st::defaultVerticalListSkip * 2);
@@ -1042,19 +1042,19 @@ not_null<Ui::RpWidget*> CreateReActivateHeader(not_null<QWidget*> parent) {
st::boxRowPadding + st::confcallLinkHeaderIconPadding);
result->add(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
object_ptr<Ui::FlatLabel>(
result,
object_ptr<Ui::FlatLabel>(
result,
tr::lng_confcall_inactive_title(),
st::boxTitle)),
st::boxRowPadding + st::confcallLinkTitlePadding);
tr::lng_confcall_inactive_title(),
st::boxTitle),
st::boxRowPadding + st::confcallLinkTitlePadding,
style::al_top);
result->add(
object_ptr<Ui::FlatLabel>(
result,
tr::lng_confcall_inactive_about(),
st::confcallLinkCenteredText),
st::boxRowPadding + st::confcallLinkTitlePadding
st::boxRowPadding + st::confcallLinkTitlePadding,
style::al_top
)->setTryMakeSimilarLines(true);
Ui::AddDivider(result);
@@ -196,22 +196,13 @@ void RecordingInfo::prepareVideo() {
}
void RecordingInfo::setLabel(const QString &text) {
const auto label = _container->add(
_container->add(
object_ptr<Ui::FlatLabel>(
_container,
text,
st::groupCallRecordingSubLabel),
st::groupCallRecordingSubLabelMargins);
rpl::combine(
sizeValue(),
label->sizeValue()
) | rpl::start_with_next([=](QSize my, QSize labelSize) {
label->moveToLeft(
(my.width() - labelSize.width()) / 2,
label->y(),
my.width());
}, label->lifetime());
st::groupCallRecordingSubLabelMargins,
style::al_top);
}
RecordingType RecordingInfo::type() const {
@@ -126,7 +126,7 @@ int Style::minButtonWidth(HistoryMessageMarkupButton::Type type) const {
BotKeyboard::BotKeyboard(
not_null<Window::SessionController*> controller,
QWidget *parent)
: TWidget(parent)
: RpWidget(parent)
, _controller(controller)
, _st(&st::botKbButton) {
setGeometry(0, 0, _st->margin, st::botKbScroll.deltat);
@@ -21,7 +21,7 @@ class SessionController;
} // namespace Window
class BotKeyboard
: public TWidget
: public Ui::RpWidget
, public Ui::AbstractTooltipShower
, public ClickHandlerHost {
public:
@@ -44,7 +44,7 @@ public:
void step_selected(crl::time ms, bool timer);
void resizeToWidth(int newWidth, int maxOuterHeight) {
_maxOuterHeight = maxOuterHeight;
return TWidget::resizeToWidth(newWidth);
return RpWidget::resizeToWidth(newWidth);
}
[[nodiscard]] bool maximizeSize() const;
@@ -1295,6 +1295,7 @@ historyRecordLockPosition: point(1px, 22px);
historyRecordCancelButtonWidth: 100px;
historyRecordCancelButtonFg: lightButtonFg;
historyRecordTooltipSkip: 8px;
historyRecordTooltip: ImportantTooltip(defaultImportantTooltip) {
padding: margins(4px, 4px, 4px, 4px);
radius: 11px;
@@ -1626,4 +1627,17 @@ frozenInfoBox: Box(defaultBox) {
shadowIgnoreTopSkip: true;
}
menuTranscribeItemPadding: margins(0px, 10px, 0px, 10px);
menuTranscribeDummyButton: IconButton(defaultIconButton) {
width: 40px;
height: 40px;
icon: icon {{ "chat/input_attach", historyComposeIconFgOver }};
iconOver: icon {{ "chat/input_attach", historyComposeIconFgOver }};
rippleAreaPosition: point(3px, 3px);
rippleAreaSize: 34px;
ripple: defaultRippleAnimationBgOver;
}
roundVideoFont: font(14px semibold);
@@ -704,12 +704,12 @@ void SuggestionsWidget::enterEventHook(QEnterEvent *e) {
if (!inner().contains(mapToInner(QCursor::pos()))) {
clearMouseSelection();
}
return TWidget::enterEventHook(e);
return RpWidget::enterEventHook(e);
}
void SuggestionsWidget::leaveEventHook(QEvent *e) {
clearMouseSelection();
return TWidget::leaveEventHook(e);
return RpWidget::leaveEventHook(e);
}
SuggestionsController::SuggestionsController(
@@ -1488,7 +1488,8 @@ void FrozenInfoBox(
content,
tr::lng_frozen_title(),
st.title ? *st.title : st::uniqueGiftTitle),
st::settingsPremiumRowTitlePadding);
st::settingsPremiumRowTitlePadding,
style::al_top);
Ui::AddSkip(content, st::defaultVerticalListSkip * 3);
@@ -277,7 +277,7 @@ void TabbedPanel::leaveEventHook(QEvent *e) {
} else {
_hideTimer.callOnce(kHideTimeoutMs);
}
return TWidget::leaveEventHook(e);
return RpWidget::leaveEventHook(e);
}
void TabbedPanel::otherEnter() {
+13 -1
Ver Arquivo
@@ -658,8 +658,20 @@ bool Application::eventFilter(QObject *object, QEvent *e) {
updateNonIdle();
} break;
case QEvent::KeyRelease: {
const auto event = static_cast<QKeyEvent*>(e);
if (Shortcuts::HandlePossibleChatSwitch(event)) {
return true;
}
} break;
case QEvent::ShortcutOverride: {
// handle shortcuts ourselves
// Ctrl+Tab/Ctrl+Shift+Tab chat switch is a special shortcut case,
// because it not only does an action on the shortcut activation,
// but also keeps the UI visible until you release the Ctrl key.
Shortcuts::HandlePossibleChatSwitch(static_cast<QKeyEvent*>(e));
// Handle all the shortcut management manually.
return true;
} break;
+10 -2
Ver Arquivo
@@ -240,7 +240,8 @@ QByteArray Settings::serialize() const {
+ Serialize::stringSize(_customFontFamily)
+ sizeof(qint32) * 3
+ Serialize::bytearraySize(_tonsiteStorageToken)
+ sizeof(qint32) * 8;
+ sizeof(qint32) * 8
+ sizeof(ushort);
// Fork Settings.
size += sizeof(qint32);
@@ -429,7 +430,8 @@ QByteArray Settings::serialize() const {
<< SerializeVideoQuality(_videoQuality)
<< qint32(_ivZoom.current())
<< qint32(_systemDarkModeEnabled.current() ? 1 : 0)
<< qint32(_quickDialogAction);
<< qint32(_quickDialogAction)
<< _notificationsVolume;
}
Ensures(result.size() == size);
@@ -572,6 +574,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
quint32 videoQuality = SerializeVideoQuality(_videoQuality);
quint32 chatFiltersHorizontal = _chatFiltersHorizontal.current() ? 1 : 0;
quint32 quickDialogAction = quint32(_quickDialogAction);
ushort notificationsVolume = _notificationsVolume;
stream >> themesAccentColors;
if (!stream.atEnd()) {
@@ -916,6 +919,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) {
stream >> quickDialogAction;
}
if (!stream.atEnd()) {
stream >> notificationsVolume;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@@ -1152,6 +1158,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
_videoQuality = DeserializeVideoQuality(videoQuality);
_chatFiltersHorizontal = (chatFiltersHorizontal == 1);
_quickDialogAction = Dialogs::Ui::QuickDialogAction(quickDialogAction);
_notificationsVolume = notificationsVolume;
}
QString Settings::getSoundPath(const QString &key) const {
@@ -1546,6 +1553,7 @@ void Settings::resetOnLastLogout() {
_videoQuality = {};
_chatFiltersHorizontal = false;
_quickDialogAction = Dialogs::Ui::QuickDialogAction::Disabled;
_notificationsVolume = 100;
_recentEmojiPreload.clear();
_recentEmoji.clear();
+9
Ver Arquivo
@@ -956,6 +956,13 @@ public:
[[nodiscard]] Dialogs::Ui::QuickDialogAction quickDialogAction() const;
void setQuickDialogAction(Dialogs::Ui::QuickDialogAction);
[[nodiscard]] ushort notificationsVolume() const {
return _notificationsVolume;
}
void setNotificationsVolume(ushort value) {
_notificationsVolume = value;
}
void resetOnLastLogout();
private:
@@ -1101,6 +1108,8 @@ private:
Dialogs::Ui::QuickDialogAction _quickDialogAction
= Dialogs::Ui::QuickDialogAction::Disabled;
ushort _notificationsVolume = 100;
QByteArray _photoEditorBrush;
};
+81 -4
Ver Arquivo
@@ -30,6 +30,10 @@ constexpr auto kCountLimit = 256; // How many shortcuts can be in json file.
rpl::event_stream<not_null<Request*>> RequestsStream;
bool Paused/* = false*/;
Qt::Key ChatSwitchModifier/* = Qt::Key()*/;
bool ChatSwitchStarted/* = false*/;
rpl::event_stream<ChatSwitchRequest> ChatSwitchStream;
const auto AutoRepeatCommands = base::flat_set<Command>{
Command::MediaPrevious,
Command::MediaNext,
@@ -112,6 +116,8 @@ const auto CommandByName = base::flat_map<QString, Command>{
{ u"show_chat_menu"_q , Command::ShowChatMenu },
{ u"show_chat_preview"_q , Command::ShowChatPreview },
{ u"record_voice"_q , Command::RecordVoice },
// Shortcuts that have no default values.
{ u"message"_q , Command::JustSendMessage },
{ u"message_silently"_q , Command::SendSilentMessage },
@@ -119,6 +125,7 @@ const auto CommandByName = base::flat_map<QString, Command>{
{ u"media_viewer_video_fullscreen"_q , Command::MediaViewerFullscreen },
{ u"show_scheduled"_q , Command::ShowScheduled },
{ u"archive_chat"_q , Command::ArchiveChat },
{ u"record_round"_q , Command::RecordRound },
//
};
@@ -140,6 +147,7 @@ const base::flat_map<Command, QString> &CommandNames() {
Command::MediaViewerFullscreen,
Command::ShowScheduled,
Command::ArchiveChat,
Command::RecordRound,
};
class Manager {
@@ -152,6 +160,7 @@ public:
void toggleMedia(bool toggled);
void toggleSupport(bool toggled);
void listen(not_null<QWidget*> widget);
[[nodiscard]] bool handles(const QKeySequence &sequence) const;
[[nodiscard]] const QStringList &errors() const;
@@ -357,6 +366,10 @@ void Manager::listen(not_null<QWidget*> widget) {
}
}
bool Manager::handles(const QKeySequence &sequence) const {
return _shortcuts.contains(sequence);
}
void Manager::pruneListened() {
for (auto i = begin(_listened); i != end(_listened);) {
if (i->data()) {
@@ -466,10 +479,6 @@ void Manager::fillDefaults() {
set(u"ctrl+pgup"_q, Command::ChatPrevious);
set(u"alt+up"_q, Command::ChatPrevious);
set(u"%1+tab"_q.arg(ctrl), Command::ChatNext);
set(u"%1+shift+tab"_q.arg(ctrl), Command::ChatPrevious);
set(u"%1+backtab"_q.arg(ctrl), Command::ChatPrevious);
set(u"ctrl+alt+home"_q, Command::ChatFirst);
set(u"ctrl+alt+end"_q, Command::ChatLast);
@@ -509,6 +518,8 @@ void Manager::fillDefaults() {
set(u"ctrl+\\"_q, Command::ShowChatMenu);
set(u"ctrl+]"_q, Command::ShowChatPreview);
set(u"ctrl+r"_q, Command::RecordVoice);
_defaults = keysCurrents();
}
@@ -794,6 +805,72 @@ bool HandleEvent(
return Launch(Data.lookup(object));
}
void CancelChatSwitch(Qt::Key result) {
ChatSwitchModifier = Qt::Key();
if (ChatSwitchStarted) {
ChatSwitchStarted = false;
ChatSwitchStream.fire({ .action = result });
}
}
rpl::producer<ChatSwitchRequest> ChatSwitchRequests() {
return ChatSwitchStream.events();
}
bool HandlePossibleChatSwitch(not_null<QKeyEvent*> event) {
const auto type = event->type();
if (Paused) {
return false;
} else if (type == QEvent::ShortcutOverride) {
const auto key = Qt::Key(event->key());
if (key == Qt::Key_Escape) {
CancelChatSwitch(Qt::Key_Escape);
return false;
} else if (key == Qt::Key_Return || key == Qt::Key_Enter) {
CancelChatSwitch(Qt::Key_Enter);
return false;
}
const auto ctrl = Platform::IsMac()
? Qt::MetaModifier
: Qt::ControlModifier;
if (Data.handles(ctrl | Qt::ShiftModifier | Qt::Key_Tab)
&& Data.handles(QKeySequence(ctrl | Qt::Key_Tab))
&& Data.handles(QKeySequence(ctrl | Qt::Key_Backtab))) {
return false;
} else if (key == Qt::Key_Control || key == Qt::Key_Meta) {
ChatSwitchModifier = key;
} else if (key == Qt::Key_Tab || key == Qt::Key_Backtab) {
const auto modifiers = event->modifiers();
if (modifiers & ctrl) {
if (Data.handles(modifiers | key)) {
return false;
}
if (ChatSwitchModifier == Qt::Key()) {
ChatSwitchModifier = Platform::IsMac()
? Qt::Key_Meta
: Qt::Key_Control;
}
const auto action = (modifiers & Qt::ShiftModifier)
? Qt::Key_Backtab
: key;
const auto started = !std::exchange(ChatSwitchStarted, true);
ChatSwitchStream.fire({
.action = action,
.started = started,
});
return true;
}
}
} else if (type == QEvent::KeyRelease) {
const auto key = Qt::Key(event->key());
if (key == ChatSwitchModifier) {
CancelChatSwitch(Qt::Key_Enter);
}
}
return false;
}
void ToggleMediaShortcuts(bool toggled) {
Data.toggleMedia(toggled);
}
+16 -2
Ver Arquivo
@@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
class QKeyEvent;
class QShortcutEvent;
namespace Shortcuts {
enum class Command {
@@ -66,6 +69,9 @@ enum class Command {
SendSilentMessage,
ScheduleMessage,
RecordVoice,
RecordRound,
ReadChat,
ArchiveChat,
@@ -119,7 +125,7 @@ private:
};
rpl::producer<not_null<Request*>> Requests();
[[nodiscard]] rpl::producer<not_null<Request*>> Requests();
void Start();
void Finish();
@@ -129,7 +135,15 @@ void Listen(not_null<QWidget*> widget);
bool Launch(Command command);
bool HandleEvent(not_null<QObject*> object, not_null<QShortcutEvent*> event);
const QStringList &Errors();
bool HandlePossibleChatSwitch(not_null<QKeyEvent*> event);
struct ChatSwitchRequest {
Qt::Key action = Qt::Key_Tab; // Key_Tab, Key_Backtab or Key_Escape.
bool started = false;
};
[[nodiscard]] rpl::producer<ChatSwitchRequest> ChatSwitchRequests();
[[nodiscard]] const QStringList &Errors();
// Media shortcuts are not enabled by default, because other
// applications also use them. They are enabled only when
+3 -3
Ver Arquivo
@@ -24,7 +24,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 6000002;
constexpr auto AppVersionStr = "6.0.2";
constexpr auto AppBetaVersion = false;
constexpr auto AppVersion = 6000003;
constexpr auto AppVersionStr = "6.0.3";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
@@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/components/recent_peers.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "history/history.h"
#include "main/main_session.h"
#include "storage/serialize_common.h"
#include "storage/serialize_peer.h"
@@ -16,6 +19,7 @@ namespace Data {
namespace {
constexpr auto kLimit = 48;
constexpr auto kMaxRememberedOpenChats = 32;
} // namespace
@@ -133,4 +137,40 @@ void RecentPeers::applyLocal(QByteArray serialized) {
("Suggestions: RecentPeers read OK, count: %1").arg(_list.size()));
}
std::vector<not_null<Thread*>> RecentPeers::collectChatOpenHistory() const {
_session->local().readSearchSuggestions();
auto result = _opens;
result.reserve(result.size() + _list.size());
for (const auto &peer : _list) {
const auto history = peer->owner().history(peer);
const auto thread = not_null<Data::Thread*>(history);
if (!ranges::contains(result, thread)) {
result.push_back(thread);
}
}
return result;
}
void RecentPeers::chatOpenPush(not_null<Thread*> thread) {
const auto i = ranges::find(_opens, thread);
if (i == end(_opens)) {
while (_opens.size() >= kMaxRememberedOpenChats) {
_opens.pop_back();
}
_opens.insert(begin(_opens), thread);
} else if (i != begin(_opens)) {
ranges::rotate(begin(_opens), i, i + 1);
}
}
void RecentPeers::chatOpenDestroyed(not_null<Thread*> thread) {
_opens.erase(ranges::remove(_opens, thread), end(_opens));
}
void RecentPeers::chatOpenKeepUserpics(
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> userpics) {
_chatOpenUserpicsCache = std::move(userpics);
}
} // namespace Data
@@ -7,12 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "ui/userpic_view.h"
namespace Main {
class Session;
} // namespace Main
namespace Data {
class Thread;
class RecentPeers final {
public:
explicit RecentPeers(not_null<Main::Session*> session);
@@ -28,10 +32,22 @@ public:
[[nodiscard]] QByteArray serialize() const;
void applyLocal(QByteArray serialized);
[[nodiscard]] auto collectChatOpenHistory() const
-> std::vector<not_null<Thread*>>;
void chatOpenPush(not_null<Thread*> thread);
void chatOpenDestroyed(not_null<Thread*> thread);
void chatOpenKeepUserpics(
base::flat_map<not_null<PeerData*>, Ui::PeerUserpicView> userpics);
private:
const not_null<Main::Session*> _session;
std::vector<not_null<PeerData*>> _list;
std::vector<not_null<Thread*>> _opens;
base::flat_map<
not_null<PeerData*>,
Ui::PeerUserpicView> _chatOpenUserpicsCache;
rpl::event_stream<> _updates;
};
+5 -1
Ver Arquivo
@@ -235,7 +235,8 @@ void ChannelData::setFlags(ChannelDataFlags which) {
| Flag::CallNotEmpty
| Flag::SimilarExpanded
| Flag::Signatures
| Flag::SignatureProfiles)) {
| Flag::SignatureProfiles
| Flag::ForumTabs)) {
if (const auto history = this->owner().historyLoaded(this)) {
if (diff & Flag::CallNotEmpty) {
history->updateChatListEntry();
@@ -262,6 +263,9 @@ void ChannelData::setFlags(ChannelDataFlags which) {
if (diff & (Flag::Signatures | Flag::SignatureProfiles)) {
session().changes().peerUpdated(this, UpdateFlag::Rights);
}
if (diff & Flag::ForumTabs) {
history->forumTabsChanged(which & Flag::ForumTabs);
}
}
}
if (const auto raw = takenForum.get()) {
+1
Ver Arquivo
@@ -98,6 +98,7 @@ struct CreditsHistoryEntry final {
bool converted : 1 = false;
bool anonymous : 1 = false;
bool stargift : 1 = false;
bool postsSearch : 1 = false;
bool giftTransferred : 1 = false;
bool giftRefunded : 1 = false;
bool giftUpgraded : 1 = false;
+30
Ver Arquivo
@@ -7,12 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/data_forum.h"
#include "data/components/recent_peers.h"
#include "data/data_channel.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "data/data_session.h"
#include "data/data_forum_icons.h"
#include "data/data_forum_topic.h"
#include "data/data_replies_list.h"
#include "data/notify/data_notify_settings.h"
#include "history/history.h"
#include "history/history_item.h"
@@ -193,6 +195,7 @@ void Forum::applyTopicDeleted(MsgId rootId) {
_activeSubsectionTopic = nullptr;
}
_topicDestroyed.fire(raw);
_history->session().recentPeers().chatOpenDestroyed(raw);
session().changes().topicUpdated(
raw,
Data::TopicUpdate::Flag::Destroyed);
@@ -276,6 +279,33 @@ Thread *Forum::activeSubsectionThread() const {
return _activeSubsectionTopic;
}
void Forum::markUnreadCountsUnknown(MsgId readTillId) {
if (!channel()->useSubsectionTabs()) {
return;
}
for (const auto &[rootId, topic] : _topics) {
const auto replies = topic->replies();
if (replies->unreadCountCurrent() > 0) {
replies->setInboxReadTill(readTillId, std::nullopt);
}
}
}
void Forum::updateUnreadCounts(
MsgId readTillId,
const base::flat_map<not_null<ForumTopic*>, int> &counts) {
if (!channel()->useSubsectionTabs()) {
return;
}
for (const auto &[rootId, topic] : _topics) {
const auto raw = topic.get();
const auto replies = raw->replies();
const auto i = counts.find(raw);
const auto count = (i != end(counts)) ? i->second : 0;
replies->setInboxReadTill(readTillId, count);
}
}
void Forum::listMessageChanged(HistoryItem *from, HistoryItem *to) {
if (from || to) {
reorderLastTopics();
+5
Ver Arquivo
@@ -99,6 +99,11 @@ public:
void saveActiveSubsectionThread(not_null<Thread*> thread);
[[nodiscard]] Thread *activeSubsectionThread() const;
void markUnreadCountsUnknown(MsgId readTillId);
void updateUnreadCounts(
MsgId readTillId,
const base::flat_map<not_null<ForumTopic*>, int> &counts);
[[nodiscard]] rpl::lifetime &lifetime() {
return _lifetime;
}
@@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/painter.h"
#include "ui/color_int_conversion.h"
#include "ui/text/text_custom_emoji.h"
#include "ui/text/text_utilities.h"
#include "styles/style_dialogs.h"
#include "styles/style_chat_helpers.h"
@@ -756,6 +757,16 @@ TextWithEntities ForumTopic::titleWithIcon() const {
return ForumTopicIconWithTitle(_rootId, _iconId, _title);
}
TextWithEntities ForumTopic::titleWithIconOrLogo() const {
if (_iconId || isGeneral()) {
return titleWithIcon();
}
return Ui::Text::SingleCustomEmoji(Data::TopicIconEmojiEntity({
.title = _title,
.colorId = _colorId,
})).append(' ').append(_title);
}
int ForumTopic::titleVersion() const {
return _titleVersion;
}
@@ -148,6 +148,7 @@ public:
[[nodiscard]] QString title() const;
[[nodiscard]] TextWithEntities titleWithIcon() const;
[[nodiscard]] TextWithEntities titleWithIconOrLogo() const;
[[nodiscard]] int titleVersion() const;
void applyTitle(const QString &title);
[[nodiscard]] DocumentId iconId() const;
+1 -1
Ver Arquivo
@@ -713,7 +713,7 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
} else {
Assert(!state->sentReadTill || state->sentReadTill > tillId);
}
history->validateMonoforumUnread(tillId);
history->validateMonoAndForumUnread(tillId);
sendReadRequests();
finish();
};
+1 -2
Ver Arquivo
@@ -2232,8 +2232,7 @@ ItemPreview MediaInvoice::toPreview(ToPreviewOptions options) const {
? parent()->translatedText()
: parent()->originalText());
const auto hasMiniImages = !images.empty();
auto nice = Ui::Text::Colorized(
Ui::CreditsEmojiSmall(&parent()->history()->session()));
auto nice = Ui::Text::Colorized(Ui::CreditsEmojiSmall());
nice.append(WithCaptionNotificationText(type, caption, hasMiniImages));
return {
.text = std::move(nice),
+6 -12
Ver Arquivo
@@ -70,12 +70,9 @@ bool PollData::closeByTimer() {
bool PollData::applyChanges(const MTPDpoll &poll) {
Expects(poll.vid().v == id);
const auto newQuestion = TextWithEntities{
.text = qs(poll.vquestion().data().vtext()),
.entities = Api::EntitiesFromMTP(
&session(),
poll.vquestion().data().ventities().v),
};
const auto newQuestion = Api::ParseTextWithEntities(
&session(),
poll.vquestion());
const auto newFlags = (poll.is_closed() ? Flag::Closed : Flag(0))
| (poll.is_public_voters() ? Flag::PublicVotes : Flag(0))
| (poll.is_multiple_choice() ? Flag::MultiChoice : Flag(0))
@@ -88,12 +85,9 @@ bool PollData::applyChanges(const MTPDpoll &poll) {
return data.match([&](const MTPDpollAnswer &answer) {
auto result = PollAnswer();
result.option = answer.voption().v;
result.text = TextWithEntities{
.text = qs(answer.vtext().data().vtext()),
.entities = Api::EntitiesFromMTP(
&session(),
answer.vtext().data().ventities().v),
};
result.text = Api::ParseTextWithEntities(
&session(),
answer.vtext());
return result;
});
}) | ranges::views::take(
@@ -16,6 +16,7 @@ struct PremiumSubscriptionOption {
QString costPerMonth;
QString costNoDiscount;
QString costTotal;
QString currency;
QString total;
QString botUrl;
};
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "core/application.h"
#include "data/components/recent_peers.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
#include "data/data_histories.h"
@@ -452,6 +453,7 @@ void SavedMessages::applySublistDeleted(not_null<PeerData*> sublistPeer) {
}
_sublistDestroyed.fire(raw);
_owner->session().recentPeers().chatOpenDestroyed(raw);
session().changes().sublistUpdated(
raw,
Data::SublistUpdate::Flag::Destroyed);
+4 -12
Ver Arquivo
@@ -45,12 +45,9 @@ Main::Session &TodoListData::session() const {
}
bool TodoListData::applyChanges(const MTPDtodoList &todolist) {
const auto newTitle = TextWithEntities{
.text = qs(todolist.vtitle().data().vtext()),
.entities = Api::EntitiesFromMTP(
&session(),
todolist.vtitle().data().ventities().v),
};
const auto newTitle = Api::ParseTextWithEntities(
&session(),
todolist.vtitle());
const auto newFlags = (todolist.is_others_can_append()
? Flag::OthersCanAppend
: Flag())
@@ -222,12 +219,7 @@ TodoListItem TodoListItemFromMTP(
const MTPTodoItem &item) {
const auto &data = item.data();
return {
.text = TextWithEntities{
.text = qs(data.vtitle().data().vtext()),
.entities = Api::EntitiesFromMTP(
session,
data.vtitle().data().ventities().v),
},
.text = Api::ParseTextWithEntities(session, data.vtitle()),
.id = data.vid().v,
};
}
@@ -21,11 +21,6 @@ class Thread;
class Forum;
class ForumTopic;
enum class DefaultNotify {
User,
Group,
Broadcast,
};
[[nodiscard]] DefaultNotify DefaultNotifyType(
not_null<const PeerData*> peer);
@@ -11,6 +11,12 @@ namespace Data {
class NotifyPeerSettingsValue;
enum class DefaultNotify : uint8_t {
User,
Group,
Broadcast,
};
struct NotifySound {
QString title;
QString data;
@@ -0,0 +1,117 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/notify/data_peer_notify_volume.h"
#include "data/data_peer.h"
#include "data/data_thread.h"
#include "data/notify/data_peer_notify_settings.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "core/application.h"
#include "window/notifications_manager.h"
#include "settings/settings_common.h"
#include "ui/vertical_list.h"
#include "ui/widgets/continuous_sliders.h"
#include "ui/widgets/labels.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "styles/style_settings.h"
namespace Data {
Data::VolumeController DefaultRingtonesVolumeController(
not_null<Main::Session*> session,
Data::DefaultNotify defaultNotify) {
return Data::VolumeController{
.volume = [=]() -> ushort {
const auto volume = session->settings().ringtoneVolume(
defaultNotify);
return volume ? volume : 100;
},
.saveVolume = [=](ushort volume) {
session->settings().setRingtoneVolume(defaultNotify, volume);
session->saveSettingsDelayed();
}};
}
Data::VolumeController ThreadRingtonesVolumeController(
not_null<Data::Thread*> thread) {
return Data::VolumeController{
.volume = [=]() -> ushort {
const auto volume = thread->session().settings().ringtoneVolume(
thread->peer()->id,
thread->topicRootId(),
thread->monoforumPeerId());
return volume ? volume : 100;
},
.saveVolume = [=](ushort volume) {
thread->session().settings().setRingtoneVolume(
thread->peer()->id,
thread->topicRootId(),
thread->monoforumPeerId(),
volume);
thread->session().saveSettingsDelayed();
}};
}
} // namespace Data
namespace Ui {
void AddRingtonesVolumeSlider(
not_null<Ui::VerticalLayout*> container,
rpl::producer<bool> toggleOn,
rpl::producer<QString> subtitle,
Data::VolumeController volumeController) {
Expects(volumeController.volume && volumeController.saveVolume);
const auto volumeWrap = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container)));
volumeWrap->toggleOn(
rpl::combine(
Core::App().notifications().volumeSupportedValue(),
std::move(toggleOn)
) | rpl::map(
rpl::mappers::_1 && rpl::mappers::_2
) | rpl::distinct_until_changed(),
anim::type::normal);
volumeWrap->finishAnimating();
Ui::AddSubsectionTitle(volumeWrap->entity(), std::move(subtitle));
auto sliderWithLabel = Settings::MakeSliderWithLabel(
volumeWrap->entity(),
st::settingsScale,
st::settingsScaleLabel,
st::normalFont->spacew * 2,
st::settingsScaleLabel.style.font->width("100%"),
true);
const auto slider = sliderWithLabel.slider;
const auto label = sliderWithLabel.label;
volumeWrap->entity()->add(
std::move(sliderWithLabel.widget),
st::settingsBigScalePadding);
const auto updateLabel = [=](int volume) {
label->setText(QString::number(volume) + '%');
};
slider->setPseudoDiscrete(
100,
[=](int index) { return index + 1; },
int(volumeController.volume()),
updateLabel,
[saveVolume = volumeController.saveVolume](int volume) {
saveVolume(volume);
});
updateLabel(volumeController.volume());
}
} // namespace Ui
@@ -0,0 +1,45 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Main {
class Session;
} // namespace Main
namespace Ui {
class VerticalLayout;
} // namespace Ui
namespace Data {
enum class DefaultNotify : uint8_t;
class Thread;
struct VolumeController {
Fn<ushort()> volume = nullptr;
Fn<void(ushort)> saveVolume = nullptr;
};
[[nodiscard]] VolumeController DefaultRingtonesVolumeController(
not_null<Main::Session*> session,
Data::DefaultNotify defaultNotify);
[[nodiscard]] VolumeController ThreadRingtonesVolumeController(
not_null<Data::Thread*> thread);
} // namespace Data
namespace Ui {
void AddRingtonesVolumeSlider(
not_null<Ui::VerticalLayout*> container,
rpl::producer<bool> toggleOn,
rpl::producer<QString> subtitle,
Data::VolumeController volumeController);
} // namespace Ui
@@ -41,7 +41,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_credits.h" // giftBoxByStarsStyle
namespace Data {
namespace {
@@ -101,10 +100,6 @@ private:
: FrameSizeFromTag(tag);
}
[[nodiscard]] QString InternalPrefix() {
return u"internal:"_q;
}
[[nodiscard]] QString UserpicEmojiPrefix() {
return u"userpic:"_q;
}
@@ -570,8 +565,6 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
const auto original = data.mid(ForceStaticPrefix().size());
return std::make_unique<Ui::Text::FirstFrameEmoji>(
create(original, std::move(update), tag, sizeOverride));
} else if (data.startsWith(InternalPrefix())) {
return internal(data);
} else if (data.startsWith(UserpicEmojiPrefix())) {
const auto ratio = style::DevicePixelRatio();
const auto size = EmojiSizeFromTag(tag) / ratio;
@@ -619,26 +612,6 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
});
}
std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::internal(
QStringView data) {
const auto v = data.mid(InternalPrefix().size()).split(',');
if (v.size() != 5 && v.size() != 1) {
return nullptr;
}
const auto index = v[0].toInt();
Assert(index >= 0 && index < _internalEmoji.size());
auto &info = _internalEmoji[index];
const auto padding = (v.size() == 5)
? QMargins(v[1].toInt(), v[2].toInt(), v[3].toInt(), v[4].toInt())
: QMargins();
return std::make_unique<Ui::CustomEmoji::Internal>(
data.toString(),
info.image,
padding,
info.textColor);
}
std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::userpic(
QStringView data,
Fn<void()> update,
@@ -1021,65 +994,6 @@ uint64 CustomEmojiManager::coloredSetId() const {
return _coloredSetId;
}
TextWithEntities CustomEmojiManager::creditsEmoji(QMargins padding) {
return Ui::Text::SingleCustomEmoji(registerInternalEmoji(
u"builtin:credits_emoji"_q,
Ui::GenerateStars(st::normalFont->height, 1),
padding,
false));
}
TextWithEntities CustomEmojiManager::ministarEmoji(QMargins padding) {
return Ui::Text::SingleCustomEmoji(registerInternalEmoji(
u"builtin:ministar_emoji"_q,
Ui::GenerateStars(st::giftBoxByStarsStyle.font->height, 1),
padding,
false));
}
QString CustomEmojiManager::registerInternalEmoji(
const QString &key,
QImage emoji,
QMargins padding,
bool textColor) {
auto i = _imageEmoji.find(key);
if (i == end(_imageEmoji)) {
i = _imageEmoji.emplace(
key,
registerImageEmoji(std::move(emoji), textColor)).first;
}
return i->second + InternalPadding(padding);
}
QString CustomEmojiManager::registerImageEmoji(
QImage emoji,
bool textColor) {
_internalEmoji.push_back({ std::move(emoji), textColor });
return InternalPrefix() + QString::number(_internalEmoji.size() - 1);
}
QString CustomEmojiManager::registerInternalEmoji(
const style::icon &icon,
QMargins padding,
bool textColor) {
const auto i = _iconEmoji.find(&icon);
if (i != end(_iconEmoji)) {
return i->second + InternalPadding(padding);
}
auto image = QImage(
icon.size() * style::DevicePixelRatio(),
QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
image.setDevicePixelRatio(style::DevicePixelRatio());
auto p = QPainter(&image);
icon.paint(p, 0, 0, icon.width());
p.end();
const auto result = registerImageEmoji(std::move(image), textColor);
_iconEmoji.emplace(&icon, result);
return result + InternalPadding(padding);
}
[[nodiscard]] QString CustomEmojiManager::peerUserpicEmojiData(
not_null<PeerData*> peer,
QMargins padding,
@@ -83,16 +83,6 @@ public:
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] Session &owner() const;
[[nodiscard]] QString registerInternalEmoji(
const QString &key,
QImage emoji,
QMargins padding = {},
bool textColor = true);
[[nodiscard]] QString registerInternalEmoji(
const style::icon &icon,
QMargins padding = {},
bool textColor = true);
[[nodiscard]] QString peerUserpicEmojiData(
not_null<PeerData*> peer,
QMargins padding = {},
@@ -100,9 +90,6 @@ public:
[[nodiscard]] uint64 coloredSetId() const;
[[nodiscard]] TextWithEntities creditsEmoji(QMargins padding = {});
[[nodiscard]] TextWithEntities ministarEmoji(QMargins padding = {});
private:
static constexpr auto kSizeCount = int(SizeTag::kCount);
@@ -128,7 +115,6 @@ private:
DocumentId documentId,
SizeTag tag,
int sizeOverride = 0);
[[nodiscard]] QString registerImageEmoji(QImage emoji, bool textColor);
void request();
void requestFinished();
@@ -154,8 +140,6 @@ private:
SizeTag tag,
int sizeOverride,
LoaderFactory factory);
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> internal(
QStringView data);
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> userpic(
QStringView data,
Fn<void()> update,
@@ -192,11 +176,6 @@ private:
bool _repaintTimerScheduled = false;
bool _requestSetsScheduled = false;
std::vector<InternalEmojiData> _internalEmoji;
base::flat_map<not_null<const style::icon*>, QString> _iconEmoji;
base::flat_map<QString, QString> _imageEmoji;
#if 0 // inject-to-on_main
crl::time _repaintsLastAdded = 0;
rpl::lifetime _repaintsLifetime;
+10 -4
Ver Arquivo
@@ -556,7 +556,10 @@ dialogsMiniForward: DialogsMiniIcon {
skipMedia: 2px;
}
dialogsMiniReplyIcon: icon {{ "mini_forward-flip_horizontal", attentionButtonFg, point(0px, 2px) }};
dialogsMiniReplyIcon: IconEmoji {
icon: icon {{ "mini_forward-flip_horizontal", attentionButtonFg }};
padding: margins(0px, 2px, 0px, 0px);
}
dialogsMiniReplyStory: DialogsMiniIcon {
icon: ThreeStateIcon {
@@ -799,8 +802,10 @@ dialogsSearchTagSkip: point(8px, 4px);
dialogsSearchTagBottom: 10px;
dialogsSearchTagLocked: icon{{ "dialogs/mini_tag_lock", lightButtonFgOver }};
dialogsSearchTagPromo: defaultTextStyle;
dialogsSearchTagArrow: icon{{ "dialogs/mini_arrow", windowSubTextFg }};
dialogsSearchTagArrowPadding: margins(-6px, 3px, 0px, 0px);
dialogsSearchTagArrow: IconEmoji {
icon: icon{{ "dialogs/mini_arrow", windowSubTextFg }};
padding: margins(-6px, 3px, 0px, 0px);
}
dialogsSearchTagPromoLeft: 6px;
dialogsSearchTagPromoRight: 1px;
dialogsSearchTagPromoSkip: 6px;
@@ -833,6 +838,8 @@ dialogsTopBarSuggestionAboutStyle: TextStyle(defaultTextStyle) {
font: font(11px);
}
dialogsMiniQuoteIcon: icon{{ "chat/mini_quote", dialogsTextFg }};
postsSearchIntroTitle: FlatLabel(defaultFlatLabel) {
textFg: windowBoldFg;
minWidth: 64px;
@@ -863,7 +870,6 @@ postsSearchIntroFooter: FlatLabel(defaultFlatLabel) {
}
}
postsSearchIntroFooterMargin: margins(20px, 12px, 20px, 0px);
postsSearchIcon: icon {{ "box_search", windowFgActive }};
postsSearchIconPadding: margins(12px, 1px, 6px, 0px);
postsSearchArrow: icon {{ "dialogs/mini_arrow", windowFgActive }};
+1 -1
Ver Arquivo
@@ -241,7 +241,7 @@ uint64 Entry::computeSortPosition(FilterId filterId) const {
void Entry::updateChatListExistence() {
if (const auto history = asHistory()) {
if (const auto channel = history->peer->asMonoforum()) {
if (history->peer->asMonoforum()) {
if (!folderKnown()) {
history->clearFolder();
}
@@ -1241,6 +1241,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
auto to = ceilclamp(r.y() + r.height() - skip, _st->height, 0, _previewResults.size());
p.translate(0, from * _st->height);
if (from < _previewResults.size()) {
const auto searchLowerText = _searchState.query.toLower();
for (; from < to; ++from) {
const auto &result = _previewResults[from];
const auto active = isSearchResultActive(result.get(), activeEntry);
@@ -1258,6 +1259,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.currentBg = currentBg(),
.filter = _filterId,
.now = ms,
.searchLowerText = QStringView(searchLowerText),
.width = fullWidth,
.active = active,
.selected = selected,
@@ -1285,6 +1287,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
tr::now,
lt_count,
_searchedMigratedCount + _searchedCount);
const auto searchLowerText = _searchState.query.toLower();
p.fillRect(0, 0, fullWidth, st::searchedBarHeight, st::searchedBarBg);
p.setFont(st::searchedBarFont);
p.setPen(st::searchedBarFg);
@@ -1332,6 +1335,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.currentBg = currentBg(),
.filter = _filterId,
.now = ms,
.searchLowerText = QStringView(searchLowerText),
.width = fullWidth,
.active = active,
.selected = selected,
@@ -4151,14 +4155,14 @@ void InnerWidget::refreshEmpty() {
.name = u"no_chats"_q,
.sizeOverride = Size(st::changePhoneIconSize),
});
_emptyList->add(
object_ptr<Ui::CenterWrap<>>(_emptyList, std::move(icon.widget)));
_emptyList->add(std::move(icon.widget), style::al_top);
Ui::AddSkip(_emptyList);
_emptyList->add(
object_ptr<Ui::FlatLabel>(
_emptyList,
tr::lng_no_conversations(),
st::dialogEmptyButtonLabel));
st::dialogEmptyButtonLabel),
style::al_top);
if (_state == WidgetState::Default) {
icon.animate(anim::repeat::once);
}
@@ -20,6 +20,12 @@ namespace {
constexpr auto kQueryDelay = crl::time(500);
constexpr auto kPerPage = 50;
[[nodiscard]] const QRegularExpression &SearchSplitter() {
static const auto result = QRegularExpression(QString::fromLatin1(""
"[\\s\\-\\+\\(\\)\\[\\]\\{\\}\\<\\>\\,\\.\\!\\_\\;\\\"\\'\\x0]"));
return result;
}
} // namespace
PostsSearch::PostsSearch(not_null<Main::Session*> session)
@@ -58,7 +64,9 @@ void PostsSearch::requestMore() {
}
void PostsSearch::setQuery(const QString &query) {
const auto words = TextUtilities::PrepareSearchWords(query);
const auto words = TextUtilities::PrepareSearchWords(
query,
&SearchSplitter());
const auto prepared = words.isEmpty() ? QString() : words.join(' ');
if (_queryExact == query) {
return;
@@ -109,7 +117,9 @@ void PostsSearch::pushStateUpdate(const Entry &entry) {
}
return;
}
if (!entry.pages.empty() || entry.loaded) {
const auto empty = entry.pages.empty()
|| (entry.pages.size() == 1 && entry.pages.front().empty());
if (!empty || (entry.loaded && !_query->isEmpty())) {
if (!entry.pages.empty()) {
++entry.pagesPushed;
}
@@ -52,24 +52,14 @@ namespace {
});
}
[[nodiscard]] Ui::Text::String FillAdditionalText(
not_null<Data::Session*> owner,
int width) {
auto emoji = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::dialogsSearchTagArrow,
st::dialogsSearchTagArrowPadding));
[[nodiscard]] Ui::Text::String FillAdditionalText(int width) {
auto emoji = Ui::Text::IconEmoji(&st::dialogsSearchTagArrow);
auto result = Ui::Text::String();
const auto context = Core::TextContext({
.session = &owner->session(),
.customEmojiLoopLimit = 1,
});
const auto attempt = [&](const auto &phrase) {
result.setMarkedText(
st::dialogsSearchTagPromo,
phrase(tr::now, lt_arrow, emoji, Ui::Text::WithEntities),
kMarkupTextOptions,
context);
kMarkupTextOptions);
return result.maxWidth() < width;
};
if (attempt(tr::lng_add_tag_phrase_long)
@@ -230,7 +220,7 @@ void SearchTags::layout() {
if (_tags.size() == 1 && _tags.front().promo) {
_additionalLeft = x - skip.x() + st::dialogsSearchTagPromoSkip;
const auto additionalWidth = _width - _additionalLeft;
_additionalText = FillAdditionalText(_owner, additionalWidth);
_additionalText = FillAdditionalText(additionalWidth);
} else {
_additionalText = {};
}
@@ -2757,6 +2757,11 @@ void Widget::showMainMenu() {
}
void Widget::searchMessages(SearchState state) {
if (const auto peer = state.inChat.peer()) {
if (_openedForum && peer->forum() != _openedForum) {
controller()->closeForum();
}
}
applySearchState(std::move(state));
session().local().saveRecentSearchHashtags(_searchState.query);
}
@@ -602,13 +602,9 @@ void PaintRow(
}),
Text::WithEntities);
if (draft && draft->reply) {
auto &data = thread->owner().customEmojiManager();
draftText = Ui::Text::Colorized(
Ui::Text::SingleCustomEmoji(
data.registerInternalEmoji(
st::dialogsMiniReplyIcon,
{},
true))).append(std::move(draftText));
Ui::Text::IconEmoji(&st::dialogsMiniReplyIcon)
).append(std::move(draftText));
}
const auto context = Core::TextContext({
.session = &thread->session(),
@@ -1163,6 +1159,7 @@ void RowPainter::Paint(
return {};
}();
previewOptions.ignoreGroup = true;
previewOptions.searchLowerText = context.searchLowerText;
const auto badgesState = context.displayUnreadInfo
? entry->chatListBadgesState()
@@ -64,6 +64,7 @@ struct PaintContext {
FilterId filter = 0;
float64 topicsExpanded = 0.;
crl::time now = 0;
QStringView searchLowerText;
int width = 0;
bool active = false;
bool selected = false;
@@ -9,15 +9,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_item.h"
#include "history/view/history_view_element.h"
#include "history/view/history_view_item_preview.h"
#include "main/main_session.h"
#include "dialogs/dialogs_three_state_icon.h"
#include "dialogs/ui/dialogs_layout.h"
#include "dialogs/ui/dialogs_topics_view.h"
#include "ui/effects/spoiler_mess.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/text_options.h"
#include "ui/text/text_utilities.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/power_saving.h"
#include "core/ui_integration.h"
#include "lang/lang_keys.h"
@@ -186,7 +189,7 @@ void MessageView::prepare(
: nullptr;
const auto hasImages = !preview.images.empty();
const auto history = item->history();
const auto context = Core::TextContext({
auto context = Core::TextContext({
.session = &history->session(),
.repaint = customEmojiRepaint,
.customEmojiLoopLimit = kEmojiLoopCount,
@@ -207,13 +210,105 @@ void MessageView::prepare(
}
TextUtilities::Trim(preview.text);
auto textToCache = DialogsPreviewText(std::move(preview.text));
if (!options.searchLowerText.isEmpty()) {
static constexpr auto kLeftShift = 15;
auto minFrom = std::numeric_limits<uint16>::max();
const auto words = Ui::Text::Words(options.searchLowerText);
textToCache.entities.reserve(textToCache.entities.size()
+ words.size());
for (const auto &word : words) {
const auto selection = HistoryView::FindSearchQueryHighlight(
textToCache.text,
word);
if (!selection.empty()) {
minFrom = std::min(minFrom, selection.from);
textToCache.entities.push_back(EntityInText{
EntityType::Colorized,
selection.from,
selection.to - selection.from
});
}
}
if (minFrom == std::numeric_limits<uint16>::max()
&& !item->replyTo().quote.empty()) {
auto textQuote = TextWithEntities();
for (const auto &word : words) {
const auto selection = HistoryView::FindSearchQueryHighlight(
item->replyTo().quote.text,
word);
if (!selection.empty()) {
minFrom = 0;
if (textQuote.empty()) {
textQuote = item->replyTo().quote;
}
textQuote.entities.push_back(EntityInText{
EntityType::Colorized,
selection.from,
selection.to - selection.from
});
}
}
if (!textQuote.empty()) {
auto helper = Ui::Text::CustomEmojiHelper(context);
const auto factory = Ui::Text::PaletteDependentEmoji{
.factory = [=] {
const auto &icon = st::dialogsMiniQuoteIcon;
auto image = QImage(
icon.size() * style::DevicePixelRatio(),
QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(style::DevicePixelRatio());
image.fill(Qt::transparent);
{
auto p = Painter(&image);
icon.paintInCenter(
p,
Rect(icon.size()),
st::dialogsTextFg->c);
}
return image;
},
.margin = QMargins(
st::lineWidth * 2,
0,
st::lineWidth * 2,
0),
};
textToCache = textQuote
.append(helper.paletteDependent(factory))
.append(std::move(textToCache));
context = helper.context(customEmojiRepaint);
}
}
if (!words.empty() && minFrom != std::numeric_limits<uint16>::max()) {
std::sort(
textToCache.entities.begin(),
textToCache.entities.end(),
[](const auto &a, const auto &b) {
return a.offset() < b.offset();
});
const auto textSize = textToCache.text.size();
minFrom = (minFrom > textSize || minFrom < kLeftShift)
? 0
: minFrom - kLeftShift;
textToCache = TextWithEntities(
minFrom > 0 ? kQEllipsis : QString())
.append(Text::Mid(std::move(textToCache), minFrom));
}
}
_hasPlainLinkAtBegin = !textToCache.entities.empty()
&& (textToCache.entities.front().type() == EntityType::Colorized);
_textCache.setMarkedText(
st::dialogsTextStyle,
std::move(textToCache),
DialogTextOptions(),
context);
std::move(context));
_textCachedFor = item;
_imagesCache = std::move(preview.images);
if (!ranges::any_of(_imagesCache, &ItemPreviewImage::hasSpoiler)) {
@@ -49,6 +49,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/controls/swipe_handler.h"
#include "ui/effects/ripple_animation.h"
#include "ui/toast/toast.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/custom_emoji_text_badge.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/buttons.h"
@@ -157,34 +159,6 @@ struct EntryMenuDescriptor {
};
}
[[nodiscard]] QImage MakeNewBadgeImage() {
auto text = Ui::Text::String(
st::settingsPremiumNewBadge.style,
tr::lng_premium_summary_new_badge(tr::now));
const auto size = QSize(text.maxWidth(), text.minHeight());
const auto padding = st::settingsPremiumNewBadgePadding;
const auto full = size.grownBy(padding);
const auto ratio = style::DevicePixelRatio();
auto result = QImage(full * ratio, QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(ratio);
result.fill(Qt::transparent);
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::windowBgActive);
const auto r = padding.left();
p.drawRoundedRect(0, 0, full.width(), full.height(), r, r);
p.setPen(st::windowFgActive);
text.draw(p, { .position = { padding.left(), padding.top() } });
p.end();
return result;
}
void FillEntryMenu(
const Ui::Menu::MenuCallback &add,
EntryMenuDescriptor &&descriptor) {
@@ -1502,25 +1476,20 @@ void Suggestions::setupTabs() {
},
};
const auto manager = &_controller->session().data().customEmojiManager();
const auto badgeData = manager->registerInternalEmoji(
u"posts_search_new_badge"_q,
MakeNewBadgeImage(),
st::badgeEmojiMargin,
false);
auto helper = Ui::Text::CustomEmojiHelper();
auto sections = std::vector<TextWithEntities>();
for (const auto key : _tabKeys) {
const auto i = labels.find(key);
Assert(i != end(labels));
auto text = TextWithEntities{ i->second };
if (key.tab == Tab::Posts) {
text.append(' ').append(Ui::Text::SingleCustomEmoji(badgeData));
text.append(' ').append(helper.paletteDependent(
Ui::Text::CustomEmojiTextBadge(
tr::lng_premium_summary_new_badge(tr::now))));
}
sections.push_back(std::move(text));
}
_tabs->setSections(sections, Core::TextContext({
.session = &_controller->session(),
}));
_tabs->setSections(sections, helper.context());
_tabs->sectionActivated(
) | rpl::start_with_next([=](int section) {
Assert(section >= 0 && section < _tabKeys.size());
@@ -1966,6 +1935,7 @@ void Suggestions::setupPostsSearch() {
nullptr,
{ .posts = true, .start = true },
state.totalCount);
_postsScroll->scrollToY(0);
updatePostsSearchVisibleRange();
}
}, _postsWrap->lifetime());
@@ -2100,6 +2070,10 @@ void Suggestions::setupPostsIntro(const PostsSearchIntroState &intro) {
}
}, _postsSearchIntro->lifetime());
_postsScroll->heightValue() | rpl::start_with_next([=](int height) {
_postsWrap->resize(_postsWrap->width(), height);
}, _postsSearchIntro->lifetime());
_postsSearchIntro->show();
updateControlsGeometry();
}
@@ -170,34 +170,41 @@ void PostsSearchIntro::setup() {
_content.get(),
std::move(title),
st::postsSearchIntroTitle),
st::postsSearchIntroTitleMargin);
st::postsSearchIntroTitleMargin,
style::al_top);
_title->setTryMakeSimilarLines(true);
_subtitle = _content->add(
object_ptr<Ui::FlatLabel>(
_content.get(),
std::move(subtitle),
st::postsSearchIntroSubtitle),
st::postsSearchIntroSubtitleMargin);
st::postsSearchIntroSubtitleMargin,
style::al_top);
_subtitle->setTryMakeSimilarLines(true);
_button = _content->add(
object_ptr<Ui::CenterWrap<Ui::RoundButton>>(
object_ptr<Ui::RoundButton>(
_content.get(),
object_ptr<Ui::RoundButton>(
_content.get(),
rpl::single(QString()),
st::postsSearchIntroButton))
)->entity();
rpl::single(QString()),
st::postsSearchIntroButton),
style::al_top);
_button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
_footer = _content->add(
object_ptr<Ui::FlatLabel>(
_content.get(),
std::move(footer),
st::postsSearchIntroFooter),
st::postsSearchIntroFooterMargin);
st::postsSearchIntroFooterMargin,
style::al_top);
_footer->setTryMakeSimilarLines(true);
_state.value(
) | rpl::start_with_next([=](const PostsSearchIntroState &state) {
if (state.query.trimmed().isEmpty()) {
_button->resize(_button->width(), 0);
_content->resizeToWidth(width());
return;
}
auto copy = _button->children();
for (const auto child : copy) {
delete child;
@@ -232,6 +239,7 @@ void PostsSearchIntro::setup() {
st::resaleButtonTitle,
st::resaleButtonSubtitle);
}
_button->resize(_button->width(), st::postsSearchIntroButton.height);
_content->resizeToWidth(width());
}, _button->lifetime());
}
+1 -1
Ver Arquivo
@@ -2068,7 +2068,7 @@ bool ApiWrap::processFileLoad(
} else if (!story && (_settings->media.types & type) != type) {
file.skipReason = SkipReason::FileType;
return true;
} else if (!story && fullSize >= _settings->media.sizeLimit) {
} else if (!story && fullSize > _settings->media.sizeLimit) {
// Don't load thumbs for large files that we skip.
file.skipReason = SkipReason::FileSize;
return true;
@@ -1009,7 +1009,7 @@ void InnerWidget::itemsAdded(Direction direction, int addedCount) {
}
void InnerWidget::updateSize() {
TWidget::resizeToWidth(width());
RpWidget::resizeToWidth(width());
restoreScrollPosition();
updateVisibleTopItem();
checkPreloadMore();
@@ -1688,7 +1688,7 @@ void InnerWidget::mouseReleaseEvent(QMouseEvent *e) {
void InnerWidget::enterEventHook(QEnterEvent *e) {
mouseActionUpdate(QCursor::pos());
return TWidget::enterEventHook(e);
return RpWidget::enterEventHook(e);
}
void InnerWidget::leaveEventHook(QEvent *e) {
@@ -1702,7 +1702,7 @@ void InnerWidget::leaveEventHook(QEvent *e) {
_cursor = style::cur_default;
setCursor(_cursor);
}
return TWidget::leaveEventHook(e);
return RpWidget::leaveEventHook(e);
}
void InnerWidget::mouseActionStart(const QPoint &screenPos, Qt::MouseButton button) {
@@ -77,7 +77,7 @@ public:
void resizeToWidth(int newWidth, int minHeight) {
_minHeight = minHeight;
return TWidget::resizeToWidth(newWidth);
return RpWidget::resizeToWidth(newWidth);
}
void saveState(not_null<SectionMemento*> memento);
@@ -37,7 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace AdminLog {
class FixedBar final : public TWidget {
class FixedBar final : public Ui::RpWidget {
public:
FixedBar(
QWidget *parent,
@@ -109,7 +109,8 @@ object_ptr<Window::SectionWidget> SectionMemento::createWidget(
FixedBar::FixedBar(
QWidget *parent,
not_null<Window::SessionController*> controller,
not_null<ChannelData*> channel) : TWidget(parent)
not_null<ChannelData*> channel)
: RpWidget(parent)
, _controller(controller)
, _channel(channel)
, _field(this, st::defaultMultiSelectSearchField, tr::lng_dlg_filter())
@@ -276,7 +277,7 @@ void FixedBar::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton) {
goBack();
} else {
TWidget::mousePressEvent(e);
RpWidget::mousePressEvent(e);
}
}
+86 -8
Ver Arquivo
@@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel_admins.h"
#include "data/data_changes.h"
#include "data/data_chat_filters.h"
#include "data/data_replies_list.h"
#include "data/data_send_action.h"
#include "data/data_star_gift.h"
#include "data/data_emoji_statuses.h"
@@ -3170,6 +3171,58 @@ void History::applyDialogTopMessage(MsgId topMessageId) {
}
}
void History::tryMarkForumIntervalRead(
MsgId wasInboxReadBefore,
MsgId nowInboxReadBefore) {
if (!isForum()
|| !peer->asChannel()->useSubsectionTabs()
|| (nowInboxReadBefore <= wasInboxReadBefore)) {
return;
} else if (loadedAtBottom() && nowInboxReadBefore >= minMsgId()) {
// Count for each sublist how many messages are still not read.
auto counts = base::flat_map<not_null<Data::ForumTopic*>, int>();
for (const auto &block : blocks) {
for (const auto &message : block->messages) {
const auto item = message->data();
if (!item->isRegular() || item->id < nowInboxReadBefore) {
continue;
}
if (const auto topic = item->topic()) {
++counts[topic];
}
}
}
if (const auto forum = peer->forum()) {
forum->updateUnreadCounts(nowInboxReadBefore - 1, counts);
}
} else if (minMsgId() <= wasInboxReadBefore
&& maxMsgId() >= nowInboxReadBefore) {
// Count for each sublist how many messages were read.
for (const auto &block : blocks) {
for (const auto &message : block->messages) {
const auto item = message->data();
if (!item->isRegular() || item->id < wasInboxReadBefore) {
continue;
} else if (item->id >= nowInboxReadBefore) {
break;
}
if (const auto topic = item->topic()) {
const auto replies = topic->replies();
const auto unread = replies->unreadCountCurrent();
if (unread > 0) {
replies->setInboxReadTill(item->id, unread - 1);
}
}
}
}
} else {
// We can't invalidate sublist unread counts here, because no read
// request was yet sent to the server (so it can't return correct
// values yet), we need to do that after we send read request.
_flags |= Flag::MonoAndForumUnreadInvalidatePending;
}
}
void History::tryMarkMonoforumIntervalRead(
MsgId wasInboxReadBefore,
MsgId nowInboxReadBefore) {
@@ -3215,24 +3268,29 @@ void History::tryMarkMonoforumIntervalRead(
// We can't invalidate sublist unread counts here, because no read
// request was yet sent to the server (so it can't return correct
// values yet), we need to do that after we send read request.
_flags |= Flag::MonoforumUnreadInvalidatePending;
_flags |= Flag::MonoAndForumUnreadInvalidatePending;
}
}
void History::validateMonoforumUnread(MsgId readTillId) {
if (!(_flags & Flag::MonoforumUnreadInvalidatePending)) {
void History::validateMonoAndForumUnread(MsgId readTillId) {
if (!(_flags & Flag::MonoAndForumUnreadInvalidatePending)) {
return;
}
_flags &= ~Flag::MonoforumUnreadInvalidatePending;
if (!amMonoforumAdmin()) {
return;
} else if (const auto monoforum = peer->monoforum()) {
monoforum->markUnreadCountsUnknown(readTillId);
_flags &= ~Flag::MonoAndForumUnreadInvalidatePending;
if (isForum()) {
if (const auto forum = peer->forum()) {
forum->markUnreadCountsUnknown(readTillId);
}
} else if (amMonoforumAdmin()) {
if (const auto monoforum = peer->monoforum()) {
monoforum->markUnreadCountsUnknown(readTillId);
}
}
}
void History::setInboxReadTill(MsgId upTo) {
if (_inboxReadBefore) {
tryMarkForumIntervalRead(*_inboxReadBefore, upTo + 1);
tryMarkMonoforumIntervalRead(*_inboxReadBefore, upTo + 1);
accumulate_max(*_inboxReadBefore, upTo + 1);
} else {
@@ -3420,6 +3478,26 @@ bool History::suggestDraftAllowed() const {
return peer->isMonoforum() && !peer->amMonoforumAdmin();
}
bool History::hasForumThreadBars() const {
if (amMonoforumAdmin()) {
return true;
} else if (const auto channel = peer->asChannel()) {
return channel->forum() && channel->useSubsectionTabs();
}
return false;
}
void History::forumTabsChanged(bool forumTabs) {
for (auto &block : blocks) {
for (auto &view : block->messages) {
view->setPendingResize();
if (forumTabs || view->Has<HistoryView::ForumThreadBar>()) {
view->previousInBlocksChanged();
}
}
}
}
not_null<History*> History::migrateToOrMe() const {
if (const auto to = peer->migrateTo()) {
return owner().history(to);
+7 -2
Ver Arquivo
@@ -80,6 +80,8 @@ public:
void monoforumChanged(Data::SavedMessages *old);
[[nodiscard]] bool amMonoforumAdmin() const;
[[nodiscard]] bool suggestDraftAllowed() const;
[[nodiscard]] bool hasForumThreadBars() const;
void forumTabsChanged(bool forumTabs);
[[nodiscard]] not_null<History*> migrateToOrMe() const;
[[nodiscard]] History *migrateFrom() const;
@@ -434,7 +436,10 @@ public:
void tryMarkMonoforumIntervalRead(
MsgId wasInboxReadBefore,
MsgId nowInboxReadBefore);
void validateMonoforumUnread(MsgId readTillId);
void tryMarkForumIntervalRead(
MsgId wasInboxReadBefore,
MsgId nowInboxReadBefore);
void validateMonoAndForumUnread(MsgId readTillId);
[[nodiscard]] bool isTopPromoted() const;
@@ -480,7 +485,7 @@ private:
FakeUnreadWhileOpened = (1 << 5),
HasPinnedMessages = (1 << 6),
ResolveChatListMessage = (1 << 7),
MonoforumUnreadInvalidatePending = (1 << 8),
MonoAndForumUnreadInvalidatePending = (1 << 8),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) {
@@ -77,6 +77,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h"
#include "mainwidget.h"
#include "menu/menu_item_download_files.h"
#include "menu/menu_item_rate_transcribe.h"
#include "menu/menu_item_rate_transcribe_session.h"
#include "menu/menu_sponsored.h"
#include "core/application.h"
#include "apiwrap.h"
@@ -934,8 +936,8 @@ void HistoryInner::enumerateDates(Method method) {
}
template <typename Method>
void HistoryInner::enumerateMonoforumSenders(Method method) {
if (!_history->amMonoforumAdmin()) {
void HistoryInner::enumerateForumThreadBars(Method method) {
if (!_history->hasForumThreadBars()) {
return;
}
@@ -952,28 +954,28 @@ void HistoryInner::enumerateMonoforumSenders(Method method) {
// -1 means we didn't find a same-day with previous message yet.
auto lowestInOneBunchItemBottom = -1;
auto senderCallback = [&](not_null<Element*> view, int itemtop, int itembottom) {
auto barCallback = [&](not_null<Element*> view, int itemtop, int itembottom) {
const auto item = view->data();
if (lowestInOneBunchItemBottom < 0 && view->isInOneBunchWithPrevious()) {
lowestInOneBunchItemBottom = itembottom - view->marginBottom();
}
// Call method on a sender for all messages that have it and for those who are not showing it
// Call method on a bar for all messages that have it and for those who are not showing it
// because they are in a one day together with the previous message if they are top-most visible.
if (view->displayMonoforumSender() || (!item->isEmpty() && itemtop <= _visibleAreaTop)) {
if (view->displayForumThreadBar() || (!item->isEmpty() && itemtop <= _visibleAreaTop)) {
if (lowestInOneBunchItemBottom < 0) {
lowestInOneBunchItemBottom = itembottom - view->marginBottom();
}
// Attach sender to the top of the visible area with the same margin as it has in service message.
int senderTop = qMax(itemtop + view->displayedDateHeight(), _visibleAreaTop + skip) + st::msgServiceMargin.top();
// Attach bar to the top of the visible area with the same margin as it has in service message.
int barTop = qMax(itemtop + view->displayedDateHeight(), _visibleAreaTop + skip) + st::msgServiceMargin.top();
// Do not let the sender go below the single-sender messages pack bottom line.
int senderHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top();
senderTop = qMin(senderTop, lowestInOneBunchItemBottom - senderHeight);
// Do not let the bar go below the single-bar messages pack bottom line.
int barHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top();
barTop = qMin(barTop, lowestInOneBunchItemBottom - barHeight);
// Call the template callback function that was passed
// and return if it finished everything it needed.
if (!method(view, itemtop, senderTop)) {
if (!method(view, itemtop, barTop)) {
return false;
}
}
@@ -986,7 +988,7 @@ void HistoryInner::enumerateMonoforumSenders(Method method) {
return true;
};
enumerateItems<EnumItemsDirection::BottomToTop>(senderCallback);
enumerateItems<EnumItemsDirection::BottomToTop>(barCallback);
}
TextSelection HistoryInner::computeRenderSelection(
@@ -1401,31 +1403,31 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
});
p.setOpacity(1.);
enumerateMonoforumSenders([&](not_null<Element*> view, int itemtop, int senderTop) {
// stop the enumeration if the sender is above the painted rect
if (senderTop + dateHeight <= clip.top()) {
enumerateForumThreadBars([&](not_null<Element*> view, int itemtop, int barTop) {
// stop the enumeration if the bar is above the painted rect
if (barTop + dateHeight <= clip.top()) {
return false;
}
const auto displaySender = view->displayMonoforumSender();
auto senderInPlace = displaySender;
if (senderInPlace) {
const auto correctSenderTop = itemtop + view->displayedDateHeight() + st::msgServiceMargin.top();
senderInPlace = (senderTop < correctSenderTop + st::msgServiceMargin.top());
const auto displayBar = view->displayForumThreadBar();
auto barInPlace = displayBar;
if (barInPlace) {
const auto correctBarTop = itemtop + view->displayedDateHeight() + st::msgServiceMargin.top();
barInPlace = (barTop < correctBarTop + st::msgServiceMargin.top());
}
// paint the sender if it intersects the painted rect
if (senderTop < clip.top() + clip.height()) {
const auto senderY = senderTop - st::msgServiceMargin.top();
if (const auto sender = view->Get<HistoryView::MonoforumSenderBar>()) {
sender->paint(p, context.st, senderY, _contentWidth, _isChatWide, !senderInPlace);
// paint the bar if it intersects the painted rect
if (barTop < clip.top() + clip.height()) {
const auto barY = barTop - st::msgServiceMargin.top();
if (const auto bar = view->Get<HistoryView::ForumThreadBar>()) {
bar->paint(p, context.st, barY, _contentWidth, _isChatWide, !barInPlace);
} else {
HistoryView::MonoforumSenderBar::PaintFor(
_forumThreadBarWidth = HistoryView::ForumThreadBar::PaintForGetWidth(
p,
context.st,
view,
_monoforumSenderUserpicView,
senderY,
_forumThreadBarUserpicView,
barY,
_contentWidth,
_isChatWide);
}
@@ -2563,6 +2565,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
Api::SendExistingPhoto(msg(), photo);
}, &st::menuIconImportTheme);
};
auto rateTranscriptionItem = (HistoryItem*)(nullptr);
const auto addDocumentActions = [&](not_null<DocumentData*> document, HistoryItem *item) {
if (document->loading()) {
_menu->addAction(tr::lng_context_cancel_download(tr::now), [=] {
@@ -2622,6 +2625,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
document);
}, &st::menuIconStickers);
}
if (item
&& (lnkIsVoice || document->isVideoMessage())
&& Menu::HasRateTranscribeItem(item)) {
rateTranscriptionItem = item;
}
_menu->addAction(tr::lng_context_to_save_messages(tr::now), [=] {
Api::SendExistingDocument(msg(), document);
@@ -3048,6 +3056,12 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
&st::menuIconGiftPremium);
}
}
} else if (!rateTranscriptionItem && media->document()) {
if ((media->document()->isVoiceMessage()
|| media->document()->isVideoMessage())
&& Menu::HasRateTranscribeItem(item)) {
rateTranscriptionItem = item;
}
}
}
if (!item->isService() && view && actionText.isEmpty()) {
@@ -3224,6 +3238,13 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_controller);
}
if (!_menu->empty() && rateTranscriptionItem) {
_menu->insertAction(0, base::make_unique_q<Menu::RateTranscribe>(
_menu,
_menu->st().menu,
Menu::RateTranscribeCallbackFactory(rateTranscriptionItem)));
}
if (_menu->empty()) {
_menu = nullptr;
return;
@@ -3772,7 +3793,7 @@ void HistoryInner::toggleScrollDateShown() {
void HistoryInner::repaintScrollDateCallback() {
int updateTop = _visibleAreaTop;
int updateHeight = st::msgServiceMargin.top() + st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
if (_history->amMonoforumAdmin()) {
if (_history->hasForumThreadBars()) {
updateHeight *= 2;
}
update(0, updateTop, width(), updateHeight);
@@ -3827,7 +3848,7 @@ void HistoryInner::setShownPinned(HistoryItem *item) {
void HistoryInner::enterEventHook(QEnterEvent *e) {
_mouseActive = true;
mouseActionUpdate(QCursor::pos());
return TWidget::enterEventHook(e);
return RpWidget::enterEventHook(e);
}
void HistoryInner::leaveEventHook(QEvent *e) {
@@ -3843,7 +3864,7 @@ void HistoryInner::leaveEventHook(QEvent *e) {
setCursor(_cursor);
}
_mouseActive = false;
return TWidget::leaveEventHook(e);
return RpWidget::leaveEventHook(e);
}
HistoryInner::~HistoryInner() {
@@ -3865,7 +3886,7 @@ HistoryInner::~HistoryInner() {
bool HistoryInner::focusNextPrevChild(bool next) {
if (_selected.empty()) {
return TWidget::focusNextPrevChild(next);
return RpWidget::focusNextPrevChild(next);
} else {
clearSelected();
return true;
@@ -4335,6 +4356,54 @@ void HistoryInner::mouseActionUpdate() {
}
return true;
});
if (!dragState.link) {
enumerateForumThreadBars([&](not_null<Element*> view, int itemtop, int barTop) {
// stop the enumeration if the bar is above our point
if (barTop + dateHeight <= point.y()) {
return false;
}
const auto displayBar = view->displayForumThreadBar();
auto barInPlace = displayBar;
if (barInPlace) {
const auto correctBarTop = itemtop + view->displayedDateHeight() + st::msgServiceMargin.top();
barInPlace = (barTop < correctBarTop + st::msgServiceMargin.top());
}
// stop enumeration if we've found a bar under the cursor
if (barTop <= point.y()) {
const auto item = view->data();
auto barWidth = 0;
if (const auto bar = view->Get<HistoryView::ForumThreadBar>()) {
barWidth = bar->width;
} else {
barWidth = _forumThreadBarWidth;
}
auto barLeft = st::msgServiceMargin.left();
auto maxwidth = _contentWidth;
if (_isChatWide) {
maxwidth = qMin(maxwidth, int32(st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left()));
}
auto widthForBar = maxwidth - st::msgServiceMargin.left() - st::msgServiceMargin.left();
barLeft += (widthForBar - barWidth) / 2;
if (point.x() >= barLeft && point.x() < barLeft + barWidth) {
if (!_forumThreadBarLink) {
_forumThreadBarLink = std::make_shared<Window::ForumThreadClickHandler>(item);
} else {
static_cast<Window::ForumThreadClickHandler*>(_forumThreadBarLink.get())->update(item);
}
dragState = TextState(
nullptr,
_forumThreadBarLink);
_dragStateItem = session().data().message(dragState.itemId);
lnkhost = view;
}
}
return true;
});
}
if (!dragState.link) {
StateRequest request;
if (_mouseAction == MouseAction::Selecting) {

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais