diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt
index 10e2d8efd..266d8218a 100644
--- a/Telegram/CMakeLists.txt
+++ b/Telegram/CMakeLists.txt
@@ -1096,8 +1096,8 @@ PRIVATE
info/saved/info_saved_sublists_widget.h
info/settings/info_settings_widget.cpp
info/settings/info_settings_widget.h
- info/similar_channels/info_similar_channels_widget.cpp
- info/similar_channels/info_similar_channels_widget.h
+ info/similar_peers/info_similar_peers_widget.cpp
+ info/similar_peers/info_similar_peers_widget.h
info/statistics/info_statistics_common.h
info/statistics/info_statistics_inner_widget.cpp
info/statistics/info_statistics_inner_widget.h
@@ -1217,6 +1217,8 @@ PRIVATE
media/audio/media_audio_loader.h
media/audio/media_audio_loaders.cpp
media/audio/media_audio_loaders.h
+ media/audio/media_audio_local_cache.cpp
+ media/audio/media_audio_local_cache.h
media/audio/media_audio_track.cpp
media/audio/media_audio_track.h
media/audio/media_child_ffmpeg_loader.cpp
diff --git a/Telegram/Resources/icons/chat/markup_webview.png b/Telegram/Resources/icons/chat/markup_webview.png
new file mode 100644
index 000000000..801937d7c
Binary files /dev/null and b/Telegram/Resources/icons/chat/markup_webview.png differ
diff --git a/Telegram/Resources/icons/chat/markup_webview@2x.png b/Telegram/Resources/icons/chat/markup_webview@2x.png
new file mode 100644
index 000000000..068f4f00b
Binary files /dev/null and b/Telegram/Resources/icons/chat/markup_webview@2x.png differ
diff --git a/Telegram/Resources/icons/chat/markup_webview@3x.png b/Telegram/Resources/icons/chat/markup_webview@3x.png
new file mode 100644
index 000000000..d52aa42c9
Binary files /dev/null and b/Telegram/Resources/icons/chat/markup_webview@3x.png differ
diff --git a/Telegram/Resources/icons/menu/nft_takeoff.png b/Telegram/Resources/icons/menu/nft_takeoff.png
new file mode 100644
index 000000000..464d149bd
Binary files /dev/null and b/Telegram/Resources/icons/menu/nft_takeoff.png differ
diff --git a/Telegram/Resources/icons/menu/nft_takeoff@2x.png b/Telegram/Resources/icons/menu/nft_takeoff@2x.png
new file mode 100644
index 000000000..6603a8194
Binary files /dev/null and b/Telegram/Resources/icons/menu/nft_takeoff@2x.png differ
diff --git a/Telegram/Resources/icons/menu/nft_takeoff@3x.png b/Telegram/Resources/icons/menu/nft_takeoff@3x.png
new file mode 100644
index 000000000..bd0d91eaf
Binary files /dev/null and b/Telegram/Resources/icons/menu/nft_takeoff@3x.png differ
diff --git a/Telegram/Resources/icons/menu/nft_wear.png b/Telegram/Resources/icons/menu/nft_wear.png
new file mode 100644
index 000000000..868711c1b
Binary files /dev/null and b/Telegram/Resources/icons/menu/nft_wear.png differ
diff --git a/Telegram/Resources/icons/menu/nft_wear@2x.png b/Telegram/Resources/icons/menu/nft_wear@2x.png
new file mode 100644
index 000000000..d94838dbe
Binary files /dev/null and b/Telegram/Resources/icons/menu/nft_wear@2x.png differ
diff --git a/Telegram/Resources/icons/menu/nft_wear@3x.png b/Telegram/Resources/icons/menu/nft_wear@3x.png
new file mode 100644
index 000000000..35545df89
Binary files /dev/null and b/Telegram/Resources/icons/menu/nft_wear@3x.png differ
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 04ee96cc1..87554281d 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -604,6 +604,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_update_fail" = "Update check failed :(";
"lng_settings_workmode_tray" = "Show tray icon";
"lng_settings_workmode_window" = "Show taskbar icon";
+"lng_settings_window_close" = "When window closed";
+"lng_settings_run_in_background" = "Run in the background";
+"lng_settings_quit_on_close" = "Quit the application";
"lng_settings_close_to_taskbar" = "Close to taskbar";
"lng_settings_monochrome_icon" = "Use monochrome icon";
"lng_settings_window_system" = "Window title bar";
@@ -1346,6 +1349,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_common_groups#other" = "{count} groups in common";
"lng_profile_similar_channels#one" = "{count} similar channel";
"lng_profile_similar_channels#other" = "{count} similar channels";
+"lng_profile_similar_bots#one" = "{count} similar bot";
+"lng_profile_similar_bots#other" = "{count} similar bots";
"lng_profile_saved_messages#one" = "{count} saved message";
"lng_profile_saved_messages#other" = "{count} saved messages";
"lng_profile_peer_gifts#one" = "{count} gift";
@@ -2020,16 +2025,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_gift_sent" = "You sent a gift for {cost}";
"lng_action_gift_unique_sent" = "You sent a unique collectible item";
"lng_action_gift_upgraded" = "{user} turned the gift from you into a unique collectible";
+"lng_action_gift_upgraded_channel" = "{user} turned this gift to {channel} into a unique collectible";
+"lng_action_gift_upgraded_self_channel" = "You turned this gift to {channel} into a unique collectible";
"lng_action_gift_upgraded_mine" = "You turned the gift from {user} into a unique collectible";
"lng_action_gift_upgraded_self" = "You turned this gift into a unique collectible";
"lng_action_gift_transferred" = "{user} transferred you a gift";
+"lng_action_gift_transferred_channel" = "{user} transferred a gift to {channel}";
+"lng_action_gift_transferred_unknown" = "Someone transferred you a gift";
+"lng_action_gift_transferred_unknown_channel" = "Someone transferred a gift to {channel}";
+"lng_action_gift_transferred_self" = "You transferred a unique collectible";
+"lng_action_gift_transferred_self_channel" = "You transferred a gift to {channel}";
"lng_action_gift_transferred_mine" = "You transferred a gift to {user}";
"lng_action_gift_received_anonymous" = "Unknown user sent you a gift for {cost}";
+"lng_action_gift_sent_channel" = "{user} sent a gift to {name} for {cost}";
+"lng_action_gift_sent_self_channel" = "You sent a gift to {name} for {cost}";
"lng_action_gift_self_bought" = "You bought a gift for {cost}";
"lng_action_gift_self_subtitle" = "Saved Gift";
"lng_action_gift_self_about#one" = "Display this gift on your page or convert it to **{count}** Star.";
"lng_action_gift_self_about#other" = "Display this gift on your page or convert it to **{count}** Stars.";
"lng_action_gift_self_about_unique" = "You can display this gift on your page or turn it into unique collectible and send to others.";
+"lng_action_gift_channel_about#one" = "Display this gift in channel's Gifts or convert it to **{count}** Star.";
+"lng_action_gift_channel_about#other" = "Display this gift in channel's Gifts or convert it to **{count}** Stars.";
+"lng_action_gift_channel_about_unique" = "You can display this gift in channel's Gifts or turn it into unique collectible.";
"lng_action_gift_for_stars#one" = "{count} Star";
"lng_action_gift_for_stars#other" = "{count} Stars";
"lng_action_gift_got_subtitle" = "Gift from {user}";
@@ -2038,6 +2055,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_gift_got_upgradable_text" = "Upgrade this gift to a unique collectible.";
"lng_action_gift_got_gift_text" = "You can keep this gift on your page.";
"lng_action_gift_can_remove_text" = "You can remove this gift from your page.";
+"lng_action_gift_got_gift_channel" = "You can keep this gift in channel's Gifts.";
+"lng_action_gift_can_remove_channel" = "You can remove this gift from channel's Gifts.";
"lng_action_gift_sent_subtitle" = "Gift for {user}";
"lng_action_gift_sent_text#one" = "{user} can display this gift on their page or convert it to {count} Star.";
"lng_action_gift_sent_text#other" = "{user} can display this gift on their page or convert it to {count} Stars.";
@@ -2108,9 +2127,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_similar_channels_premium_all_link" = "Telegram Premium";
"lng_similar_channels_show_more" = "Show more channels";
+"lng_similar_bots_title" = "Similar bots";
+"lng_similar_bots_premium_all#one" = "Subscribe to {link} to unlock up to **{count}** similar bot.";
+"lng_similar_bots_premium_all#other" = "Subscribe to {link} to unlock up to **{count}** similar bots.";
+"lng_similar_bots_show_more" = "Show more bots";
+
"lng_peer_gifts_title" = "Gifts";
"lng_peer_gifts_about" = "These gifts were sent to {user} by other users.";
"lng_peer_gifts_about_mine" = "These gifts were sent to you by other users. Click on a gift to convert it to Stars or change its privacy settings.";
+"lng_peer_gifts_notify" = "Notify About New Gifts";
+"lng_peer_gifts_notify_enabled" = "You will receive a message from Telegram when your channel receives a gift.";
+"lng_peer_gifts_filter_by_value" = "Sort by Value";
+"lng_peer_gifts_filter_by_date" = "Sort by Date";
+"lng_peer_gifts_filter_unlimited" = "Unlimited";
+"lng_peer_gifts_filter_limited" = "Limited";
+"lng_peer_gifts_filter_unique" = "Unique";
+"lng_peer_gifts_filter_saved" = "Displayed";
+"lng_peer_gifts_filter_unsaved" = "Hidden";
"lng_premium_gift_duration_months#one" = "for {count} month";
"lng_premium_gift_duration_months#other" = "for {count} months";
@@ -2373,6 +2406,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_stickers_add" = "Choose sticker set";
"lng_group_emoji" = "Select Emoji Pack";
"lng_group_emoji_description" = "Choose an emoji pack that will be available to all members within the group.";
+"lng_collectible_emoji" = "Collectibles";
"lng_premium" = "Premium";
"lng_premium_free" = "Free";
@@ -2960,6 +2994,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boost_group_needs_level_emoji#one" = "Your group needs to reach **Level {count}** to set emoji pack.";
"lng_boost_group_needs_level_emoji#other" = "Your group needs to reach **Level {count}** to set emoji pack.";
+"lng_boost_channel_title_wear" = "Wear Item";
+"lng_boost_channel_needs_level_wear#one" = "Your channel needs **Level {count}** to wear collectibles.";
+"lng_boost_channel_needs_level_wear#other" = "Your channel needs **Level {count}** to wear collectibles.";
+
"lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:";
"lng_boost_channel_ask_button" = "Copy Link";
"lng_boost_channel_or" = "or";
@@ -3239,10 +3277,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_send_anonymous" = "Hide My Name";
"lng_gift_send_anonymous_self" = "Hide my name and message from visitors to my profile.";
"lng_gift_send_anonymous_about" = "You can hide your name and message from visitors to {user}'s profile. {recipient} will still see your name and message.";
+"lng_gift_send_anonymous_about_channel" = "You can hide your name and message from all visitors of this channel except its admins.";
"lng_gift_send_unique" = "Make Unique for {price}";
"lng_gift_send_unique_about" = "Enable this to let {user} turn your gift into a unique collectible. {link}";
+"lng_gift_send_unique_about_channel" = "Enable this to let the admins of {name} turn your gift into a unique collectible. {link}";
"lng_gift_send_unique_link" = "Learn More >";
"lng_gift_send_premium_about" = "Only {user} will see your message.";
+"lng_gift_send_limited_sold#one" = "{count} sold";
+"lng_gift_send_limited_sold#other" = "{count} sold";
+"lng_gift_send_limited_left#one" = "{count} left";
+"lng_gift_send_limited_left#other" = "{count} left";
"lng_gift_send_button" = "Send a Gift for {cost}";
"lng_gift_send_button_self" = "Buy a Gift for {cost}";
"lng_gift_sent_title" = "Gift Sent!";
@@ -3254,20 +3298,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_price_unique" = "Unique";
"lng_gift_view_unpack" = "Unpack";
"lng_gift_anonymous_hint" = "Only you can see the sender's name.";
+"lng_gift_anonymous_hint_channel" = "Only admins of this channel can see the sender's name.";
"lng_gift_hidden_hint" = "This gift is hidden. Only you can see it.";
-"lng_gift_visible_hint" = "This gift is visible to visitors of your page.";
+"lng_gift_hidden_unique" = "This gift is not displayed on your page.";
+"lng_gift_visible_hint" = "This gift is visible on your page.";
+"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_show_on_page" = "Display on my Page";
+"lng_gift_show_on_channel" = "Display in channel's Gifts";
"lng_gift_availability" = "Availability";
"lng_gift_from_hidden" = "Hidden User";
-"lng_gift_visibility" = "Visibility";
-"lng_gift_visibility_shown" = "Visible on your page";
-"lng_gift_visibility_hidden" = "Not visible on your page";
-"lng_gift_visibility_show" = "show";
-"lng_gift_visibility_hide" = "hide";
"lng_gift_self_status" = "buy yourself a gift";
"lng_gift_self_title" = "Buy a Gift";
"lng_gift_self_about" = "Buy yourself a gift to display on your page or reserve for later.\n\nLimited-edition gifts upgraded to collectibles can be gifted to others later.";
+"lng_gift_channel_title" = "Send a Gift";
+"lng_gift_channel_about" = "Select a gift to show appreciation for {name}.";
"lng_gift_unique_owner" = "Owner";
-"lng_gift_unique_owner_change" = "change";
+"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";
@@ -3291,14 +3341,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_convert_sure_title" = "Convert Gift to Stars";
"lng_gift_convert_sure_confirm#one" = "Do you want to convert this gift from {user} to **{count} Star**?";
"lng_gift_convert_sure_confirm#other" = "Do you want to convert this gift from {user} to **{count} Stars**?";
+"lng_gift_convert_sure_confirm_channel#one" = "Do you want to convert this gift to {channel} to **{count} Star**?";
+"lng_gift_convert_sure_confirm_channel#other" = "Do you want to convert this gift to {channel} to **{count} Stars**?";
"lng_gift_convert_sure_limit#one" = "Conversion is available for the next **{count} day**.";
"lng_gift_convert_sure_limit#other" = "Conversion is available for the next **{count} days**.";
"lng_gift_convert_sure_caution" = "This action cannot be undone. This will permanently destroy the gift.";
"lng_gift_convert_sure" = "Convert";
"lng_gift_display_done" = "The gift is now shown on your profile page.";
+"lng_gift_display_done_channel" = "The gift is now shown in channel's Gifts.";
"lng_gift_display_done_hide" = "The gift is now hidden from your profile page.";
+"lng_gift_display_done_hide_channel" = "The gift is now hidden from channel's Gifts.";
"lng_gift_got_stars#one" = "You got **{count} Star** for this gift.";
"lng_gift_got_stars#other" = "You got **{count} Stars** for this gift.";
+"lng_gift_channel_got#one" = "Channel got **{count} Star** for this gift.";
+"lng_gift_channel_got#other" = "Channel got **{count} Stars** for this gift.";
"lng_gift_sold_out_title" = "Sold Out!";
"lng_gift_sold_out_text#one" = "All {count} gift was already sold.";
"lng_gift_sold_out_text#other" = "All {count} gifts were already sold.";
@@ -3309,6 +3365,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_upgrade_about" = "Turn your gift into a unique collectible\nthat you can transfer or auction.";
"lng_gift_upgrade_preview_title" = "Make Unique";
"lng_gift_upgrade_preview_about" = "Let {name} turn your gift into a unique collectible.";
+"lng_gift_upgrade_preview_about_channel" = "Let the admins of {name} turn your gift into a unique collectible.";
"lng_gift_upgrade_unique_title" = "Unique";
"lng_gift_upgrade_unique_about" = "Get a unique number, model, backdrop and symbol for your gift.";
"lng_gift_upgrade_transferable_title" = "Transferable";
@@ -3328,6 +3385,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_transferred_about" = "{name} was successfully transferred to {recipient}.";
"lng_gift_transfer_title" = "Transfer {name}";
"lng_gift_transfer_via_blockchain" = "Send via Blockchain";
+"lng_gift_transfer_password_title" = "Two-step verification";
+"lng_gift_transfer_password_description" = "Please enter your password to transfer.";
+"lng_gift_transfer_password_about" = "You can withdraw only if you have:";
+"lng_gift_transfer_confirm_title" = "Manage with Fragment";
+"lng_gift_transfer_confirm_text" = "You can use Fragment, a third-party service, to transfer {name} to your TON account. After that, you can manage it as an NFT with any TON wallet outside Telegram.\n\nYou can also move such NFTs back to your Telegram account via Fragment.";
+"lng_gift_transfer_confirm_button" = "Open Fragment";
"lng_gift_transfer_unlocks_days#one" = "unlocks in {count} day";
"lng_gift_transfer_unlocks_days#other" = "unlocks in {count} days";
"lng_gift_transfer_unlocks_hours#one" = "unlocks in {count} hour";
@@ -3344,6 +3407,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_transfer_sure_for" = "Do you want to transfer ownership of {name} to {recipient} for {price}?";
"lng_gift_transfer_button" = "Transfer";
"lng_gift_transfer_button_for" = "Transfer for {price}";
+"lng_gift_transfer_wear" = "Wear";
+"lng_gift_transfer_take_off" = "Take Off";
+"lng_gift_wear_title" = "Wear {name}";
+"lng_gift_wear_about" = "and get these benefits:";
+"lng_gift_wear_badge_title" = "Radiant Badge";
+"lng_gift_wear_badge_about" = "The glittering icon of this item will be displayed next to your name.";
+"lng_gift_wear_badge_about_channel" = "The glittering icon of this item will be displayed next to channel's name.";
+"lng_gift_wear_proof_title" = "Proof of Ownership";
+"lng_gift_wear_proof_about" = "Clicking the icon of this item next to your name will show its info and owner.";
+"lng_gift_wear_proof_about_channel" = "Clicking the icon of this item next to channel's name will show its info and owner.";
+"lng_gift_wear_start" = "Start Wearing";
+"lng_gift_wear_subscribe" = "Subscribe to {link} to wear collectibles.";
+"lng_gift_wear_start_toast" = "You put on {name}";
+"lng_gift_wear_end_toast" = "You took off {name}";
"lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";
@@ -5520,6 +5597,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_view_button_iv" = "Instant View";
"lng_view_button_stickerset" = "View stickers";
"lng_view_button_emojipack" = "View emoji";
+"lng_view_button_collectible" = "View collectible";
"lng_sponsored_hide_ads" = "Hide";
"lng_sponsored_title" = "What are sponsored messages?";
@@ -5836,6 +5914,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boosts_list_tab_gifts#other" = "{count} Gifts";
"lng_boosts_prepaid_giveaway_title" = "Prepaid giveaways";
+"lng_boosts_prepaid_giveaway_title_subtext" = "Select a giveaway you already paid for to set it up.";
"lng_boosts_prepaid_giveaway_single" = "Prepaid giveaway";
"lng_boosts_prepaid_giveaway_quantity#one" = "{count} Telegram Premium";
"lng_boosts_prepaid_giveaway_quantity#other" = "{count} Telegram Premium";
@@ -5895,6 +5974,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_earn_learn_coin_link" = "https://telegram.org/blog/monetization-for-channels";
"lng_channel_earn_chart_top_hours" = "Ad impressions";
"lng_channel_earn_chart_revenue" = "Ad rewards";
+"lng_channel_earn_chart_overriden_detail_credits" = "Rewards in Stars";
"lng_channel_earn_chart_overriden_detail_currency" = "Rewards in TON";
"lng_channel_earn_chart_overriden_detail_usd" = "Rewards in USD";
"lng_channel_earn_currency_history" = "TON Transactions";
diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml
index 5f8a2f3e8..a9f716c9e 100644
--- a/Telegram/Resources/uwp/AppX/AppxManifest.xml
+++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml
@@ -10,7 +10,7 @@
+ Version="5.10.7.0" />
Telegram Desktop
Telegram Messenger LLP
diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc
index d4fea4b71..2d5590296 100644
--- a/Telegram/Resources/winrc/Telegram.rc
+++ b/Telegram/Resources/winrc/Telegram.rc
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,10,3,0
- PRODUCTVERSION 5,10,3,0
+ FILEVERSION 5,10,7,0
+ PRODUCTVERSION 5,10,7,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
- VALUE "FileVersion", "5.10.3.0"
+ VALUE "FileVersion", "5.10.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "5.10.3.0"
+ VALUE "ProductVersion", "5.10.7.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc
index db48deca9..39318b864 100644
--- a/Telegram/Resources/winrc/Updater.rc
+++ b/Telegram/Resources/winrc/Updater.rc
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,10,3,0
- PRODUCTVERSION 5,10,3,0
+ FILEVERSION 5,10,7,0
+ PRODUCTVERSION 5,10,7,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater"
- VALUE "FileVersion", "5.10.3.0"
+ VALUE "FileVersion", "5.10.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "5.10.3.0"
+ VALUE "ProductVersion", "5.10.7.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/SourceFiles/api/api_chat_participants.cpp b/Telegram/SourceFiles/api/api_chat_participants.cpp
index 10663d1de..478390798 100644
--- a/Telegram/SourceFiles/api/api_chat_participants.cpp
+++ b/Telegram/SourceFiles/api/api_chat_participants.cpp
@@ -211,11 +211,10 @@ void ApplyBotsList(
Data::PeerUpdate::Flag::FullInfo);
}
-[[nodiscard]] ChatParticipants::Channels ParseSimilar(
+[[nodiscard]] ChatParticipants::Peers ParseSimilarChannels(
not_null session,
const MTPmessages_Chats &chats) {
- auto result = ChatParticipants::Channels();
- std::vector>();
+ auto result = ChatParticipants::Peers();
chats.match([&](const auto &data) {
const auto &list = data.vchats().v;
result.list.reserve(list.size());
@@ -234,10 +233,29 @@ void ApplyBotsList(
return result;
}
-[[nodiscard]] ChatParticipants::Channels ParseSimilar(
+[[nodiscard]] ChatParticipants::Peers ParseSimilarChannels(
not_null channel,
const MTPmessages_Chats &chats) {
- return ParseSimilar(&channel->session(), chats);
+ return ParseSimilarChannels(&channel->session(), chats);
+}
+
+[[nodiscard]] ChatParticipants::Peers ParseSimilarBots(
+ not_null session,
+ const MTPusers_Users &users) {
+ auto result = ChatParticipants::Peers();
+ users.match([&](const auto &data) {
+ const auto &list = data.vusers().v;
+ result.list.reserve(list.size());
+ for (const auto &user : list) {
+ result.list.push_back(session->data().processUser(user));
+ }
+ if constexpr (MTPDusers_usersSlice::Is()) {
+ if (session->premiumPossible()) {
+ result.more = data.vcount().v - data.vusers().v.size();
+ }
+ }
+ });
+ return result;
}
} // namespace
@@ -782,52 +800,65 @@ void ChatParticipants::unblock(
_kickRequests.emplace(kick, requestId);
}
-void ChatParticipants::loadSimilarChannels(not_null channel) {
- if (!channel->isBroadcast()) {
- return;
- } else if (const auto i = _similar.find(channel); i != end(_similar)) {
+void ChatParticipants::loadSimilarPeers(not_null peer) {
+ if (const auto i = _similar.find(peer); i != end(_similar)) {
if (i->second.requestId
- || !i->second.channels.more
- || !channel->session().premium()) {
+ || !i->second.peers.more
+ || !peer->session().premium()) {
return;
}
}
- using Flag = MTPchannels_GetChannelRecommendations::Flag;
- _similar[channel].requestId = _api.request(
- MTPchannels_GetChannelRecommendations(
- MTP_flags(Flag::f_channel),
- channel->inputChannel)
- ).done([=](const MTPmessages_Chats &result) {
- auto &similar = _similar[channel];
- similar.requestId = 0;
- auto parsed = ParseSimilar(channel, result);
- if (similar.channels == parsed) {
- return;
- }
- similar.channels = std::move(parsed);
- if (const auto history = channel->owner().historyLoaded(channel)) {
- if (const auto item = history->joinedMessageInstance()) {
- history->owner().requestItemResize(item);
+ if (const auto channel = peer->asBroadcast()) {
+ using Flag = MTPchannels_GetChannelRecommendations::Flag;
+ _similar[peer].requestId = _api.request(
+ MTPchannels_GetChannelRecommendations(
+ MTP_flags(Flag::f_channel),
+ channel->inputChannel)
+ ).done([=](const MTPmessages_Chats &result) {
+ auto &similar = _similar[channel];
+ similar.requestId = 0;
+ auto parsed = ParseSimilarChannels(channel, result);
+ if (similar.peers == parsed) {
+ return;
}
- }
- _similarLoaded.fire_copy(channel);
- }).send();
+ similar.peers = std::move(parsed);
+ if (const auto history = channel->owner().historyLoaded(channel)) {
+ if (const auto item = history->joinedMessageInstance()) {
+ history->owner().requestItemResize(item);
+ }
+ }
+ _similarLoaded.fire_copy(channel);
+ }).send();
+ } else if (const auto bot = peer->asBot()) {
+ _similar[peer].requestId = _api.request(
+ MTPbots_GetBotRecommendations(bot->inputUser)
+ ).done([=](const MTPusers_Users &result) {
+ auto &similar = _similar[peer];
+ similar.requestId = 0;
+ auto parsed = ParseSimilarBots(&peer->session(), result);
+ if (similar.peers == parsed) {
+ return;
+ }
+ similar.peers = std::move(parsed);
+ _similarLoaded.fire_copy(peer);
+ }).send();
+ }
}
-auto ChatParticipants::similar(not_null channel)
--> const Channels & {
- const auto i = channel->isBroadcast()
- ? _similar.find(channel)
+auto ChatParticipants::similar(not_null peer)
+-> const Peers & {
+ const auto i = (peer->isBroadcast() || peer->isBot())
+ ? _similar.find(peer)
: end(_similar);
if (i != end(_similar)) {
- return i->second.channels;
+ return i->second.peers;
}
- static const auto empty = Channels();
+ static const auto empty = Peers();
return empty;
}
auto ChatParticipants::similarLoaded() const
--> rpl::producer> {
+-> rpl::producer> {
return _similarLoaded.events();
}
@@ -841,15 +872,15 @@ void ChatParticipants::loadRecommendations() {
MTP_inputChannelEmpty())
).done([=](const MTPmessages_Chats &result) {
_recommendations.requestId = 0;
- auto parsed = ParseSimilar(_session, result);
- _recommendations.channels = std::move(parsed);
- _recommendations.channels.more = 0;
+ auto parsed = ParseSimilarChannels(_session, result);
+ _recommendations.peers = std::move(parsed);
+ _recommendations.peers.more = 0;
_recommendationsLoaded = true;
}).send();
}
-const ChatParticipants::Channels &ChatParticipants::recommendations() const {
- return _recommendations.channels;
+const ChatParticipants::Peers &ChatParticipants::recommendations() const {
+ return _recommendations.peers;
}
rpl::producer<> ChatParticipants::recommendationsLoaded() const {
diff --git a/Telegram/SourceFiles/api/api_chat_participants.h b/Telegram/SourceFiles/api/api_chat_participants.h
index df332522d..4f073eb8e 100644
--- a/Telegram/SourceFiles/api/api_chat_participants.h
+++ b/Telegram/SourceFiles/api/api_chat_participants.h
@@ -138,27 +138,27 @@ public:
not_null channel,
not_null participant);
- void loadSimilarChannels(not_null channel);
+ void loadSimilarPeers(not_null peer);
- struct Channels {
- std::vector> list;
+ struct Peers {
+ std::vector> list;
int more = 0;
friend inline bool operator==(
- const Channels &,
- const Channels &) = default;
+ const Peers &,
+ const Peers &) = default;
};
- [[nodiscard]] const Channels &similar(not_null channel);
+ [[nodiscard]] const Peers &similar(not_null peer);
[[nodiscard]] auto similarLoaded() const
- -> rpl::producer>;
+ -> rpl::producer>;
void loadRecommendations();
- [[nodiscard]] const Channels &recommendations() const;
+ [[nodiscard]] const Peers &recommendations() const;
[[nodiscard]] rpl::producer<> recommendationsLoaded() const;
private:
- struct SimilarChannels {
- Channels channels;
+ struct SimilarPeers {
+ Peers peers;
mtpRequestId requestId = 0;
};
@@ -186,10 +186,10 @@ private:
not_null>;
base::flat_map _kickRequests;
- base::flat_map, SimilarChannels> _similar;
- rpl::event_stream> _similarLoaded;
+ base::flat_map, SimilarPeers> _similar;
+ rpl::event_stream> _similarLoaded;
- SimilarChannels _recommendations;
+ SimilarPeers _recommendations;
rpl::variable _recommendationsLoaded = false;
};
diff --git a/Telegram/SourceFiles/api/api_credits.cpp b/Telegram/SourceFiles/api/api_credits.cpp
index 7d17ca41e..bdb10d02d 100644
--- a/Telegram/SourceFiles/api/api_credits.cpp
+++ b/Telegram/SourceFiles/api/api_credits.cpp
@@ -513,4 +513,12 @@ void EditCreditsSubscription(
)).done(done).fail([=](const MTP::Error &e) { fail(e.type()); }).send();
}
+MTPInputSavedStarGift InputSavedStarGiftId(const Data::SavedStarGiftId &id) {
+ return id.isUser()
+ ? MTP_inputSavedStarGiftUser(MTP_int(id.userMessageId().bare))
+ : MTP_inputSavedStarGiftChat(
+ id.chat()->input,
+ MTP_long(id.chatSavedId()));
+}
+
} // namespace Api
diff --git a/Telegram/SourceFiles/api/api_credits.h b/Telegram/SourceFiles/api/api_credits.h
index 4f697cf09..c7005073e 100644
--- a/Telegram/SourceFiles/api/api_credits.h
+++ b/Telegram/SourceFiles/api/api_credits.h
@@ -12,6 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_credits_earn.h"
#include "mtproto/sender.h"
+namespace Data {
+class SavedStarGiftId;
+} // namespace Data
+
namespace Main {
class Session;
} // namespace Main
@@ -116,4 +120,7 @@ void EditCreditsSubscription(
Fn done,
Fn fail);
+[[nodiscard]] MTPInputSavedStarGift InputSavedStarGiftId(
+ const Data::SavedStarGiftId &id);
+
} // namespace Api
diff --git a/Telegram/SourceFiles/api/api_editing.cpp b/Telegram/SourceFiles/api/api_editing.cpp
index 662bfc980..313d6bfef 100644
--- a/Telegram/SourceFiles/api/api_editing.cpp
+++ b/Telegram/SourceFiles/api/api_editing.cpp
@@ -283,7 +283,9 @@ mtpRequestId EditTextMessage(
return MTP_inputMediaDocument(
MTP_flags(flags),
document->mtpInput(),
+ MTPInputPhoto(), // video_cover
MTP_int(media->ttlSeconds()),
+ MTPint(), // video_timestamp
MTPstring()); // query
};
takeFileReference = [=] { return document->fileReference(); };
diff --git a/Telegram/SourceFiles/api/api_media.cpp b/Telegram/SourceFiles/api/api_media.cpp
index 22fc37631..3bbc00f5f 100644
--- a/Telegram/SourceFiles/api/api_media.cpp
+++ b/Telegram/SourceFiles/api/api_media.cpp
@@ -121,6 +121,8 @@ MTPInputMedia PrepareUploadedDocument(
ComposeSendingDocumentAttributes(document),
MTP_vector(
ranges::to>(info.attachedStickers)),
+ MTPInputPhoto(), // video_cover
+ MTP_int(0), // video_timestamp
MTP_int(ttlSeconds));
}
diff --git a/Telegram/SourceFiles/api/api_messages_search.cpp b/Telegram/SourceFiles/api/api_messages_search.cpp
index 4fbcaebf0..8bc7a4e3d 100644
--- a/Telegram/SourceFiles/api/api_messages_search.cpp
+++ b/Telegram/SourceFiles/api/api_messages_search.cpp
@@ -103,6 +103,7 @@ void MessagesSearch::searchRequest() {
_requestId = _history->session().api().request(MTPmessages_Search(
MTP_flags((fromPeer ? Flag::f_from_id : Flag())
| (savedPeer ? Flag::f_saved_peer_id : Flag())
+ | (_request.topMsgId ? Flag::f_top_msg_id : Flag())
| (_request.tags.empty() ? Flag() : Flag::f_saved_reaction)),
_history->peer->input,
MTP_string(_request.query),
@@ -111,7 +112,7 @@ void MessagesSearch::searchRequest() {
MTP_vector_from_range(_request.tags | ranges::views::transform(
Data::ReactionToMTP
)),
- MTPint(), // top_msg_id
+ MTP_int(_request.topMsgId), // top_msg_id
MTP_inputMessagesFilterEmpty(),
MTP_int(0), // min_date
MTP_int(0), // max_date
diff --git a/Telegram/SourceFiles/api/api_messages_search.h b/Telegram/SourceFiles/api/api_messages_search.h
index 76046aaa9..b650b8799 100644
--- a/Telegram/SourceFiles/api/api_messages_search.h
+++ b/Telegram/SourceFiles/api/api_messages_search.h
@@ -32,6 +32,7 @@ public:
QString query;
PeerData *from = nullptr;
std::vector tags;
+ MsgId topMsgId;
friend inline bool operator==(
const Request &,
diff --git a/Telegram/SourceFiles/api/api_messages_search_merged.cpp b/Telegram/SourceFiles/api/api_messages_search_merged.cpp
index 1990cfd21..5a26e4386 100644
--- a/Telegram/SourceFiles/api/api_messages_search_merged.cpp
+++ b/Telegram/SourceFiles/api/api_messages_search_merged.cpp
@@ -64,6 +64,10 @@ MessagesSearchMerged::MessagesSearchMerged(not_null history)
}
}
+void MessagesSearchMerged::disableMigrated() {
+ _migratedSearch = std::nullopt;
+}
+
void MessagesSearchMerged::addFound(const FoundMessages &data) {
for (const auto &message : data.messages) {
_concatedFound.messages.push_back(message);
diff --git a/Telegram/SourceFiles/api/api_messages_search_merged.h b/Telegram/SourceFiles/api/api_messages_search_merged.h
index 1e7c0493b..1a949c6ed 100644
--- a/Telegram/SourceFiles/api/api_messages_search_merged.h
+++ b/Telegram/SourceFiles/api/api_messages_search_merged.h
@@ -29,6 +29,7 @@ public:
void clear();
void search(const Request &search);
void searchMore();
+ void disableMigrated();
[[nodiscard]] const FoundMessages &messages() const;
[[nodiscard]] const Request &request() const;
diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp
index 682f34cde..3bd36b40c 100644
--- a/Telegram/SourceFiles/api/api_premium.cpp
+++ b/Telegram/SourceFiles/api/api_premium.cpp
@@ -805,8 +805,14 @@ std::optional FromTL(
auto result = Data::StarGift{
.id = uint64(data.vid().v),
.unique = std::make_shared(Data::UniqueGift{
+ .id = data.vid().v,
+ .slug = qs(data.vslug()),
.title = qs(data.vtitle()),
- .ownerId = peerFromUser(UserId(data.vowner_id().v)),
+ .ownerAddress = qs(data.vowner_address().value_or_empty()),
+ .ownerName = qs(data.vowner_name().value_or_empty()),
+ .ownerId = (data.vowner_id()
+ ? peerFromMTP(*data.vowner_id())
+ : PeerId()),
.number = data.vnum().v,
.model = *model,
.pattern = *pattern,
@@ -829,9 +835,9 @@ std::optional FromTL(
});
}
-std::optional FromTL(
- not_null to,
- const MTPuserStarGift &gift) {
+std::optional FromTL(
+ not_null to,
+ const MTPsavedStarGift &gift) {
const auto session = &to->session();
const auto &data = gift.data();
auto parsed = FromTL(session, data.vgift());
@@ -841,8 +847,12 @@ std::optional FromTL(
unique->starsForTransfer = data.vtransfer_stars().value_or(-1);
unique->exportAt = data.vcan_export_at().value_or_empty();
}
- return Data::UserStarGift{
+ using Id = Data::SavedStarGiftId;
+ return Data::SavedStarGift{
.info = std::move(*parsed),
+ .manageId = (to->isUser()
+ ? Id::User(data.vmsg_id().value_or_empty())
+ : Id::Chat(to, data.vsaved_id().value_or_empty())),
.message = (data.vmessage()
? TextWithEntities{
.text = qs(data.vmessage()->data().vtext()),
@@ -855,9 +865,8 @@ std::optional FromTL(
.starsUpgradedBySender = int64(
data.vupgrade_stars().value_or_empty()),
.fromId = (data.vfrom_id()
- ? peerFromUser(data.vfrom_id()->v)
+ ? peerFromMTP(*data.vfrom_id())
: PeerId()),
- .messageId = data.vmsg_id().value_or_empty(),
.date = data.vdate().v,
.upgradable = data.is_can_upgrade(),
.anonymous = data.is_name_hidden(),
@@ -910,11 +919,9 @@ Data::UniqueGiftOriginalDetails FromTL(
auto result = Data::UniqueGiftOriginalDetails();
result.date = data.vdate().v;
result.senderId = data.vsender_id()
- ? peerFromUser(
- UserId(data.vsender_id().value_or_empty()))
+ ? peerFromMTP(*data.vsender_id())
: PeerId();
- result.recipientId = peerFromUser(
- UserId(data.vrecipient_id().v));
+ result.recipientId = peerFromMTP(data.vrecipient_id());
result.message = data.vmessage()
? ParseTextWithEntities(session, *data.vmessage())
: TextWithEntities();
diff --git a/Telegram/SourceFiles/api/api_premium.h b/Telegram/SourceFiles/api/api_premium.h
index 4617da755..a7757a490 100644
--- a/Telegram/SourceFiles/api/api_premium.h
+++ b/Telegram/SourceFiles/api/api_premium.h
@@ -259,9 +259,9 @@ enum class RequirePremiumState {
[[nodiscard]] std::optional FromTL(
not_null session,
const MTPstarGift &gift);
-[[nodiscard]] std::optional FromTL(
- not_null to,
- const MTPuserStarGift &gift);
+[[nodiscard]] std::optional FromTL(
+ not_null to,
+ const MTPsavedStarGift &gift);
[[nodiscard]] Data::UniqueGiftModel FromTL(
not_null session,
diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp
index d0b897a07..193e2e71b 100644
--- a/Telegram/SourceFiles/api/api_sending.cpp
+++ b/Telegram/SourceFiles/api/api_sending.cpp
@@ -272,7 +272,9 @@ void SendExistingDocument(
return MTP_inputMediaDocument(
MTP_flags(0),
document->mtpInput(),
+ MTPInputPhoto(), // video_cover
MTPint(), // ttl_seconds
+ MTPint(), // video_timestamp
MTPstring()); // query
};
SendExistingMedia(
@@ -550,6 +552,8 @@ void SendConfirmedFile(
| (file->spoiler ? Flag::f_spoiler : Flag())),
file->document,
MTPVector(), // alt_documents
+ MTPPhoto(), // video_cover
+ MTPint(), // video_timestamp
MTPint());
} else if (file->type == SendMediaType::Audio) {
const auto ttlSeconds = file->to.options.ttlSeconds;
@@ -560,6 +564,8 @@ void SendConfirmedFile(
| (ttlSeconds ? Flag::f_ttl_seconds : Flag())),
file->document,
MTPVector(), // alt_documents
+ MTPPhoto(), // video_cover
+ MTPint(), // video_timestamp
MTP_int(ttlSeconds));
} else if (file->type == SendMediaType::Round) {
using Flag = MTPDmessageMediaDocument::Flag;
@@ -571,6 +577,8 @@ void SendConfirmedFile(
| (file->spoiler ? Flag::f_spoiler : Flag())),
file->document,
MTPVector(), // alt_documents
+ MTPPhoto(), // video_cover
+ MTPint(), // video_timestamp
MTP_int(ttlSeconds));
} else {
Unexpected("Type in sendFilesConfirmed.");
diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 7e5e5a0b6..86cfd12f2 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -1812,7 +1812,7 @@ void ApiWrap::joinChannel(not_null channel) {
_channelAmInRequests.emplace(channel, requestId);
using Flag = ChannelDataFlag;
- chatParticipants().loadSimilarChannels(channel);
+ chatParticipants().loadSimilarPeers(channel);
const auto settings = &AyuSettings::getInstance();
if (!settings->collapseSimilarChannels) {
@@ -3422,7 +3422,8 @@ void ApiWrap::forwardMessages(
MTP_int(topMsgId),
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
- Data::ShortcutIdToMTP(_session, action.options.shortcutId)
+ Data::ShortcutIdToMTP(_session, action.options.shortcutId),
+ MTPint() // video_timestamp
)).done([=](const MTPUpdates &result) {
if (!scheduled) {
this->updates().checkForSentToScheduled(result);
@@ -4218,7 +4219,9 @@ void ApiWrap::uploadAlbumMedia(
fields.vid(),
fields.vaccess_hash(),
fields.vfile_reference()),
+ MTPInputPhoto(), // video_cover
MTP_int(data.vttl_seconds().value_or_empty()),
+ MTPint(), // video_timestamp
MTPstring()); // query
sendAlbumWithUploaded(item, groupId, media);
} break;
diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.cpp b/Telegram/SourceFiles/boxes/gift_premium_box.cpp
index 2b396aec4..987538be5 100644
--- a/Telegram/SourceFiles/boxes/gift_premium_box.cpp
+++ b/Telegram/SourceFiles/boxes/gift_premium_box.cpp
@@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h"
#include "data/data_channel.h"
#include "data/data_credits.h"
+#include "data/data_emoji_statuses.h"
#include "data/data_media_types.h" // Data::GiveawayStart.
#include "data/data_peer_values.h" // Data::PeerPremiumValue.
#include "data/data_session.h"
@@ -30,11 +31,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
#include "info/channel_statistics/boosts/giveaway/boost_badge.h" // InfiniteRadialAnimationWidget.
+#include "info/profile/info_profile_badge.h"
+#include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h"
+#include "main/main_app_config.h"
#include "main/main_session.h"
#include "mainwidget.h"
#include "payments/payments_checkout_process.h"
#include "payments/payments_form.h"
+#include "settings/settings_credits_graphics.h"
#include "settings/settings_premium.h"
#include "ui/basic_click_handlers.h" // UrlClickHandler::Open.
#include "ui/boxes/boost_box.h" // StartFireworks.
@@ -127,29 +132,46 @@ constexpr auto kRarityTooltipDuration = 3 * crl::time(1000);
: tr::lng_premium_gift_duration_years;
}
+[[nodiscard]] object_ptr MakeMaybeMultilineTokenValue(
+ not_null table,
+ const QString &token,
+ Settings::CreditsEntryBoxStyleOverrides st) {
+ constexpr auto kOneLineCount = 24;
+ const auto oneLine = token.length() <= kOneLineCount;
+ return object_ptr(
+ table,
+ rpl::single(
+ Ui::Text::Wrapped({ token }, EntityType::Code, {})),
+ (oneLine
+ ? table->st().defaultValue
+ : st.tableValueMultiline
+ ? *st.tableValueMultiline
+ : st::giveawayGiftCodeValueMultiline));
+}
+
[[nodiscard]] object_ptr MakePeerTableValue(
- not_null parent,
- not_null controller,
+ not_null table,
+ std::shared_ptr show,
PeerId id,
rpl::producer button = nullptr,
Fn handler = nullptr) {
- auto result = object_ptr(parent);
+ auto result = object_ptr(table);
const auto raw = result.data();
const auto &st = st::giveawayGiftCodeUserpic;
raw->resize(raw->width(), st.photoSize);
- const auto peer = controller->session().data().peer(id);
+ const auto peer = show->session().data().peer(id);
const auto userpic = Ui::CreateChild(raw, peer, st);
const auto label = Ui::CreateChild(
raw,
(button && handler) ? peer->shortName() : peer->name(),
- st::giveawayGiftCodeValue);
+ table->st().defaultValue);
const auto send = (button && handler)
? Ui::CreateChild(
raw,
std::move(button),
- st::starGiftSmallButton)
+ table->st().smallButton)
: nullptr;
if (send) {
send->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
@@ -171,27 +193,109 @@ constexpr auto kRarityTooltipDuration = 3 * crl::time(1000);
send->moveToLeft(
position.x() + label->width() + st::normalFont->spacew,
(position.y()
- + st::giveawayGiftCodeValue.style.font->ascent
- - st::starGiftSmallButton.style.font->ascent),
+ + table->st().defaultValue.style.font->ascent
+ - table->st().smallButton.style.font->ascent),
width);
}
}, label->lifetime());
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
- label->setTextColorOverride(st::windowActiveTextFg->c);
+ label->setTextColorOverride(table->st().defaultValue.palette.linkFg->c);
raw->setClickedCallback([=] {
- controller->uiShow()->showBox(PrepareShortInfoBox(peer, controller));
+ show->showBox(PrepareShortInfoBox(peer, show));
+ });
+
+ return result;
+}
+
+[[nodiscard]] object_ptr MakePeerWithStatusValue(
+ not_null table,
+ std::shared_ptr show,
+ PeerId id,
+ Fn, EmojiStatusId)> pushStatusId) {
+ auto result = object_ptr(table);
+ const auto raw = result.data();
+
+ const auto &st = st::giveawayGiftCodeUserpic;
+ raw->resize(raw->width(), st.photoSize);
+
+ const auto peer = show->session().data().peer(id);
+ const auto userpic = Ui::CreateChild(raw, peer, st);
+ const auto label = Ui::CreateChild(
+ raw,
+ peer->name(),
+ table->st().defaultValue);
+
+ using namespace Info::Profile;
+ struct State {
+ rpl::variable content;
+ };
+ const auto state = label->lifetime().make_state();
+ state->content = EmojiStatusIdValue(
+ peer
+ ) | rpl::map([=](EmojiStatusId emojiStatusId) {
+ if (!peer->session().premium()
+ || (!peer->isSelf() && !emojiStatusId)) {
+ return Badge::Content();
+ }
+ return Badge::Content{
+ .badge = BadgeType::Premium,
+ .emojiStatusId = emojiStatusId,
+ };
+ });
+ const auto badge = label->lifetime().make_state(
+ raw,
+ st::infoPeerBadge,
+ &peer->session(),
+ state->content.value(),
+ nullptr,
+ [=] { return show->paused(ChatHelpers::PauseReason::Layer); });
+ state->content.value(
+ ) | rpl::start_with_next([=](const Badge::Content &content) {
+ if (const auto widget = badge->widget()) {
+ pushStatusId(widget, content.emojiStatusId);
+ }
+ }, raw->lifetime());
+
+ rpl::combine(
+ raw->widthValue(),
+ rpl::single(rpl::empty) | rpl::then(badge->updated())
+ ) | rpl::start_with_next([=](int width, const auto &) {
+ const auto position = st::giveawayGiftCodeNamePosition;
+ const auto badgeWidget = badge->widget();
+ const auto badgeSkip = badgeWidget
+ ? (st::normalFont->spacew + badgeWidget->width())
+ : 0;
+ label->resizeToNaturalWidth(width - position.x() - badgeSkip);
+ label->moveToLeft(position.x(), position.y(), width);
+ const auto top = (raw->height() - userpic->height()) / 2;
+ userpic->moveToLeft(0, top, width);
+ if (badgeWidget) {
+ badgeWidget->moveToLeft(
+ position.x() + label->width() + st::normalFont->spacew,
+ (position.y()
+ + table->st().defaultValue.style.font->ascent
+ - table->st().smallButton.style.font->ascent),
+ width);
+ }
+ }, label->lifetime());
+
+ userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
+ label->setAttribute(Qt::WA_TransparentForMouseEvents);
+ label->setTextColorOverride(table->st().defaultValue.palette.linkFg->c);
+
+ raw->setClickedCallback([=] {
+ show->showBox(PrepareShortInfoBox(peer, show));
});
return result;
}
[[nodiscard]] object_ptr MakeHiddenPeerTableValue(
- not_null parent,
- not_null controller) {
- auto result = object_ptr(parent);
+ not_null table) {
+ auto result = object_ptr(table);
const auto raw = result.data();
const auto &st = st::giveawayGiftCodeUserpic;
@@ -208,7 +312,7 @@ constexpr auto kRarityTooltipDuration = 3 * crl::time(1000);
const auto label = Ui::CreateChild(
raw,
tr::lng_gift_from_hidden(),
- st::giveawayGiftCodeValue);
+ table->st().defaultValue);
raw->widthValue(
) | rpl::start_with_next([=](int width) {
const auto position = st::giveawayGiftCodeNamePosition;
@@ -235,7 +339,7 @@ void AddTableRow(
? object_ptr(
table,
std::move(label),
- st::giveawayGiftCodeLabel)
+ table->st().defaultLabel)
: object_ptr(nullptr)),
std::move(value),
st::giveawayGiftCodeLabelMargin,
@@ -243,23 +347,23 @@ void AddTableRow(
}
[[nodiscard]] object_ptr MakeAttributeValue(
- not_null parent,
+ not_null table,
const Data::UniqueGiftAttribute &attribute,
Fn, int)> showTooltip) {
- auto result = object_ptr(parent);
+ auto result = object_ptr(table);
const auto raw = result.data();
const auto label = Ui::CreateChild(
raw,
attribute.name,
- st::giveawayGiftCodeValue);
+ table->st().defaultValue);
const auto permille = attribute.rarityPermille;
const auto text = QString::number(permille / 10.) + '%';
const auto rarity = Ui::CreateChild(
raw,
rpl::single(text),
- st::starGiftSmallButton);
+ table->st().smallButton);
rarity->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
rpl::combine(
@@ -273,8 +377,8 @@ void AddTableRow(
label->moveToLeft(0, 0, width);
rarity->moveToLeft(
label->width() + st::normalFont->spacew,
- (st::giveawayGiftCodeValue.style.font->ascent
- - st::starGiftSmallButton.style.font->ascent),
+ (table->st().defaultValue.style.font->ascent
+ - table->st().smallButton.style.font->ascent),
width);
}, label->lifetime());
@@ -294,14 +398,14 @@ void AddTableRow(
}
[[nodiscard]] object_ptr MakeStarGiftStarsValue(
- not_null parent,
- not_null controller,
+ not_null table,
+ std::shared_ptr show,
const Data::CreditsHistoryEntry &entry,
Fn convertToStars) {
- auto result = object_ptr(parent);
+ auto result = object_ptr(table);
const auto raw = result.data();
- const auto session = &controller->session();
+ const auto session = &show->session();
const auto makeContext = [session](Fn update) {
return Core::MarkedTextContext{
.session = session,
@@ -313,7 +417,7 @@ void AddTableRow(
raw,
rpl::single(star.append(
' ' + Lang::FormatStarsAmountDecimal(entry.credits))),
- st::giveawayGiftCodeValue,
+ table->st().defaultValue,
st::defaultPopupMenu,
std::move(makeContext));
@@ -323,7 +427,7 @@ void AddTableRow(
tr::lng_gift_sell_small(
lt_count_decimal,
rpl::single(entry.starsConverted * 1.)),
- st::starGiftSmallButton)
+ table->st().smallButton)
: nullptr;
if (convert) {
convert->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
@@ -341,8 +445,8 @@ void AddTableRow(
if (convert) {
convert->moveToLeft(
label->width() + st::normalFont->spacew,
- (st::giveawayGiftCodeValue.style.font->ascent
- - st::starGiftSmallButton.style.font->ascent),
+ (table->st().defaultValue.style.font->ascent
+ - table->st().smallButton.style.font->ascent),
width);
}
}, label->lifetime());
@@ -358,94 +462,46 @@ void AddTableRow(
return result;
}
-[[nodiscard]] object_ptr MakeVisibilityTableValue(
- not_null parent,
- not_null controller,
- bool savedToProfile,
- Fn toggleVisibility) {
- auto result = object_ptr(parent);
- const auto raw = result.data();
-
- const auto label = Ui::CreateChild(
- raw,
- (savedToProfile
- ? tr::lng_gift_visibility_shown()
- : tr::lng_gift_visibility_hidden()),
- st::giveawayGiftCodeValue,
- st::defaultPopupMenu);
-
- const auto toggle = Ui::CreateChild(
- raw,
- (savedToProfile
- ? tr::lng_gift_visibility_hide()
- : tr::lng_gift_visibility_show()),
- st::starGiftSmallButton);
- toggle->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
- toggle->setClickedCallback([=] {
- toggleVisibility(!savedToProfile);
- });
-
- rpl::combine(
- raw->widthValue(),
- toggle->widthValue()
- ) | rpl::start_with_next([=](int width, int toggleWidth) {
- const auto toggleSkip = toggleWidth
- ? (st::normalFont->spacew + toggleWidth)
- : 0;
- label->resizeToNaturalWidth(width - toggleSkip);
- label->moveToLeft(0, 0, width);
- toggle->moveToLeft(
- label->width() + st::normalFont->spacew,
- (st::giveawayGiftCodeValue.style.font->ascent
- - st::starGiftSmallButton.style.font->ascent),
- width);
- }, label->lifetime());
-
- label->heightValue() | rpl::start_with_next([=](int height) {
- raw->resize(
- raw->width(),
- height + st::giveawayGiftCodeValueMargin.bottom());
- }, raw->lifetime());
-
- label->setAttribute(Qt::WA_TransparentForMouseEvents);
-
- return result;
-}
-
[[nodiscard]] object_ptr MakeNonUniqueStatusTableValue(
- not_null parent,
- not_null controller,
+ not_null table,
Fn startUpgrade) {
- auto result = object_ptr(parent);
+ auto result = object_ptr(table);
const auto raw = result.data();
const auto label = Ui::CreateChild(
raw,
tr::lng_gift_unique_status_non(),
- st::giveawayGiftCodeValue,
+ table->st().defaultValue,
st::defaultPopupMenu);
- const auto upgrade = Ui::CreateChild(
- raw,
- tr::lng_gift_unique_status_upgrade(),
- st::starGiftSmallButton);
- upgrade->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
- upgrade->setClickedCallback(startUpgrade);
+ const auto upgrade = startUpgrade
+ ? Ui::CreateChild(
+ 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->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);
label->moveToLeft(0, 0, width);
- upgrade->moveToLeft(
- label->width() + st::normalFont->spacew,
- (st::giveawayGiftCodeValue.style.font->ascent
- - st::starGiftSmallButton.style.font->ascent),
- 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) {
@@ -467,7 +523,7 @@ not_null AddTableRow(
auto widget = object_ptr(
table,
std::move(value),
- st::giveawayGiftCodeValue,
+ table->st().defaultValue,
st::defaultPopupMenu,
std::move(makeContext));
const auto result = widget.data();
@@ -482,7 +538,7 @@ not_null AddTableRow(
void AddTableRow(
not_null table,
rpl::producer label,
- not_null controller,
+ std::shared_ptr show,
PeerId id) {
if (!id) {
return;
@@ -490,32 +546,33 @@ void AddTableRow(
AddTableRow(
table,
std::move(label),
- MakePeerTableValue(table, controller, id),
+ MakePeerTableValue(table, show, id),
st::giveawayGiftCodePeerMargin);
}
void AddTable(
not_null container,
- not_null controller,
+ std::shared_ptr show,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Api::GiftCode ¤t,
bool skipReason) {
auto table = container->add(
object_ptr(
container,
- st::giveawayGiftCodeTable),
+ st.table ? *st.table : st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
if (current.from) {
AddTableRow(
table,
tr::lng_gift_link_label_from(),
- controller,
+ show,
current.from);
}
if (current.from && current.to) {
AddTableRow(
table,
tr::lng_gift_link_label_to(),
- controller,
+ show,
current.to);
} else if (current.from) {
AddTableRow(
@@ -547,10 +604,12 @@ void AddTable(
) | rpl::type_erased())
: tr::lng_gift_link_reason_chosen(Ui::Text::WithEntities)));
reason->setClickHandlerFilter([=](const auto &...) {
- controller->showPeerHistory(
- current.from,
- Window::SectionShow::Way::Forward,
- current.giveawayId);
+ if (const auto window = show->resolveWindow()) {
+ window->showPeerHistory(
+ current.from,
+ Window::SectionShow::Way::Forward,
+ current.giveawayId);
+ }
return false;
});
}
@@ -678,7 +737,8 @@ void GiftCodeBox(
MakeLinkCopyIcon(box)),
st::giveawayGiftCodeLinkMargin);
- AddTable(box->verticalLayout(), controller, state->data.current(), false);
+ const auto show = controller->uiShow();
+ AddTable(box->verticalLayout(), show, {}, state->data.current(), false);
auto shareLink = tr::lng_gift_link_also_send_link(
) | rpl::map([](const QString &text) {
@@ -760,7 +820,6 @@ void GiftCodeBox(
}, button->lifetime());
}
-
void GiftCodePendingBox(
not_null box,
not_null controller,
@@ -838,7 +897,8 @@ void GiftCodePendingBox(
spoiler->show();
}
- AddTable(box->verticalLayout(), controller, data, true);
+ const auto show = controller->uiShow();
+ AddTable(box->verticalLayout(), show, {}, data, true);
box->addRow(
object_ptr(
@@ -1188,60 +1248,184 @@ void ResolveGiveawayInfo(
crl::guard(controller, show));
}
+QString TonAddressUrl(
+ not_null session,
+ const QString &address) {
+ const auto prefix = session->appConfig().get(
+ u"ton_blockchain_explorer_url"_q,
+ u"https://tonviewer.com/"_q);
+ return prefix + address;
+}
+
void AddStarGiftTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::CreditsHistoryEntry &entry,
- Fn toggleVisibility,
Fn convertToStars,
Fn startUpgrade) {
auto table = container->add(
object_ptr(
container,
- st::giveawayGiftCodeTable),
+ st.table ? *st.table : st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
const auto peerId = PeerId(entry.barePeerId);
- const auto session = &controller->session();
+ const auto session = &show->session();
const auto unique = entry.uniqueGift.get();
const auto selfBareId = session->userPeerId().value;
const auto giftToSelf = (peerId == session->userPeerId())
&& (entry.in || entry.bareGiftOwnerId == selfBareId);
- if (unique) {
+ const auto giftToChannel = entry.giftSavedId
+ && peerIsChannel(PeerId(entry.bareGiftListPeerId));
+
+ const auto raw = std::make_shared(nullptr);
+ const auto showTooltip = [=](
+ not_null widget,
+ rpl::producer text) {
+ if (*raw) {
+ (*raw)->toggleAnimated(false);
+ }
+ const auto tooltip = Ui::CreateChild(
+ container,
+ Ui::MakeNiceTooltipLabel(
+ container,
+ std::move(text),
+ st::boxWideWidth,
+ st::defaultImportantTooltipLabel),
+ st::defaultImportantTooltip);
+ tooltip->toggleFast(false);
+
+ const auto update = [=] {
+ const auto geometry = Ui::MapFrom(
+ container,
+ widget,
+ widget->rect());
+ const auto countPosition = [=](QSize size) {
+ const auto left = geometry.x()
+ + (geometry.width() - size.width()) / 2;
+ const auto right = container->width()
+ - st::normalFont->spacew;
+ return QPoint(
+ std::max(std::min(left, right - size.width()), 0),
+ geometry.y() - size.height() - st::normalFont->descent);
+ };
+ tooltip->pointAt(geometry, RectPart::Top, countPosition);
+ };
+ container->widthValue(
+ ) | rpl::start_with_next(update, tooltip->lifetime());
+
+ update();
+ tooltip->toggleAnimated(true);
+
+ *raw = tooltip;
+ tooltip->shownValue() | rpl::filter(
+ !rpl::mappers::_1
+ ) | rpl::start_with_next([=] {
+ crl::on_main(tooltip, [=] {
+ if (tooltip->isHidden()) {
+ if (*raw == tooltip) {
+ *raw = nullptr;
+ }
+ delete tooltip;
+ }
+ });
+ }, tooltip->lifetime());
+
+ base::timer_once(
+ kRarityTooltipDuration
+ ) | rpl::start_with_next([=] {
+ tooltip->toggleAnimated(false);
+ }, tooltip->lifetime());
+ };
+
+ if (unique && entry.bareGiftOwnerId) {
const auto ownerId = PeerId(entry.bareGiftOwnerId);
- const auto transfer = entry.in
- && entry.bareMsgId
- && (unique->starsForTransfer >= 0);
- auto send = transfer ? tr::lng_gift_unique_owner_change() : nullptr;
- auto handler = transfer ? Fn([=] {
- ShowTransferGiftBox(
- controller->parentController(),
- entry.uniqueGift,
- MsgId(entry.bareMsgId));
- }) : nullptr;
+ const auto was = std::make_shared>();
+ const auto handleChange = [=](
+ not_null badge,
+ EmojiStatusId emojiStatusId) {
+ const auto id = emojiStatusId.collectible
+ ? emojiStatusId.collectible->id
+ : 0;
+ const auto show = [&](const auto &phrase) {
+ showTooltip(badge, phrase(
+ lt_name,
+ rpl::single(Ui::Text::Bold(UniqueGiftName(*unique))),
+ Ui::Text::WithEntities));
+ };
+ if (!*was || *was == id) {
+ *was = id;
+ return;
+ } else if (*was == unique->id) {
+ show(tr::lng_gift_wear_end_toast);
+ } else if (id == unique->id) {
+ show(tr::lng_gift_wear_start_toast);
+ }
+ *was = id;
+ };
AddTableRow(
table,
tr::lng_gift_unique_owner(),
- MakePeerTableValue(table, controller, ownerId, send, handler),
+ MakePeerWithStatusValue(table, show, ownerId, handleChange),
st::giveawayGiftCodePeerMargin);
- } else if (peerId) {
- if (!giftToSelf) {
- const auto user = session->data().peer(peerId)->asUser();
- const auto withSendButton = entry.in && user && !user->isBot();
- auto send = withSendButton ? tr::lng_gift_send_small() : nullptr;
- auto handler = send ? Fn([=] {
- Ui::ShowStarGiftBox(controller->parentController(), user);
- }) : nullptr;
+ } else if (unique) {
+ if (!unique->ownerName.isEmpty()) {
AddTableRow(
table,
- tr::lng_credits_box_history_entry_peer_in(),
- MakePeerTableValue(table, controller, peerId, send, handler),
+ tr::lng_gift_unique_owner(),
+ rpl::single(TextWithEntities{ unique->ownerName }));
+ } else if (auto address = unique->ownerAddress; !address.isEmpty()) {
+ auto label = MakeMaybeMultilineTokenValue(table, address, st);
+ label->setClickHandlerFilter([=](const auto &...) {
+ TextUtilities::SetClipboardText(
+ TextForMimeData::Simple(address));
+ show->showToast(
+ tr::lng_gift_unique_address_copied(tr::now));
+ return false;
+ });
+ AddTableRow(
+ table,
+ tr::lng_gift_unique_owner(),
+ std::move(label),
+ st::giveawayGiftCodeValueMargin);
+ }
+ } else if (giftToChannel) {
+ AddTableRow(
+ table,
+ tr::lng_credits_box_history_entry_peer_in(),
+ (entry.bareActorId
+ ? MakePeerTableValue(table, show, PeerId(entry.bareActorId))
+ : MakeHiddenPeerTableValue(table)),
+ st::giveawayGiftCodePeerMargin);
+ if (entry.bareGiftListPeerId) {
+ AddTableRow(
+ table,
+ tr::lng_credits_box_history_entry_peer(),
+ MakePeerTableValue(
+ table,
+ show,
+ PeerId(entry.bareGiftListPeerId)),
st::giveawayGiftCodePeerMargin);
}
+ } else if (peerId && !giftToSelf) {
+ const auto user = session->data().peer(peerId)->asUser();
+ const auto withSendButton = entry.in && user && !user->isBot();
+ auto send = withSendButton ? tr::lng_gift_send_small() : nullptr;
+ auto handler = send ? Fn([=] {
+ if (const auto window = show->resolveWindow()) {
+ Ui::ShowStarGiftBox(window, user);
+ }
+ }) : nullptr;
+ AddTableRow(
+ table,
+ tr::lng_credits_box_history_entry_peer_in(),
+ MakePeerTableValue(table, show, peerId, send, handler),
+ st::giveawayGiftCodePeerMargin);
} else if (!entry.soldOutInfo) {
AddTableRow(
table,
tr::lng_credits_box_history_entry_peer_in(),
- MakeHiddenPeerTableValue(table, controller),
+ MakeHiddenPeerTableValue(table),
st::giveawayGiftCodePeerMargin);
}
if (!unique && !entry.firstSaleDate.isNull()) {
@@ -1267,84 +1451,29 @@ void AddStarGiftTable(
const auto marginWithButton = st::giveawayGiftCodeValueMargin
- QMargins(0, 0, 0, st::giveawayGiftCodeValueMargin.bottom());
if (unique) {
- const auto raw = std::make_shared(nullptr);
- const auto showTooltip = [=](
+ const auto showRarity = [=](
not_null widget,
int rarity) {
- if (*raw) {
- (*raw)->toggleAnimated(false);
- }
- const auto text = QString::number(rarity / 10.) + '%';
- const auto tooltip = Ui::CreateChild(
- container,
- Ui::MakeNiceTooltipLabel(
- container,
- tr::lng_gift_unique_rarity(
- lt_percent,
- rpl::single(TextWithEntities{ text }),
- Ui::Text::WithEntities),
- st::boxWideWidth,
- st::defaultImportantTooltipLabel),
- st::defaultImportantTooltip);
- tooltip->toggleFast(false);
-
- const auto update = [=] {
- const auto geometry = Ui::MapFrom(
- container,
- widget,
- widget->rect());
- const auto countPosition = [=](QSize size) {
- const auto left = geometry.x()
- + (geometry.width() - size.width()) / 2;
- const auto right = container->width()
- - st::normalFont->spacew;
- return QPoint(
- std::max(std::min(left, right - size.width()), 0),
- geometry.y() - size.height() - st::normalFont->descent);
- };
- tooltip->pointAt(geometry, RectPart::Top, countPosition);
- };
- container->widthValue(
- ) | rpl::start_with_next(update, tooltip->lifetime());
-
- update();
- tooltip->toggleAnimated(true);
-
- *raw = tooltip;
- tooltip->shownValue() | rpl::filter(
- !rpl::mappers::_1
- ) | rpl::start_with_next([=] {
- crl::on_main(tooltip, [=] {
- if (tooltip->isHidden()) {
- if (*raw == tooltip) {
- *raw = nullptr;
- }
- delete tooltip;
- }
- });
- }, tooltip->lifetime());
-
- base::timer_once(
- kRarityTooltipDuration
- ) | rpl::start_with_next([=] {
- tooltip->toggleAnimated(false);
- }, tooltip->lifetime());
+ const auto percent = QString::number(rarity / 10.) + '%';
+ showTooltip(widget, tr::lng_gift_unique_rarity(
+ lt_percent,
+ rpl::single(TextWithEntities{ percent }),
+ Ui::Text::WithEntities));
};
-
AddTableRow(
table,
tr::lng_gift_unique_model(),
- MakeAttributeValue(container, unique->model, showTooltip),
+ MakeAttributeValue(table, unique->model, showRarity),
marginWithButton);
AddTableRow(
table,
tr::lng_gift_unique_backdrop(),
- MakeAttributeValue(container, unique->backdrop, showTooltip),
+ MakeAttributeValue(table, unique->backdrop, showRarity),
marginWithButton);
AddTableRow(
table,
tr::lng_gift_unique_symbol(),
- MakeAttributeValue(container, unique->pattern, showTooltip),
+ MakeAttributeValue(table, unique->pattern, showRarity),
marginWithButton);
} else {
AddTableRow(
@@ -1352,22 +1481,11 @@ void AddStarGiftTable(
tr::lng_gift_link_label_value(),
MakeStarGiftStarsValue(
table,
- controller,
+ show,
entry,
std::move(convertToStars)),
marginWithButton);
}
- if (toggleVisibility) {
- AddTableRow(
- table,
- tr::lng_gift_visibility(),
- MakeVisibilityTableValue(
- table,
- controller,
- entry.savedToProfile,
- std::move(toggleVisibility)),
- marginWithButton);
- }
if (entry.limitedCount > 0 && !entry.giftRefunded) {
auto amount = rpl::single(TextWithEntities{
Lang::FormatCountDecimal(entry.limitedCount)
@@ -1389,20 +1507,17 @@ void AddStarGiftTable(
std::move(amount),
Ui::Text::WithEntities)));
}
- if (!unique && startUpgrade) {
+ if (!unique && !entry.soldOutInfo) {
AddTableRow(
table,
tr::lng_gift_unique_status(),
- MakeNonUniqueStatusTableValue(
- table,
- controller,
- std::move(startUpgrade)),
+ MakeNonUniqueStatusTableValue(table, std::move(startUpgrade)),
marginWithButton);
}
if (unique) {
const auto &original = unique->originalDetails;
if (original.recipientId) {
- const auto owner = &controller->session().data();
+ const auto owner = &show->session().data();
const auto to = owner->peer(original.recipientId);
const auto from = original.senderId
? owner->peer(original.senderId).get()
@@ -1452,13 +1567,14 @@ void AddStarGiftTable(
lt_text,
rpl::single(original.message),
Ui::Text::WithEntities))),
- st::giveawayGiftMessage,
+ (st.tableValueMessage
+ ? *st.tableValueMessage
+ : st::giveawayGiftMessage),
st::defaultPopupMenu,
makeContext);
const auto showBoxLink = [=](not_null peer) {
return std::make_shared([=] {
- controller->uiShow()->showBox(
- PrepareShortInfoBox(peer, controller));
+ show->showBox(PrepareShortInfoBox(peer, show));
});
};
label->setLink(1, showBoxLink(to));
@@ -1482,7 +1598,9 @@ void AddStarGiftTable(
auto label = object_ptr(
table,
rpl::single(entry.description),
- st::giveawayGiftMessage,
+ (st.tableValueMessage
+ ? *st.tableValueMessage
+ : st::giveawayGiftMessage),
st::defaultPopupMenu,
makeContext);
label->setSelectable(true);
@@ -1495,8 +1613,9 @@ void AddStarGiftTable(
}
void AddCreditsHistoryEntryTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::CreditsHistoryEntry &entry) {
if (!entry) {
return;
@@ -1504,12 +1623,12 @@ void AddCreditsHistoryEntryTable(
auto table = container->add(
object_ptr(
container,
- st::giveawayGiftCodeTable),
+ st.table ? *st.table : st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
const auto peerId = PeerId(entry.barePeerId);
const auto actorId = PeerId(entry.bareActorId);
const auto starrefRecipientId = PeerId(entry.starrefRecipientId);
- const auto session = &controller->session();
+ const auto session = &show->session();
if (entry.starrefCommission) {
if (entry.starrefAmount) {
AddTableRow(
@@ -1529,7 +1648,7 @@ void AddCreditsHistoryEntryTable(
AddTableRow(
table,
tr::lng_credits_box_history_entry_affiliate(),
- controller,
+ show,
starrefRecipientId);
}
if (peerId && entry.starrefCommission) {
@@ -1538,7 +1657,7 @@ void AddCreditsHistoryEntryTable(
(entry.starrefAmount
? tr::lng_credits_box_history_entry_referred
: tr::lng_credits_box_history_entry_miniapp)(),
- controller,
+ show,
peerId);
}
if (actorId || (!entry.starrefCommission && peerId)) {
@@ -1552,7 +1671,7 @@ void AddCreditsHistoryEntryTable(
AddTableRow(
table,
std::move(text),
- controller,
+ show,
actorId ? actorId : peerId);
}
if (const auto msgId = MsgId(peerId ? entry.bareMsgId : 0)) {
@@ -1565,9 +1684,11 @@ void AddCreditsHistoryEntryTable(
auto label = object_ptr(
table,
rpl::single(Ui::Text::Link(link)),
- st::giveawayGiftCodeValue);
+ table->st().defaultValue);
label->setClickHandlerFilter([=](const auto &...) {
- controller->showPeerHistory(channel, {}, msgId);
+ if (const auto window = show->resolveWindow()) {
+ window->showPeerHistory(channel, {}, msgId);
+ }
return false;
});
AddTableRow(
@@ -1618,8 +1739,8 @@ void AddCreditsHistoryEntryTable(
AddTableRow(
table,
tr::lng_gift_link_label_to(),
- controller,
- controller->session().userId());
+ show,
+ show->session().userId());
}
if (entry.bareGiveawayMsgId && entry.credits) {
AddTableRow(
@@ -1653,19 +1774,11 @@ void AddCreditsHistoryEntryTable(
Ui::Text::WithEntities));
}
if (!entry.id.isEmpty()) {
- constexpr auto kOneLineCount = 24;
- const auto oneLine = entry.id.length() <= kOneLineCount;
- auto label = object_ptr(
- table,
- rpl::single(
- Ui::Text::Wrapped({ entry.id }, EntityType::Code, {})),
- oneLine
- ? st::giveawayGiftCodeValue
- : st::giveawayGiftCodeValueMultiline);
+ auto label = MakeMaybeMultilineTokenValue(table, entry.id, st);
label->setClickHandlerFilter([=](const auto &...) {
TextUtilities::SetClipboardText(
TextForMimeData::Simple(entry.id));
- controller->showToast(
+ show->showToast(
tr::lng_credits_box_history_entry_id_copied(tr::now));
return false;
});
@@ -1705,8 +1818,9 @@ void AddCreditsHistoryEntryTable(
}
void AddSubscriptionEntryTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::SubscriptionEntry &s) {
if (!s) {
return;
@@ -1714,11 +1828,11 @@ void AddSubscriptionEntryTable(
auto table = container->add(
object_ptr(
container,
- st::giveawayGiftCodeTable),
+ st.table ? *st.table : st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
const auto peerId = PeerId(s.barePeerId);
const auto user = peerIsUser(peerId)
- ? controller->session().data().peer(peerId)->asUser()
+ ? show->session().data().peer(peerId)->asUser()
: nullptr;
AddTableRow(
table,
@@ -1727,7 +1841,7 @@ void AddSubscriptionEntryTable(
: (!s.title.isEmpty() && user && !user->botInfo)
? tr::lng_credits_subscription_row_to_business()
: tr::lng_credits_subscription_row_to(),
- controller,
+ show,
peerId);
if (!s.title.isEmpty()) {
AddTableRow(
@@ -1758,19 +1872,20 @@ void AddSubscriptionEntryTable(
}
void AddSubscriberEntryTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
not_null peer,
TimeId date) {
auto table = container->add(
object_ptr(
container,
- st::giveawayGiftCodeTable),
+ st.table ? *st.table : st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
AddTableRow(
table,
tr::lng_group_invite_joined_row_subscriber(),
- controller,
+ show,
peer->id);
if (const auto d = base::unixtime::parse(date); !d.isNull()) {
AddTableRow(
@@ -1781,23 +1896,24 @@ void AddSubscriberEntryTable(
}
void AddCreditsBoostTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::Boost &b) {
auto table = container->add(
object_ptr(
container,
- st::giveawayGiftCodeTable),
+ st.table ? *st.table : st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
const auto peerId = b.giveawayMessage.peer;
if (!peerId) {
return;
}
- const auto from = controller->session().data().peer(peerId);
+ const auto from = show->session().data().peer(peerId);
AddTableRow(
table,
tr::lng_credits_box_history_entry_peer_in(),
- controller,
+ show,
from->id);
if (b.credits) {
AddTableRow(
@@ -1810,7 +1926,7 @@ void AddCreditsBoostTable(
}
{
const auto link = CreateMessageLink(
- &controller->session(),
+ &show->session(),
peerId,
b.giveawayMessage.msg.bare);
if (!link.isEmpty()) {
diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.h b/Telegram/SourceFiles/boxes/gift_premium_box.h
index d29c1fca4..ec3282e24 100644
--- a/Telegram/SourceFiles/boxes/gift_premium_box.h
+++ b/Telegram/SourceFiles/boxes/gift_premium_box.h
@@ -13,6 +13,10 @@ namespace Api {
struct GiftCode;
} // namespace Api
+namespace ChatHelpers {
+class Show;
+} // namespace ChatHelpers
+
namespace Data {
struct Boost;
struct CreditsHistoryEntry;
@@ -21,6 +25,14 @@ struct GiveawayResults;
struct SubscriptionEntry;
} // namespace Data
+namespace Main {
+class Session;
+} // namespace Main
+
+namespace Settings {
+struct CreditsEntryBoxStyleOverrides;
+} // namespace Settings
+
namespace Ui {
class GenericBox;
class VerticalLayout;
@@ -54,29 +66,37 @@ void ResolveGiveawayInfo(
std::optional start,
std::optional results);
+[[nodiscard]] QString TonAddressUrl(
+ not_null session,
+ const QString &address);
+
void AddStarGiftTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::CreditsHistoryEntry &entry,
- Fn toggleVisibility,
Fn convertToStars,
Fn startUpgrade);
void AddCreditsHistoryEntryTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::CreditsHistoryEntry &entry);
void AddSubscriptionEntryTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::SubscriptionEntry &s);
void AddSubscriberEntryTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
not_null peer,
TimeId date);
void AddCreditsBoostTable(
- not_null controller,
+ std::shared_ptr show,
not_null container,
+ Settings::CreditsEntryBoxStyleOverrides st,
const Data::Boost &boost);
diff --git a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp
index 49df5b0ea..8007b9383 100644
--- a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp
+++ b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp
@@ -72,6 +72,16 @@ ModerateOptions CalculateModerateOptions(const HistoryItemsList &items) {
if (peer != item->history()->peer) {
return {};
}
+ {
+ const auto author = item->author();
+ if (author == peer) {
+ return {};
+ } else if (const auto channel = author->asChannel()) {
+ if (channel->linkedChat() == peer) {
+ return {};
+ }
+ }
+ }
if (!item->suggestBanReport()) {
result.allCanBan = false;
}
diff --git a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp
index be668fcd3..fe675532a 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp
@@ -265,7 +265,7 @@ struct IconSelector {
const auto manager = &controller->session().data().customEmojiManager();
auto factory = [=](DocumentId id, Fn repaint)
- -> std::unique_ptr {
+ -> std::unique_ptr {
const auto tag = Data::CustomEmojiManager::SizeTag::Large;
if (id == kDefaultIconId) {
return std::make_unique(
@@ -288,7 +288,7 @@ struct IconSelector {
.show = controller->uiShow(),
.mode = EmojiListWidget::Mode::TopicIcon,
.paused = Window::PausedIn(controller, PauseReason::Layer),
- .customRecentList = recent(),
+ .customRecentList = DocumentListToRecent(recent()),
.customRecentFactory = std::move(factory),
.st = &st::reactPanelEmojiPan,
}),
@@ -297,7 +297,7 @@ struct IconSelector {
icons->requestDefaultIfUnknown();
icons->defaultUpdates(
) | rpl::start_with_next([=] {
- selector->provideRecent(recent());
+ selector->provideRecent(DocumentListToRecent(recent()));
}, selector->lifetime());
placeFooter(selector->createFooter());
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
index b2e292a3c..8b827dc7c 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
@@ -313,6 +313,7 @@ PreviewWrap::PreviewWrap(
WebPageCollage(),
nullptr, // iv
nullptr, // stickerSet
+ nullptr, // uniqueGift
0, // duration
QString(), // author
false, // hasLargeMedia
@@ -525,7 +526,7 @@ void LevelBadge::paintEvent(QPaintEvent *e) {
struct SetValues {
uint8 colorIndex = 0;
DocumentId backgroundEmojiId = 0;
- DocumentId statusId = 0;
+ EmojiStatusId statusId;
TimeId statusUntil = 0;
bool statusChanged = false;
};
@@ -807,7 +808,7 @@ int ColorSelector::resizeGetHeight(int newWidth) {
const auto state = right->lifetime().make_state();
state->panel.someCustomChosen(
) | rpl::start_with_next([=](EmojiStatusPanel::CustomChosen chosen) {
- emojiIdChosen(chosen.id);
+ emojiIdChosen(chosen.id.documentId);
}, raw->lifetime());
std::move(colorIndexValue) | rpl::start_with_next([=](uint8 index) {
@@ -871,13 +872,12 @@ int ColorSelector::resizeGetHeight(int newWidth) {
const auto customTextColor = [=] {
return style->coloredValues(false, state->index).name;
};
- const auto controller = show->resolveWindow(
- ChatHelpers::WindowUsage::PremiumPromo);
+ const auto controller = show->resolveWindow();
if (controller) {
state->panel.show({
.controller = controller,
.button = right,
- .ensureAddedEmojiId = state->emojiId,
+ .ensureAddedEmojiId = { state->emojiId },
.customTextColor = customTextColor,
.backgroundEmojiMode = true,
});
@@ -901,8 +901,8 @@ int ColorSelector::resizeGetHeight(int newWidth) {
not_null parent,
std::shared_ptr show,
not_null channel,
- rpl::producer statusIdValue,
- Fn statusIdChosen,
+ rpl::producer statusIdValue,
+ Fn statusIdChosen,
bool group) {
const auto button = ButtonStyleWithRightEmoji(
parent,
@@ -924,20 +924,20 @@ int ColorSelector::resizeGetHeight(int newWidth) {
struct State {
EmojiStatusPanel panel;
std::unique_ptr emoji;
- DocumentId statusId = 0;
+ EmojiStatusId statusId;
};
const auto state = right->lifetime().make_state();
state->panel.someCustomChosen(
) | rpl::start_with_next([=](EmojiStatusPanel::CustomChosen chosen) {
- statusIdChosen(chosen.id, chosen.until);
+ statusIdChosen({ chosen.id }, chosen.until);
}, raw->lifetime());
const auto session = &show->session();
- std::move(statusIdValue) | rpl::start_with_next([=](DocumentId id) {
+ std::move(statusIdValue) | rpl::start_with_next([=](EmojiStatusId id) {
state->statusId = id;
state->emoji = id
? session->data().customEmojiManager().create(
- id,
+ Data::EmojiStatusCustomId(id),
[=] { right->update(); })
: nullptr;
right->resize(
@@ -985,13 +985,12 @@ int ColorSelector::resizeGetHeight(int newWidth) {
}, right->lifetime());
raw->setClickedCallback([=] {
- const auto controller = show->resolveWindow(
- ChatHelpers::WindowUsage::PremiumPromo);
+ const auto controller = show->resolveWindow();
if (controller) {
state->panel.show({
.controller = controller,
.button = right,
- .ensureAddedEmojiId = state->statusId,
+ .ensureAddedEmojiId = { state->statusId },
.channelStatusMode = true,
});
}
@@ -1183,7 +1182,7 @@ void EditPeerColorBox(
struct State {
rpl::variable index;
rpl::variable emojiId;
- rpl::variable statusId;
+ rpl::variable statusId;
TimeId statusUntil = 0;
bool statusChanged = false;
bool changing = false;
@@ -1263,8 +1262,7 @@ void EditPeerColorBox(
{ &st::menuBlueIconWallpaper }
);
button->setClickedCallback([=] {
- const auto usage = ChatHelpers::WindowUsage::PremiumPromo;
- if (const auto strong = show->resolveWindow(usage)) {
+ if (const auto strong = show->resolveWindow()) {
show->show(Box(strong, channel));
}
});
@@ -1321,7 +1319,7 @@ void EditPeerColorBox(
show,
channel,
state->statusId.value(),
- [=](DocumentId id, TimeId until) {
+ [=](EmojiStatusId id, TimeId until) {
state->statusId = id;
state->statusUntil = until;
state->statusChanged = true;
@@ -1471,8 +1469,7 @@ void CheckBoostLevel(
return;
}
const auto openStatistics = [=] {
- if (const auto controller = show->resolveWindow(
- ChatHelpers::WindowUsage::PremiumPromo)) {
+ if (const auto controller = show->resolveWindow()) {
controller->showSection(Info::Boosts::Make(peer));
}
};
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
index a16505f6a..b5cad4e65 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
@@ -1242,7 +1242,9 @@ void Controller::fillManageSection() {
? channel->canViewMembers()
: chat->amIn();
const auto canViewKicked = isChannel
- && (channel->isBroadcast() || channel->isGigagroup());
+ && (channel->isMegagroup()
+ ? (channel->isBroadcast() || channel->isGigagroup())
+ : true);
const auto hasRecentActions = isChannel
&& (channel->hasAdminRights() || channel->amCreator());
const auto hasStarRef = Info::BotStarRef::Join::Allowed(_peer)
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp
index 29504ab63..2797b5394 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp
@@ -1019,7 +1019,8 @@ void Controller::rowClicked(not_null row) {
Ui::AddSkip(content);
Ui::AddSkip(content);
- AddSubscriberEntryTable(controller, content, row->peer(), data.date);
+ const auto show = controller->uiShow();
+ AddSubscriberEntryTable(show, content, {}, row->peer(), data.date);
Ui::AddSkip(content);
Ui::AddSkip(content);
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
index 81236068e..1b6996fad 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp
@@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "main/main_session.h"
+#include "mtproto/mtproto_config.h" // megagroupSizeMax
#include "apiwrap.h"
#include "settings/settings_common.h"
#include "styles/style_layers.h"
@@ -49,7 +50,6 @@ namespace {
constexpr auto kSlowmodeValues = 7;
constexpr auto kBoostsUnrestrictValues = 5;
-constexpr auto kSuggestGigagroupThreshold = 199000;
constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
[[nodiscard]] auto Dependencies(PowerSaving::Flags)
@@ -1191,8 +1191,11 @@ void ShowEditPeerPermissionsBox(
});
if (const auto channel = peer->asChannel()) {
+ constexpr auto kThresholdOffset = int(1000);
+ const auto threshold = -kThresholdOffset
+ + channel->session().serverConfig().megagroupSizeMax;
if (channel->amCreator()
- && channel->membersCount() >= kSuggestGigagroupThreshold) {
+ && channel->membersCount() >= threshold) {
AddSuggestGigagroup(
inner,
AboutGigagroupCallback(
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp
index f7b1a6b4c..96ed8c949 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "base/event_filter.h"
+#include "chat_helpers/emoji_list_widget.h"
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h"
#include "core/ui_integration.h"
@@ -491,7 +492,8 @@ object_ptr AddReactionsSelector(
panelList.erase(
ranges::remove(panelList, paid->selectAnimation->id),
end(panelList));
- panel->selector()->provideRecentEmoji(panelList);
+ panel->selector()->provideRecentEmoji(
+ ChatHelpers::DocumentListToRecent(panelList));
panel->setDesiredHeightValues(
1.,
st::emojiPanMinHeight / 2,
diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp
index 760a821c7..9341b7089 100644
--- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp
@@ -486,20 +486,23 @@ object_ptr PrepareShortInfoBox(
object_ptr PrepareShortInfoBox(
not_null peer,
- not_null navigation,
+ std::shared_ptr show,
const style::ShortInfoBox *stOverride) {
- const auto open = [=] { navigation->showPeerHistory(peer); };
+ const auto open = [=] {
+ if (const auto window = show->resolveWindow()) {
+ window->showPeerHistory(peer);
+ }
+ };
const auto videoIsPaused = [=] {
- return navigation->parentController()->isGifPausedAtLeastFor(
- Window::GifPauseReason::Layer);
+ return show->paused(Window::GifPauseReason::Layer);
};
auto menuFiller = [=](Ui::Menu::MenuCallback addAction) {
- const auto controller = navigation->parentController();
const auto peerSeparateId = Window::SeparateId(peer);
- if (controller->windowId() != peerSeparateId) {
+ const auto window = show->resolveWindow();
+ if (window && window->windowId() != peerSeparateId) {
addAction(tr::lng_context_new_window(tr::now), [=] {
Ui::PreventDelayedActivation();
- controller->showInNewWindow(peer);
+ window->showInNewWindow(peer);
}, &st::menuIconNewWindow);
}
};
@@ -511,6 +514,13 @@ object_ptr PrepareShortInfoBox(
stOverride);
}
+object_ptr PrepareShortInfoBox(
+ not_null peer,
+ not_null navigation,
+ const style::ShortInfoBox *stOverride) {
+ return PrepareShortInfoBox(peer, navigation->uiShow(), stOverride);
+}
+
rpl::producer PrepareShortInfoStatus(not_null peer) {
return StatusValue(peer);
}
diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h
index 2edd5cd92..2213f4da2 100644
--- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h
+++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h
@@ -16,6 +16,10 @@ struct ShortInfoCover;
struct ShortInfoBox;
} // namespace style
+namespace ChatHelpers {
+class Show;
+} // namespace ChatHelpers
+
namespace Ui::Menu {
struct MenuCallback;
} // namespace Ui::Menu
@@ -42,6 +46,11 @@ struct PreparedShortInfoUserpic {
Fn menuFiller,
const style::ShortInfoBox *stOverride = nullptr);
+[[nodiscard]] object_ptr PrepareShortInfoBox(
+ not_null peer,
+ std::shared_ptr show,
+ const style::ShortInfoBox *stOverride = nullptr);
+
[[nodiscard]] object_ptr PrepareShortInfoBox(
not_null peer,
not_null navigation,
diff --git a/Telegram/SourceFiles/boxes/premium_preview_box.cpp b/Telegram/SourceFiles/boxes/premium_preview_box.cpp
index 2ef807604..570fb75e6 100644
--- a/Telegram/SourceFiles/boxes/premium_preview_box.cpp
+++ b/Telegram/SourceFiles/boxes/premium_preview_box.cpp
@@ -1139,8 +1139,7 @@ void PreviewBox(
button->resizeToWidth(width);
if (!descriptor.fromSettings) {
button->setClickedCallback([=] {
- const auto window = show->resolveWindow(
- ChatHelpers::WindowUsage::PremiumPromo);
+ const auto window = show->resolveWindow();
if (!window) {
return;
}
diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp
index 78412ebe1..0c8079585 100644
--- a/Telegram/SourceFiles/boxes/share_box.cpp
+++ b/Telegram/SourceFiles/boxes/share_box.cpp
@@ -53,6 +53,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "core/application.h"
#include "core/core_settings.h"
+#include "styles/style_calls.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_menu_icons.h"
@@ -202,16 +203,16 @@ ShareBox::ShareBox(QWidget*, Descriptor &&descriptor)
, _api(&_descriptor.session->mtp())
, _select(
this,
- (_descriptor.stMultiSelect
- ? *_descriptor.stMultiSelect
+ (_descriptor.st.multiSelect
+ ? *_descriptor.st.multiSelect
: st::defaultMultiSelect),
tr::lng_participant_filter())
, _comment(
this,
object_ptr(
this,
- (_descriptor.stComment
- ? *_descriptor.stComment
+ (_descriptor.st.comment
+ ? *_descriptor.st.comment
: st::shareComment),
Ui::InputField::Mode::MultiLine,
tr::lng_photos_comment()),
@@ -256,7 +257,7 @@ void ShareBox::prepareCommentField() {
.session = _descriptor.session,
.show = Main::MakeSessionShow(show, _descriptor.session),
.field = field,
- .fieldStyle = _descriptor.stLabel,
+ .fieldStyle = _descriptor.st.label,
});
}
field->setSubmitSettings(Core::App().settings().sendSubmitWay());
@@ -566,6 +567,9 @@ void ShareBox::showMenu(not_null parent) {
submit(action.options);
return;
}
+ const auto st = _descriptor.st.scheduleBox
+ ? *_descriptor.st.scheduleBox
+ : HistoryView::ScheduleBoxStyleArgs();
uiShow()->showBox(
HistoryView::PrepareScheduleBox(
this,
@@ -574,7 +578,7 @@ void ShareBox::showMenu(not_null parent) {
[=](Api::SendOptions options) { submit(options); },
action.options,
HistoryView::DefaultScheduleTime(),
- _descriptor.scheduleBoxStyle));
+ st));
});
_menu->setForcedVerticalOrigin(Ui::PopupMenu::VerticalOrigin::Bottom);
const auto result = FillSendMenu(
@@ -709,7 +713,9 @@ ShareBox::Inner::Inner(
: RpWidget(parent)
, _descriptor(descriptor)
, _show(std::move(show))
-, _st(_descriptor.st ? *_descriptor.st : st::shareBoxList)
+, _st(_descriptor.st.peerList
+ ? *_descriptor.st.peerList
+ : st::shareBoxList)
, _defaultChatsIndexed(
std::make_unique(
Dialogs::SortMode::Add))
@@ -1586,7 +1592,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
MTP_int(topMsgId),
MTP_int(options.scheduled),
MTP_inputPeerEmpty(), // send_as
- Data::ShortcutIdToMTP(session, options.shortcutId)
+ Data::ShortcutIdToMTP(session, options.shortcutId),
+ MTPint() // video_timestamp
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {
threadHistory->session().api().applyUpdates(updates);
state->requests.remove(reqId);
@@ -1624,9 +1631,37 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
};
}
+ShareBoxStyleOverrides DarkShareBoxStyle() {
+ using namespace HistoryView;
+
+ const auto schedule = [&] {
+ auto date = Ui::ChooseDateTimeStyleArgs();
+ date.labelStyle = &st::groupCallBoxLabel;
+ date.dateFieldStyle = &st::groupCallScheduleDateField;
+ date.timeFieldStyle = &st::groupCallScheduleTimeField;
+ date.separatorStyle = &st::callMuteButtonLabel;
+ date.atStyle = &st::callMuteButtonLabel;
+ date.calendarStyle = &st::groupCallCalendarColors;
+
+ auto st = ScheduleBoxStyleArgs();
+ st.topButtonStyle = &st::groupCallMenuToggle;
+ st.popupMenuStyle = &st::groupCallPopupMenu;
+ st.chooseDateTimeArgs = std::move(date);
+ return st;
+ };
+ return {
+ .multiSelect = &st::groupCallMultiSelect,
+ .comment = &st::groupCallShareBoxComment,
+ .peerList = &st::groupCallShareBoxList,
+ .label = &st::groupCallField,
+ .scheduleBox = std::make_shared(schedule()),
+ };
+}
+
void FastShareMessage(
std::shared_ptr show,
- not_null item) {
+ not_null item,
+ ShareBoxStyleOverrides st) {
const auto history = item->history();
const auto owner = &history->owner();
const auto session = &history->session();
@@ -1695,6 +1730,7 @@ void FastShareMessage(
history,
msgIds),
.filterCallback = std::move(filterCallback),
+ .st = st,
.forwardOptions = {
.sendersCount = ItemsForwardSendersCount(items),
.captionsCount = ItemsForwardCaptionsCount(items),
@@ -1706,19 +1742,22 @@ void FastShareMessage(
void FastShareMessage(
not_null controller,
- not_null item) {
- FastShareMessage(controller->uiShow(), item);
+ not_null item,
+ ShareBoxStyleOverrides st) {
+ FastShareMessage(controller->uiShow(), item, st);
}
void FastShareLink(
not_null controller,
- const QString &url) {
- FastShareLink(controller->uiShow(), url);
+ const QString &url,
+ ShareBoxStyleOverrides st) {
+ FastShareLink(controller->uiShow(), url, st);
}
void FastShareLink(
std::shared_ptr show,
- const QString &url) {
+ const QString &url,
+ ShareBoxStyleOverrides st) {
const auto box = std::make_shared