diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt
index de5b7ab5aa..adfedd45c6 100644
--- a/Telegram/CMakeLists.txt
+++ b/Telegram/CMakeLists.txt
@@ -482,8 +482,14 @@ PRIVATE
boxes/send_files_box.h
boxes/share_box.cpp
boxes/share_box.h
+ boxes/star_gift_auction_box.cpp
+ boxes/star_gift_auction_box.h
boxes/star_gift_box.cpp
boxes/star_gift_box.h
+ boxes/star_gift_preview_box.cpp
+ boxes/star_gift_preview_box.h
+ boxes/star_gift_resale_box.cpp
+ boxes/star_gift_resale_box.h
boxes/sticker_set_box.cpp
boxes/sticker_set_box.h
boxes/stickers_box.cpp
@@ -526,6 +532,8 @@ PRIVATE
calls/group/calls_group_rtmp.h
calls/group/calls_group_settings.cpp
calls/group/calls_group_settings.h
+ calls/group/calls_group_stars_box.cpp
+ calls/group/calls_group_stars_box.h
calls/group/calls_group_toasts.cpp
calls/group/calls_group_toasts.h
calls/group/calls_group_viewport.cpp
@@ -662,8 +670,12 @@ PRIVATE
data/components/credits.h
data/components/factchecks.cpp
data/components/factchecks.h
+ data/components/gift_auctions.cpp
+ data/components/gift_auctions.h
data/components/location_pickers.cpp
data/components/location_pickers.h
+ data/components/passkeys.cpp
+ data/components/passkeys.h
data/components/promo_suggestions.cpp
data/components/promo_suggestions.h
data/components/recent_peers.cpp
@@ -1193,6 +1205,8 @@ PRIVATE
info/polls/info_polls_results_widget.h
info/profile/info_profile_actions.cpp
info/profile/info_profile_actions.h
+ info/profile/info_profile_badge_tooltip.cpp
+ info/profile/info_profile_badge_tooltip.h
info/profile/info_profile_badge.cpp
info/profile/info_profile_badge.h
info/profile/info_profile_cover.cpp
@@ -1207,6 +1221,10 @@ PRIVATE
info/profile/info_profile_members_controllers.h
info/profile/info_profile_phone_menu.cpp
info/profile/info_profile_phone_menu.h
+ info/profile/info_profile_status_label.cpp
+ info/profile/info_profile_status_label.h
+ info/profile/info_profile_top_bar.cpp
+ info/profile/info_profile_top_bar.h
info/profile/info_profile_values.cpp
info/profile/info_profile_values.h
info/profile/info_profile_widget.cpp
@@ -1215,6 +1233,7 @@ PRIVATE
info/reactions_list/info_reactions_list_widget.h
info/requests_list/info_requests_list_widget.cpp
info/requests_list/info_requests_list_widget.h
+ info/saved/info_saved_music_common.cpp
info/saved/info_saved_music_common.h
info/saved/info_saved_music_provider.cpp
info/saved/info_saved_music_provider.h
@@ -1442,6 +1461,8 @@ PRIVATE
media/view/media_view_playback_progress.h
media/view/media_view_playback_sponsored.cpp
media/view/media_view_playback_sponsored.h
+ media/view/media_view_video_stream.cpp
+ media/view/media_view_video_stream.h
media/system_media_controls_manager.h
media/system_media_controls_manager.cpp
menu/menu_antispam_validator.cpp
@@ -1531,6 +1552,7 @@ PRIVATE
platform/linux/specific_linux.h
platform/linux/tray_linux.cpp
platform/linux/tray_linux.h
+ platform/linux/webauthn_linux.cpp
platform/mac/file_utilities_mac.mm
platform/mac/file_utilities_mac.h
platform/mac/launcher_mac.mm
@@ -1550,6 +1572,7 @@ PRIVATE
platform/mac/specific_mac_p.h
platform/mac/tray_mac.mm
platform/mac/tray_mac.h
+ platform/mac/webauthn_mac.mm
platform/mac/window_title_mac.mm
platform/mac/touchbar/items/mac_formatter_item.h
platform/mac/touchbar/items/mac_formatter_item.mm
@@ -1584,6 +1607,7 @@ PRIVATE
platform/win/specific_win.h
platform/win/tray_win.cpp
platform/win/tray_win.h
+ platform/win/webauthn_win.cpp
platform/win/windows_app_user_model_id.cpp
platform/win/windows_app_user_model_id.h
platform/win/windows_dlls.cpp
@@ -1602,6 +1626,7 @@ PRIVATE
platform/platform_overlay_widget.h
platform/platform_specific.h
platform/platform_tray.h
+ platform/platform_webauthn.h
platform/platform_window_title.h
profile/profile_back_button.cpp
profile/profile_back_button.h
@@ -1687,6 +1712,8 @@ PRIVATE
settings/settings_notifications.h
settings/settings_notifications_type.cpp
settings/settings_notifications_type.h
+ settings/settings_passkeys.cpp
+ settings/settings_passkeys.h
settings/settings_power_saving.cpp
settings/settings_power_saving.h
settings/settings_premium.cpp
@@ -1776,6 +1803,8 @@ PRIVATE
ui/controls/location_picker.h
ui/controls/silent_toggle.cpp
ui/controls/silent_toggle.h
+ ui/controls/table_rows.cpp
+ ui/controls/table_rows.h
ui/controls/userpic_button.cpp
ui/controls/userpic_button.h
ui/effects/credits_graphics.cpp
@@ -1814,8 +1843,12 @@ PRIVATE
ui/item_text_options.cpp
ui/item_text_options.h
ui/resize_area.h
+ ui/top_background_gradient.cpp
+ ui/top_background_gradient.h
ui/unread_badge.cpp
ui/unread_badge.h
+ ui/peer/video_userpic_player.cpp
+ ui/peer/video_userpic_player.h
window/main_window.cpp
window/main_window.h
window/notifications_manager.cpp
@@ -1857,6 +1890,8 @@ PRIVATE
window/window_session_controller.cpp
window/window_session_controller.h
window/window_session_controller_link_info.h
+ window/window_setup_email.cpp
+ window/window_setup_email.h
window/window_top_bar_wrap.h
window/themes/window_theme.cpp
window/themes/window_theme.h
diff --git a/Telegram/Resources/animations/my_gifts_empty.tgs b/Telegram/Resources/animations/my_gifts_empty.tgs
new file mode 100644
index 0000000000..85393b18fe
Binary files /dev/null and b/Telegram/Resources/animations/my_gifts_empty.tgs differ
diff --git a/Telegram/Resources/animations/passkeys.tgs b/Telegram/Resources/animations/passkeys.tgs
new file mode 100644
index 0000000000..62e11b2540
Binary files /dev/null and b/Telegram/Resources/animations/passkeys.tgs differ
diff --git a/Telegram/Resources/animations/profile/profile_muting.tgs b/Telegram/Resources/animations/profile/profile_muting.tgs
new file mode 100644
index 0000000000..bdae1b5f90
Binary files /dev/null and b/Telegram/Resources/animations/profile/profile_muting.tgs differ
diff --git a/Telegram/Resources/animations/profile/profile_unmuting.tgs b/Telegram/Resources/animations/profile/profile_unmuting.tgs
new file mode 100644
index 0000000000..a1dd834d6c
Binary files /dev/null and b/Telegram/Resources/animations/profile/profile_unmuting.tgs differ
diff --git a/Telegram/Resources/animations/rtmp.tgs b/Telegram/Resources/animations/rtmp.tgs
new file mode 100644
index 0000000000..53917fd1a0
Binary files /dev/null and b/Telegram/Resources/animations/rtmp.tgs differ
diff --git a/Telegram/Resources/animations/show_or_premium_lastseen.tgs b/Telegram/Resources/animations/show_or_premium_lastseen.tgs
new file mode 100644
index 0000000000..1048f5806e
Binary files /dev/null and b/Telegram/Resources/animations/show_or_premium_lastseen.tgs differ
diff --git a/Telegram/Resources/animations/show_or_premium_readtime.tgs b/Telegram/Resources/animations/show_or_premium_readtime.tgs
new file mode 100644
index 0000000000..ac3ea3f758
Binary files /dev/null and b/Telegram/Resources/animations/show_or_premium_readtime.tgs differ
diff --git a/Telegram/Resources/animations/toast/chats_filter_in.tgs b/Telegram/Resources/animations/toast/chats_filter_in.tgs
new file mode 100644
index 0000000000..aba04090d0
Binary files /dev/null and b/Telegram/Resources/animations/toast/chats_filter_in.tgs differ
diff --git a/Telegram/Resources/emoji/emoji_1.webp b/Telegram/Resources/emoji/emoji_1.webp
index 4669e60222..a46934a411 100644
Binary files a/Telegram/Resources/emoji/emoji_1.webp and b/Telegram/Resources/emoji/emoji_1.webp differ
diff --git a/Telegram/Resources/emoji/emoji_2.webp b/Telegram/Resources/emoji/emoji_2.webp
index 0c0d7c2956..1ed5db43fb 100644
Binary files a/Telegram/Resources/emoji/emoji_2.webp and b/Telegram/Resources/emoji/emoji_2.webp differ
diff --git a/Telegram/Resources/emoji/emoji_3.webp b/Telegram/Resources/emoji/emoji_3.webp
index 4d874b37bf..f31b74cbe7 100644
Binary files a/Telegram/Resources/emoji/emoji_3.webp and b/Telegram/Resources/emoji/emoji_3.webp differ
diff --git a/Telegram/Resources/emoji/emoji_4.webp b/Telegram/Resources/emoji/emoji_4.webp
index bc4eead449..53f65c27a0 100644
Binary files a/Telegram/Resources/emoji/emoji_4.webp and b/Telegram/Resources/emoji/emoji_4.webp differ
diff --git a/Telegram/Resources/emoji/emoji_5.webp b/Telegram/Resources/emoji/emoji_5.webp
index 9a4e9afd6d..dda7edca30 100644
Binary files a/Telegram/Resources/emoji/emoji_5.webp and b/Telegram/Resources/emoji/emoji_5.webp differ
diff --git a/Telegram/Resources/emoji/emoji_6.webp b/Telegram/Resources/emoji/emoji_6.webp
index 7d5842d8e6..d8dbd4774c 100644
Binary files a/Telegram/Resources/emoji/emoji_6.webp and b/Telegram/Resources/emoji/emoji_6.webp differ
diff --git a/Telegram/Resources/emoji/emoji_7.webp b/Telegram/Resources/emoji/emoji_7.webp
index b324a3e832..13e3a97437 100644
Binary files a/Telegram/Resources/emoji/emoji_7.webp and b/Telegram/Resources/emoji/emoji_7.webp differ
diff --git a/Telegram/Resources/emoji/emoji_8.webp b/Telegram/Resources/emoji/emoji_8.webp
index 5ac85a8a71..585d8c7182 100644
Binary files a/Telegram/Resources/emoji/emoji_8.webp and b/Telegram/Resources/emoji/emoji_8.webp differ
diff --git a/Telegram/Resources/export_html/css/style.css b/Telegram/Resources/export_html/css/style.css
index f9727d68ac..3189390b4c 100644
--- a/Telegram/Resources/export_html/css/style.css
+++ b/Telegram/Resources/export_html/css/style.css
@@ -440,6 +440,9 @@ div.toast_shown {
.section.stories {
background-image: url(../images/section_stories.png);
}
+.section.music {
+ background-image: url(../images/section_music.png);
+}
.section.web {
background-image: url(../images/section_web.png);
}
@@ -481,6 +484,16 @@ div.toast_shown {
.media_video .fill {
background-image: url(../images/media_video.png)
}
+.audio_icon {
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ background-color: #4f9cd9;
+ background-image: url(../images/media_music.png);
+ background-repeat: no-repeat;
+ background-position: 12px 12px;
+ background-size: 24px 24px;
+}
@media only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) {
.section.calls {
@@ -504,6 +517,9 @@ div.toast_shown {
.section.stories {
background-image: url(../images/section_stories@2x.png);
}
+.section.music {
+ background-image: url(../images/section_music@2x.png);
+}
.section.web {
background-image: url(../images/section_web@2x.png);
}
@@ -545,6 +561,9 @@ div.toast_shown {
.media_video .fill {
background-image: url(../images/media_video@2x.png)
}
+.audio_icon {
+ background-image: url(../images/media_music@2x.png);
+}
}
.spoiler {
@@ -633,4 +652,101 @@ div.toast_shown {
.reactions .reaction .count {
margin-right: 8px;
line-height: 20px;
+}
+
+@media (prefers-color-scheme: dark) {
+html, body {
+ background-color: #1a2026; /* groupCallBg */
+ margin: 0;
+ padding: 0;
+}
+.page_wrap {
+ background-color: #1a2026; /* groupCallBg */
+ color: #ffffff; /* groupCallMembersFg */
+ min-height: 100vh;
+}
+.page_wrap a {
+ color: #4db8ff; /* groupCallActiveFg */
+}
+.page_header {
+ background-color: #1a2026; /* groupCallBg */
+ border-bottom: 1px solid #2c333d; /* groupCallMembersBg */
+}
+.bold {
+ color: #ffffff; /* groupCallMembersFg */
+}
+.details {
+ color: #91979e; /* groupCallMemberNotJoinedStatus */
+}
+.page_body {
+ background-color: #1a2026; /* groupCallBg */
+}
+code {
+ color: #ff8aac; /* historyPeer6UserpicBg */
+ background-color: #2c333d; /* groupCallMembersBg */
+}
+pre {
+ color: #ffffff; /* groupCallMembersFg */
+ background-color: #2c333d; /* groupCallMembersBg */
+ border: 1px solid #323a45; /* groupCallMembersBgOver */
+}
+.with_divider {
+ border-top: 1px solid #2c333d; /* groupCallMembersBg */
+}
+a.block_link:hover {
+ background-color: #323a45; /* groupCallMembersBgOver */
+}
+.list_page .entry {
+ color: #ffffff; /* groupCallMembersFg */
+}
+.message {
+ color: #ffffff; /* groupCallMembersFg */
+}
+div.selected {
+ background-color: #323a45; /* groupCallMembersBgOver */
+}
+.default .from_name {
+ color: #4db8ff; /* groupCallActiveFg */
+}
+.default .media .description {
+ color: #ffffff; /* groupCallMembersFg */
+}
+msgInBg,
+.historyComposeAreaBg {
+ background-color: #2c333d; /* groupCallMembersBg */
+}
+msgOutBg {
+ background-color: #323a45; /* groupCallMembersBgOver */
+}
+msgInBgSelected {
+ background-color: #39424f; /* groupCallMembersBgRipple */
+}
+msgOutBgSelected {
+ background-color: #39424f; /* groupCallMembersBgRipple */
+}
+.spoiler {
+ background: #323a45; /* groupCallMembersBgOver */
+}
+.spoiler.hidden {
+ background: #61c0ff; /* groupCallMemberInactiveStatus */
+}
+.bot_button {
+ background-color: #4db8ff40; /* groupCallActiveFg with opacity */
+}
+.reactions .reaction {
+ background-color: #2c333d; /* groupCallMembersBg */
+ color: #4db8ff; /* groupCallActiveFg */
+}
+.reactions .reaction.active {
+ background-color: #4db8ff; /* groupCallActiveFg */
+ color: #1a2026; /* groupCallBg */
+}
+.reactions .reaction.paid {
+ background-color: #323a45; /* groupCallMembersBgOver */
+ color: #febb5b; /* historyPeer8UserpicBg */
+}
+.reactions .reaction.active.paid {
+ background-color: #febb5b; /* historyPeer8UserpicBg */
+ color: #1a2026; /* groupCallBg */
+}
}
\ No newline at end of file
diff --git a/Telegram/Resources/export_html/images/section_music.png b/Telegram/Resources/export_html/images/section_music.png
new file mode 100644
index 0000000000..a76a2449d5
Binary files /dev/null and b/Telegram/Resources/export_html/images/section_music.png differ
diff --git a/Telegram/Resources/export_html/images/section_music@2x.png b/Telegram/Resources/export_html/images/section_music@2x.png
new file mode 100644
index 0000000000..53dc7022c6
Binary files /dev/null and b/Telegram/Resources/export_html/images/section_music@2x.png differ
diff --git a/Telegram/Resources/icons/calls/filled_stream_crown.svg b/Telegram/Resources/icons/calls/filled_stream_crown.svg
new file mode 100644
index 0000000000..f1b17ee2be
--- /dev/null
+++ b/Telegram/Resources/icons/calls/filled_stream_crown.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/chat/input_comments_expand.png b/Telegram/Resources/icons/chat/input_comments_expand.png
new file mode 100644
index 0000000000..2a67d96318
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_comments_expand.png differ
diff --git a/Telegram/Resources/icons/chat/input_comments_expand@2x.png b/Telegram/Resources/icons/chat/input_comments_expand@2x.png
new file mode 100644
index 0000000000..5fe041c4ad
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_comments_expand@2x.png differ
diff --git a/Telegram/Resources/icons/chat/input_comments_expand@3x.png b/Telegram/Resources/icons/chat/input_comments_expand@3x.png
new file mode 100644
index 0000000000..4e675a43f0
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_comments_expand@3x.png differ
diff --git a/Telegram/Resources/icons/chat/input_comments_hide.png b/Telegram/Resources/icons/chat/input_comments_hide.png
new file mode 100644
index 0000000000..606fb2c497
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_comments_hide.png differ
diff --git a/Telegram/Resources/icons/chat/input_comments_hide@2x.png b/Telegram/Resources/icons/chat/input_comments_hide@2x.png
new file mode 100644
index 0000000000..233fd06490
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_comments_hide@2x.png differ
diff --git a/Telegram/Resources/icons/chat/input_comments_hide@3x.png b/Telegram/Resources/icons/chat/input_comments_hide@3x.png
new file mode 100644
index 0000000000..e6f6d925c0
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_comments_hide@3x.png differ
diff --git a/Telegram/Resources/icons/chat/input_send_round.png b/Telegram/Resources/icons/chat/input_send_round.png
new file mode 100644
index 0000000000..7052e9116d
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_send_round.png differ
diff --git a/Telegram/Resources/icons/chat/input_send_round@2x.png b/Telegram/Resources/icons/chat/input_send_round@2x.png
new file mode 100644
index 0000000000..92b3b02c7f
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_send_round@2x.png differ
diff --git a/Telegram/Resources/icons/chat/input_send_round@3x.png b/Telegram/Resources/icons/chat/input_send_round@3x.png
new file mode 100644
index 0000000000..f33a744a62
Binary files /dev/null and b/Telegram/Resources/icons/chat/input_send_round@3x.png differ
diff --git a/Telegram/Resources/icons/chat/mini_gift_hidden.png b/Telegram/Resources/icons/chat/mini_gift_hidden.png
new file mode 100644
index 0000000000..3c7afb68fb
Binary files /dev/null and b/Telegram/Resources/icons/chat/mini_gift_hidden.png differ
diff --git a/Telegram/Resources/icons/chat/mini_gift_hidden@2x.png b/Telegram/Resources/icons/chat/mini_gift_hidden@2x.png
new file mode 100644
index 0000000000..c212d24dfd
Binary files /dev/null and b/Telegram/Resources/icons/chat/mini_gift_hidden@2x.png differ
diff --git a/Telegram/Resources/icons/chat/mini_gift_hidden@3x.png b/Telegram/Resources/icons/chat/mini_gift_hidden@3x.png
new file mode 100644
index 0000000000..cb21e63b36
Binary files /dev/null and b/Telegram/Resources/icons/chat/mini_gift_hidden@3x.png differ
diff --git a/Telegram/Resources/icons/mediaview/recognize.png b/Telegram/Resources/icons/mediaview/recognize.png
new file mode 100644
index 0000000000..05941e3246
Binary files /dev/null and b/Telegram/Resources/icons/mediaview/recognize.png differ
diff --git a/Telegram/Resources/icons/mediaview/recognize@2x.png b/Telegram/Resources/icons/mediaview/recognize@2x.png
new file mode 100644
index 0000000000..bc86664b69
Binary files /dev/null and b/Telegram/Resources/icons/mediaview/recognize@2x.png differ
diff --git a/Telegram/Resources/icons/mediaview/recognize@3x.png b/Telegram/Resources/icons/mediaview/recognize@3x.png
new file mode 100644
index 0000000000..0be9ab5e32
Binary files /dev/null and b/Telegram/Resources/icons/mediaview/recognize@3x.png differ
diff --git a/Telegram/Resources/icons/menu/2sv_off.png b/Telegram/Resources/icons/menu/2sv_off.png
new file mode 100644
index 0000000000..78a2886000
Binary files /dev/null and b/Telegram/Resources/icons/menu/2sv_off.png differ
diff --git a/Telegram/Resources/icons/menu/2sv_off@2x.png b/Telegram/Resources/icons/menu/2sv_off@2x.png
new file mode 100644
index 0000000000..98cae67216
Binary files /dev/null and b/Telegram/Resources/icons/menu/2sv_off@2x.png differ
diff --git a/Telegram/Resources/icons/menu/2sv_off@3x.png b/Telegram/Resources/icons/menu/2sv_off@3x.png
new file mode 100644
index 0000000000..cf1b017bae
Binary files /dev/null and b/Telegram/Resources/icons/menu/2sv_off@3x.png differ
diff --git a/Telegram/Resources/icons/menu/2sv_on.png b/Telegram/Resources/icons/menu/2sv_on.png
new file mode 100644
index 0000000000..f7089daa1f
Binary files /dev/null and b/Telegram/Resources/icons/menu/2sv_on.png differ
diff --git a/Telegram/Resources/icons/menu/2sv_on@2x.png b/Telegram/Resources/icons/menu/2sv_on@2x.png
new file mode 100644
index 0000000000..021ec634e6
Binary files /dev/null and b/Telegram/Resources/icons/menu/2sv_on@2x.png differ
diff --git a/Telegram/Resources/icons/menu/2sv_on@3x.png b/Telegram/Resources/icons/menu/2sv_on@3x.png
new file mode 100644
index 0000000000..5e74c1fcc3
Binary files /dev/null and b/Telegram/Resources/icons/menu/2sv_on@3x.png differ
diff --git a/Telegram/Resources/icons/menu/auction_carry.png b/Telegram/Resources/icons/menu/auction_carry.png
new file mode 100644
index 0000000000..d63bbb745f
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_carry.png differ
diff --git a/Telegram/Resources/icons/menu/auction_carry@2x.png b/Telegram/Resources/icons/menu/auction_carry@2x.png
new file mode 100644
index 0000000000..dd5367f943
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_carry@2x.png differ
diff --git a/Telegram/Resources/icons/menu/auction_carry@3x.png b/Telegram/Resources/icons/menu/auction_carry@3x.png
new file mode 100644
index 0000000000..c8f1888737
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_carry@3x.png differ
diff --git a/Telegram/Resources/icons/menu/auction_drop.png b/Telegram/Resources/icons/menu/auction_drop.png
new file mode 100644
index 0000000000..d1b3af2c33
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_drop.png differ
diff --git a/Telegram/Resources/icons/menu/auction_drop@2x.png b/Telegram/Resources/icons/menu/auction_drop@2x.png
new file mode 100644
index 0000000000..3ced06af81
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_drop@2x.png differ
diff --git a/Telegram/Resources/icons/menu/auction_drop@3x.png b/Telegram/Resources/icons/menu/auction_drop@3x.png
new file mode 100644
index 0000000000..c2f58a2377
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_drop@3x.png differ
diff --git a/Telegram/Resources/icons/menu/auction_refund.png b/Telegram/Resources/icons/menu/auction_refund.png
new file mode 100644
index 0000000000..aebc536a0f
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_refund.png differ
diff --git a/Telegram/Resources/icons/menu/auction_refund@2x.png b/Telegram/Resources/icons/menu/auction_refund@2x.png
new file mode 100644
index 0000000000..5cc6db3dcb
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_refund@2x.png differ
diff --git a/Telegram/Resources/icons/menu/auction_refund@3x.png b/Telegram/Resources/icons/menu/auction_refund@3x.png
new file mode 100644
index 0000000000..eb9f032df0
Binary files /dev/null and b/Telegram/Resources/icons/menu/auction_refund@3x.png differ
diff --git a/Telegram/Resources/icons/profile/call.svg b/Telegram/Resources/icons/profile/call.svg
new file mode 100644
index 0000000000..4882bb6228
--- /dev/null
+++ b/Telegram/Resources/icons/profile/call.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/gift.svg b/Telegram/Resources/icons/profile/gift.svg
new file mode 100644
index 0000000000..0d6880abee
--- /dev/null
+++ b/Telegram/Resources/icons/profile/gift.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/join.svg b/Telegram/Resources/icons/profile/join.svg
new file mode 100644
index 0000000000..7c53bdae00
--- /dev/null
+++ b/Telegram/Resources/icons/profile/join.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/leave.svg b/Telegram/Resources/icons/profile/leave.svg
new file mode 100644
index 0000000000..a91a104440
--- /dev/null
+++ b/Telegram/Resources/icons/profile/leave.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/message.svg b/Telegram/Resources/icons/profile/message.svg
new file mode 100644
index 0000000000..685cf25a68
--- /dev/null
+++ b/Telegram/Resources/icons/profile/message.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/mute.svg b/Telegram/Resources/icons/profile/mute.svg
new file mode 100644
index 0000000000..d9fea015ed
--- /dev/null
+++ b/Telegram/Resources/icons/profile/mute.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/profile_manage.png b/Telegram/Resources/icons/profile/profile_manage.png
new file mode 100644
index 0000000000..38f1a731dd
Binary files /dev/null and b/Telegram/Resources/icons/profile/profile_manage.png differ
diff --git a/Telegram/Resources/icons/profile/profile_manage@2x.png b/Telegram/Resources/icons/profile/profile_manage@2x.png
new file mode 100644
index 0000000000..e5ab30a518
Binary files /dev/null and b/Telegram/Resources/icons/profile/profile_manage@2x.png differ
diff --git a/Telegram/Resources/icons/profile/profile_manage@3x.png b/Telegram/Resources/icons/profile/profile_manage@3x.png
new file mode 100644
index 0000000000..8bf97111c7
Binary files /dev/null and b/Telegram/Resources/icons/profile/profile_manage@3x.png differ
diff --git a/Telegram/Resources/icons/profile/profile_more.png b/Telegram/Resources/icons/profile/profile_more.png
new file mode 100644
index 0000000000..a35e32ff95
Binary files /dev/null and b/Telegram/Resources/icons/profile/profile_more.png differ
diff --git a/Telegram/Resources/icons/profile/profile_more@2x.png b/Telegram/Resources/icons/profile/profile_more@2x.png
new file mode 100644
index 0000000000..c7ceb94e58
Binary files /dev/null and b/Telegram/Resources/icons/profile/profile_more@2x.png differ
diff --git a/Telegram/Resources/icons/profile/profile_more@3x.png b/Telegram/Resources/icons/profile/profile_more@3x.png
new file mode 100644
index 0000000000..3851073ed9
Binary files /dev/null and b/Telegram/Resources/icons/profile/profile_more@3x.png differ
diff --git a/Telegram/Resources/icons/profile/report.svg b/Telegram/Resources/icons/profile/report.svg
new file mode 100644
index 0000000000..2dc982d75f
--- /dev/null
+++ b/Telegram/Resources/icons/profile/report.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/unmute.svg b/Telegram/Resources/icons/profile/unmute.svg
new file mode 100644
index 0000000000..80bd6c2fa4
--- /dev/null
+++ b/Telegram/Resources/icons/profile/unmute.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/settings/button_auction.png b/Telegram/Resources/icons/settings/button_auction.png
new file mode 100644
index 0000000000..6fbaa5e019
Binary files /dev/null and b/Telegram/Resources/icons/settings/button_auction.png differ
diff --git a/Telegram/Resources/icons/settings/button_auction@2x.png b/Telegram/Resources/icons/settings/button_auction@2x.png
new file mode 100644
index 0000000000..c4c3ef1d8f
Binary files /dev/null and b/Telegram/Resources/icons/settings/button_auction@2x.png differ
diff --git a/Telegram/Resources/icons/settings/button_auction@3x.png b/Telegram/Resources/icons/settings/button_auction@3x.png
new file mode 100644
index 0000000000..c9c6b28561
Binary files /dev/null and b/Telegram/Resources/icons/settings/button_auction@3x.png differ
diff --git a/Telegram/Resources/icons/settings/large_auctions.png b/Telegram/Resources/icons/settings/large_auctions.png
new file mode 100644
index 0000000000..e567876247
Binary files /dev/null and b/Telegram/Resources/icons/settings/large_auctions.png differ
diff --git a/Telegram/Resources/icons/settings/large_auctions@2x.png b/Telegram/Resources/icons/settings/large_auctions@2x.png
new file mode 100644
index 0000000000..1a32e7584c
Binary files /dev/null and b/Telegram/Resources/icons/settings/large_auctions@2x.png differ
diff --git a/Telegram/Resources/icons/settings/large_auctions@3x.png b/Telegram/Resources/icons/settings/large_auctions@3x.png
new file mode 100644
index 0000000000..652c413bc8
Binary files /dev/null and b/Telegram/Resources/icons/settings/large_auctions@3x.png differ
diff --git a/Telegram/Resources/icons/settings/premium/features/feature_color_profile.png b/Telegram/Resources/icons/settings/premium/features/feature_color_profile.png
new file mode 100644
index 0000000000..33a6d47c9f
Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/features/feature_color_profile.png differ
diff --git a/Telegram/Resources/icons/settings/premium/features/feature_color_profile@2x.png b/Telegram/Resources/icons/settings/premium/features/feature_color_profile@2x.png
new file mode 100644
index 0000000000..dcb515f560
Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/features/feature_color_profile@2x.png differ
diff --git a/Telegram/Resources/icons/settings/premium/features/feature_color_profile@3x.png b/Telegram/Resources/icons/settings/premium/features/feature_color_profile@3x.png
new file mode 100644
index 0000000000..08f0296671
Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/features/feature_color_profile@3x.png differ
diff --git a/Telegram/Resources/icons/settings/premium/features/feature_profile_cover.png b/Telegram/Resources/icons/settings/premium/features/feature_profile_cover.png
new file mode 100644
index 0000000000..657fd9390a
Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/features/feature_profile_cover.png differ
diff --git a/Telegram/Resources/icons/settings/premium/features/feature_profile_cover@2x.png b/Telegram/Resources/icons/settings/premium/features/feature_profile_cover@2x.png
new file mode 100644
index 0000000000..250be37750
Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/features/feature_profile_cover@2x.png differ
diff --git a/Telegram/Resources/icons/settings/premium/features/feature_profile_cover@3x.png b/Telegram/Resources/icons/settings/premium/features/feature_profile_cover@3x.png
new file mode 100644
index 0000000000..ae696a8f34
Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/features/feature_profile_cover@3x.png differ
diff --git a/Telegram/Resources/icons/settings/premium/large_lastseen.png b/Telegram/Resources/icons/settings/premium/large_lastseen.png
deleted file mode 100644
index e47bd7935b..0000000000
Binary files a/Telegram/Resources/icons/settings/premium/large_lastseen.png and /dev/null differ
diff --git a/Telegram/Resources/icons/settings/premium/large_lastseen@2x.png b/Telegram/Resources/icons/settings/premium/large_lastseen@2x.png
deleted file mode 100644
index 305b6a4919..0000000000
Binary files a/Telegram/Resources/icons/settings/premium/large_lastseen@2x.png and /dev/null differ
diff --git a/Telegram/Resources/icons/settings/premium/large_lastseen@3x.png b/Telegram/Resources/icons/settings/premium/large_lastseen@3x.png
deleted file mode 100644
index 0cd1e12ab0..0000000000
Binary files a/Telegram/Resources/icons/settings/premium/large_lastseen@3x.png and /dev/null differ
diff --git a/Telegram/Resources/icons/settings/premium/large_readtime.png b/Telegram/Resources/icons/settings/premium/large_readtime.png
deleted file mode 100644
index c06294a82e..0000000000
Binary files a/Telegram/Resources/icons/settings/premium/large_readtime.png and /dev/null differ
diff --git a/Telegram/Resources/icons/settings/premium/large_readtime@2x.png b/Telegram/Resources/icons/settings/premium/large_readtime@2x.png
deleted file mode 100644
index f30a355ee8..0000000000
Binary files a/Telegram/Resources/icons/settings/premium/large_readtime@2x.png and /dev/null differ
diff --git a/Telegram/Resources/icons/settings/premium/large_readtime@3x.png b/Telegram/Resources/icons/settings/premium/large_readtime@3x.png
deleted file mode 100644
index 1e7d022a30..0000000000
Binary files a/Telegram/Resources/icons/settings/premium/large_readtime@3x.png and /dev/null differ
diff --git a/Telegram/Resources/icons/settings/premium/peer_colors.svg b/Telegram/Resources/icons/settings/premium/peer_colors.svg
new file mode 100644
index 0000000000..0a3c1b0854
--- /dev/null
+++ b/Telegram/Resources/icons/settings/premium/peer_colors.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/settings/toast_auction.png b/Telegram/Resources/icons/settings/toast_auction.png
new file mode 100644
index 0000000000..41b34d5fe1
Binary files /dev/null and b/Telegram/Resources/icons/settings/toast_auction.png differ
diff --git a/Telegram/Resources/icons/settings/toast_auction@2x.png b/Telegram/Resources/icons/settings/toast_auction@2x.png
new file mode 100644
index 0000000000..e03d6a987f
Binary files /dev/null and b/Telegram/Resources/icons/settings/toast_auction@2x.png differ
diff --git a/Telegram/Resources/icons/settings/toast_auction@3x.png b/Telegram/Resources/icons/settings/toast_auction@3x.png
new file mode 100644
index 0000000000..8bf2db0ab2
Binary files /dev/null and b/Telegram/Resources/icons/settings/toast_auction@3x.png differ
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index b45a10f2d7..ec27f33636 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -328,6 +328,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_proxy_box_password" = "Password";
"lng_proxy_invalid" = "The proxy link is invalid.";
"lng_proxy_unsupported" = "Your Telegram Desktop version doesn't support this proxy type or the proxy link is invalid. Please update Telegram Desktop to the latest version.";
+"lng_proxy_incorrect_secret" = "This proxy link uses invalid **secret** parameter. Please contact the proxy provider and ask him to update MTProxy source code and configure it with a correct **secret** value. Then let him provide a new link.";
"lng_edit_deleted" = "This message was deleted";
"lng_edit_limit_reached#one" = "You've reached the message text limit. Please make the text shorter by {count} character.";
@@ -377,6 +378,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_intro_qr_step2" = "Go to Settings > Devices > Link Desktop Device";
"lng_intro_qr_step3" = "Scan this image to Log In";
"lng_intro_qr_skip" = "Or log in using your phone number";
+"lng_intro_qr_phone" = "Log in using phone number";
+"lng_intro_qr_passkey" = "Log in using passkey";
"lng_intro_fragment_title" = "Enter code";
"lng_intro_fragment_about" = "Get the code for {phone_number} in the Anonymous Numbers section on Fragment.";
@@ -742,6 +745,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_language" = "Language";
"lng_settings_default_scale" = "Default interface scale";
+"lng_settings_scale" = "Interface scale";
"lng_settings_connection_type" = "Connection type";
"lng_settings_downloading_update" = "Downloading update {progress}...";
"lng_settings_privacy_title" = "Privacy";
@@ -758,6 +762,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_bio_privacy" = "Bio";
"lng_settings_gifts_privacy" = "Gifts";
"lng_settings_birthday_privacy" = "Date of Birth";
+"lng_settings_saved_music_privacy" = "Saved Music";
"lng_settings_privacy_premium" = "Only subscribers of {link} can restrict receiving voice messages.";
"lng_settings_privacy_premium_link" = "Telegram Premium";
"lng_settings_passcode_disable" = "Disable passcode";
@@ -928,6 +933,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_cloud_login_email_code_title" = "Check Your New Email";
"lng_settings_cloud_login_email_code_about" = "Please enter the code we have sent to your new email {email}";
"lng_settings_cloud_login_email_success" = "Your email has been changed.";
+"lng_settings_cloud_login_email_set_success" = "Your login email has been set successfully.";
+"lng_settings_cloud_login_email_busy" = "Please set up login email in another window.";
"lng_settings_error_email_not_alowed" = "Sorry, this email is not allowed";
"lng_settings_ttl_title" = "Auto-Delete Messages";
@@ -976,6 +983,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_font_family" = "Font family";
"lng_settings_color_title" = "Color preview";
+"lng_settings_color_tab_profile" = "Profile";
+"lng_settings_color_tab_name" = "Name";
"lng_settings_color_reply" = "Reply to your message";
"lng_settings_color_reply_channel" = "Reply to your channel message";
"lng_settings_color_text" = "Your name and replies to your messages will be shown in the selected color.";
@@ -990,10 +999,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_color_emoji_off" = "Off";
"lng_settings_color_emoji_about" = "Make replies to your messages stand out by adding custom patterns to them.";
"lng_settings_color_emoji_about_channel" = "Select an icon to create a custom pattern for replies to your messages.";
-"lng_settings_color_subscribe" = "Subscribe to {link} to choose a custom color for your name.";
"lng_settings_color_changed" = "Your name color has been updated!";
"lng_settings_color_changed_channel" = "Your channel color has been updated!";
+"lng_settings_color_changed_profile" = "Your profile style has been updated!";
+"lng_settings_color_changed_profile_channel" = "Your channel profile style has been updated!";
"lng_settings_color_apply" = "Apply Style";
+"lng_settings_color_wear" = "Wear Collectible";
+"lng_settings_color_profile_emoji" = "Add icons to Profile";
+"lng_settings_color_profile_emoji_channel" = "Profile Logo";
+"lng_settings_color_reset" = "Reset Profile Color";
+"lng_settings_color_profile_about" = "You can change the color of your name and customize replies to you. {link}";
+"lng_settings_color_profile_about_link" = "Change {emoji}";
+"lng_settings_color_choose_channel" = "Choose a color and a logo for your channel's profile";
+"lng_settings_color_choose_group" = "Choose a color and a logo for the group's profile";
+"lng_settings_color_group_boost_footer#one" = "The group has **{count}** boost. {link}";
+"lng_settings_color_group_boost_footer#other" = "The group has **{count}** boosts. {link}";
+"lng_settings_color_group_boost_footer_link" = "What are boosts?";
"lng_suggest_hide_new_title" = "Hide new chats?";
"lng_suggest_hide_new_about" = "You are receiving lots of new chats from users who are not in your Contact List.\n\nDo you want to have such chats **automatically muted** and **archived**?";
@@ -1233,6 +1254,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_restart_now" = "Restart";
"lng_settings_restart_later" = "Later";
+"lng_settings_passkeys_title" = "Passkeys";
+"lng_settings_passkeys_about" = "Manage your passkey, stored safely in the cloud service you choose.";
+"lng_settings_passkeys_button" = "Add Passkey";
+"lng_settings_passkeys_button_about" = "Your passkey is stored securely in your password manager. {link}";
+"lng_settings_passkeys_delete_sure_title" = "Delete Passkey";
+"lng_settings_passkeys_delete_sure_about" = "Once deleted, this passkey can't be used to log in.";
+"lng_settings_passkeys_delete_sure_about2" = "Don't forget to remove it from your password manager too.";
+"lng_settings_passkeys_none_title" = "Protect your account";
+"lng_settings_passkeys_none_about" = "Log in safely and keep your account secure.";
+"lng_settings_passkeys_none_info1_title" = "Create a Passkey";
+"lng_settings_passkeys_none_info1_about" = "Make a passkey to sign in easily and safely.";
+"lng_settings_passkeys_none_info2_title" = "Log in with face recognition";
+"lng_settings_passkeys_none_info2_about" = "Use your face, fingerprint, or screen lock to sign in.";
+"lng_settings_passkeys_none_info3_title" = "Store Passkey securely";
+"lng_settings_passkeys_none_info3_about" = "Your passkey is stored safely in the cloud service you choose.";
+"lng_settings_passkeys_none_button" = "Create Passkey";
+"lng_settings_passkeys_created" = "Created {date}";
+"lng_settings_passkeys_last_used" = "Last used {date}";
+"lng_settings_passkeys_unsigned_error" = "Passkeys are not available in unsigned builds. Please use an official signed version of Telegram Desktop.";
+
+
"lng_settings_quick_dialog_action_title" = "Chat list quick action";
"lng_settings_quick_dialog_action_about" = "Choose the action you want to perform when you middle-click or swipe left in the chat list.";
"lng_settings_quick_dialog_action_both" = "Swipe left and Middle-click";
@@ -1392,6 +1434,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_gifts_unlimited" = "Unlimited";
"lng_edit_privacy_gifts_limited" = "Limited-Edition";
"lng_edit_privacy_gifts_unique" = "Unique";
+"lng_edit_privacy_gifts_channels" = "From Channels";
"lng_edit_privacy_gifts_types_about" = "Choose the types of gifts that you accept.";
"lng_edit_privacy_gifts_show_icon" = "Show Gift Icon in Chats";
"lng_edit_privacy_gifts_show_icon_about" = "Display the {emoji}Gift icon in the message input field for both participants in all chats.";
@@ -1451,6 +1494,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_voices_always_title" = "Always allow";
"lng_edit_privacy_voices_never_title" = "Never Allow";
+"lng_edit_privacy_saved_music_title" = "Saved Music";
+"lng_edit_privacy_saved_music_header" = "Who can see my saved music in profile";
+"lng_edit_privacy_saved_music_always_empty" = "Always allow";
+"lng_edit_privacy_saved_music_never_empty" = "Never allow";
+"lng_edit_privacy_saved_music_exceptions" = "These users will or will not be able to see your saved music regardless of the settings above.";
+"lng_edit_privacy_saved_music_always_title" = "Always allow";
+"lng_edit_privacy_saved_music_never_title" = "Never allow";
+
"lng_messages_privacy_title" = "Messages";
"lng_messages_privacy_subtitle" = "Who can send me messages";
"lng_messages_privacy_everyone" = "Everybody";
@@ -1564,6 +1615,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_administrators#one" = "{count} administrator";
"lng_profile_administrators#other" = "{count} administrators";
"lng_profile_manage" = "Channel settings";
+"lng_profile_topic_toast" = "This topic contains {name}";
"lng_invite_upgrade_title" = "Upgrade to Premium";
"lng_invite_upgrade_group_invite#one" = "{users} only accepts invitations to groups from Contacts and **Premium** users.";
@@ -1618,6 +1670,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_delete_note" = "Delete Note";
"lng_info_bio_label" = "Bio";
"lng_info_link_label" = "Link";
+"lng_info_link_topic_label" = "This topic link will only work for group members";
"lng_info_location_label" = "Location";
"lng_info_about_label" = "Description";
"lng_info_work_open" = "Open";
@@ -1646,6 +1699,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_open_app_short" = "Open";
"lng_profile_open_app_about" = "By launching this mini app, you agree to the {terms}.";
"lng_profile_open_app_terms" = "Terms of Service for Mini Apps";
+"lng_profile_open_photo" = "Open Photo";
"lng_profile_bot_permissions_title" = "Allow access to";
"lng_profile_bot_emoji_status_access" = "Emoji Status";
"lng_info_add_as_contact" = "Add to contacts";
@@ -1653,9 +1707,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_suggest_photo" = "Suggest Profile Photo";
"lng_profile_suggest_photo_from_clipboard" = "Suggest From Clipboard";
"lng_profile_set_photo_for" = "Set Profile Photo";
+"lng_profile_set_photo_for_group" = "Set Group Photo";
+"lng_profile_set_photo_for_channel" = "Set Channel Photo";
"lng_profile_set_photo_for_from_clipboard" = "Set From Clipboard";
"lng_profile_set_photo_for_about" = "You can replace {user}'s photo with another photo that only you will see.";
"lng_profile_photo_reset" = "Reset to Original";
+"lng_profile_photo_reset_button" = "Reset";
"lng_profile_photo_reset_sure" = "Are you sure you want to reset {user}'s photo to the original?";
"lng_profile_photo_from_clipboard" = "From clipboard";
"lng_profile_suggest_sure" = "You can suggest {user} to set this photo for their Telegram profile.";
@@ -1668,6 +1725,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_changed_photo_title" = "Photo updated";
"lng_profile_changed_photo_about" = "You can change it in {link}.";
"lng_profile_changed_photo_link" = "Settings";
+
+"lng_profile_action_short_message" = "Message";
+"lng_profile_action_short_channel" = "Channel";
+"lng_profile_action_short_mute" = "Mute";
+"lng_profile_action_short_unmute" = "Unmute";
+"lng_profile_action_short_call" = "Call";
+"lng_profile_action_short_discuss" = "Discuss";
+"lng_profile_action_short_gift" = "Gift";
+"lng_profile_action_short_join" = "Join";
+"lng_profile_action_short_report" = "Report";
+"lng_profile_action_short_leave" = "Leave";
+"lng_profile_action_short_more" = "More";
+"lng_profile_action_short_manage" = "Manage";
+
"lng_media_type_photos" = "Photos";
"lng_media_type_gifs" = "GIFs";
"lng_media_type_videos" = "Videos";
@@ -1687,6 +1758,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_block_user" = "Block user";
"lng_profile_unblock_user" = "Unblock user";
"lng_profile_export_chat" = "Export chat history";
+"lng_profile_export_topic" = "Export topic history";
"lng_profile_gift_premium" = "Gift Premium";
"lng_media_selected_photo#one" = "{count} Photo";
"lng_media_selected_photo#other" = "{count} Photos";
@@ -2219,8 +2291,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_proximity_distance_km#other" = "{count} km";
"lng_action_webview_data_done" = "Data from the \"{text}\" button was transferred to the bot.";
"lng_action_gift_received" = "{user} sent you a gift for {cost}";
+"lng_action_gift_received_sold" = "{user} sold you a gift for {cost}";
"lng_action_gift_unique_received" = "{user} sent you a unique collectible item";
"lng_action_gift_sent" = "You sent a gift for {cost}";
+"lng_action_gift_sent_sold" = "You sold 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";
@@ -2246,6 +2320,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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_auction" = "You've successfully bought a gift in the auction for {cost}.";
+"lng_action_gift_auction_won" = "You won the auction with a bid of {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.";
@@ -2274,6 +2350,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_gift_premium_about" = "Subscription for exclusive Telegram features.";
"lng_action_gift_refunded" = "This gift was downgraded because a request to refund the payment related to this gift was made, and the money was returned.";
"lng_action_gift_got_ton" = "Use TON to suggest posts to channels.";
+"lng_action_gift_offer" = "{user} offered you {cost} for {name}.";
+"lng_action_gift_offer_you" = "You offered {cost} for {name}.";
+"lng_action_gift_offer_state_expires" = "This offer expires in {time}.";
+"lng_action_gift_offer_time_large" = "{hours} h";
+"lng_action_gift_offer_time_medium" = "{hours} h {minutes} m";
+"lng_action_gift_offer_time_small" = "{minutes} m";
+"lng_action_gift_offer_state_accepted" = "This offer was accepted.";
+"lng_action_gift_offer_state_rejected" = "This offer was rejected.";
+"lng_action_gift_offer_state_expired" = "This offer has expired.";
+"lng_action_gift_offer_sold" = "{user} sold {name} for {cost}.";
+"lng_action_gift_offer_sold_you" = "You sold {name} for {cost}.";
+"lng_action_gift_offer_decline" = "Reject";
+"lng_action_gift_offer_accept" = "Accept";
+"lng_action_gift_offer_expired" = "The offer from {user} to buy your {name} for {cost} has expired.";
+"lng_action_gift_offer_expired_your" = "Your offer to buy {name} for {cost} has expired.";
+"lng_action_gift_offer_declined" = "{user} rejected your offer to buy {name} for {cost}.";
+"lng_action_gift_offer_declined_you" = "You rejected {user}'s offer to buy your {name} for {cost}.";
"lng_action_suggested_photo_me" = "You suggested this photo for {user}'s Telegram profile.";
"lng_action_suggested_photo" = "{user} suggests this photo for your Telegram profile.";
"lng_action_suggested_photo_button" = "View Photo";
@@ -2401,6 +2494,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_peer_gifts_filter_saved" = "Displayed";
"lng_peer_gifts_filter_unsaved" = "Hidden";
+"lng_premium_gift_duration_days#one" = "for {count} day";
+"lng_premium_gift_duration_days#other" = "for {count} days";
"lng_premium_gift_duration_months#one" = "for {count} month";
"lng_premium_gift_duration_months#other" = "for {count} months";
"lng_premium_gift_duration_years#one" = "for {count} year";
@@ -2578,6 +2673,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edited" = "edited";
"lng_commented" = "commented";
"lng_approximate" = "appx.";
+"lng_repeated_daily" = "daily";
+"lng_repeated_weekly" = "weekly";
+"lng_repeated_biweekly" = "biweekly";
+"lng_repeated_monthly" = "monthly";
+"lng_repeated_every_month#one" = "{count}-monthly";
+"lng_repeated_every_month#other" = "{count}-monthly";
+"lng_repeated_yearly" = "yearly";
"lng_edited_date" = "Edited: {date}";
"lng_sent_date" = "Sent: {date}";
"lng_approximate_about" = "Estimated date of video publishing.";
@@ -2696,8 +2798,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_summary_title_subscribed" = "You are all set!";
"lng_premium_summary_subtitle_gift#one" = "{user} has gifted you a {count}-month subscription to Telegram Premium.";
"lng_premium_summary_subtitle_gift#other" = "{user} has gifted you a {count}-months subscription to Telegram Premium.";
+"lng_premium_summary_subtitle_gift_days#one" = "{user} has gifted you a {count}-day subscription to Telegram Premium.";
+"lng_premium_summary_subtitle_gift_days#other" = "{user} has gifted you a {count}-days subscription to Telegram Premium.";
"lng_premium_summary_subtitle_gift_me#one" = "You gifted {user} a {count}-month subscription to Telegram Premium.";
"lng_premium_summary_subtitle_gift_me#other" = "You gifted {user} a {count}-months subscription to Telegram Premium.";
+"lng_premium_summary_subtitle_gift_days_me#one" = "You gifted {user} a {count}-month subscription to Telegram Premium.";
+"lng_premium_summary_subtitle_gift_days_me#other" = "You gifted {user} a {count}-months subscription to Telegram Premium.";
"lng_premium_summary_subtitle_wallpapers" = "Wallpapers for Both Sides";
"lng_premium_summary_about_wallpapers" = "Set custom wallpapers for you and your chat partner.";
"lng_premium_summary_subtitle_stories" = "Stories";
@@ -2742,6 +2848,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_summary_about_filter_tags" = "Display folder names for each chat in the chat list.";
"lng_premium_summary_subtitle_todo_lists" = "Checklists";
"lng_premium_summary_about_todo_lists" = "Plan, assign, and complete tasks - seamlessly and efficiently.";
+"lng_premium_summary_subtitle_peer_colors" = "Name and Profile Colors";
+"lng_premium_summary_about_peer_colors" = "Choose a color and logo for your profile and replies to your messages.";
+"lng_premium_summary_subtitle_gifts" = "Telegram Gifts";
+"lng_premium_summary_about_gifts" = "Gifts are collectible items you can trade or showcase on your profile.";
"lng_premium_summary_bottom_subtitle" = "About Telegram Premium";
"lng_premium_summary_bottom_about" = "While the free version of Telegram already gives its users more than any other messaging application, **Telegram Premium** pushes its capabilities even further.\n\n**Telegram Premium** is a paid option, because most Premium Features require additional expenses from Telegram to third parties such as data center providers and server manufacturers. Contributions from **Telegram Premium** users allow us to cover such costs and also help Telegram stay free for everyone.";
"lng_premium_summary_button" = "Subscribe for {cost} per month";
@@ -2892,6 +3002,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_summary_history_entry_inner_in" = "In-App Purchase";
"lng_credits_summary_balance" = "Balance";
"lng_credits_commission" = "{amount} commission";
+"lng_credits_paid_messages_fee_live_reaction" = "Fee for Live Story Reaction";
"lng_credits_paid_messages_fee#one" = "Fee for {count} Message";
"lng_credits_paid_messages_fee#other" = "Fee for {count} Messages";
"lng_credits_paid_messages_fee_about" = "You receive {percent} of the price that you charge for each incoming message. {link}";
@@ -3023,11 +3134,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_small_balance_title#other" = "{count} Stars Needed";
"lng_credits_small_balance_about" = "Buy **Stars** and use them on **{bot}** and other miniapps.";
"lng_credits_small_balance_reaction" = "Buy **Stars** and send them to {channel} to support their posts.";
+"lng_credits_small_balance_video_stream" = "Buy **Stars** to send them to {name} to support their stream.";
"lng_credits_small_balance_subscribe" = "Buy **Stars** and subscribe to **{channel}** and other channels.";
"lng_credits_small_balance_star_gift" = "Buy **Stars** to send gifts to {user} and other contacts.";
"lng_credits_small_balance_for_message" = "Buy **Stars** to send messages to {user}.";
"lng_credits_small_balance_for_messages" = "Buy **Stars** to send messages.";
"lng_credits_small_balance_for_suggest" = "Buy **Stars** to suggest post to {channel}.";
+"lng_credits_small_balance_for_offer" = "Buy **Stars** to offer for this gift.";
"lng_credits_small_balance_for_search" = "Buy **Stars** to search through public posts.";
"lng_credits_small_balance_fallback" = "Buy **Stars** to unlock content and services on Telegram.";
"lng_credits_purchase_blocked" = "Sorry, you can't purchase this item with Telegram Stars.";
@@ -3351,6 +3464,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_feature_custom_emoji_pack" = "Custom Emoji Pack";
"lng_feature_transcribe" = "Voice-to-Text Conversion";
"lng_feature_autotranslate" = "Autotranslation of Messages";
+"lng_feature_profile_color_channel#one" = "**{count}** Color for Channel Cover";
+"lng_feature_profile_color_channel#other" = "**{count}** Colors for Channel Cover";
+"lng_feature_profile_color_group#one" = "**{count}** Color for Group Cover";
+"lng_feature_profile_color_group#other" = "**{count}** Colors for Group Cover";
+"lng_feature_profile_icon_channel" = "Custom Logo for Channel Cover";
+"lng_feature_profile_icon_group" = "Custom Logo for Group Cover";
"lng_edit_topics_enable" = "Enable Topics";
"lng_edit_topics_about" = "The group chat will be divided into topics created by admins or users.";
@@ -3616,11 +3735,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_stars_resale" = "resale";
"lng_gift_stars_on_sale" = "on sale";
"lng_gift_stars_premium" = "premium";
+"lng_gift_stars_auction" = "auction";
+"lng_gift_stars_auction_join" = "Join";
+"lng_gift_stars_auction_view" = "View";
+"lng_gift_stars_auction_soon" = "soon";
+"lng_gift_stars_auction_upgraded" = "upgraded";
"lng_gift_stars_your_left#one" = "{count} left";
"lng_gift_stars_your_left#other" = "{count} left";
"lng_gift_stars_your_finished" = "none left";
"lng_gift_stars_tabs_all" = "All Gifts";
"lng_gift_stars_tabs_my" = "My Gifts";
+"lng_gift_stars_tabs_my_empty" = "You don't have any gifts you can use as a profile cover.";
+"lng_gift_stars_tabs_my_empty_next" = "Browse gifts available for purchase {emoji}";
"lng_gift_stars_tabs_collectibles" = "Collectibles";
"lng_gift_send_title" = "Send a Gift";
"lng_gift_send_message" = "Enter Message";
@@ -3782,6 +3908,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_upgrade_tradable_about" = "Sell or auction your gift on third-party NFT marketplaces.";
"lng_gift_upgrade_tradable_about_user" = "{name} will be able to sell the gift on Telegram and NFT marketplaces.";
"lng_gift_upgrade_tradable_about_channel" = "Admins of {name} will be able to sell the gift on Telegram and NFT marketplaces.";
+"lng_gift_upgrade_wearable_title" = "Wearable";
+"lng_gift_upgrade_wearable_about" = "Display gifts on your page and set them as profile covers or statuses.";
"lng_gift_upgrade_button" = "Upgrade for {price}";
"lng_gift_upgrade_decreases" = "Price decreases in {time}";
"lng_gift_upgrade_see_table" = "See how this price will decrease {arrow}";
@@ -3834,6 +3962,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_transfer_unlist" = "Unlist";
"lng_gift_transfer_locked_title" = "Action Locked";
"lng_gift_transfer_locked_text" = "Transfer this gift to your Telegram account on Fragment to unlock this action.";
+"lng_gift_offer_button" = "Offer to Buy";
+"lng_gift_offer_title" = "Offer to Buy";
+"lng_gift_offer_stars_about" = "Choose how many Stars you'd like to offer for {name}.";
+"lng_gift_offer_ton_about" = "Choose how many TON you'd like to offer for {name}.";
+"lng_gift_offer_duration" = "Offer Duration";
+"lng_gift_offer_duration_about" = "Choose how long {user} can accept your offer. When the time expires, the amount will be refunded.";
+"lng_gift_offer_cost_button" = "Offer {cost}";
+"lng_gift_offer_reject_title" = "Reject Offer";
+"lng_gift_offer_confirm_reject" = "Are you sure you want to reject the offer from {user}?";
+"lng_gift_offer_confirm_accept" = "Do you want to sell {name} to {user} for {cost}?";
+"lng_gift_offer_you_get" = "You will receive {cost} after fees.";
+"lng_gift_offer_higher" = "The price you are offered is {percent} higher than the average price for {name}.";
+"lng_gift_offer_lower" = "The price you are offered is {percent} lower than the average price for {name}.";
+"lng_gift_offer_sell_for" = "Sell for {price}";
+"lng_gift_offer_confirm_title" = "Confirm Offer";
+"lng_gift_offer_confirm_text" = "Do you want to offer {cost} to {user} for {name}?";
+"lng_gift_offer_table_offer" = "Offer";
+"lng_gift_offer_table_fee" = "Fee";
+"lng_gift_offer_table_duration" = "Duration";
"lng_gift_sell_unlist_title" = "Unlist {name}";
"lng_gift_sell_unlist_sure" = "Are you sure you want to unlist your gift?";
"lng_gift_sell_title" = "Price in Stars";
@@ -3861,6 +4008,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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_design_title" = "Unique Profile Design";
+"lng_gift_wear_design_about" = "Your profile page will get the color and the symbol of this item.";
+"lng_gift_wear_design_about_channel" = "Your channel page will get the color and the symbol of this item.";
"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.";
@@ -3917,6 +4067,138 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_collection_remove_from" = "Remove from Collection";
"lng_gift_locked_title" = "Gift Locked";
+"lng_auction_about_title" = "Auction";
+"lng_auction_about_subtitle" = "Join the battle for exclusive gifts.";
+"lng_auction_about_top_title#one" = "Top {count} Bidder";
+"lng_auction_about_top_title#other" = "Top {count} Bidders";
+"lng_auction_about_top_rounds#one" = "{count} round";
+"lng_auction_about_top_rounds#other" = "{count} rounds";
+"lng_auction_about_top_bidders#one" = "top {count} bidder";
+"lng_auction_about_top_bidders#other" = "top {count} bidders";
+"lng_auction_about_top_about#one" = "{count} gift is dropped in {rounds} to the {bidders} by bid amount.";
+"lng_auction_about_top_about#other" = "{count} gifts are dropped in {rounds} to the {bidders} by bid amount.";
+"lng_auction_about_top_short#one" = "{count} gift is dropped to the {bidders} by bid amount. {link}";
+"lng_auction_about_top_short#other" = "{count} gifts are dropped to the {bidders} by bid amount. {link}";
+"lng_auction_about_bid_title" = "Bid Carryover";
+"lng_auction_about_bid_about#one" = "If your bid leaves the top {count}, it will automatically join the next round.";
+"lng_auction_about_bid_about#other" = "If your bid leaves the top {count}, it will automatically join the next round.";
+"lng_auction_about_missed_title" = "Missed Bidders";
+"lng_auction_about_missed_about" = "If your bid doesn't win after the final round, your Stars will be fully refunded.";
+"lng_auction_about_understood" = "Understood";
+"lng_auction_text#one" = "Top **{count}** bidder will get {name} gifts this round. {link}";
+"lng_auction_text#other" = "Top **{count}** bidders will get {name} gifts this round. {link}";
+"lng_auction_text_link" = "Learn more {arrow}";
+"lng_auction_text_ended" = "Auction ended.";
+"lng_auction_start_label" = "Started";
+"lng_auction_starts_label" = "Starts";
+"lng_auction_rounds_label" = "Rounds";
+"lng_auction_rounds_exact" = "Round {n}";
+"lng_auction_rounds_range" = "Rounds {n}-{last}";
+"lng_auction_rounds_seconds#one" = "{count} minute each";
+"lng_auction_rounds_seconds#other" = "{count} minutes each";
+"lng_auction_rounds_minutes#one" = "{count} minute each";
+"lng_auction_rounds_minutes#other" = "{count} minutes each";
+"lng_auction_rounds_hours#one" = "{count} hour each";
+"lng_auction_rounds_hours#other" = "{count} hours each";
+"lng_auction_rounds_extended" = "{duration} + {increase} for late bids in top {n}";
+"lng_auction_end_label" = "Ends";
+"lng_auction_round_label" = "Current Round";
+"lng_auction_round_value" = "{n} of {amount}";
+"lng_auction_average_label" = "Average Price";
+"lng_auction_average_tooltip" = "{amount} is the average sale price for {gift} gifts.";
+"lng_auction_availability_label" = "Availability";
+"lng_auction_availability_value" = "{n} of {amount} left";
+"lng_auction_bought#one" = "{count} {emoji} item bought {arrow}";
+"lng_auction_bought#other" = "{count} {emoji} items bought {arrow}";
+"lng_auction_join_button" = "Join Auction";
+"lng_auction_join_bid" = "Place a Bid";
+"lng_auction_join_time_left" = "{time} left";
+"lng_auction_join_time_medium" = "{hours} h {minutes} m";
+"lng_auction_join_time_small" = "{minutes} m";
+"lng_auction_join_starts_in" = "starts in {time}";
+"lng_auction_join_early_bid" = "Place an Early Bid";
+"lng_auction_menu_about" = "About";
+"lng_auction_menu_copy_link" = "Copy Link";
+"lng_auction_menu_share" = "Share";
+"lng_auction_bid_title" = "Place a Bid";
+"lng_auction_bid_title_early" = "Place an Early Bid";
+"lng_auction_bid_subtitle#one" = "Top {count} bidder will win";
+"lng_auction_bid_subtitle#other" = "Top {count} bidders will win";
+"lng_auction_bid_your" = "your bid";
+"lng_auction_bid_custom" = "click to bid more";
+"lng_auction_bid_threshold#one" = "TOP {count}";
+"lng_auction_bid_threshold#other" = "TOP {count}";
+"lng_auction_bid_minimal#one" = "minimum bid";
+"lng_auction_bid_minimal#other" = "minimum bid";
+"lng_auction_bid_until" = "until next round";
+"lng_auction_bid_left#one" = "left";
+"lng_auction_bid_left#other" = "left";
+"lng_auction_bid_before_start" = "before start";
+"lng_auction_bid_your_title" = "Your bid will be";
+"lng_auction_bid_your_outbid" = "You've been outbid";
+"lng_auction_bid_your_winning" = "You're winning";
+"lng_auction_bid_winners_title" = "Top winners";
+"lng_auction_bid_place" = "Place a {stars} Bid";
+"lng_auction_bid_increase" = "Add {stars} to Your Bid";
+"lng_auction_bid_placed_title" = "Your bid has been placed";
+"lng_auction_bid_increased_title" = "Your bid has been increased";
+"lng_auction_bid_done_text#one" = "If you fall below the **top {count}**, your bid will roll over to the next round.";
+"lng_auction_bid_done_text#other" = "If you fall below the **top {count}**, your bid will roll over to the next round.";
+"lng_auction_bid_custom_title" = "Custom Amount";
+"lng_auction_preview_left#one" = "{count} left";
+"lng_auction_preview_left#other" = "{count} left";
+"lng_auction_preview_join" = "Join";
+"lng_auctino_preview_finished" = "Finished";
+"lng_auction_preview_sold_out" = "Sold Out";
+"lng_auction_preview_view_results" = "View Results";
+"lng_auction_bar_active" = "Active Auction";
+"lng_auction_bar_active_many#one" = "{count} Active Auction";
+"lng_auction_bar_active_many#other" = "{count} Active Auctions";
+"lng_auction_bar_winning#one" = "You're winning ({count}st place).";
+"lng_auction_bar_winning#other" = "You're winning ({count}th place).";
+"lng_auction_bar_outbid" = "You've been outbid.";
+"lng_auction_bar_winning_all" = "You're winning in all of them.";
+"lng_auction_bar_outbid_some#one" = "You've been outbid in {count} of them.";
+"lng_auction_bar_outbid_some#other" = "You've been outbid in {count} of them.";
+"lng_auction_bar_outbid_all" = "You've been outbid in all of them.";
+"lng_auction_bar_view" = "View";
+"lng_auction_bar_round" = "Round {n} of {amount}";
+"lng_auction_bar_bid_ranked" = "Your bid **{stars}** is ranked **#{n}**";
+"lng_auction_bar_bid_outbid" = "Your bid **{stars}** is outbid";
+"lng_auction_bar_raise_bid" = "Raise Bid";
+"lng_auction_bought_title#one" = "{count} Item Bought";
+"lng_auction_bought_title#other" = "{count} Items Bought";
+"lng_auction_bought_date" = "Date";
+"lng_auction_bought_bid" = "Accepted Bid";
+"lng_auction_bought_in_round" = "{name} in round {n}";
+"lng_auction_change_title" = "Change Recipient";
+"lng_auction_change_button" = "Change";
+"lng_auction_change_already" = "You've already placed a bid on this gift for {name}.";
+"lng_auction_change_to" = "Do you want to raise your bid and change the recipient to {name}?";
+"lng_auction_change_already_me" = "You've already placed a bid on this gift for yourself.";
+"lng_auction_change_to_me" = "Do you want to raise your bid and change the recipient to yourself?";
+"lng_auction_preview_name" = "Upcoming Auction";
+"lng_auction_preview_learn_gifts" = "Learn more about Telegram Gifts {arrow}";
+"lng_auction_preview_variants#one" = "View {emoji} {count} Variant {arrow}";
+"lng_auction_preview_variants#other" = "View {emoji} {count} Variants {arrow}";
+"lng_auction_preview_random" = "Random Traits";
+"lng_auction_preview_selected" = "Selected Traits";
+"lng_auction_preview_randomize" = "Randomize Traits";
+"lng_auction_preview_model" = "model";
+"lng_auction_preview_models#one" = "This collectible features **{count}** unique model.";
+"lng_auction_preview_models#other" = "This collectible features **{count}** unique models.";
+"lng_auction_preview_models_button" = "Models";
+"lng_auction_preview_backdrop" = "backdrop";
+"lng_auction_preview_backdrops#one" = "This collectible features **{count}** unique backdrop.";
+"lng_auction_preview_backdrops#other" = "This collectible features **{count}** unique backdrops.";
+"lng_auction_preview_backdrops_button" = "Backdrops";
+"lng_auction_preview_symbol" = "symbol";
+"lng_auction_preview_symbols#one" = "This collectible features **{count}** unique symbol.";
+"lng_auction_preview_symbols#other" = "This collectible features **{count}** unique symbols.";
+"lng_auction_preview_symbols_button" = "Symbols";
+"lng_auction_preview_wear" = "More about wearing gifts {arrow}";
+"lng_auction_preview_free_upgrade" = "You can upgrade your gift for free, sell it on the market, or set it as your profile cover.";
+
"lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";
"lng_accounts_limit1#other" = "You have reached the limit of **{count}** connected accounts.";
@@ -4097,6 +4379,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_reminder_message" = "Set a reminder";
"lng_schedule_title" = "Send this message on...";
"lng_remind_title" = "Remind me on...";
+"lng_schedule_repeat_label" = "Repeat:";
+"lng_schedule_repeat_never" = "Never";
+"lng_schedule_repeat_daily" = "Daily";
+"lng_schedule_repeat_weekly" = "Weekly";
+"lng_schedule_repeat_biweekly" = "Biweekly";
+"lng_schedule_repeat_monthly" = "Monthly";
+"lng_schedule_repeat_every_month#one" = "Every {count} month";
+"lng_schedule_repeat_every_month#other" = "Every {count} month";
+"lng_schedule_repeat_yearly" = "Yearly";
+"lng_schedule_repeat_promo" = "Subscribe to {link} to schedule repeating messages.";
+"lng_schedule_repeat_promo_link" = "Telegram Premium";
"lng_schedule_at" = "at";
"lng_message_ph" = "Write a message...";
"lng_broadcast_ph" = "Broadcast a message...";
@@ -4104,6 +4397,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_send_anonymous_ph" = "Send anonymously...";
"lng_story_reply_ph" = "Reply privately...";
"lng_story_comment_ph" = "Comment story...";
+"lng_video_stream_comment_ph" = "Comment";
+"lng_video_stream_comment_paid_ph#one" = "Comment for {count} Star";
+"lng_video_stream_comment_paid_ph#other" = "Comment for {count} Stars";
+"lng_video_stream_comments_disabled" = "Comments disabled.";
+"lng_video_stream_stars" = "Add Stars to highlight your comment";
+"lng_video_stream_live" = "LIVE";
+"lng_video_stream_watched#one" = "{count} watching";
+"lng_video_stream_watched#other" = "{count} watching";
+"lng_video_stream_edit_stars" = "Edit Stars";
+"lng_video_stream_remove_stars" = "Remove Stars";
"lng_message_stars_ph#one" = "Message for {count} Star";
"lng_message_stars_ph#other" = "Message for {count} Stars";
"lng_send_text_no" = "Text not allowed.";
@@ -4508,6 +4811,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_seen_reacted_none" = "Nobody Reacted";
"lng_context_seen_reacted_all" = "Show All Reactions";
"lng_context_sent_by" = "Sent by {user}";
+"lng_context_sent_today" = "Sent today at {time}";
+"lng_context_sent_yesterday" = "Sent yesterday at {time}";
+"lng_context_sent_date" = "Sent {date} at {time}";
"lng_context_set_as_quick" = "Set As Quick";
"lng_context_filter_by_tag" = "Filter by Tag";
"lng_context_tag_add_name" = "Add Name";
@@ -4542,6 +4848,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_message_tagged_with" = "Message tagged with {emoji}";
"lng_tagged_view_saved" = "View";
+"lng_add_channel_to_filter_selector" = "You can add a channel to your folder";
+"lng_add_group_to_filter_selector" = "You can add a group to your folder";
+
"lng_context_animated_emoji" = "This message contains emoji from **{name} pack**.";
"lng_context_animated_emoji_many#one" = "This message contains emoji from **{count} pack**.";
"lng_context_animated_emoji_many#other" = "This message contains emoji from **{count} packs**.";
@@ -4591,6 +4900,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_paid_react_send" = "Send {price}";
"lng_paid_react_agree" = "By sending stars, you agree to the {link}.";
"lng_paid_react_agree_link" = "Terms of Service";
+"lng_paid_react_admin_cant" = "You can't send Stars to your own Live Story.";
"lng_paid_react_toast#one" = "Star Sent!";
"lng_paid_react_toast#other" = "Stars Sent!";
"lng_paid_react_toast_anonymous#one" = "Star sent anonymously!";
@@ -4601,6 +4911,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_paid_react_show_in_top" = "Show me in Top Senders";
"lng_paid_react_anonymous" = "Anonymous";
+"lng_paid_comment_title" = "Highlight and Pin";
+"lng_paid_comment_about" = "Highlight and pin your message by adding Stars for {name}.";
+"lng_paid_comment_button" = "Add {stars}";
+"lng_paid_comment_pin_about" = "pin in chat";
+"lng_paid_comment_limit_about#one" = "character";
+"lng_paid_comment_limit_about#other" = "characters";
+"lng_paid_comment_emoji_about#one" = "emoji";
+"lng_paid_comment_emoji_about#other" = "emoji";
+"lng_paid_reaction_title" = "React with Stars";
+"lng_paid_reaction_about" = "Highlight and pin your message by sending Stars to {name}.";
+"lng_paid_reaction_button" = "Send {stars}";
+"lng_paid_admin_title" = "Receive Stars from Viewers";
+"lng_paid_admin_about" = "Viewers can send you Star Reactions.";
+
"lng_sensitive_tag" = "18+";
"lng_sensitive_title" = "18+";
"lng_sensitive_text" = "This media may contain sensitive content suitable only for adults. Do you still want to view it?";
@@ -6093,12 +6417,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_export_option_contacts_about" = "If you allow access, contacts are continuously synced with Telegram. You can adjust this in Settings > Privacy & Security on mobile devices.";
"lng_export_option_stories" = "Story archive";
"lng_export_option_stories_about" = "All stories you posted from Telegram mobile apps.";
+"lng_export_option_profile_music" = "Music on Profiles";
+"lng_export_option_profile_music_about" = "All tracks you saved to your playlist.";
"lng_export_option_sessions" = "Active sessions";
"lng_export_option_sessions_about" = "We may store this to display your connected devices in Settings > Privacy & Security > Show all sessions.";
"lng_export_header_other" = "Other";
"lng_export_option_other" = "Miscellaneous data";
"lng_export_option_other_about" = "Other types of data not mentioned above (beta).";
"lng_export_header_chats" = "Chat export settings";
+"lng_export_header_topic" = "Topic export settings";
"lng_export_option_personal_chats" = "Personal chats";
"lng_export_option_bot_chats" = "Bot chats";
"lng_export_option_private_groups" = "Private groups";
@@ -6593,6 +6920,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stories_my_name" = "My Story";
"lng_stories_archive" = "Hide Stories";
"lng_stories_unarchive" = "Unhide Stories";
+"lng_stories_view_anonymously" = "View Anonymously";
"lng_stories_row_count#one" = "{count} Story";
"lng_stories_row_count#other" = "{count} Stories";
"lng_stories_views#one" = "{count} view";
@@ -6687,6 +7015,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stealth_mode_next_about" = "Hide my views for the next 25 minutes.";
"lng_stealth_mode_unlock" = "Unlock Stealth Mode";
"lng_stealth_mode_enable" = "Enable Stealth Mode";
+"lng_stealth_mode_enable_and_open" = "Enable and open the story";
"lng_stealth_mode_cooldown_in" = "Available in {left}";
"lng_stealth_mode_cooldown_tip" = "Please wait until **Stealth Mode** is ready to use again.";
"lng_stealth_mode_enabled_tip_title" = "Stealth Mode On";
@@ -6696,6 +7025,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stealth_mode_already_about" = "The creators of stories you view in the next **{left}** won't see you in the viewers' lists.";
"lng_stories_link_invalid" = "This link is broken or has expired.";
+"lng_stories_live_finished" = "The live story has ended.";
"lng_stats_title" = "Statistics";
"lng_stats_message_title" = "Message Statistic";
diff --git a/Telegram/Resources/qrc/telegram/animations.qrc b/Telegram/Resources/qrc/telegram/animations.qrc
index 363c9e924a..34e0b4591e 100644
--- a/Telegram/Resources/qrc/telegram/animations.qrc
+++ b/Telegram/Resources/qrc/telegram/animations.qrc
@@ -45,6 +45,15 @@
../../animations/photo_suggest_icon.tgs
../../animations/toast/saved_messages.tgs
../../animations/toast/tagged.tgs
+ ../../animations/my_gifts_empty.tgs
+ ../../animations/toast/chats_filter_in.tgs
+ ../../animations/rtmp.tgs
+ ../../animations/show_or_premium_lastseen.tgs
+ ../../animations/show_or_premium_readtime.tgs
+ ../../animations/passkeys.tgs
+
+ ../../animations/profile/profile_muting.tgs
+ ../../animations/profile/profile_unmuting.tgs
../../animations/dice/dice_idle.tgs
../../animations/dice/dart_idle.tgs
diff --git a/Telegram/Resources/qrc/telegram/export.qrc b/Telegram/Resources/qrc/telegram/export.qrc
index 290d24a30b..e3656ae944 100644
--- a/Telegram/Resources/qrc/telegram/export.qrc
+++ b/Telegram/Resources/qrc/telegram/export.qrc
@@ -31,6 +31,8 @@
../../export_html/images/section_contacts@2x.png
../../export_html/images/section_frequent.png
../../export_html/images/section_frequent@2x.png
+ ../../export_html/images/section_music.png
+ ../../export_html/images/section_music@2x.png
../../export_html/images/section_other.png
../../export_html/images/section_other@2x.png
../../export_html/images/section_photos.png
diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml
index a237a7a381..a2a0a88f9d 100644
--- a/Telegram/Resources/uwp/AppX/AppxManifest.xml
+++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml
@@ -10,7 +10,7 @@
+ Version="6.3.6.0" />
Telegram Desktop
Telegram Messenger LLP
diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc
index 377039706d..10970299d8 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 6,2,4,0
- PRODUCTVERSION 6,2,4,0
+ FILEVERSION 6,3,6,0
+ PRODUCTVERSION 6,3,6,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
- VALUE "FileVersion", "6.2.4.0"
+ VALUE "FileVersion", "6.3.6.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "6.2.4.0"
+ VALUE "ProductVersion", "6.3.6.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc
index 6d075b5aed..2a5ec310d1 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 6,2,4,0
- PRODUCTVERSION 6,2,4,0
+ FILEVERSION 6,3,6,0
+ PRODUCTVERSION 6,3,6,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater"
- VALUE "FileVersion", "6.2.4.0"
+ VALUE "FileVersion", "6.3.6.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "6.2.4.0"
+ VALUE "ProductVersion", "6.3.6.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/SourceFiles/api/api_bot.cpp b/Telegram/SourceFiles/api/api_bot.cpp
index 05c0d46928..5eeddb0a18 100644
--- a/Telegram/SourceFiles/api/api_bot.cpp
+++ b/Telegram/SourceFiles/api/api_bot.cpp
@@ -400,7 +400,7 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
}
}
const auto replyTo = FullReplyTo();
- const auto suggest = SuggestPostOptions();
+ const auto suggest = SuggestOptions();
Window::PeerMenuCreatePoll(
controller,
item->history()->peer,
diff --git a/Telegram/SourceFiles/api/api_common.cpp b/Telegram/SourceFiles/api/api_common.cpp
index 55017ade84..9e86c94abf 100644
--- a/Telegram/SourceFiles/api/api_common.cpp
+++ b/Telegram/SourceFiles/api/api_common.cpp
@@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Api {
-MTPSuggestedPost SuggestToMTP(SuggestPostOptions suggest) {
+MTPSuggestedPost SuggestToMTP(SuggestOptions suggest) {
using Flag = MTPDsuggestedPost::Flag;
return suggest.exists
? MTP_suggestedPost(
diff --git a/Telegram/SourceFiles/api/api_common.h b/Telegram/SourceFiles/api/api_common.h
index bbbff2b0cc..44233354be 100644
--- a/Telegram/SourceFiles/api/api_common.h
+++ b/Telegram/SourceFiles/api/api_common.h
@@ -19,12 +19,13 @@ namespace Api {
inline constexpr auto kScheduledUntilOnlineTimestamp = TimeId(0x7FFFFFFE);
-[[nodiscard]] MTPSuggestedPost SuggestToMTP(SuggestPostOptions suggest);
+[[nodiscard]] MTPSuggestedPost SuggestToMTP(SuggestOptions suggest);
struct SendOptions {
uint64 price = 0;
PeerData *sendAs = nullptr;
TimeId scheduled = 0;
+ TimeId scheduleRepeatPeriod = 0;
BusinessShortcutId shortcutId = 0;
EffectId effectId = 0;
int starsApproved = 0;
@@ -33,7 +34,7 @@ struct SendOptions {
bool invertCaption = false;
bool hideViaBot = false;
crl::time ttlSeconds = 0;
- SuggestPostOptions suggest;
+ SuggestOptions suggest;
friend inline bool operator==(
const SendOptions &,
diff --git a/Telegram/SourceFiles/api/api_credits_history_entry.cpp b/Telegram/SourceFiles/api/api_credits_history_entry.cpp
index dbf616471d..2aa3423e85 100644
--- a/Telegram/SourceFiles/api/api_credits_history_entry.cpp
+++ b/Telegram/SourceFiles/api/api_credits_history_entry.cpp
@@ -146,6 +146,8 @@ Data::CreditsHistoryEntry CreditsHistoryEntryFromTL(
? starrefAmount
: CreditsAmount()),
.paidMessagesCommission = paidMessagesCount ? starrefCommission : 0,
+ .limitedCount = parsedGift ? parsedGift->limitedCount : 0,
+ .limitedLeft = parsedGift ? parsedGift->limitedLeft : 0,
.starsConverted = int(nonUniqueGift
? nonUniqueGift->vconvert_stars().v
: 0),
diff --git a/Telegram/SourceFiles/api/api_editing.cpp b/Telegram/SourceFiles/api/api_editing.cpp
index e3ec52e172..c3afa0b728 100644
--- a/Telegram/SourceFiles/api/api_editing.cpp
+++ b/Telegram/SourceFiles/api/api_editing.cpp
@@ -154,6 +154,7 @@ mtpRequestId SuggestMedia(
MTPReplyMarkup(),
sentEntities,
MTPint(), // schedule_date
+ MTPint(), // schedule_repeat_period
MTPInputPeer(), // send_as
MTPInputQuickReplyShortcut(), // quick_reply_shortcut
MTPlong(), // effect
@@ -295,6 +296,9 @@ mtpRequestId EditMessage(
| (options.scheduled
? MTPmessages_EditMessage::Flag::f_schedule_date
: emptyFlag)
+ | ((options.scheduled && options.scheduleRepeatPeriod)
+ ? MTPmessages_EditMessage::Flag::f_schedule_repeat_period
+ : emptyFlag)
| (item->isBusinessShortcut()
? MTPmessages_EditMessage::Flag::f_quick_reply_shortcut_id
: emptyFlag);
@@ -313,6 +317,7 @@ mtpRequestId EditMessage(
MTPReplyMarkup(),
sentEntities,
MTP_int(options.scheduled),
+ MTP_int(options.scheduleRepeatPeriod),
MTP_int(item->shortcutId())
)).done([=](
const MTPUpdates &result,
diff --git a/Telegram/SourceFiles/api/api_global_privacy.cpp b/Telegram/SourceFiles/api/api_global_privacy.cpp
index 0beb421833..3dbce0425a 100644
--- a/Telegram/SourceFiles/api/api_global_privacy.cpp
+++ b/Telegram/SourceFiles/api/api_global_privacy.cpp
@@ -262,6 +262,9 @@ void GlobalPrivacy::update(
: DisallowedFlag())
| ((disallowedGiftTypes & DisallowedGiftType::Unique)
? DisallowedFlag::f_disallow_unique_stargifts
+ : DisallowedFlag())
+ | ((disallowedGiftTypes & DisallowedGiftType::FromChannels)
+ ? DisallowedFlag::f_disallow_stargifts_from_channels
: DisallowedFlag());
const auto typesWas = _disallowedGiftTypes.current();
const auto typesChanged = (typesWas != disallowedGiftTypes);
@@ -322,6 +325,9 @@ void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) {
| (disallow.is_disallow_premium_gifts()
? DisallowedGiftType::Premium
: DisallowedGiftType())
+ | (disallow.is_disallow_stargifts_from_channels()
+ ? DisallowedGiftType::FromChannels
+ : DisallowedGiftType())
| (data.is_display_gifts_button()
? DisallowedGiftType::SendHide
: DisallowedGiftType());
diff --git a/Telegram/SourceFiles/api/api_global_privacy.h b/Telegram/SourceFiles/api/api_global_privacy.h
index 7346f2ff00..dcd86edddc 100644
--- a/Telegram/SourceFiles/api/api_global_privacy.h
+++ b/Telegram/SourceFiles/api/api_global_privacy.h
@@ -25,11 +25,12 @@ enum class UnarchiveOnNewMessage {
};
enum class DisallowedGiftType : uchar {
- Limited = 0x01,
- Unlimited = 0x02,
- Unique = 0x04,
- Premium = 0x08,
- SendHide = 0x10,
+ Limited = 0x01,
+ Unlimited = 0x02,
+ Unique = 0x04,
+ FromChannels = 0x08,
+ Premium = 0x10,
+ SendHide = 0x20,
};
inline constexpr bool is_flag_type(DisallowedGiftType) { return true; }
diff --git a/Telegram/SourceFiles/api/api_peer_colors.cpp b/Telegram/SourceFiles/api/api_peer_colors.cpp
index 5f3fe12d20..330863d90d 100644
--- a/Telegram/SourceFiles/api/api_peer_colors.cpp
+++ b/Telegram/SourceFiles/api/api_peer_colors.cpp
@@ -9,7 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "data/data_peer.h"
+#include "window/themes/window_theme.h"
#include "ui/chat/chat_style.h"
+#include "ui/color_int_conversion.h"
namespace Api {
namespace {
@@ -20,8 +22,9 @@ constexpr auto kRequestEach = 3600 * crl::time(1000);
PeerColors::PeerColors(not_null api)
: _api(&api->instance())
-, _timer([=] { request(); }) {
+, _timer([=] { request(); requestProfile(); }) {
request();
+ requestProfile();
_timer.callEach(kRequestEach);
}
@@ -45,6 +48,24 @@ void PeerColors::request() {
}).send();
}
+void PeerColors::requestProfile() {
+ if (_profileRequestId) {
+ return;
+ }
+ _profileRequestId = _api.request(MTPhelp_GetPeerProfileColors(
+ MTP_int(_profileHash)
+ )).done([=](const MTPhelp_PeerColors &result) {
+ _profileRequestId = 0;
+ result.match([&](const MTPDhelp_peerColors &data) {
+ _profileHash = data.vhash().v;
+ applyProfile(data);
+ }, [](const MTPDhelp_peerColorsNotModified &) {
+ });
+ }).fail([=] {
+ _profileRequestId = 0;
+ }).send();
+}
+
std::vector PeerColors::suggested() const {
return _suggested.current();
}
@@ -76,21 +97,27 @@ const base::flat_map &PeerColors::requiredLevelsChannel() const {
return _requiredLevelsChannel;
}
-int PeerColors::requiredGroupLevelFor(PeerId channel, uint8 index) const {
+int PeerColors::requiredLevelFor(
+ PeerId channel,
+ uint8 index,
+ bool isMegagroup,
+ bool profile) const {
if (Data::DecideColorIndex(channel) == index) {
return 0;
- } else if (const auto i = _requiredLevelsGroup.find(index)
- ; i != end(_requiredLevelsGroup)) {
- return i->second;
}
- return 1;
-}
-
-int PeerColors::requiredChannelLevelFor(PeerId channel, uint8 index) const {
- if (Data::DecideColorIndex(channel) == index) {
- return 0;
- } else if (const auto i = _requiredLevelsChannel.find(index)
- ; i != end(_requiredLevelsChannel)) {
+ if (profile) {
+ const auto it = _profileColors.find(index);
+ if (it != end(_profileColors)) {
+ return isMegagroup
+ ? it->second.requiredLevelsGroup
+ : it->second.requiredLevelsChannel;
+ }
+ return 1;
+ }
+ const auto &levels = isMegagroup
+ ? _requiredLevelsGroup
+ : _requiredLevelsChannel;
+ if (const auto i = levels.find(index); i != end(levels)) {
return i->second;
}
return 1;
@@ -165,4 +192,87 @@ void PeerColors::apply(const MTPDhelp_peerColors &data) {
_suggested = std::move(suggested);
}
+void PeerColors::applyProfile(const MTPDhelp_peerColors &data) {
+ const auto parseColors = [](const MTPhelp_PeerColorSet &set) {
+ const auto toUint = [](const MTPint &c) {
+ return (uint32(1) << 24) | uint32(c.v);
+ };
+ return set.match([&](const MTPDhelp_peerColorSet &) {
+ LOG(("API Error: peerColorSet in profile colors result!"));
+ return Data::ColorProfileSet();
+ }, [&](const MTPDhelp_peerColorProfileSet &data) {
+ auto set = Data::ColorProfileSet();
+ set.palette.reserve(data.vpalette_colors().v.size());
+ set.bg.reserve(data.vbg_colors().v.size());
+ set.story.reserve(data.vstory_colors().v.size());
+ for (const auto &c : data.vpalette_colors().v) {
+ set.palette.push_back(Ui::ColorFromSerialized(toUint(c)));
+ }
+ for (const auto &c : data.vbg_colors().v) {
+ set.bg.push_back(Ui::ColorFromSerialized(toUint(c)));
+ }
+ for (const auto &c : data.vstory_colors().v) {
+ set.story.push_back(Ui::ColorFromSerialized(toUint(c)));
+ }
+ return set;
+ });
+ };
+
+ auto suggested = std::vector();
+ const auto &list = data.vcolors().v;
+ suggested.reserve(list.size());
+ for (const auto &color : list) {
+ const auto &data = color.data();
+ const auto colorIndexBare = data.vcolor_id().v;
+ if (colorIndexBare < 0 || colorIndexBare >= Ui::kColorIndexCount) {
+ LOG(("API Error: Bad color index: %1").arg(colorIndexBare));
+ continue;
+ }
+ const auto colorIndex = uint8(colorIndexBare);
+ auto result = ProfileColorOption();
+ result.isHidden = data.is_hidden();
+ if (const auto min = data.vgroup_min_level()) {
+ result.requiredLevelsGroup = min->v;
+ }
+ if (const auto min = data.vchannel_min_level()) {
+ result.requiredLevelsChannel = min->v;
+ }
+ if (const auto light = data.vcolors()) {
+ result.data.light = parseColors(*light);
+ }
+ if (const auto dark = data.vdark_colors()) {
+ result.data.dark = parseColors(*dark);
+ }
+ _profileColors[colorIndex] = std::move(result);
+ }
+}
+
+std::optional PeerColors::colorProfileFor(
+ not_null peer) const {
+ if (const auto colorProfileIndex = peer->colorProfileIndex()) {
+ return colorProfileFor(*colorProfileIndex);
+ }
+ return std::nullopt;
+}
+
+std::optional PeerColors::colorProfileFor(
+ uint8 index) const {
+ const auto i = _profileColors.find(index);
+ if (i != end(_profileColors)) {
+ return Window::Theme::IsNightMode()
+ ? i->second.data.dark
+ : i->second.data.light;
+ }
+ return std::nullopt;
+}
+
+std::vector PeerColors::profileColorIndices() const {
+ auto result = std::vector();
+ result.reserve(_profileColors.size());
+ for (const auto &[index, option] : _profileColors) {
+ result.push_back(index);
+ }
+ return result;
+}
+
} // namespace Api
diff --git a/Telegram/SourceFiles/api/api_peer_colors.h b/Telegram/SourceFiles/api/api_peer_colors.h
index f8d379020b..690073d856 100644
--- a/Telegram/SourceFiles/api/api_peer_colors.h
+++ b/Telegram/SourceFiles/api/api_peer_colors.h
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/timer.h"
+#include "data/data_peer_colors.h"
#include "mtproto/sender.h"
class ApiWrap;
@@ -34,27 +35,45 @@ public:
[[nodiscard]] auto requiredLevelsChannel() const
-> const base::flat_map &;
- [[nodiscard]] int requiredGroupLevelFor(
- PeerId channel,
- uint8 index) const;
- [[nodiscard]] int requiredChannelLevelFor(
+ [[nodiscard]] int requiredLevelFor(
PeerId channel,
+ uint8 index,
+ bool isMegagroup,
+ bool profile) const;
+
+ [[nodiscard]] std::optional colorProfileFor(
+ not_null peer) const;
+ [[nodiscard]] std::optional colorProfileFor(
uint8 index) const;
+ [[nodiscard]] std::vector profileColorIndices() const;
+
private:
+ struct ProfileColorOption {
+ Data::ColorProfileData data;
+ int requiredLevelsChannel = 0;
+ int requiredLevelsGroup = 0;
+ bool isHidden = false;
+ };
+
void request();
+ void requestProfile();
void apply(const MTPDhelp_peerColors &data);
+ void applyProfile(const MTPDhelp_peerColors &data);
MTP::Sender _api;
int32 _hash = 0;
+ int32 _profileHash = 0;
mtpRequestId _requestId = 0;
+ mtpRequestId _profileRequestId = 0;
base::Timer _timer;
rpl::variable> _suggested;
base::flat_map _requiredLevelsGroup;
base::flat_map _requiredLevelsChannel;
rpl::event_stream<> _colorIndicesChanged;
std::unique_ptr _colorIndicesCurrent;
+ base::flat_map _profileColors;
};
diff --git a/Telegram/SourceFiles/api/api_polls.cpp b/Telegram/SourceFiles/api/api_polls.cpp
index b259be273a..06cc565aa4 100644
--- a/Telegram/SourceFiles/api/api_polls.cpp
+++ b/Telegram/SourceFiles/api/api_polls.cpp
@@ -66,6 +66,9 @@ void Polls::create(
}
if (action.options.scheduled) {
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
@@ -100,6 +103,7 @@ void Polls::create(
MTPReplyMarkup(),
MTPVector(),
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
MTP_long(action.options.effectId),
@@ -202,6 +206,7 @@ void Polls::close(not_null item) {
MTPReplyMarkup(),
MTPVector(),
MTP_int(0), // schedule_date
+ MTP_int(0), // schedule_repeat_period
MTPint() // quick_reply_shortcut_id
)).done([=](const MTPUpdates &result) {
_pollCloseRequestIds.erase(itemId);
diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp
index 562bdfa866..316681746a 100644
--- a/Telegram/SourceFiles/api/api_premium.cpp
+++ b/Telegram/SourceFiles/api/api_premium.cpp
@@ -36,7 +36,7 @@ namespace {
.giveawayId = data.vgiveaway_msg_id().value_or_empty(),
.date = data.vdate().v,
.used = data.vused_date().value_or_empty(),
- .months = data.vmonths().v,
+ .days = data.vdays().v,
.giveaway = data.is_via_giveaway(),
};
}
@@ -848,8 +848,22 @@ std::optional FromTL(
const auto releasedBy = releasedById
? session->data().peer(releasedById).get()
: nullptr;
+ const auto background = [&] {
+ if (!data.vbackground()) {
+ return std::shared_ptr();
+ }
+ const auto &fields = data.vbackground()->data();
+ using namespace Ui;
+ return std::make_shared(
+ Data::StarGiftBackground{
+ .center = ColorFromSerialized(fields.vcenter_color()),
+ .edge = ColorFromSerialized(fields.vedge_color()),
+ .text = ColorFromSerialized(fields.vtext_color()),
+ });
+ };
return std::optional(Data::StarGift{
.id = uint64(data.vid().v),
+ .background = background(),
.stars = int64(data.vstars().v),
.starsConverted = int64(data.vconvert_stars().v),
.starsToUpgrade = int64(data.vupgrade_stars().value_or_empty()),
@@ -858,10 +872,14 @@ std::optional FromTL(
.releasedBy = releasedBy,
.resellTitle = qs(data.vtitle().value_or_empty()),
.resellCount = int(data.vavailability_resale().value_or_empty()),
+ .auctionSlug = qs(data.vauction_slug().value_or_empty()),
+ .auctionGiftsPerRound = data.vgifts_per_round().value_or_empty(),
+ .auctionStartDate = data.vauction_start_date().value_or_empty(),
.limitedLeft = remaining.value_or_empty(),
.limitedCount = total.value_or_empty(),
.perUserTotal = data.vper_user_total().value_or_empty(),
.perUserRemains = data.vper_user_remains().value_or_empty(),
+ .upgradeVariants = data.vupgrade_variants().value_or_empty(),
.firstSaleDate = data.vfirst_sale_date().value_or_empty(),
.lastSaleDate = data.vlast_sale_date().value_or_empty(),
.lockedUntilDate = data.vlocked_until_date().value_or_empty(),
@@ -928,6 +946,7 @@ std::optional FromTL(
.themeUser = themeUser,
.nanoTonForResale = FindTonForResale(data.vresell_amount()),
.starsForResale = FindStarsForResale(data.vresell_amount()),
+ .starsMinOffer = data.voffer_min_stars().value_or(-1),
.number = data.vnum().v,
.onlyAcceptTon = data.is_resale_ton_only(),
.canBeTheme = data.is_theme_available(),
@@ -940,6 +959,8 @@ std::optional FromTL(
data.vvalue_currency().value_or_empty()),
.valuePrice = int64(
data.vvalue_amount().value_or_empty()),
+ .valuePriceUsd = int64(
+ data.vvalue_usd_amount().value_or_empty()),
})
: nullptr),
.peerColor = colorCollectible,
@@ -961,7 +982,7 @@ std::optional FromTL(
unique->originalDetails = FromTL(session, data);
});
}
- return std::make_optional(result);
+ return std::make_optional(std::move(result));
});
}
@@ -1007,6 +1028,7 @@ std::optional FromTL(
? peerFromMTP(*data.vfrom_id())
: PeerId()),
.date = data.vdate().v,
+ .giftNum = data.vgift_num().value_or_empty(),
.upgradeSeparate = data.is_upgrade_separate(),
.upgradable = data.is_can_upgrade(),
.anonymous = data.is_name_hidden(),
diff --git a/Telegram/SourceFiles/api/api_premium.h b/Telegram/SourceFiles/api/api_premium.h
index e3eb8f1e45..08b0f28b1b 100644
--- a/Telegram/SourceFiles/api/api_premium.h
+++ b/Telegram/SourceFiles/api/api_premium.h
@@ -30,11 +30,11 @@ struct GiftCode {
MsgId giveawayId = 0;
TimeId date = 0;
TimeId used = 0; // 0 if not used.
- int months = 0;
+ int days = 0;
bool giveaway = false;
explicit operator bool() const {
- return months != 0;
+ return days != 0;
}
friend inline bool operator==(
diff --git a/Telegram/SourceFiles/api/api_premium_option.cpp b/Telegram/SourceFiles/api/api_premium_option.cpp
index f5f0af380d..5cc9c9a125 100644
--- a/Telegram/SourceFiles/api/api_premium_option.cpp
+++ b/Telegram/SourceFiles/api/api_premium_option.cpp
@@ -36,7 +36,9 @@ Data::PremiumSubscriptionOption CreateSubscriptionOption(
.costNoDiscount = Ui::FillAmountAndCurrency(
monthlyAmount * months,
currency),
- .costTotal = Ui::FillAmountAndCurrency(amount, currency),
+ .costPerYear = Ui::FillAmountAndCurrency(
+ amount / float64(months / 12.),
+ currency),
.botUrl = botUrl,
};
}
diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp
index cbfa6a937d..a77cc1beb4 100644
--- a/Telegram/SourceFiles/api/api_sending.cpp
+++ b/Telegram/SourceFiles/api/api_sending.cpp
@@ -101,6 +101,9 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
@@ -136,6 +139,7 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
MTPReplyMarkup(),
MTPvector(),
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId),
@@ -207,6 +211,9 @@ void SendExistingMedia(
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
@@ -260,6 +267,7 @@ void SendExistingMedia(
MTPReplyMarkup(),
sentEntities,
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId),
@@ -392,6 +400,9 @@ bool SendDice(MessageToSend &message) {
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
@@ -445,6 +456,7 @@ bool SendDice(MessageToSend &message) {
MTPReplyMarkup(),
MTP_vector(),
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId),
diff --git a/Telegram/SourceFiles/api/api_suggest_post.cpp b/Telegram/SourceFiles/api/api_suggest_post.cpp
index 05d0304452..cb5aa52e3c 100644
--- a/Telegram/SourceFiles/api/api_suggest_post.cpp
+++ b/Telegram/SourceFiles/api/api_suggest_post.cpp
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "base/unixtime.h"
+#include "boxes/transfer_gift_box.h"
#include "chat_helpers/message_field.h"
#include "core/click_handler_types.h"
#include "data/components/credits.h"
@@ -44,7 +45,7 @@ void SendApproval(
not_null item,
TimeId scheduleDate = 0) {
using Flag = MTPmessages_ToggleSuggestedPostApproval::Flag;
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion
|| suggestion->accepted
|| suggestion->rejected
@@ -56,7 +57,7 @@ void SendApproval(
const auto session = &show->session();
const auto finish = [=] {
if (const auto item = session->data().message(id)) {
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (suggestion) {
suggestion->requestId = 0;
}
@@ -83,7 +84,7 @@ void ConfirmApproval(
not_null item,
TimeId scheduleDate = 0,
Fn accepted = nullptr) {
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion
|| suggestion->accepted
|| suggestion->rejected
@@ -244,7 +245,7 @@ void SendDecline(
not_null item,
const QString &comment) {
using Flag = MTPmessages_ToggleSuggestedPostApproval::Flag;
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion
|| suggestion->accepted
|| suggestion->rejected
@@ -256,7 +257,7 @@ void SendDecline(
const auto session = &show->session();
const auto finish = [=] {
if (const auto item = session->data().message(id)) {
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (suggestion) {
suggestion->requestId = 0;
}
@@ -365,10 +366,10 @@ void SendSuggest(
std::shared_ptr show,
not_null item,
std::shared_ptr state,
- Fn modify,
+ Fn modify,
Fn done = nullptr,
int starsApproved = 0) {
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
const auto id = item->fullId();
const auto withPaymentApproved = [=](int stars) {
if (const auto item = show->session().data().message(id)) {
@@ -416,7 +417,7 @@ void SendSuggest(
void SuggestApprovalDate(
std::shared_ptr show,
not_null item) {
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion) {
return;
}
@@ -437,7 +438,7 @@ void SuggestApprovalDate(
show,
item,
state,
- [=](SuggestPostOptions &options) { options.date = result; },
+ [=](SuggestOptions &options) { options.date = result; },
close);
};
using namespace HistoryView;
@@ -454,12 +455,12 @@ void SuggestApprovalDate(
void SuggestOfferForMessage(
std::shared_ptr show,
not_null item,
- SuggestPostOptions values,
+ SuggestOptions values,
HistoryView::SuggestMode mode) {
const auto id = item->fullId();
const auto state = std::make_shared();
const auto weak = std::make_shared>();
- const auto done = [=](SuggestPostOptions result) {
+ const auto done = [=](SuggestOptions result) {
const auto item = show->session().data().message(id);
if (!item) {
return;
@@ -473,7 +474,7 @@ void SuggestOfferForMessage(
show,
item,
state,
- [=](SuggestPostOptions &options) { options = result; },
+ [=](SuggestOptions &options) { options = result; },
close);
};
using namespace HistoryView;
@@ -490,7 +491,7 @@ void SuggestOfferForMessage(
void SuggestApprovalPrice(
std::shared_ptr show,
not_null item) {
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion) {
return;
}
@@ -504,6 +505,20 @@ void SuggestApprovalPrice(
}, SuggestMode::Change);
}
+void ConfirmGiftSaleAccept(
+ not_null window,
+ not_null item,
+ not_null suggestion) {
+ ShowGiftSaleAcceptBox(window, item, suggestion);
+}
+
+void ConfirmGiftSaleDecline(
+ not_null window,
+ not_null item,
+ not_null suggestion) {
+ ShowGiftSaleRejectBox(window, item, suggestion);
+}
+
} // namespace
std::shared_ptr AcceptClickHandler(
@@ -521,9 +536,11 @@ std::shared_ptr AcceptClickHandler(
return;
}
const auto show = controller->uiShow();
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion) {
return;
+ } else if (suggestion->gift) {
+ ConfirmGiftSaleAccept(controller, item, suggestion);
} else if (!suggestion->date) {
RequestApprovalDate(show, item);
} else {
@@ -546,7 +563,12 @@ std::shared_ptr DeclineClickHandler(
if (!item) {
return;
}
- RequestDeclineComment(controller->uiShow(), item);
+ const auto suggestion = item->Get();
+ if (suggestion && suggestion->gift) {
+ ConfirmGiftSaleDecline(controller, item, suggestion);
+ } else {
+ RequestDeclineComment(controller->uiShow(), item);
+ }
});
}
@@ -573,7 +595,7 @@ std::shared_ptr SuggestChangesClickHandler(
if (!item) {
return;
}
- const auto suggestion = item->Get();
+ const auto suggestion = item->Get();
if (!suggestion) {
return;
}
@@ -594,7 +616,7 @@ std::shared_ptr SuggestChangesClickHandler(
.messageId = FullMsgId(history->peer->id, item->id),
.monoforumPeerId = monoforumPeerId,
},
- SuggestPostOptions{
+ SuggestOptions{
.exists = uint32(1),
.priceWhole = uint32(suggestion->price.whole()),
.priceNano = uint32(suggestion->price.nano()),
diff --git a/Telegram/SourceFiles/api/api_todo_lists.cpp b/Telegram/SourceFiles/api/api_todo_lists.cpp
index 7471f55846..192df853bd 100644
--- a/Telegram/SourceFiles/api/api_todo_lists.cpp
+++ b/Telegram/SourceFiles/api/api_todo_lists.cpp
@@ -66,6 +66,9 @@ void TodoLists::create(
}
if (action.options.scheduled) {
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
@@ -100,6 +103,7 @@ void TodoLists::create(
MTPReplyMarkup(),
MTPVector(),
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
MTP_long(action.options.effectId),
diff --git a/Telegram/SourceFiles/api/api_toggling_media.cpp b/Telegram/SourceFiles/api/api_toggling_media.cpp
index 65d2ce317f..6c28df197d 100644
--- a/Telegram/SourceFiles/api/api_toggling_media.cpp
+++ b/Telegram/SourceFiles/api/api_toggling_media.cpp
@@ -24,7 +24,7 @@ void ToggleExistingMedia(
Data::FileOrigin origin,
ToggleRequestCallback toggleRequest,
DoneCallback &&done) {
- const auto api = &document->owner().session().api();
+ const auto api = &document->session().api();
auto performRequest = [=](const auto &repeatRequest) -> void {
const auto usedFileReference = document->fileReference();
diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp
index 3906d748fd..7e7025b2c5 100644
--- a/Telegram/SourceFiles/api/api_updates.cpp
+++ b/Telegram/SourceFiles/api/api_updates.cpp
@@ -23,12 +23,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_dc_options.h"
#include "data/business/data_shortcut_messages.h"
#include "data/components/credits.h"
+#include "data/components/gift_auctions.h"
#include "data/components/promo_suggestions.h"
#include "data/components/scheduled_messages.h"
#include "data/components/top_peers.h"
#include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h"
#include "data/data_saved_messages.h"
+#include "data/data_saved_sublist.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/data_chat.h"
@@ -42,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_histories.h"
#include "data/data_folder.h"
#include "data/data_forum.h"
+#include "data/data_forum_topic.h"
#include "data/data_send_action.h"
#include "data/data_stories.h"
#include "data/data_message_reactions.h"
@@ -1243,7 +1246,8 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
MTPFactCheck(),
MTPint(), // report_delivery_until_date
MTPlong(), // paid_message_stars
- MTPSuggestedPost()),
+ MTPSuggestedPost(),
+ MTPint()), // schedule_repeat_period
MessageFlags(),
NewMessageType::Unread);
} break;
@@ -1283,7 +1287,8 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
MTPFactCheck(),
MTPint(), // report_delivery_until_date
MTPlong(), // paid_message_stars
- MTPSuggestedPost()),
+ MTPSuggestedPost(),
+ MTPint()), // schedule_repeat_period
MessageFlags(),
NewMessageType::Unread);
} break;
@@ -1707,13 +1712,21 @@ void Updates::feedUpdate(const MTPUpdate &update) {
local->history()->peer,
local->date());
}
- local->setRealId(d.vid().v);
+ local->setRealId(newId);
+ if (const auto topic = local->topic()) {
+ topic->applyMaybeLast(local);
+ }
+ if (const auto sublist = local->savedSublist()) {
+ sublist->applyMaybeLast(local);
+ }
}
}
} else {
owner.histories().checkTopicCreated(id, newId);
}
session().data().unregisterMessageRandomId(randomId);
+ } else {
+ Core::App().calls().handleUpdate(&session(), update);
}
session().data().unregisterMessageSentData(randomId);
} break;
@@ -2151,7 +2164,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateGroupCallConnection:
case mtpc_updateGroupCall:
case mtpc_updateGroupCallMessage:
- case mtpc_updateGroupCallEncryptedMessage: {
+ case mtpc_updateGroupCallEncryptedMessage:
+ case mtpc_updateDeleteGroupCallMessages: {
Core::App().calls().handleUpdate(&session(), update);
} break;
@@ -2794,6 +2808,15 @@ void Updates::feedUpdate(const MTPUpdate &update) {
Api::ParsePaidReactionShownPeer(_session, data.vprivate()));
} break;
+ case mtpc_updateStarGiftAuctionState: {
+ const auto &data = update.c_updateStarGiftAuctionState();
+ _session->giftAuctions().apply(data);
+ } break;
+
+ case mtpc_updateStarGiftAuctionUserState: {
+ const auto &data = update.c_updateStarGiftAuctionUserState();
+ _session->giftAuctions().apply(data);
+ } break;
}
}
diff --git a/Telegram/SourceFiles/api/api_user_privacy.cpp b/Telegram/SourceFiles/api/api_user_privacy.cpp
index e07858dda7..9b968392f6 100644
--- a/Telegram/SourceFiles/api/api_user_privacy.cpp
+++ b/Telegram/SourceFiles/api/api_user_privacy.cpp
@@ -211,6 +211,7 @@ MTPInputPrivacyKey KeyToTL(UserPrivacy::Key key) {
case Key::Birthday: return MTP_inputPrivacyKeyBirthday();
case Key::GiftsAutoSave: return MTP_inputPrivacyKeyStarGiftsAutoSave();
case Key::NoPaidMessages: return MTP_inputPrivacyKeyNoPaidMessages();
+ case Key::SavedMusic: return MTP_inputPrivacyKeySavedMusic();
}
Unexpected("Key in Api::UserPrivacy::KetToTL.");
}
@@ -244,6 +245,8 @@ std::optional TLToKey(mtpTypeId type) {
case mtpc_inputPrivacyKeyStarGiftsAutoSave: return Key::GiftsAutoSave;
case mtpc_privacyKeyNoPaidMessages:
case mtpc_inputPrivacyKeyNoPaidMessages: return Key::NoPaidMessages;
+ case mtpc_privacyKeySavedMusic:
+ case mtpc_inputPrivacyKeySavedMusic: return Key::SavedMusic;
}
return std::nullopt;
}
diff --git a/Telegram/SourceFiles/api/api_user_privacy.h b/Telegram/SourceFiles/api/api_user_privacy.h
index 676e9be11d..42a5b1e946 100644
--- a/Telegram/SourceFiles/api/api_user_privacy.h
+++ b/Telegram/SourceFiles/api/api_user_privacy.h
@@ -33,6 +33,7 @@ public:
Birthday,
GiftsAutoSave,
NoPaidMessages,
+ SavedMusic,
};
enum class Option {
Everyone,
diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index fd9becfc29..10b077e301 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -805,8 +805,10 @@ QString ApiWrap::exportDirectStoryLink(not_null story) {
const auto peer = story->peer();
const auto fallback = [&] {
const auto base = peer->username();
- const auto story = QString::number(storyId.story);
- const auto query = base + "/s/" + story;
+ const auto id = story->call()
+ ? u"live"_q
+ : QString::number(storyId.story);
+ const auto query = base + "/s/" + id;
return session().createInternalLinkFull(query);
};
const auto i = _unlikelyStoryLinks.find(storyId);
@@ -1234,6 +1236,10 @@ void ApiWrap::gotUserFull(
void ApiWrap::requestPeerSettings(not_null peer) {
if (!_requestedPeerSettings.emplace(peer).second) {
return;
+ } else if (peer->isMonoforum()) {
+ peer->setBarSettings(PeerBarSettings());
+ _requestedPeerSettings.erase(peer);
+ return;
}
request(MTPmessages_GetPeerSettings(
peer->input
@@ -1245,6 +1251,7 @@ void ApiWrap::requestPeerSettings(not_null peer) {
_requestedPeerSettings.erase(peer);
});
}).fail([=] {
+ peer->setBarSettings(PeerBarSettings());
_requestedPeerSettings.erase(peer);
}).send();
}
@@ -1775,6 +1782,11 @@ void ApiWrap::joinChannel(not_null channel) {
)).done([=](const MTPUpdates &result) {
_channelAmInRequests.remove(channel);
applyUpdates(result);
+
+ session().data().addRecentJoinChat({
+ .fromPeerId = channel->id,
+ .joinedPeerId = channel->id,
+ });
}).fail([=](const MTP::Error &error) {
const auto &type = error.type();
@@ -3518,11 +3530,17 @@ void ApiWrap::forwardMessages(
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= SendFlag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= SendFlag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
sendFlags |= SendFlag::f_quick_reply_shortcut;
}
+ if (action.options.effectId) {
+ sendFlags |= SendFlag::f_effect;
+ }
if (draft.options != Data::ForwardOptions::PreserveInfo) {
sendFlags |= SendFlag::f_drop_author;
}
@@ -3585,8 +3603,10 @@ void ApiWrap::forwardMessages(
? MTP_inputReplyToMonoForum(monoforumPeer->input)
: MTPInputReplyTo()),
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
+ MTP_long(action.options.effectId),
MTPint(), // video_timestamp
MTP_long(starsPaid),
Api::SuggestToMTP(action.options.suggest)
@@ -4131,6 +4151,10 @@ void ApiWrap::sendMessage(
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date;
mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
+ if (action.options.scheduleRepeatPeriod) {
+ sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_repeat_period;
+ mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_repeat_period;
+ }
}
if (action.options.shortcutId) {
flags |= MessageFlag::ShortcutMessage;
@@ -4159,6 +4183,7 @@ void ApiWrap::sendMessage(
.from = NewMessageFromId(action),
.replyTo = action.replyTo,
.date = NewMessageDate(action.options),
+ .scheduleRepeatPeriod = action.options.scheduleRepeatPeriod,
.shortcutId = action.options.shortcutId,
.starsPaid = starsPaid,
.postAuthor = NewMessagePostAuthor(action),
@@ -4212,6 +4237,7 @@ void ApiWrap::sendMessage(
MTPReplyMarkup(),
sentEntities,
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
mtpShortcut,
MTP_long(action.options.effectId),
@@ -4232,6 +4258,7 @@ void ApiWrap::sendMessage(
MTPReplyMarkup(),
sentEntities,
MTP_int(action.options.scheduled),
+ MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
mtpShortcut,
MTP_long(action.options.effectId),
@@ -4552,6 +4579,9 @@ void ApiWrap::sendMediaWithRandomId(
: Flag(0))
| (!sentEntities.v.isEmpty() ? Flag::f_entities : Flag(0))
| (options.scheduled ? Flag::f_schedule_date : Flag(0))
+ | ((options.scheduled && options.scheduleRepeatPeriod)
+ ? Flag::f_schedule_repeat_period
+ : Flag(0))
| (options.sendAs ? Flag::f_send_as : Flag(0))
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0))
| (options.effectId ? Flag::f_effect : Flag(0))
@@ -4581,6 +4611,7 @@ void ApiWrap::sendMediaWithRandomId(
MTPReplyMarkup(),
sentEntities,
MTP_int(options.scheduled),
+ MTP_int(options.scheduleRepeatPeriod),
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, options.shortcutId),
MTP_long(options.effectId),
@@ -4639,6 +4670,9 @@ void ApiWrap::sendMultiPaidMedia(
: Flag(0))
| (!sentEntities.v.isEmpty() ? Flag::f_entities : Flag(0))
| (options.scheduled ? Flag::f_schedule_date : Flag(0))
+ | (options.scheduleRepeatPeriod
+ ? Flag::f_schedule_repeat_period
+ : Flag(0))
| (options.sendAs ? Flag::f_send_as : Flag(0))
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0))
| (options.effectId ? Flag::f_effect : Flag(0))
@@ -4667,6 +4701,7 @@ void ApiWrap::sendMultiPaidMedia(
MTPReplyMarkup(),
sentEntities,
MTP_int(options.scheduled),
+ MTP_int(options.scheduleRepeatPeriod),
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, options.shortcutId),
MTP_long(options.effectId),
@@ -4780,6 +4815,9 @@ void ApiWrap::sendAlbumIfReady(not_null album) {
? Flag::f_silent
: Flag(0))
| (album->options.scheduled ? Flag::f_schedule_date : Flag(0))
+ //| (album->options.scheduleRepeatPeriod
+ // ? Flag::f_schedule_repeat_period
+ // : Flag(0))
| (sendAs ? Flag::f_send_as : Flag(0))
| (album->options.shortcutId
? Flag::f_quick_reply_shortcut
@@ -4800,6 +4838,7 @@ void ApiWrap::sendAlbumIfReady(not_null album) {
Data::Histories::ReplyToPlaceholder(),
MTP_vector(medias),
MTP_int(album->options.scheduled),
+ //MTP_int(album->options.scheduleRepeatPeriod),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, album->options.shortcutId),
MTP_long(album->options.effectId),
diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp
index 6e9bc23955..72e71e0ba7 100644
--- a/Telegram/SourceFiles/boxes/add_contact_box.cpp
+++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp
@@ -111,6 +111,10 @@ void ChatCreateDone(
show,
chat,
CollectForbiddenUsers(&chat->session(), result));
+ chat->owner().addRecentJoinChat({
+ .fromPeerId = chat->id,
+ .joinedPeerId = chat->id,
+ });
}
};
if (!success) {
@@ -454,10 +458,12 @@ void AddContactBox::save() {
MTP_vector(
1,
MTP_inputPhoneContact(
+ MTP_flags(0),
MTP_long(_contactId),
MTP_string(phone),
MTP_string(firstName),
- MTP_string(lastName)))
+ MTP_string(lastName),
+ MTPTextWithEntities())) // note
)).done(crl::guard(weak, [=](
const MTPcontacts_ImportedContacts &result) {
const auto &data = result.data();
diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style
index 21e74b0fce..77a7a008ba 100644
--- a/Telegram/SourceFiles/boxes/boxes.style
+++ b/Telegram/SourceFiles/boxes/boxes.style
@@ -378,10 +378,8 @@ connectionPortInputField: InputField(defaultInputField) {
width: 55px;
}
connectionUserInputField: InputField(defaultInputField) {
- width: 95px;
}
connectionPasswordInputField: InputField(defaultInputField) {
- width: 120px;
}
connectionIPv6Skip: 11px;
@@ -537,7 +535,6 @@ changePhoneDescription: FlatLabel(defaultFlatLabel) {
}
changePhoneDescriptionPadding: margins(0px, 1px, 0px, 8px);
changePhoneIconPadding: margins(0px, 39px, 0px, 5px);
-changePhoneIconSize: 120px;
changePhoneLabel: FlatLabel(defaultFlatLabel) {
minWidth: 275px;
textFg: windowSubTextFg;
@@ -546,6 +543,8 @@ changePhoneError: FlatLabel(changePhoneLabel) {
textFg: boxTextFgError;
}
+normalBoxLottieSize: size(120px, 120px);
+
adminLogFilterUserpicLeft: 15px;
adminLogFilterLittleSkip: 16px;
adminLogFilterCheckbox: Checkbox(defaultBoxCheckbox) {
@@ -928,6 +927,14 @@ scheduleTimeSeparator: FlatLabel(defaultFlatLabel) {
}
}
scheduleTimeSeparatorPadding: margins(2px, 0px, 2px, 0px);
+scheduleRepeatDropdownLock: IconEmoji {
+ icon: icon {{ "emoji/premium_lock", windowActiveTextFg }};
+ padding: margins(-2px, 1px, 0px, 0px);
+}
+scheduleRepeatDropdownArrow: IconEmoji {
+ icon: icon {{ "intro_country_dropdown", windowActiveTextFg }};
+ padding: margins(3px, 6px, 3px, 0px);
+}
muteBoxTimeField: InputField(scheduleDateField) {
textMargins: margins(0px, 0px, 0px, 0px);
@@ -997,9 +1004,8 @@ contactsWithStories: PeerList(peerListBox) {
statusPosition: point(70px, 27px);
checkbox: RoundImageCheckbox(defaultPeerListCheckbox) {
- selectExtendTwice: 1px;
imageRadius: 21px;
- imageSmallRadius: 19px;
+ imageSmallRadius: 18px;
check: RoundCheckbox(defaultPeerListCheck) {
size: 0px;
}
diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp
index 898c049d66..9f2ea2ff41 100644
--- a/Telegram/SourceFiles/boxes/connection_box.cpp
+++ b/Telegram/SourceFiles/boxes/connection_box.cpp
@@ -115,6 +115,7 @@ void AddProxyFromClipboard(
Success,
Failed,
Unsupported,
+ IncorrectSecret,
Invalid,
};
@@ -154,8 +155,11 @@ void AddProxyFromClipboard(
qthelp::UrlParamNameTransform::ToLower);
const auto proxy = ProxyDataFromFields(type, fields);
if (!proxy) {
- return (proxy.status() == ProxyData::Status::Unsupported)
+ const auto status = proxy.status();
+ return (status == ProxyData::Status::Unsupported)
? Result::Unsupported
+ : (status == ProxyData::Status::IncorrectSecret)
+ ? Result::IncorrectSecret
: Result::Invalid;
}
const auto contains = controller->contains(proxy);
@@ -189,9 +193,11 @@ void AddProxyFromClipboard(
tr::lng_proxy_add_from_clipboard_failed_toast(tr::now));
} else {
show->showBox(Ui::MakeInformBox(
- (success == Result::Unsupported
- ? tr::lng_proxy_unsupported(tr::now)
- : tr::lng_proxy_invalid(tr::now))));
+ ((success == Result::IncorrectSecret)
+ ? tr::lng_proxy_incorrect_secret(tr::now, tr::rich)
+ : (success == Result::Unsupported)
+ ? tr::lng_proxy_unsupported(tr::now, tr::rich)
+ : tr::lng_proxy_invalid(tr::now, tr::rich))));
}
}
}
@@ -1183,7 +1189,7 @@ void ProxyBox::setupSocketAddress(const ProxyData &data) {
}
void ProxyBox::setupCredentials(const ProxyData &data) {
- _credentials = _content->add(
+ _credentials = _content->add(
object_ptr>(
_content,
object_ptr(_content)));
@@ -1316,10 +1322,13 @@ void ProxiesBoxController::ShowApplyConfirmation(
const QMap &fields) {
const auto proxy = ProxyDataFromFields(type, fields);
if (!proxy) {
+ const auto status = proxy.status();
auto box = Ui::MakeInformBox(
- (proxy.status() == ProxyData::Status::Unsupported
- ? tr::lng_proxy_unsupported(tr::now)
- : tr::lng_proxy_invalid(tr::now)));
+ ((status == ProxyData::Status::Unsupported)
+ ? tr::lng_proxy_unsupported(tr::now, tr::rich)
+ : (status == ProxyData::Status::IncorrectSecret)
+ ? tr::lng_proxy_incorrect_secret(tr::now, tr::rich)
+ : tr::lng_proxy_invalid(tr::now, tr::rich)));
if (controller) {
controller->uiShow()->showBox(std::move(box));
} else {
diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp
index cc971734df..24c3ab7d3a 100644
--- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp
+++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp
@@ -232,7 +232,7 @@ EditCaptionBox::EditCaptionBox(
not_null controller,
not_null item,
TextWithTags &&text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Ui::PreparedList &&list,
@@ -273,7 +273,7 @@ void EditCaptionBox::StartMediaReplace(
not_null controller,
FullMsgId itemId,
TextWithTags text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Fn saved) {
@@ -304,7 +304,7 @@ void EditCaptionBox::StartMediaReplace(
FullMsgId itemId,
Ui::PreparedList &&list,
TextWithTags text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Fn saved) {
@@ -353,7 +353,7 @@ void EditCaptionBox::StartPhotoEdit(
std::shared_ptr media,
FullMsgId itemId,
TextWithTags text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Fn saved) {
diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.h b/Telegram/SourceFiles/boxes/edit_caption_box.h
index 0b0c5f7f96..569039ad05 100644
--- a/Telegram/SourceFiles/boxes/edit_caption_box.h
+++ b/Telegram/SourceFiles/boxes/edit_caption_box.h
@@ -39,7 +39,7 @@ public:
not_null controller,
not_null item,
TextWithTags &&text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Ui::PreparedList &&list,
@@ -50,7 +50,7 @@ public:
not_null controller,
FullMsgId itemId,
TextWithTags text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Fn saved);
@@ -59,7 +59,7 @@ public:
FullMsgId itemId,
Ui::PreparedList &&list,
TextWithTags text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Fn saved);
@@ -68,7 +68,7 @@ public:
std::shared_ptr media,
FullMsgId itemId,
TextWithTags text,
- SuggestPostOptions suggest,
+ SuggestOptions suggest,
bool spoilered,
bool invertCaption,
Fn saved);
@@ -117,7 +117,7 @@ private:
const not_null _controller;
const not_null _historyItem;
- const SuggestPostOptions _suggest;
+ const SuggestOptions _suggest;
const bool _isAllowedEditMedia;
const Ui::AlbumType _albumType;
diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp
index 7584c9f137..248c170af6 100644
--- a/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp
+++ b/Telegram/SourceFiles/boxes/filters/edit_filter_box.cpp
@@ -16,11 +16,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/premium_preview_box.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/message_field.h"
+#include "chat_helpers/tabbed_panel.h"
+#include "chat_helpers/tabbed_selector.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "core/ui_integration.h"
+#include "data/stickers/data_custom_emoji.h"
+#include "data/stickers/data_stickers.h"
#include "data/data_channel.h"
#include "data/data_chat_filters.h"
+#include "data/data_document.h"
#include "data/data_peer.h"
#include "data/data_peer_values.h" // Data::AmPremiumValue.
#include "data/data_premium_limits.h"
@@ -32,6 +37,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/chat/chats_filter_tag.h"
+#include "ui/controls/emoji_button_factory.h"
+#include "ui/controls/emoji_button.h"
#include "ui/effects/animation_value_f.h"
#include "ui/effects/animations.h"
#include "ui/effects/panel_animation.h"
@@ -54,6 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_layers.h"
#include "styles/style_window.h"
#include "styles/style_chat.h"
+#include "styles/style_chat_helpers.h"
#include "styles/style_info_userpic_builder.h"
namespace {
@@ -357,6 +365,7 @@ void EditFilterBox(
rpl::variable title;
rpl::variable staticTitle;
rpl::variable colorIndex;
+ base::unique_qptr emojiPanel;
};
const auto owner = &window->session().data();
const auto state = box->lifetime().make_state(State{
@@ -423,7 +432,22 @@ void EditFilterBox(
current.text,
TextUtilities::ConvertEntitiesToTextTags(current.entities),
}, Ui::InputField::HistoryAction::Clear);
- name->setMaxLength(kMaxFilterTitleLength);
+ Ui::AddLengthLimitLabel(
+ name,
+ kMaxFilterTitleLength,
+ Ui::LengthLimitLabelOptions{
+ .customThreshold = 0,
+ .customUpdatePosition = [=](QSize parent, QSize label) {
+ return QPoint(
+ parent.width()
+ - st::windowFilterNameCharsLimitRightPosition.x()
+ - label.width() / 2,
+ st::windowFilterNameCharsLimitRightPosition.y());
+ },
+ .customCharactersCount = [=] {
+ return Ui::ComputeFieldCharacterCount(name);
+ },
+ });
const auto nameEditing = box->lifetime().make_state(
NameEditing{ name });
@@ -468,6 +492,47 @@ void EditFilterBox(
nameEditing->custom = true;
}, box->lifetime());
+ using Selector = ChatHelpers::TabbedSelector;
+ state->emojiPanel = base::make_unique_q(
+ box->getDelegate()->outerContainer(),
+ window,
+ object_ptr(
+ nullptr,
+ window->uiShow(),
+ Window::GifPauseReason::Layer,
+ Selector::Mode::EmojiOnly));
+ state->emojiPanel->setDesiredHeightValues(
+ 1.,
+ st::emojiPanMinHeight / 2,
+ st::emojiPanMinHeight);
+ state->emojiPanel->hide();
+ state->emojiPanel->selector()->setCurrentPeer(window->session().user());
+ state->emojiPanel->selector()->emojiChosen(
+ ) | rpl::start_with_next([=](ChatHelpers::EmojiChosen data) {
+ Ui::InsertEmojiAtCursor(name->textCursor(), data.emoji);
+ }, name->lifetime());
+ state->emojiPanel->selector()->customEmojiChosen(
+ ) | rpl::start_with_next([=](ChatHelpers::FileChosen data) {
+ const auto info = data.document->sticker();
+ if (info
+ && info->setType == Data::StickersType::Emoji
+ && !window->session().premium()) {
+ ShowPremiumPreviewBox(
+ window,
+ PremiumFeature::AnimatedEmoji);
+ } else {
+ Data::InsertCustomEmoji(name, data.document);
+ }
+ }, name->lifetime());
+
+ const auto emojiButton = Ui::AddEmojiToggleToField(
+ name,
+ box,
+ window,
+ state->emojiPanel.get(),
+ st::windowFilterNameEmojiPosition);
+ emojiButton->show();
+
name->changes(
) | rpl::start_with_next([=] {
if (!nameEditing->settingDefault) {
@@ -585,18 +650,31 @@ void EditFilterBox(
}),
anim::type::instant);
+ const auto &padding = st::defaultSubsectionTitlePadding;
const auto isPremium = session->premium();
- const auto title = Ui::AddSubsectionTitle(
- colors,
- tr::lng_filters_tag_color_subtitle());
- const auto preview = Ui::CreateChild(colors);
- title->geometryValue(
- ) | rpl::start_with_next([=](const QRect &r) {
+ const auto titleWrap = colors->add(
+ object_ptr(
+ colors,
+ rect::m::sum::v(padding)
+ + st::defaultSubsectionTitle.style.font->height));
+ const auto title = Ui::CreateChild(
+ titleWrap,
+ tr::lng_filters_tag_color_subtitle(),
+ st::defaultSubsectionTitle);
+ title->move(rect::m::pos::tl(padding));
+ const auto preview = Ui::CreateChild(titleWrap);
+ rpl::combine(
+ title->sizeValue(),
+ titleWrap->widthValue()
+ ) | rpl::start_with_next([=](const QSize &s, int w) {
const auto h = st::normalFont->height;
+ const auto left = padding.left()
+ + s.width()
+ + st::settingsFilterTagPreviewSkip;
preview->setGeometry(
- rect::right(colors) - st::settingsFilterTagPreviewSkip,
- r.y() + (r.height() - h) / 2 + st::lineWidth,
- colors->width(),
+ left,
+ padding.top() + (s.height() - h) / 2,
+ w - left,
h);
}, preview->lifetime());
@@ -608,12 +686,16 @@ void EditFilterBox(
};
const auto tag = preview->lifetime().make_state();
tag->context.textContext = Core::TextContext({ .session = session });
+ const auto shift = st::settingsFilterTagPreviewSkip / 2;
preview->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(preview);
p.setOpacity(tag->alpha);
const auto size = tag->frame.size() / style::DevicePixelRatio();
const auto rect = QRect(
- preview->width() - size.width() - st::boxRowPadding.right(),
+ preview->width()
+ - size.width()
+ - st::boxRowPadding.right()
+ - shift,
(st::normalFont->height - size.height()) / 2,
size.width(),
size.height());
@@ -623,7 +705,7 @@ void EditFilterBox(
p.setFont(st::normalFont);
p.setPen(st::windowSubTextFg);
p.drawText(
- preview->rect() - st::boxRowPadding,
+ preview->rect().translated(-shift, 0) - st::boxRowPadding,
tr::lng_filters_tag_color_no(tr::now),
style::al_right);
}
@@ -741,7 +823,8 @@ void EditFilterBox(
const auto staticTitle = !title.entities.isEmpty()
&& state->staticTitle.current();
const auto rules = data->current();
- if (title.empty()) {
+ if (Ui::ComputeFieldCharacterCount(name) > kMaxFilterTitleLength
+ || title.empty()) {
name->showError();
box->scrollToY(0);
return {};
diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.cpp b/Telegram/SourceFiles/boxes/gift_premium_box.cpp
index 0a1a8333e3..8ed8781e1a 100644
--- a/Telegram/SourceFiles/boxes/gift_premium_box.cpp
+++ b/Telegram/SourceFiles/boxes/gift_premium_box.cpp
@@ -31,10 +31,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_premium_subscription_option.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
-#include "info/channel_statistics/boosts/giveaway/boost_badge.h" // InfiniteRadialAnimationWidget.
+//#include "info/channel_statistics/boosts/giveaway/boost_badge.h" // InfiniteRadialAnimationWidget.
#include "info/channel_statistics/earn/earn_icons.h"
-#include "info/profile/info_profile_badge.h"
-#include "info/profile/info_profile_values.h"
+//#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"
@@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/boxes/boost_box.h" // StartFireworks.
#include "ui/boxes/confirm_box.h"
#include "ui/controls/userpic_button.h"
+#include "ui/controls/table_rows.h"
#include "ui/effects/credits_graphics.h"
#include "ui/effects/premium_graphics.h"
#include "ui/effects/premium_stars_colored.h"
@@ -81,79 +82,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace {
constexpr auto kTooltipDuration = 3 * crl::time(1000);
-constexpr auto kPriceTooltipDuration = 6 * crl::time(1000);
constexpr auto kHorizontalBar = QChar(0x2015);
-struct InfoTooltipData {
- not_null parent;
- Ui::ImportantTooltip *raw = nullptr;
-};
-
-void ShowInfoTooltip(
- std::shared_ptr data,
- not_null target,
- rpl::producer text,
- int duration) {
- if (data->raw) {
- data->raw->toggleAnimated(false);
- }
- const auto parent = data->parent;
- const auto tooltip = Ui::CreateChild(
- parent,
- Ui::MakeNiceTooltipLabel(
- parent,
- std::move(text),
- st::boxWideWidth,
- st::defaultImportantTooltipLabel),
- st::defaultImportantTooltip);
- tooltip->toggleFast(false);
-
- base::install_event_filter(tooltip, qApp, [=](not_null e) {
- if (e->type() == QEvent::MouseButtonPress) {
- tooltip->toggleAnimated(false);
- }
- return base::EventFilterResult::Continue;
- });
-
- const auto update = [=] {
- const auto geometry = Ui::MapFrom(parent, target, target->rect());
- const auto countPosition = [=](QSize size) {
- const auto left = geometry.x()
- + (geometry.width() - size.width()) / 2;
- const auto right = parent->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);
- };
- parent->widthValue(
- ) | rpl::start_with_next(update, tooltip->lifetime());
-
- update();
- tooltip->toggleAnimated(true);
-
- data->raw = tooltip;
- tooltip->shownValue() | rpl::filter(
- !rpl::mappers::_1
- ) | rpl::start_with_next([=] {
- crl::on_main(tooltip, [=] {
- if (tooltip->isHidden()) {
- if (data->raw == tooltip) {
- data->raw = nullptr;
- }
- delete tooltip;
- }
- });
- }, tooltip->lifetime());
-
- base::timer_once(
- duration
- ) | rpl::start_with_next([=] {
- tooltip->toggleAnimated(false);
- }, tooltip->lifetime());
-}
+using Ui::AddTableRow;
+using Ui::TableRowTooltipData;
[[nodiscard]] QString CreateMessageLink(
not_null session,
@@ -236,8 +168,10 @@ void ShowInfoTooltip(
return result;
}
-[[nodiscard]] tr::phrase GiftDurationPhrase(int months) {
- return (months < 12)
+[[nodiscard]] tr::phrase GiftDurationPhrase(int days) {
+ return (days < 30)
+ ? tr::lng_premium_gift_duration_days
+ : (days < 30 * 12)
? tr::lng_premium_gift_duration_months
: tr::lng_premium_gift_duration_years;
}
@@ -260,230 +194,6 @@ void ShowInfoTooltip(
: st::giveawayGiftCodeValueMultiline));
}
-[[nodiscard]] object_ptr MakeValueWithSmallButton(
- not_null table,
- not_null value,
- rpl::producer buttonText,
- Fn button)> handler = nullptr,
- int topSkip = 0) {
- class MarginedWidget final : public Ui::RpWidget {
- public:
- using RpWidget::RpWidget;
- QMargins getMargins() const override {
- return { 0, 0, 0, st::giveawayGiftCodePeerMargin.bottom() };
- }
- };
- auto result = object_ptr(table);
- const auto raw = result.data();
-
- value->setParent(raw);
- value->show();
-
- const auto button = Ui::CreateChild(
- raw,
- std::move(buttonText),
- table->st().smallButton);
- button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
- if (handler) {
- button->setClickedCallback([button, handler = std::move(handler)] {
- handler(button);
- });
- } else {
- button->setAttribute(Qt::WA_TransparentForMouseEvents);
- }
- rpl::combine(
- raw->widthValue(),
- button->widthValue(),
- value->naturalWidthValue()
- ) | rpl::start_with_next([=](int width, int buttonWidth, int) {
- const auto buttonSkip = st::normalFont->spacew + buttonWidth;
- value->resizeToNaturalWidth(width - buttonSkip);
- value->moveToLeft(0, 0, width);
- button->moveToLeft(
- rect::right(value) + st::normalFont->spacew,
- (topSkip
- + (table->st().defaultValue.style.font->ascent
- - table->st().smallButton.style.font->ascent)),
- width);
- }, value->lifetime());
-
- value->heightValue() | rpl::start_with_next([=](int height) {
- const auto bottom = st::giveawayGiftCodePeerMargin.bottom();
- raw->resize(raw->width(), height + bottom);
- }, raw->lifetime());
-
- return result;
-}
-
-[[nodiscard]] object_ptr MakePeerTableValue(
- not_null table,
- std::shared_ptr show,
- PeerId id,
- rpl::producer button = nullptr,
- Fn handler = nullptr) {
- 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,
- (button && handler) ? peer->shortName() : peer->name(),
- table->st().defaultValue);
-
- raw->widthValue() | rpl::start_with_next([=](int width) {
- const auto position = st::giveawayGiftCodeNamePosition;
- label->resizeToNaturalWidth(width - position.x());
- label->moveToLeft(position.x(), position.y(), width);
- const auto top = (raw->height() - userpic->height()) / 2;
- userpic->moveToLeft(0, top, width);
- }, label->lifetime());
-
- label->naturalWidthValue() | rpl::start_with_next([=](int width) {
- raw->setNaturalWidth(st::giveawayGiftCodeNamePosition.x() + 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));
- });
-
- if (!button || !handler) {
- return result;
- }
- return MakeValueWithSmallButton(
- table,
- result.release(),
- std::move(button),
- [=](not_null button) { handler(); },
- st::giveawayGiftCodeNamePosition.y());
-}
-
-[[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 peerLabel = MakePeerTableValue(table, show, id).release();
- peerLabel->setParent(raw);
- peerLabel->show();
-
- raw->resize(raw->width(), peerLabel->height());
-
- using namespace Info::Profile;
- struct State {
- rpl::variable content;
- };
- const auto peer = show->session().data().peer(id);
- const auto state = peerLabel->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 = peerLabel->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 badgeWidget = badge->widget();
- const auto badgeSkip = badgeWidget
- ? (st::normalFont->spacew + badgeWidget->width())
- : 0;
- peerLabel->resizeToNaturalWidth(width - badgeSkip);
- peerLabel->moveToLeft(0, 0, width);
- if (badgeWidget) {
- badgeWidget->moveToLeft(
- peerLabel->width() + st::normalFont->spacew,
- st::giftBoxByStarsStarTop,
- width);
- }
- }, raw->lifetime());
-
- return result;
-}
-
-[[nodiscard]] object_ptr MakeHiddenPeerTableValue(
- not_null table) {
- auto result = object_ptr(table);
- const auto raw = result.data();
-
- const auto &st = st::giveawayGiftCodeUserpic;
- raw->resize(raw->width(), st.photoSize);
-
- const auto userpic = Ui::CreateChild(raw);
- const auto usize = st.photoSize;
- userpic->resize(usize, usize);
- userpic->paintRequest() | rpl::start_with_next([=] {
- auto p = QPainter(userpic);
- Ui::EmptyUserpic::PaintHiddenAuthor(p, 0, 0, usize, usize);
- }, userpic->lifetime());
-
- const auto label = Ui::CreateChild(
- raw,
- tr::lng_gift_from_hidden(),
- table->st().defaultValue);
- raw->widthValue(
- ) | rpl::start_with_next([=](int width) {
- const auto position = st::giveawayGiftCodeNamePosition;
- label->resizeToNaturalWidth(width - position.x());
- label->moveToLeft(position.x(), position.y(), width);
- const auto top = (raw->height() - userpic->height()) / 2;
- userpic->moveToLeft(0, top, width);
- }, label->lifetime());
-
- userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
- label->setAttribute(Qt::WA_TransparentForMouseEvents);
- label->setTextColorOverride(st::windowFg->c);
-
- return result;
-}
-
-void AddTableRow(
- not_null table,
- rpl::producer label,
- object_ptr value,
- style::margins valueMargins = st::giveawayGiftCodeValueMargin) {
- table->addRow(
- (label
- ? object_ptr(
- table,
- std::move(label),
- table->st().defaultLabel)
- : object_ptr(nullptr)),
- std::move(value),
- st::giveawayGiftCodeLabelMargin,
- valueMargins);
-}
-
[[nodiscard]] object_ptr MakePriceWithChangePercentValue(
not_null table,
const std::shared_ptr &value) {
@@ -509,35 +219,13 @@ void AddTableRow(
return MakeValueWithSmallButton(table, label, std::move(text));
}
-[[nodiscard]] object_ptr MakePriceValueWithTooltip(
- not_null table,
- std::shared_ptr data,
- TextWithEntities price,
- TextWithEntities tooltip) {
- const auto label = Ui::CreateChild(
- table,
- rpl::single(price),
- table->st().defaultValue);
- label->setAttribute(Qt::WA_TransparentForMouseEvents);
-
- const auto handler = [=](not_null button) {
- ShowInfoTooltip(
- data,
- button,
- rpl::single(tooltip),
- kPriceTooltipDuration);
- };
- auto text = rpl::single(u"?"_q);
- return MakeValueWithSmallButton(table, label, std::move(text), handler);
-}
-
[[nodiscard]] object_ptr MakeMinimumPriceValue(
not_null table,
- std::shared_ptr tooltip,
+ std::shared_ptr tooltip,
const std::shared_ptr &unique) {
const auto &value = unique->value;
const auto text = FormatValuePrice(value->minimumPrice, value->currency);
- return MakePriceValueWithTooltip(
+ return Ui::MakeTableValueWithTooltip(
table,
std::move(tooltip),
text,
@@ -552,11 +240,11 @@ void AddTableRow(
[[nodiscard]] object_ptr MakeAveragePriceValue(
not_null table,
- std::shared_ptr tooltip,
+ std::shared_ptr tooltip,
const std::shared_ptr &unique) {
const auto &value = unique->value;
const auto text = FormatValuePrice(value->averagePrice, value->currency);
- return MakePriceValueWithTooltip(
+ return Ui::MakeTableValueWithTooltip(
table,
std::move(tooltip),
text,
@@ -592,13 +280,12 @@ void AddUniqueGiftPropertyRows(
not_null container,
not_null table,
not_null unique) {
- const auto tooltip = std::make_shared(InfoTooltipData{
- .parent = container,
- });
+ const auto tooltip = std::make_shared(
+ TableRowTooltipData{ .parent = container });
const auto showTooltip = [=](
not_null widget,
rpl::producer text) {
- ShowInfoTooltip(tooltip, widget, std::move(text), kTooltipDuration);
+ ShowTableRowTooltip(tooltip, widget, std::move(text), kTooltipDuration);
};
const auto showRarity = [=](
not_null widget,
@@ -629,8 +316,17 @@ void AddUniqueGiftPropertyRows(
const Data::CreditsHistoryEntry &entry,
Fn convertToStars) {
auto helper = Ui::Text::CustomEmojiHelper();
+ const auto addUpgradeToValue = !entry.credits.ton()
+ && !entry.giftUpgradeGifted
+ && !entry.giftUpgradeSeparate
+ && entry.starsUpgradedBySender;
+ const auto amount = addUpgradeToValue
+ ? CreditsAmount(
+ entry.credits.whole() + entry.starsUpgradedBySender,
+ entry.credits.nano())
+ : entry.credits;
const auto price = helper.paletteDependent(Ui::Earn::IconCreditsEmoji(
- )).append(' ').append(Lang::FormatCreditsAmountDecimal(entry.credits));
+ )).append(' ').append(Lang::FormatCreditsAmountDecimal(amount));
auto label = object_ptr(
table,
rpl::single(price),
@@ -712,37 +408,6 @@ void AddUniqueGiftPropertyRows(
handler);
}
-not_null AddTableRow(
- not_null table,
- rpl::producer label,
- rpl::producer value,
- const Ui::Text::MarkedContext &context = {}) {
- auto widget = object_ptr(
- table,
- std::move(value),
- table->st().defaultValue,
- st::defaultPopupMenu,
- context);
- const auto result = widget.data();
- AddTableRow(table, std::move(label), std::move(widget));
- return result;
-}
-
-void AddTableRow(
- not_null table,
- rpl::producer label,
- std::shared_ptr show,
- PeerId id) {
- if (!id) {
- return;
- }
- AddTableRow(
- table,
- std::move(label),
- MakePeerTableValue(table, show, id),
- st::giveawayGiftCodePeerMargin);
-}
-
void AddTable(
not_null container,
std::shared_ptr show,
@@ -778,7 +443,7 @@ void AddTable(
tr::lng_gift_link_label_gift(),
tr::lng_gift_link_gift_premium(
lt_duration,
- GiftDurationValue(current.months) | Ui::Text::ToWithEntities(),
+ GiftDurationValue(current.days) | Ui::Text::ToWithEntities(),
Ui::Text::WithEntities));
if (!skipReason && current.from) {
const auto reason = AddTableRow(
@@ -863,17 +528,22 @@ void ShowAlreadyPremiumToast(
} // namespace
-rpl::producer GiftDurationValue(int months) {
- return GiftDurationPhrase(months)(
+rpl::producer GiftDurationValue(int days) {
+ return GiftDurationPhrase(days)(
lt_count,
- rpl::single(float64((months < 12) ? months : (months / 12))));
+ rpl::single(float64((days < 30)
+ ? days
+ : (days < 30 * 12)
+ ? (days / 30)
+ : (days / (30 * 12)))));
}
-QString GiftDuration(int months) {
- return GiftDurationPhrase(months)(
- tr::now,
- lt_count,
- (months < 12) ? months : (months / 12));
+QString GiftDuration(int days) {
+ return GiftDurationPhrase(days)(tr::now, lt_count, (days < 30)
+ ? days
+ : (days < 30 * 12)
+ ? (days / 30)
+ : (days / (30 * 12)));
}
void GiftCodeBox(
@@ -1121,9 +791,9 @@ void ResolveGiftCode(
code.to = toId;
const auto self = (fromId == selfId);
const auto peer = session->data().peer(self ? toId : fromId);
- const auto months = code.months;
+ const auto days = code.days;
const auto parent = controller->parentController();
- Settings::ShowGiftPremium(parent, peer, months, self);
+ Settings::ShowGiftPremium(parent, peer, days, self);
} else {
controller->uiShow()->showBox(Box(GiftCodeBox, controller, slug));
}
@@ -1242,7 +912,7 @@ void GiveawayInfoBox(
lt_channel,
Ui::Text::Bold(first),
lt_duration,
- TextWithEntities{ GiftDuration(months) },
+ TextWithEntities{ GiftDuration(months * 30) },
Ui::Text::RichLangValue),
Ui::Text::RichLangValue));
const auto many = start
@@ -1550,13 +1220,12 @@ void AddStarGiftTable(
const auto giftToChannel = entry.giftChannelSavedId
&& peerIsChannel(PeerId(entry.bareEntryOwnerId));
- const auto tooltip = std::make_shared(InfoTooltipData{
- .parent = container,
- });
+ const auto tooltip = std::make_shared(
+ TableRowTooltipData{ .parent = container });
const auto showTooltip = [=](
not_null widget,
rpl::producer text) {
- ShowInfoTooltip(tooltip, widget, std::move(text), kTooltipDuration);
+ ShowTableRowTooltip(tooltip, widget, std::move(text), kTooltipDuration);
};
if (unique && entry.bareGiftResaleRecipientId) {
@@ -1668,6 +1337,15 @@ void AddStarGiftTable(
PeerId(entry.bareEntryOwnerId)),
st::giveawayGiftCodePeerMargin);
}
+ } else if (entry.auction && entry.bareGiftOwnerId) {
+ AddTableRow(
+ table,
+ tr::lng_credits_box_history_entry_peer(),
+ MakePeerTableValue(
+ table,
+ show,
+ PeerId(entry.bareGiftOwnerId)),
+ st::giveawayGiftCodePeerMargin);
} else if (peerId && !giftToSelf) {
const auto user = session->data().peer(peerId)->asUser();
const auto withSendButton = entry.in && user && !user->isBot();
@@ -1938,11 +1616,30 @@ void AddCreditsHistoryEntryTable(
: entry.giftUpgraded
? tr::lng_credits_box_history_entry_gift_from()
: tr::lng_credits_box_history_entry_peer();
+ const auto targetId = actorId ? actorId : peerId;
+ const auto isPeerDefault = !entry.starrefCommission
+ && !entry.in
+ && !entry.giftResale
+ && !entry.giftUpgraded;
+ const auto user = isPeerDefault
+ ? session->data().peer(targetId)->asUser()
+ : nullptr;
+ const auto withSendButton = user
+ && !user->isInaccessible()
+ && !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,
std::move(text),
- show,
- actorId ? actorId : peerId);
+ MakePeerTableValue(table, show, targetId, send, handler),
+ st::giveawayGiftCodePeerMargin);
}
if (const auto msgId = MsgId(peerId ? entry.bareMsgId : 0)) {
const auto peer = session->data().peer(peerId);
@@ -2102,6 +1799,19 @@ void AddCreditsHistoryEntryTable(
rpl::single(
Ui::Text::Link(entry.successLink, entry.successLink)));
}
+ if (entry.limitedCount > 0 && entry.limitedLeft >= 0) {
+ AddTableRow(
+ table,
+ tr::lng_gift_availability(),
+ tr::lng_gift_availability_left(
+ lt_count_decimal,
+ rpl::single(entry.limitedLeft) | tr::to_count(),
+ lt_amount,
+ rpl::single(TextWithEntities{
+ Lang::FormatCountDecimal(entry.limitedCount)
+ }),
+ Ui::Text::WithEntities));
+ }
}
void AddSubscriptionEntryTable(
@@ -2313,9 +2023,8 @@ void AddUniqueGiftValueTable(
MakePriceWithChangePercentValue(table, value));
}
- const auto tooltip = std::make_shared(InfoTooltipData{
- .parent = container,
- });
+ const auto tooltip = std::make_shared(
+ TableRowTooltipData{ .parent = container });
if (value->minimumPrice) {
AddTableRow(
table,
diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.h b/Telegram/SourceFiles/boxes/gift_premium_box.h
index 64c103a1fa..452599b753 100644
--- a/Telegram/SourceFiles/boxes/gift_premium_box.h
+++ b/Telegram/SourceFiles/boxes/gift_premium_box.h
@@ -44,8 +44,8 @@ namespace Window {
class SessionNavigation;
} // namespace Window
-[[nodiscard]] rpl::producer GiftDurationValue(int months);
-[[nodiscard]] QString GiftDuration(int months);
+[[nodiscard]] rpl::producer GiftDurationValue(int days);
+[[nodiscard]] QString GiftDuration(int days);
void GiftCodeBox(
not_null box,
diff --git a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp
index 7ab0c2e396..ec249bf5ef 100644
--- a/Telegram/SourceFiles/boxes/moderate_messages_box.cpp
+++ b/Telegram/SourceFiles/boxes/moderate_messages_box.cpp
@@ -466,8 +466,7 @@ void CreateModerateMessagesBox(
inner->add(object_ptr(
inner,
std::move(label),
- st::defaultBoxDividerLabelPadding,
- RectPart::Top | RectPart::Bottom));
+ st::defaultBoxDividerLabelPadding));
using Flag = ChatRestriction;
using Flags = ChatRestrictions;
diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp
index fe03444089..eb61a75185 100644
--- a/Telegram/SourceFiles/boxes/peer_list_box.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp
@@ -993,10 +993,11 @@ void PeerListRow::setCheckedInternal(bool checked, anim::type animated) {
}
void PeerListRow::setCustomizedCheckSegments(
- std::vector segments) {
+ std::vector segments,
+ bool liveBadge) {
Expects(_checkbox != nullptr);
- _checkbox->setCustomizedSegments(std::move(segments));
+ _checkbox->setCustomizedSegments(std::move(segments), liveBadge);
}
void PeerListRow::finishCheckedAnimation() {
diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h
index 0ae796e131..133019793f 100644
--- a/Telegram/SourceFiles/boxes/peer_list_box.h
+++ b/Telegram/SourceFiles/boxes/peer_list_box.h
@@ -229,7 +229,8 @@ public:
setCheckedInternal(checked, animated);
}
void setCustomizedCheckSegments(
- std::vector segments);
+ std::vector segments,
+ bool liveBadge);
void setHidden(bool hidden) {
_hidden = hidden;
}
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
index 3b984c171a..e6d54fc826 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
@@ -132,27 +132,36 @@ QBrush PeerListStoriesGradient(const style::PeerList &st) {
}
std::vector PeerListStoriesSegments(
- int count,
- int unread,
+ PeerListStoriesCounts counts,
const QBrush &unreadBrush) {
- Expects(unread <= count);
- Expects(count > 0);
+ Expects(counts.unread <= counts.count);
+ Expects(counts.count > 0);
auto result = std::vector();
const auto add = [&](bool unread) {
result.push_back({
- .brush = unread ? unreadBrush : st::dialogsUnreadBgMuted->b,
+ .brush = (counts.videoStream
+ ? st::attentionButtonFg->b
+ : unread
+ ? unreadBrush
+ : st::dialogsUnreadBgMuted->b),
.width = (unread
? st::dialogsStoriesFull.lineTwice / 2.
: st::dialogsStoriesFull.lineReadTwice / 2.),
});
};
- result.reserve(count);
- for (auto i = 0, till = count - unread; i != till; ++i) {
- add(false);
- }
- for (auto i = 0; i != unread; ++i) {
+ if (counts.videoStream) {
add(true);
+ } else {
+ const auto count = counts.count;
+ const auto unread = counts.unread;
+ result.reserve(count);
+ for (auto i = 0, till = count - unread; i != till; ++i) {
+ add(false);
+ }
+ for (auto i = 0; i != unread; ++i) {
+ add(true);
+ }
}
return result;
}
@@ -521,18 +530,15 @@ void PeerListStories::updateColors() {
for (auto i = begin(_counts); i != end(_counts); ++i) {
if (const auto row = _delegate->peerListFindRow(i->first)) {
if (i->second.count >= 0 && i->second.unread >= 0) {
- applyForRow(row, i->second.count, i->second.unread, true);
+ applyForRow(row, i->second, true);
}
}
}
}
-void PeerListStories::updateFor(
- uint64 id,
- int count,
- int unread) {
+void PeerListStories::updateFor(uint64 id, Counts counts) {
if (const auto row = _delegate->peerListFindRow(id)) {
- applyForRow(row, count, unread);
+ applyForRow(row, counts);
_delegate->peerListUpdateRow(row);
}
}
@@ -550,11 +556,14 @@ void PeerListStories::process(not_null row) {
? 1
: 0;
const auto unread = source
- ? source->info().unreadCount
+ ? int(source->info().unreadCount)
: user->hasUnreadStories()
? 1
: 0;
- applyForRow(row, count, unread, true);
+ const auto videoStream = source
+ ? bool(source->info().hasVideoStream)
+ : user->hasActiveVideoStream();
+ applyForRow(row, { count, unread, videoStream }, true);
}
bool PeerListStories::handleClick(not_null peer) {
@@ -597,25 +606,28 @@ void PeerListStories::prepare(not_null delegate) {
const auto info = source
? source->info()
: Data::StoriesSourceInfo();
- updateFor(id.value, info.count, info.unreadCount);
+ updateFor(id.value, {
+ int(info.count),
+ int(info.unreadCount),
+ bool(info.hasVideoStream),
+ });
}, _lifetime);
}
void PeerListStories::applyForRow(
not_null row,
- int count,
- int unread,
+ Counts counts,
bool force) {
- auto &counts = _counts[row->id()];
- if (!force && counts.count == count && counts.unread == unread) {
+ auto &existing = _counts[row->id()];
+ if (!force && existing == counts) {
return;
}
- counts.count = count;
- counts.unread = unread;
- _delegate->peerListSetRowChecked(row, count > 0);
- if (count > 0) {
+ existing = counts;
+ _delegate->peerListSetRowChecked(row, counts.count > 0);
+ if (counts.count > 0) {
row->setCustomizedCheckSegments(
- PeerListStoriesSegments(count, unread, _unreadBrush));
+ PeerListStoriesSegments(counts, _unreadBrush),
+ counts.videoStream);
}
}
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h
index 24887d3df2..fa02b17a58 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.h
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h
@@ -42,9 +42,18 @@ class SessionController;
[[nodiscard]] object_ptr PrepareContactsBox(
not_null sessionController);
[[nodiscard]] QBrush PeerListStoriesGradient(const style::PeerList &st);
+
+struct PeerListStoriesCounts {
+ int count = 0;
+ int unread = 0;
+ bool videoStream = false;
+
+ friend inline bool operator==(
+ const PeerListStoriesCounts &a,
+ const PeerListStoriesCounts &b) = default;
+};
[[nodiscard]] std::vector PeerListStoriesSegments(
- int count,
- int unread,
+ PeerListStoriesCounts counts,
const QBrush &unreadBrush);
class PeerListRowWithLink : public PeerListRow {
@@ -211,17 +220,13 @@ public:
bool handleClick(not_null peer);
private:
- struct Counts {
- int count = 0;
- int unread = 0;
- };
+ using Counts = PeerListStoriesCounts;
void updateColors();
- void updateFor(uint64 id, int count, int unread);
+ void updateFor(uint64 id, Counts counts);
void applyForRow(
not_null row,
- int count,
- int unread,
+ Counts counts,
bool force = false);
const not_null _controller;
diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp
index a5f2ec3c30..2ece4c18aa 100644
--- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp
@@ -1070,6 +1070,10 @@ void AddParticipantsBoxController::Start(
channel,
params,
ShowAtTheEndMsgId);
+ channel->owner().addRecentJoinChat({
+ .fromPeerId = channel->id,
+ .joinedPeerId = channel->id,
+ });
}
}, box->lifetime());
}
diff --git a/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp b/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp
index ca10840712..f8362cedb7 100644
--- a/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp
@@ -97,6 +97,7 @@ using RightsMap = std::vector>>;
{ Flag::ManageCall, tr::lng_request_channel_manage_livestreams },
{ Flag::ManageDirect, tr::lng_request_channel_manage_direct },
{ Flag::AddAdmins, tr::lng_request_channel_add_admins },
+ { Flag::BanUsers, tr::lng_request_group_ban_users },
};
}
diff --git a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp
index eae56c342c..a55c575100 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp
@@ -658,7 +658,7 @@ void Controller::setupPhotoButtons() {
_window->session().api().peerPhoto().clearPersonal(_user);
close();
},
- .confirmText = tr::lng_profile_photo_reset(tr::now),
+ .confirmText = tr::lng_profile_photo_reset_button(tr::now),
}));
});
diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
index 84c47cd928..612d438f7e 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
@@ -246,7 +246,8 @@ ChatAdminRightsInfo EditAdminBox::defaultRights() const {
| Flag::DeleteStories
| Flag::InviteByLinkOrAdd
| Flag::ManageCall
- | Flag::ManageDirect) };
+ | Flag::ManageDirect
+ | Flag::BanUsers) };
}
void EditAdminBox::prepare() {
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
index 266c3b8148..9457279ddf 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h"
#include "boxes/peers/replace_boost_box.h"
#include "boxes/background_box.h"
+#include "boxes/premium_preview_box.h"
#include "boxes/star_gift_box.h"
#include "boxes/stickers_box.h"
#include "boxes/transfer_gift_box.h"
@@ -37,6 +38,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/channel_statistics/boosts/info_boosts_widget.h"
#include "info/peer_gifts/info_peer_gifts_common.h"
#include "info/profile/info_profile_emoji_status_panel.h"
+#include "info/profile/info_profile_top_bar.h"
+#include "info/info_controller.h" // Key
#include "info/info_memento.h"
#include "iv/iv_data.h"
#include "lang/lang_keys.h"
@@ -53,6 +56,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/path_shift_gradient.h"
#include "ui/effects/premium_graphics.h"
#include "ui/layers/generic_box.h"
+#include "ui/new_badges.h"
+#include "ui/peer/color_sample.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/slide_wrap.h"
@@ -77,40 +82,89 @@ using namespace Settings;
constexpr auto kFakeChannelId = ChannelId(0xFFFFFFF000ULL);
constexpr auto kFakeWebPageId = WebPageId(0xFFFFFFFF00000000ULL);
-constexpr auto kSelectAnimationDuration = crl::time(150);
constexpr auto kUnsetColorIndex = uint8(0xFF);
-class ColorSample final : public Ui::AbstractButton {
-public:
- ColorSample(
- not_null parent,
- not_null session,
- std::shared_ptr style,
- rpl::producer colorIndex,
- rpl::producer> collectible,
- const QString &name);
- ColorSample(
- not_null parent,
- std::shared_ptr style,
- uint8 colorIndex,
- bool selected);
+base::unique_qptr CreateEmptyPlaceholder(
+ not_null parent,
+ int width,
+ const QMargins &padding,
+ Fn switchToNextTab) {
+ const auto container = Ui::CreateChild(parent);
+ auto result = base::unique_qptr{ container };
- [[nodiscard]] uint8 index() const;
+ auto icon = Settings::CreateLottieIcon(
+ container,
+ {
+ .name = u"my_gifts_empty"_q,
+ .sizeOverride = st::normalBoxLottieSize,
+ },
+ st::settingsBlockedListIconPadding);
+ const auto iconWidget = icon.widget.data();
+ iconWidget->show();
- void setSelected(bool selected);
+ const auto emptyLabel = Ui::CreateChild(
+ container,
+ tr::lng_gift_stars_tabs_my_empty(),
+ st::giftBoxGiftEmptyLabel);
+ emptyLabel->setTryMakeSimilarLines(true);
+ emptyLabel->resizeToWidth(
+ width - st::boxRowPadding.left() - st::boxRowPadding.right());
+ emptyLabel->show();
-private:
- void paintEvent(QPaintEvent *e) override;
+ const auto emptyNextLabel = switchToNextTab
+ ? Ui::CreateChild(
+ container,
+ tr::lng_gift_stars_tabs_my_empty_next(
+ lt_emoji,
+ rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
+ tr::link),
+ st::giftBoxGiftEmptyLabel)
+ : nullptr;
+ if (emptyNextLabel) {
+ emptyNextLabel->resizeToWidth(
+ width - st::boxRowPadding.left() - st::boxRowPadding.right());
+ emptyNextLabel->setClickHandlerFilter([=](auto...) {
+ switchToNextTab();
+ return false;
+ });
+ }
- std::shared_ptr _style;
- Ui::Text::String _name;
- uint8 _index = 0;
- std::shared_ptr _collectible;
- Ui::Animations::Simple _selectAnimation;
- bool _selected = false;
- bool _simple = false;
+ icon.animate(anim::repeat::loop);
-};
+ const auto labelHeight = emptyLabel->height();
+ const auto nextLabelHeight = emptyNextLabel
+ ? emptyNextLabel->height()
+ : 0;
+ const auto totalHeight = iconWidget->height()
+ + st::normalFont->height + labelHeight + nextLabelHeight
+ + (nextLabelHeight ? st::normalFont->height : 0)
+ + padding.top() + padding.bottom();
+ container->resize(width, totalHeight);
+
+ container->sizeValue(
+ ) | rpl::start_with_next([=](QSize size) {
+ const auto totalContentHeight = iconWidget->height()
+ + st::normalFont->height + emptyLabel->height()
+ + (emptyNextLabel
+ ? st::normalFont->height + emptyNextLabel->height()
+ : 0);
+ const auto iconY = (size.height() - totalContentHeight) / 2;
+ iconWidget->move(
+ (size.width() - iconWidget->width()) / 2,
+ iconY);
+ emptyLabel->move(
+ (size.width() - emptyLabel->width()) / 2,
+ iconY + iconWidget->height() + st::normalFont->height);
+ if (emptyNextLabel) {
+ emptyNextLabel->move(
+ (size.width() - emptyNextLabel->width()) / 2,
+ iconY + iconWidget->height() + st::normalFont->height
+ + emptyLabel->height() + st::normalFont->height);
+ }
+ }, container->lifetime());
+
+ return result;
+}
class PreviewDelegate final : public HistoryView::DefaultElementDelegate {
public:
@@ -185,153 +239,7 @@ private:
};
-ColorSample::ColorSample(
- not_null parent,
- not_null