Merge tag 'v4.15.2' into dev
# Conflicts: # Telegram/Resources/winrc/Telegram.rc # Telegram/Resources/winrc/Updater.rc # Telegram/SourceFiles/core/version.h # Telegram/SourceFiles/info/info_wrap_widget.cpp # Telegram/SourceFiles/settings/settings_common_session.cpp # Telegram/lib_ui # docs/building-mac.md # snap/snapcraft.yaml
2
.github/workflows/mac.yml
vendored
|
@ -64,7 +64,7 @@ jobs:
|
|||
- name: First set up.
|
||||
run: |
|
||||
sudo chown -R `whoami`:admin /usr/local/share
|
||||
brew install automake ninja pkg-config
|
||||
brew install automake ninja pkg-config nasm meson
|
||||
|
||||
# Disable spotlight.
|
||||
sudo mdutil -a -i off
|
||||
|
|
3
.gitmodules
vendored
|
@ -100,3 +100,6 @@
|
|||
[submodule "Telegram/ThirdParty/libprisma"]
|
||||
path = Telegram/ThirdParty/libprisma
|
||||
url = https://github.com/desktop-app/libprisma.git
|
||||
[submodule "Telegram/ThirdParty/xdg-desktop-portal"]
|
||||
path = Telegram/ThirdParty/xdg-desktop-portal
|
||||
url = https://github.com/flatpak/xdg-desktop-portal.git
|
||||
|
|
|
@ -248,6 +248,8 @@ PRIVATE
|
|||
boxes/filters/edit_filter_box.h
|
||||
boxes/filters/edit_filter_chats_list.cpp
|
||||
boxes/filters/edit_filter_chats_list.h
|
||||
boxes/filters/edit_filter_chats_preview.cpp
|
||||
boxes/filters/edit_filter_chats_preview.h
|
||||
boxes/filters/edit_filter_links.cpp
|
||||
boxes/filters/edit_filter_links.h
|
||||
boxes/peers/add_bot_to_chat_box.cpp
|
||||
|
@ -514,6 +516,14 @@ PRIVATE
|
|||
core/version.h
|
||||
countries/countries_manager.cpp
|
||||
countries/countries_manager.h
|
||||
data/business/data_business_chatbots.cpp
|
||||
data/business/data_business_chatbots.h
|
||||
data/business/data_business_common.cpp
|
||||
data/business/data_business_common.h
|
||||
data/business/data_business_info.cpp
|
||||
data/business/data_business_info.h
|
||||
data/business/data_shortcut_messages.cpp
|
||||
data/business/data_shortcut_messages.h
|
||||
data/notify/data_notify_settings.cpp
|
||||
data/notify/data_notify_settings.h
|
||||
data/notify/data_peer_notify_settings.cpp
|
||||
|
@ -1345,6 +1355,22 @@ PRIVATE
|
|||
profile/profile_block_widget.h
|
||||
profile/profile_cover_drop_area.cpp
|
||||
profile/profile_cover_drop_area.h
|
||||
settings/business/settings_away_message.cpp
|
||||
settings/business/settings_away_message.h
|
||||
settings/business/settings_shortcut_messages.cpp
|
||||
settings/business/settings_shortcut_messages.h
|
||||
settings/business/settings_chatbots.cpp
|
||||
settings/business/settings_chatbots.h
|
||||
settings/business/settings_greeting.cpp
|
||||
settings/business/settings_greeting.h
|
||||
settings/business/settings_location.cpp
|
||||
settings/business/settings_location.h
|
||||
settings/business/settings_quick_replies.cpp
|
||||
settings/business/settings_quick_replies.h
|
||||
settings/business/settings_recipients_helper.cpp
|
||||
settings/business/settings_recipients_helper.h
|
||||
settings/business/settings_working_hours.cpp
|
||||
settings/business/settings_working_hours.h
|
||||
settings/cloud_password/settings_cloud_password_common.cpp
|
||||
settings/cloud_password/settings_cloud_password_common.h
|
||||
settings/cloud_password/settings_cloud_password_email.cpp
|
||||
|
@ -1363,6 +1389,8 @@ PRIVATE
|
|||
settings/settings_advanced.h
|
||||
settings/settings_blocked_peers.cpp
|
||||
settings/settings_blocked_peers.h
|
||||
settings/settings_business.cpp
|
||||
settings/settings_business.h
|
||||
settings/settings_chat.cpp
|
||||
settings/settings_chat.h
|
||||
settings/settings_calls.cpp
|
||||
|
@ -1722,7 +1750,7 @@ else()
|
|||
)
|
||||
|
||||
include(${cmake_helpers_loc}/external/glib/generate_dbus.cmake)
|
||||
generate_dbus(Telegram org.freedesktop.portal. XdpInhibit ${src_loc}/platform/linux/org.freedesktop.portal.Inhibit.xml)
|
||||
generate_dbus(Telegram org.freedesktop.portal. XdpBackground ${third_party_loc}/xdg-desktop-portal/data/org.freedesktop.portal.Background.xml)
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_X11_INTEGRATION)
|
||||
target_link_libraries(Telegram
|
||||
|
@ -1796,6 +1824,7 @@ set_target_properties(Telegram PROPERTIES
|
|||
XCODE_ATTRIBUTE_ALWAYS_SEARCH_USER_PATHS NO
|
||||
XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY libc++
|
||||
XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS --deep
|
||||
XCODE_ATTRIBUTE_CLANG_DEBUG_INFORMATION_LEVEL $<IF:$<CONFIG:Debug>,default,line-tables-only>
|
||||
)
|
||||
set(entitlement_sources
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Telegram/Telegram.entitlements"
|
||||
|
|
BIN
Telegram/Resources/animations/greeting.tgs
Normal file
BIN
Telegram/Resources/animations/hours.tgs
Normal file
BIN
Telegram/Resources/animations/location.tgs
Normal file
BIN
Telegram/Resources/animations/phone.tgs
Normal file
BIN
Telegram/Resources/animations/robot.tgs
Normal file
BIN
Telegram/Resources/animations/sleep.tgs
Normal file
BIN
Telegram/Resources/animations/writing.tgs
Normal file
BIN
Telegram/Resources/art/business_logo.png
Normal file
After Width: | Height: | Size: 47 KiB |
|
@ -559,3 +559,26 @@ div.toast_shown {
|
|||
opacity: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.bot_buttons_table {
|
||||
border-spacing: 0px 2px;
|
||||
width: 100%;
|
||||
}
|
||||
.bot_button {
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-color: #168acd40;
|
||||
}
|
||||
.bot_button_row {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
padding: 0px;
|
||||
width:100%;
|
||||
}
|
||||
.bot_button_row div {
|
||||
display: table-cell;
|
||||
}
|
||||
.bot_button_column_separator {
|
||||
width: 2px
|
||||
}
|
||||
|
|
|
@ -62,6 +62,12 @@ function ShowNotAvailableEmoji() {
|
|||
return false;
|
||||
}
|
||||
|
||||
function ShowTextCopied(content) {
|
||||
navigator.clipboard.writeText(content);
|
||||
ShowToast("Text copied to clipboard.");
|
||||
return false;
|
||||
}
|
||||
|
||||
function ShowSpoiler(target) {
|
||||
if (target.classList.contains("hidden")) {
|
||||
target.classList.toggle("hidden");
|
||||
|
|
BIN
Telegram/Resources/icons/chat/large_away.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Telegram/Resources/icons/chat/large_away@2x.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
Telegram/Resources/icons/chat/large_away@3x.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
Telegram/Resources/icons/chat/large_greeting.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
Telegram/Resources/icons/chat/large_greeting@2x.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
Telegram/Resources/icons/chat/large_greeting@3x.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
Telegram/Resources/icons/chat/large_quickreply.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Telegram/Resources/icons/chat/large_quickreply@2x.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
Telegram/Resources/icons/chat/large_quickreply@3x.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
Telegram/Resources/icons/folders/folder_existing_chats.png
Normal file
After Width: | Height: | Size: 592 B |
BIN
Telegram/Resources/icons/folders/folder_existing_chats@2x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/folders/folder_existing_chats@3x.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/folders/folder_new_chats.png
Normal file
After Width: | Height: | Size: 598 B |
BIN
Telegram/Resources/icons/folders/folder_new_chats@2x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/folders/folder_new_chats@3x.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/menu/shop.png
Normal file
After Width: | Height: | Size: 687 B |
BIN
Telegram/Resources/icons/menu/shop@2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/menu/shop@3x.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 662 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 499 B |
After Width: | Height: | Size: 928 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 765 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 454 B |
After Width: | Height: | Size: 845 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 615 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
BIN
Telegram/Resources/icons/settings/premium/market.png
Normal file
After Width: | Height: | Size: 396 B |
BIN
Telegram/Resources/icons/settings/premium/market@2x.png
Normal file
After Width: | Height: | Size: 607 B |
BIN
Telegram/Resources/icons/settings/premium/market@3x.png
Normal file
After Width: | Height: | Size: 955 B |
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 568 B |
Before Width: | Height: | Size: 787 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -1313,6 +1313,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_info_link_label" = "Link";
|
||||
"lng_info_location_label" = "Location";
|
||||
"lng_info_about_label" = "About";
|
||||
"lng_info_work_open" = "Open";
|
||||
"lng_info_work_closed" = "Closed";
|
||||
"lng_info_hours_label" = "Business hours";
|
||||
"lng_info_hours_closed" = "closed";
|
||||
"lng_info_hours_opens_in_minutes#one" = "opens in {count} minute";
|
||||
"lng_info_hours_opens_in_minutes#other" = "opens in {count} minutes";
|
||||
"lng_info_hours_opens_in_hours#one" = "opens in {count} hour";
|
||||
"lng_info_hours_opens_in_hours#other" = "opens in {count} hours";
|
||||
"lng_info_hours_opens_in_days#one" = "opens in {count} day";
|
||||
"lng_info_hours_opens_in_days#other" = "opens in {count} days";
|
||||
"lng_info_hours_open_full" = "open 24 hours";
|
||||
"lng_info_hours_next_day" = "{time} (next day)";
|
||||
"lng_info_hours_local_time" = "local time";
|
||||
"lng_info_hours_my_time" = "my time";
|
||||
"lng_info_user_title" = "User Info";
|
||||
"lng_info_bot_title" = "Bot Info";
|
||||
"lng_info_group_title" = "Group Info";
|
||||
|
@ -2056,6 +2070,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_premium_summary_about_animated_userpics" = "Video avatars animated in chat lists and chats to allow for additional self-expression.";
|
||||
"lng_premium_summary_subtitle_translation" = "Real-Time Translation";
|
||||
"lng_premium_summary_about_translation" = "Real-time translation of channels and chats into other languages.";
|
||||
"lng_premium_summary_subtitle_business" = "Telegram Business";
|
||||
"lng_premium_summary_about_business" = "Upgrade your account with business features such as location, opening hours and quick replies.";
|
||||
"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";
|
||||
|
@ -2154,6 +2170,125 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_premium_gifts_terms" = "By gifting Telegram Premium, you agree to the Telegram {link} and {policy}.";
|
||||
"lng_premium_gifts_terms_policy" = "Privacy Policy";
|
||||
|
||||
"lng_business_title" = "Telegram Business";
|
||||
"lng_business_about" = "Turn your account to a business page with these additional features.";
|
||||
"lng_business_unlocked" = "You have now unlocked these additional business features.";
|
||||
"lng_business_subtitle_location" = "Location";
|
||||
"lng_business_about_location" = "Display the location of your business on your account.";
|
||||
"lng_business_subtitle_opening_hours" = "Opening Hours";
|
||||
"lng_business_about_opening_hours" = "Show to your customers when you are open for business.";
|
||||
"lng_business_subtitle_quick_replies" = "Quick Replies";
|
||||
"lng_business_about_quick_replies" = "Set up shortcuts up to 20 messages each to respond to customers faster.";
|
||||
"lng_business_subtitle_greeting_messages" = "Greeting Messages";
|
||||
"lng_business_about_greeting_messages" = "Create greetings that will be automatically sent to new customers.";
|
||||
"lng_business_subtitle_away_messages" = "Away Messages";
|
||||
"lng_business_about_away_messages" = "Define messages that are automatically sent when you are off.";
|
||||
"lng_business_subtitle_chatbots" = "Chatbots";
|
||||
"lng_business_about_chatbots" = "Add any third party chatbots that will process customer interactions.";
|
||||
|
||||
"lng_location_title" = "Location";
|
||||
"lng_location_about" = "Display the location of your business on your account.";
|
||||
"lng_location_address" = "Enter Address";
|
||||
"lng_location_fallback" = "You can set your location on the map from your mobile device.";
|
||||
|
||||
"lng_hours_title" = "Business Hours";
|
||||
"lng_hours_about" = "Turn this on to show your opening hours schedule to your customers.";
|
||||
"lng_hours_show" = "Show Business Hours";
|
||||
"lng_hours_time_zone" = "Time Zone";
|
||||
"lng_hours_monday" = "Monday";
|
||||
"lng_hours_tuesday" = "Tuesday";
|
||||
"lng_hours_wednesday" = "Wednesday";
|
||||
"lng_hours_thursday" = "Thursday";
|
||||
"lng_hours_friday" = "Friday";
|
||||
"lng_hours_saturday" = "Saturday";
|
||||
"lng_hours_sunday" = "Sunday";
|
||||
"lng_hours_closed" = "Closed";
|
||||
"lng_hours_open_full" = "Open 24 hours";
|
||||
"lng_hours_next_day" = "{time} (Next day)";
|
||||
"lng_hours_on_next_day" = "Next day {time}";
|
||||
"lng_hours_time_zone_title" = "Choose Time Zone";
|
||||
"lng_hours_add_button" = "Add a Set of Hours";
|
||||
"lng_hours_opening" = "Opening Time";
|
||||
"lng_hours_closing" = "Closing Time";
|
||||
"lng_hours_remove" = "Remove";
|
||||
"lng_hours_about_day" = "Specify your working hours during the day.";
|
||||
|
||||
"lng_replies_title" = "Quick Replies";
|
||||
"lng_replies_about" = "Set up shortcuts with rich text and media to respond to messages faster.";
|
||||
"lng_replies_add" = "Add Quick Reply";
|
||||
"lng_replies_add_title" = "New Quick Reply";
|
||||
"lng_replies_add_shortcut" = "Add a shortcut for your reply.";
|
||||
"lng_replies_add_placeholder" = "Shortcut";
|
||||
"lng_replies_add_exists" = "This shortcut already exists.";
|
||||
"lng_replies_empty_title" = "New Quick Reply";
|
||||
"lng_replies_empty_about" = "Enter a message below that will be sent in chat when you type {shortcut}.\n\nYou can access Quick Replies in any chat by typing /.";
|
||||
"lng_replies_remove_title" = "Remove Shortcut";
|
||||
"lng_replies_remove_text" = "You didn't create a quick reply message. Do you want to remove the shortcut?";
|
||||
"lng_replies_edit_title" = "Edit Shortcut";
|
||||
"lng_replies_edit_about" = "Edit the name for this shortcut.";
|
||||
"lng_replies_message_placeholder" = "Add a Quick Reply";
|
||||
"lng_replies_delete_sure" = "Are you sure you want to delete this quick reply with all its messages?";
|
||||
"lng_replies_error_occupied" = "This shortcut is already used.";
|
||||
"lng_replies_edit_button" = "Edit Quick Replies";
|
||||
|
||||
"lng_greeting_title" = "Greeting Message";
|
||||
"lng_greeting_about" = "Greet customers when they message you the first time or after a period of no activity.";
|
||||
"lng_greeting_enable" = "Send Greeting Message";
|
||||
"lng_greeting_create" = "Create a Greeting Message";
|
||||
"lng_greeting_recipients" = "Recipients";
|
||||
"lng_greeting_select" = "Select chats or entire chat categories for sending a greeting message.";
|
||||
"lng_greeting_period_title" = "Period of no activity";
|
||||
"lng_greeting_period_about" = "Choose how many days should pass after your last interaction with a recipient to send them a greeting in response to their message.";
|
||||
"lng_greeting_empty_title" = "New Greeting Message";
|
||||
"lng_greeting_empty_about" = "Create greetings that will be automatically sent to new customers.";
|
||||
"lng_greeting_message_placeholder" = "Add a Greeting";
|
||||
"lng_greeting_limit_reached" = "You have too many quick replies. Remove one to add a greeting message.";
|
||||
"lng_greeting_recipients_empty" = "Please choose at least one recipient.";
|
||||
|
||||
"lng_away_title" = "Away Message";
|
||||
"lng_away_about" = "Automatically reply with a message when you are away.";
|
||||
"lng_away_enable" = "Send Away Message";
|
||||
"lng_away_create" = "Create an Away Message";
|
||||
"lng_away_schedule" = "Schedule";
|
||||
"lng_away_schedule_always" = "Send Always";
|
||||
"lng_away_schedule_outside" = "Outside of Business Hours";
|
||||
"lng_away_schedule_custom" = "Custom Schedule";
|
||||
"lng_away_custom_start" = "Start Time";
|
||||
"lng_away_custom_end" = "End Time";
|
||||
"lng_away_offline_only" = "Only if Offline";
|
||||
"lng_away_offline_only_about" = "Don't send the away message if you've recently been online.";
|
||||
"lng_away_recipients" = "Recipients";
|
||||
"lng_away_select" = "Select chats or entire chat categories for sending an away message.";
|
||||
"lng_away_empty_title" = "New Away Message";
|
||||
"lng_away_empty_about" = "Add messages that will be automatically sent when you are off.";
|
||||
"lng_away_message_placeholder" = "Add an Away Message";
|
||||
"lng_away_limit_reached" = "You have too many quick replies. Remove one to add an away message.";
|
||||
|
||||
"lng_business_edit_messages" = "Edit messages";
|
||||
"lng_business_limit_reached#one" = "Limit of {count} message reached.";
|
||||
"lng_business_limit_reached#other" = "Limit of {count} messages reached.";
|
||||
|
||||
"lng_chatbots_title" = "Chatbots";
|
||||
"lng_chatbots_about" = "Add a bot to your account to help you automatically process and respond to the messages you receive. {link}";
|
||||
"lng_chatbots_about_link" = "Learn more...";
|
||||
"lng_chatbots_placeholder" = "Enter bot URL or username";
|
||||
"lng_chatbots_add_about" = "Enter the link to the Telegram bot that you want to automatically process your chats.";
|
||||
"lng_chatbots_access_title" = "Chats accessible for the bot";
|
||||
"lng_chatbots_all_except" = "All 1-to-1 Chats Except...";
|
||||
"lng_chatbots_selected" = "Only Selected Chats";
|
||||
"lng_chatbots_excluded_title" = "Excluded chats";
|
||||
"lng_chatbots_exclude_button" = "Exclude Chats";
|
||||
"lng_chatbots_included_title" = "Included chats";
|
||||
"lng_chatbots_include_button" = "Select Chats";
|
||||
"lng_chatbots_exclude_about" = "Select chats or entire chat categories which the bot will not have access to.";
|
||||
"lng_chatbots_permissions_title" = "Bot permissions";
|
||||
"lng_chatbots_reply" = "Reply to Messages";
|
||||
"lng_chatbots_reply_about" = "The bot will be able to view all new incoming messages, but not the messages that had been sent before you added the bot.";
|
||||
"lng_chatbots_remove" = "Remove Bot";
|
||||
"lng_chatbots_not_found" = "Chatbot not found.";
|
||||
"lng_chatbots_add" = "Add";
|
||||
"lng_chatbots_info_url" = "https://telegram.org/privacy";
|
||||
|
||||
"lng_boost_channel_button" = "Boost Channel";
|
||||
"lng_boost_group_button" = "Boost Group";
|
||||
"lng_boost_again_button" = "Boost Again";
|
||||
|
@ -2917,6 +3052,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_context_translate_selected" = "Translate Selected Text";
|
||||
"lng_context_read_hidden" = "read";
|
||||
"lng_context_read_show" = "show when";
|
||||
"lng_context_edit_shortcut" = "Edit Shortcut";
|
||||
"lng_context_delete_shortcut" = "Delete Quick Reply";
|
||||
|
||||
"lng_add_tag_about" = "Tag this message with an emoji for quick search.";
|
||||
"lng_subscribe_tag_about" = "Organize your Saved Messages with tags. {link}";
|
||||
|
@ -4305,6 +4442,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_filters_type_non_contacts" = "Non-Contacts";
|
||||
"lng_filters_type_groups" = "Groups";
|
||||
"lng_filters_type_channels" = "Channels";
|
||||
"lng_filters_type_new" = "New Chats";
|
||||
"lng_filters_type_existing" = "Existing Chats";
|
||||
"lng_filters_type_bots" = "Bots";
|
||||
"lng_filters_type_no_archived" = "Archived";
|
||||
"lng_filters_type_no_muted" = "Muted";
|
||||
|
@ -4724,6 +4863,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_boosts_prepaid_giveaway_status#one" = "{count} subscription {duration}";
|
||||
"lng_boosts_prepaid_giveaway_status#other" = "{count} subscriptions {duration}";
|
||||
|
||||
"lng_contact_add" = "Add";
|
||||
"lng_contact_send_message" = "message";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||
|
|
|
@ -14,5 +14,12 @@
|
|||
<file alias="voice_ttl_idle.tgs">../../animations/voice_ttl_idle.tgs</file>
|
||||
<file alias="voice_ttl_start.tgs">../../animations/voice_ttl_start.tgs</file>
|
||||
<file alias="palette.tgs">../../animations/palette.tgs</file>
|
||||
<file alias="sleep.tgs">../../animations/sleep.tgs</file>
|
||||
<file alias="greeting.tgs">../../animations/greeting.tgs</file>
|
||||
<file alias="location.tgs">../../animations/location.tgs</file>
|
||||
<file alias="robot.tgs">../../animations/robot.tgs</file>
|
||||
<file alias="writing.tgs">../../animations/writing.tgs</file>
|
||||
<file alias="hours.tgs">../../animations/hours.tgs</file>
|
||||
<file alias="phone.tgs">../../animations/phone.tgs</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<file alias="art/background.tgv">../../art/background.tgv</file>
|
||||
<file alias="art/bg_thumbnail.png">../../art/bg_thumbnail.png</file>
|
||||
<file alias="art/bg_initial.jpg">../../art/bg_initial.jpg</file>
|
||||
<file alias="art/business_logo.png">../../art/business_logo.png</file>
|
||||
<file alias="art/logo_256.png">../../art/logo_256.png</file>
|
||||
<file alias="art/logo_256_no_margin.png">../../art/logo_256_no_margin.png</file>
|
||||
<file alias="art/themeimage.jpg">../../art/themeimage.jpg</file>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="4.15.0.0" />
|
||||
Version="4.15.2.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
|
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,15,0,0
|
||||
PRODUCTVERSION 4,15,0,0
|
||||
FILEVERSION 4,15,2,0
|
||||
PRODUCTVERSION 4,15,2,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -62,10 +62,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop"
|
||||
VALUE "FileVersion", "4.15.0.0"
|
||||
VALUE "FileVersion", "4.15.2.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.15.0.0"
|
||||
VALUE "ProductVersion", "4.15.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,15,0,0
|
||||
PRODUCTVERSION 4,15,0,0
|
||||
FILEVERSION 4,15,2,0
|
||||
PRODUCTVERSION 4,15,2,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -53,10 +53,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop Updater"
|
||||
VALUE "FileVersion", "4.15.0.0"
|
||||
VALUE "FileVersion", "4.15.2.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2024"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.15.0.0"
|
||||
VALUE "ProductVersion", "4.15.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -22,6 +22,7 @@ inline constexpr auto kScheduledUntilOnlineTimestamp = TimeId(0x7FFFFFFE);
|
|||
struct SendOptions {
|
||||
PeerData *sendAs = nullptr;
|
||||
TimeId scheduled = 0;
|
||||
BusinessShortcutId shortcutId = 0;
|
||||
bool silent = false;
|
||||
bool handleSupportSwitch = false;
|
||||
bool hideViaBot = false;
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_media.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -88,10 +89,15 @@ mtpRequestId EditMessage(
|
|||
: emptyFlag)
|
||||
| (options.scheduled
|
||||
? MTPmessages_EditMessage::Flag::f_schedule_date
|
||||
: emptyFlag)
|
||||
| (item->isBusinessShortcut()
|
||||
? MTPmessages_EditMessage::Flag::f_quick_reply_shortcut_id
|
||||
: emptyFlag);
|
||||
|
||||
const auto id = item->isScheduled()
|
||||
? session->data().scheduledMessages().lookupId(item)
|
||||
: item->isBusinessShortcut()
|
||||
? session->data().shortcutMessages().lookupId(item)
|
||||
: item->id;
|
||||
return api->request(MTPmessages_EditMessage(
|
||||
MTP_flags(flags),
|
||||
|
@ -101,7 +107,8 @@ mtpRequestId EditMessage(
|
|||
inputMedia.value_or(Data::WebPageForMTP(webpage, text.isEmpty())),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(options.scheduled)
|
||||
MTP_int(options.scheduled),
|
||||
MTP_int(item->shortcutId())
|
||||
)).done([=](
|
||||
const MTPUpdates &result,
|
||||
[[maybe_unused]] mtpRequestId requestId) {
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_updates.h"
|
||||
#include "apiwrap.h"
|
||||
#include "base/random.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_poll.h"
|
||||
|
@ -69,6 +70,9 @@ void Polls::create(
|
|||
if (action.options.scheduled) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
|
||||
}
|
||||
if (action.options.shortcutId) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
|
||||
}
|
||||
const auto sendAs = action.options.sendAs;
|
||||
if (sendAs) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
|
||||
|
@ -89,7 +93,8 @@ void Polls::create(
|
|||
MTPReplyMarkup(),
|
||||
MTPVector<MTPMessageEntity>(),
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, action.options.shortcutId)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
if (clearCloudDraft) {
|
||||
history->finishSavingCloudDraft(
|
||||
|
@ -184,7 +189,8 @@ void Polls::close(not_null<HistoryItem*> item) {
|
|||
PollDataToInputMedia(poll, true),
|
||||
MTPReplyMarkup(),
|
||||
MTPVector<MTPMessageEntity>(),
|
||||
MTP_int(0) // schedule_date
|
||||
MTP_int(0), // schedule_date
|
||||
MTPint() // quick_reply_shortcut_id
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_pollCloseRequestIds.erase(itemId);
|
||||
_session->updates().applyUpdates(result);
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_text_entities.h"
|
||||
#include "base/random.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "data/data_channel.h" // ChannelData::addsSignature.
|
||||
|
@ -84,20 +85,21 @@ void SendExistingMedia(
|
|||
? (*localMessageId)
|
||||
: session->data().nextLocalMessageId());
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
const auto &action = message.action;
|
||||
|
||||
auto flags = NewMessageFlags(peer);
|
||||
auto sendFlags = MTPmessages_SendMedia::Flags(0);
|
||||
if (message.action.replyTo) {
|
||||
if (action.replyTo) {
|
||||
flags |= MessageFlag::HasReplyInfo;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
||||
}
|
||||
const auto anonymousPost = peer->amAnonymous();
|
||||
const auto silentPost = ShouldSendSilent(peer, message.action.options);
|
||||
InnerFillMessagePostFlags(message.action.options, peer, flags);
|
||||
const auto silentPost = ShouldSendSilent(peer, action.options);
|
||||
InnerFillMessagePostFlags(action.options, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||
}
|
||||
const auto sendAs = message.action.options.sendAs;
|
||||
const auto sendAs = action.options.sendAs;
|
||||
const auto messageFromId = sendAs
|
||||
? sendAs->id
|
||||
: anonymousPost
|
||||
|
@ -124,32 +126,34 @@ void SendExistingMedia(
|
|||
}
|
||||
const auto captionText = caption.text;
|
||||
|
||||
if (message.action.options.scheduled) {
|
||||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
|
||||
}
|
||||
if (action.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
|
||||
}
|
||||
|
||||
session->data().registerMessageRandomId(randomId, newId);
|
||||
|
||||
const auto viaBotId = UserId();
|
||||
history->addNewLocalMessage(
|
||||
newId.msg,
|
||||
flags,
|
||||
viaBotId,
|
||||
message.action.replyTo,
|
||||
HistoryItem::NewMessageDate(message.action.options.scheduled),
|
||||
messageFromId,
|
||||
messagePostAuthor,
|
||||
media,
|
||||
caption,
|
||||
HistoryMessageMarkupData());
|
||||
history->addNewLocalMessage({
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = action.replyTo,
|
||||
.date = HistoryItem::NewMessageDate(action.options),
|
||||
.shortcutId = action.options.shortcutId,
|
||||
.postAuthor = messagePostAuthor,
|
||||
}, media, caption);
|
||||
|
||||
const auto performRequest = [=](const auto &repeatRequest) -> void {
|
||||
auto &histories = history->owner().histories();
|
||||
const auto session = &history->session();
|
||||
const auto usedFileReference = media->fileReference();
|
||||
histories.sendPreparedMessage(
|
||||
history,
|
||||
message.action.replyTo,
|
||||
action.replyTo,
|
||||
randomId,
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(sendFlags),
|
||||
|
@ -160,8 +164,9 @@ void SendExistingMedia(
|
|||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(message.action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(session, action.options.shortcutId)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
if (error.code() == 400
|
||||
|
@ -180,7 +185,7 @@ void SendExistingMedia(
|
|||
};
|
||||
performRequest(performRequest);
|
||||
|
||||
api->finishForwarding(message.action);
|
||||
api->finishForwarding(action);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -259,7 +264,10 @@ bool SendDice(MessageToSend &message) {
|
|||
message.textWithTags = TextWithTags();
|
||||
message.action.clearDraft = false;
|
||||
message.action.generateLocal = true;
|
||||
api->sendAction(message.action);
|
||||
|
||||
|
||||
const auto &action = message.action;
|
||||
api->sendAction(action);
|
||||
|
||||
const auto newId = FullMsgId(
|
||||
peer->id,
|
||||
|
@ -269,17 +277,17 @@ bool SendDice(MessageToSend &message) {
|
|||
auto &histories = history->owner().histories();
|
||||
auto flags = NewMessageFlags(peer);
|
||||
auto sendFlags = MTPmessages_SendMedia::Flags(0);
|
||||
if (message.action.replyTo) {
|
||||
if (action.replyTo) {
|
||||
flags |= MessageFlag::HasReplyInfo;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
||||
}
|
||||
const auto anonymousPost = peer->amAnonymous();
|
||||
const auto silentPost = ShouldSendSilent(peer, message.action.options);
|
||||
InnerFillMessagePostFlags(message.action.options, peer, flags);
|
||||
const auto silentPost = ShouldSendSilent(peer, action.options);
|
||||
InnerFillMessagePostFlags(action.options, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||
}
|
||||
const auto sendAs = message.action.options.sendAs;
|
||||
const auto sendAs = action.options.sendAs;
|
||||
const auto messageFromId = sendAs
|
||||
? sendAs->id
|
||||
: anonymousPost
|
||||
|
@ -292,28 +300,31 @@ bool SendDice(MessageToSend &message) {
|
|||
? session->user()->name()
|
||||
: QString();
|
||||
|
||||
if (message.action.options.scheduled) {
|
||||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
|
||||
}
|
||||
if (action.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
|
||||
}
|
||||
|
||||
session->data().registerMessageRandomId(randomId, newId);
|
||||
|
||||
const auto viaBotId = UserId();
|
||||
history->addNewLocalMessage(
|
||||
newId.msg,
|
||||
flags,
|
||||
viaBotId,
|
||||
message.action.replyTo,
|
||||
HistoryItem::NewMessageDate(message.action.options.scheduled),
|
||||
messageFromId,
|
||||
messagePostAuthor,
|
||||
TextWithEntities(),
|
||||
MTP_messageMediaDice(MTP_int(0), MTP_string(emoji)),
|
||||
HistoryMessageMarkupData());
|
||||
history->addNewLocalMessage({
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = action.replyTo,
|
||||
.date = HistoryItem::NewMessageDate(action.options),
|
||||
.shortcutId = action.options.shortcutId,
|
||||
.postAuthor = messagePostAuthor,
|
||||
}, TextWithEntities(), MTP_messageMediaDice(
|
||||
MTP_int(0),
|
||||
MTP_string(emoji)));
|
||||
histories.sendPreparedMessage(
|
||||
history,
|
||||
message.action.replyTo,
|
||||
action.replyTo,
|
||||
randomId,
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(sendFlags),
|
||||
|
@ -324,13 +335,14 @@ bool SendDice(MessageToSend &message) {
|
|||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
MTP_vector<MTPMessageEntity>(),
|
||||
MTP_int(message.action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(session, action.options.shortcutId)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
});
|
||||
api->finishForwarding(message.action);
|
||||
api->finishForwarding(action);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -406,7 +418,13 @@ void SendConfirmedFile(
|
|||
if (file->to.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
|
||||
// Scheduled messages have no the 'edited' badge.
|
||||
// Scheduled messages have no 'edited' badge.
|
||||
flags |= MessageFlag::HideEdited;
|
||||
}
|
||||
if (file->to.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
|
||||
// Shortcut messages have no 'edited' badge.
|
||||
flags |= MessageFlag::HideEdited;
|
||||
}
|
||||
if (file->type == SendMediaType::Audio) {
|
||||
|
@ -415,8 +433,7 @@ void SendConfirmedFile(
|
|||
}
|
||||
}
|
||||
|
||||
const auto messageFromId =
|
||||
file->to.options.sendAs
|
||||
const auto messageFromId = file->to.options.sendAs
|
||||
? file->to.options.sendAs->id
|
||||
: anonymousPost
|
||||
? PeerId()
|
||||
|
@ -486,19 +503,16 @@ void SendConfirmedFile(
|
|||
edition.savePreviousMedia = true;
|
||||
itemToEdit->applyEdition(std::move(edition));
|
||||
} else {
|
||||
const auto viaBotId = UserId();
|
||||
history->addNewLocalMessage(
|
||||
newId.msg,
|
||||
flags,
|
||||
viaBotId,
|
||||
file->to.replyTo,
|
||||
HistoryItem::NewMessageDate(file->to.options.scheduled),
|
||||
messageFromId,
|
||||
messagePostAuthor,
|
||||
caption,
|
||||
media,
|
||||
HistoryMessageMarkupData(),
|
||||
groupId);
|
||||
history->addNewLocalMessage({
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = file->to.replyTo,
|
||||
.date = HistoryItem::NewMessageDate(file->to.options),
|
||||
.shortcutId = file->to.options.shortcutId,
|
||||
.postAuthor = messagePostAuthor,
|
||||
.groupedId = groupId,
|
||||
}, caption, media);
|
||||
}
|
||||
|
||||
if (isEditing) {
|
||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mtproto/mtp_instance.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "mtproto/mtproto_dc_options.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "data/data_saved_messages.h"
|
||||
|
@ -1141,7 +1142,8 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
|
|||
MTPlong(),
|
||||
MTPMessageReactions(),
|
||||
MTPVector<MTPRestrictionReason>(),
|
||||
MTP_int(d.vttl_period().value_or_empty())),
|
||||
MTP_int(d.vttl_period().value_or_empty()),
|
||||
MTPint()), // quick_reply_shortcut_id
|
||||
MessageFlags(),
|
||||
NewMessageType::Unread);
|
||||
} break;
|
||||
|
@ -1174,7 +1176,8 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
|
|||
MTPlong(),
|
||||
MTPMessageReactions(),
|
||||
MTPVector<MTPRestrictionReason>(),
|
||||
MTP_int(d.vttl_period().value_or_empty())),
|
||||
MTP_int(d.vttl_period().value_or_empty()),
|
||||
MTPint()), // quick_reply_shortcut_id
|
||||
MessageFlags(),
|
||||
NewMessageType::Unread);
|
||||
} break;
|
||||
|
@ -1565,6 +1568,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
if (const auto local = owner.message(id)) {
|
||||
if (local->isScheduled()) {
|
||||
session().data().scheduledMessages().apply(d, local);
|
||||
} else if (local->isBusinessShortcut()) {
|
||||
session().data().shortcutMessages().apply(d, local);
|
||||
} else {
|
||||
const auto existing = session().data().message(
|
||||
id.peer,
|
||||
|
@ -1780,6 +1785,31 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
session().data().scheduledMessages().apply(d);
|
||||
} break;
|
||||
|
||||
case mtpc_updateQuickReplies: {
|
||||
const auto &d = update.c_updateQuickReplies();
|
||||
session().data().shortcutMessages().apply(d);
|
||||
} break;
|
||||
|
||||
case mtpc_updateNewQuickReply: {
|
||||
const auto &d = update.c_updateNewQuickReply();
|
||||
session().data().shortcutMessages().apply(d);
|
||||
} break;
|
||||
|
||||
case mtpc_updateDeleteQuickReply: {
|
||||
const auto &d = update.c_updateDeleteQuickReply();
|
||||
session().data().shortcutMessages().apply(d);
|
||||
} break;
|
||||
|
||||
case mtpc_updateQuickReplyMessage: {
|
||||
const auto &d = update.c_updateQuickReplyMessage();
|
||||
session().data().shortcutMessages().apply(d);
|
||||
} break;
|
||||
|
||||
case mtpc_updateDeleteQuickReplyMessages: {
|
||||
const auto &d = update.c_updateDeleteQuickReplyMessages();
|
||||
session().data().shortcutMessages().apply(d);
|
||||
} break;
|
||||
|
||||
case mtpc_updateWebPage: {
|
||||
auto &d = update.c_updateWebPage();
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_premium.h"
|
||||
#include "api/api_user_names.h"
|
||||
#include "api/api_websites.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_web_page.h"
|
||||
|
@ -968,6 +969,7 @@ void ApiWrap::requestMoreDialogsIfNeeded() {
|
|||
}
|
||||
}
|
||||
requestContacts();
|
||||
_session->data().shortcutMessages().preloadShortcuts();
|
||||
}
|
||||
|
||||
void ApiWrap::updateDialogsOffset(
|
||||
|
@ -2480,6 +2482,14 @@ void ApiWrap::refreshFileReference(
|
|||
request(MTPmessages_GetScheduledMessages(
|
||||
item->history()->peer->input,
|
||||
MTP_vector<MTPint>(1, MTP_int(realId))));
|
||||
} else if (item->isBusinessShortcut()) {
|
||||
const auto &shortcuts = _session->data().shortcutMessages();
|
||||
const auto realId = shortcuts.lookupId(item);
|
||||
request(MTPmessages_GetQuickReplyMessages(
|
||||
MTP_flags(MTPmessages_GetQuickReplyMessages::Flag::f_id),
|
||||
MTP_int(item->shortcutId()),
|
||||
MTP_vector<MTPint>(1, MTP_int(realId)),
|
||||
MTP_long(0)));
|
||||
} else if (const auto channel = item->history()->peer->asChannel()) {
|
||||
request(MTPchannels_GetMessages(
|
||||
channel->inputChannel,
|
||||
|
@ -3155,6 +3165,7 @@ void ApiWrap::sharedMediaDone(
|
|||
if (topicRootId && !topic) {
|
||||
return;
|
||||
}
|
||||
const auto hasMessages = !parsed.messageIds.empty();
|
||||
_session->storage().add(Storage::SharedMediaAddSlice(
|
||||
peer->id,
|
||||
topicRootId,
|
||||
|
@ -3163,7 +3174,7 @@ void ApiWrap::sharedMediaDone(
|
|||
parsed.noSkipRange,
|
||||
parsed.fullCount
|
||||
));
|
||||
if (type == SharedMediaType::Pinned && !parsed.messageIds.empty()) {
|
||||
if (type == SharedMediaType::Pinned && hasMessages) {
|
||||
peer->owner().history(peer)->setHasPinnedMessages(true);
|
||||
if (topic) {
|
||||
topic->setHasPinnedMessages(true);
|
||||
|
@ -3172,7 +3183,9 @@ void ApiWrap::sharedMediaDone(
|
|||
}
|
||||
|
||||
void ApiWrap::sendAction(const SendAction &action) {
|
||||
if (!action.options.scheduled && !action.replaceMediaOf) {
|
||||
if (!action.options.scheduled
|
||||
&& !action.options.shortcutId
|
||||
&& !action.replaceMediaOf) {
|
||||
const auto topicRootId = action.replyTo.topicRootId;
|
||||
const auto topic = topicRootId
|
||||
? action.history->peer->forumTopicFor(topicRootId)
|
||||
|
@ -3207,11 +3220,13 @@ void ApiWrap::finishForwarding(const SendAction &action) {
|
|||
}
|
||||
|
||||
_session->data().sendHistoryChangeNotifications();
|
||||
_session->changes().historyUpdated(
|
||||
history,
|
||||
(action.options.scheduled
|
||||
? Data::HistoryUpdate::Flag::ScheduledSent
|
||||
: Data::HistoryUpdate::Flag::MessageSent));
|
||||
if (!action.options.shortcutId) {
|
||||
_session->changes().historyUpdated(
|
||||
history,
|
||||
(action.options.scheduled
|
||||
? Data::HistoryUpdate::Flag::ScheduledSent
|
||||
: Data::HistoryUpdate::Flag::MessageSent));
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::forwardMessages(
|
||||
|
@ -3240,7 +3255,7 @@ void ApiWrap::forwardMessages(
|
|||
const auto history = action.history;
|
||||
const auto peer = history->peer;
|
||||
|
||||
if (!action.options.scheduled) {
|
||||
if (!action.options.scheduled && !action.options.shortcutId) {
|
||||
histories.readInbox(history);
|
||||
}
|
||||
const auto anonymousPost = peer->amAnonymous();
|
||||
|
@ -3258,6 +3273,10 @@ void ApiWrap::forwardMessages(
|
|||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
sendFlags |= SendFlag::f_schedule_date;
|
||||
}
|
||||
if (action.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
sendFlags |= SendFlag::f_quick_reply_shortcut;
|
||||
}
|
||||
if (draft.options != Data::ForwardOptions::PreserveInfo) {
|
||||
sendFlags |= SendFlag::f_drop_author;
|
||||
}
|
||||
|
@ -3296,7 +3315,8 @@ void ApiWrap::forwardMessages(
|
|||
peer->input,
|
||||
MTP_int(topMsgId),
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, action.options.shortcutId)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
if (shared && !--shared->requestsLeft) {
|
||||
|
@ -3340,14 +3360,15 @@ void ApiWrap::forwardMessages(
|
|||
const auto messagePostAuthor = peer->isBroadcast()
|
||||
? self->name()
|
||||
: QString();
|
||||
history->addNewLocalMessage(
|
||||
newId.msg,
|
||||
flags,
|
||||
HistoryItem::NewMessageDate(action.options.scheduled),
|
||||
messageFromId,
|
||||
messagePostAuthor,
|
||||
item,
|
||||
topMsgId);
|
||||
history->addNewLocalMessage({
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = { .topicRootId = topMsgId },
|
||||
.date = HistoryItem::NewMessageDate(action.options),
|
||||
.shortcutId = action.options.shortcutId,
|
||||
.postAuthor = messagePostAuthor,
|
||||
}, item);
|
||||
_session->data().registerMessageRandomId(randomId, newId);
|
||||
if (!localIds) {
|
||||
localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();
|
||||
|
@ -3428,6 +3449,9 @@ void ApiWrap::sendSharedContact(
|
|||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
}
|
||||
if (action.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
}
|
||||
const auto messageFromId = action.options.sendAs
|
||||
? action.options.sendAs->id
|
||||
: anonymousPost
|
||||
|
@ -3436,23 +3460,20 @@ void ApiWrap::sendSharedContact(
|
|||
const auto messagePostAuthor = peer->isBroadcast()
|
||||
? _session->user()->name()
|
||||
: QString();
|
||||
const auto viaBotId = UserId();
|
||||
const auto item = history->addNewLocalMessage(
|
||||
newId.msg,
|
||||
flags,
|
||||
viaBotId,
|
||||
action.replyTo,
|
||||
HistoryItem::NewMessageDate(action.options.scheduled),
|
||||
messageFromId,
|
||||
messagePostAuthor,
|
||||
TextWithEntities(),
|
||||
MTP_messageMediaContact(
|
||||
MTP_string(phone),
|
||||
MTP_string(firstName),
|
||||
MTP_string(lastName),
|
||||
MTP_string(), // vcard
|
||||
MTP_long(userId.bare)),
|
||||
HistoryMessageMarkupData());
|
||||
const auto item = history->addNewLocalMessage({
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = action.replyTo,
|
||||
.date = HistoryItem::NewMessageDate(action.options),
|
||||
.shortcutId = action.options.shortcutId,
|
||||
.postAuthor = messagePostAuthor,
|
||||
}, TextWithEntities(), MTP_messageMediaContact(
|
||||
MTP_string(phone),
|
||||
MTP_string(firstName),
|
||||
MTP_string(lastName),
|
||||
MTP_string(), // vcard
|
||||
MTP_long(userId.bare)));
|
||||
|
||||
const auto media = MTP_inputMediaContact(
|
||||
MTP_string(phone),
|
||||
|
@ -3635,6 +3656,17 @@ void ApiWrap::cancelLocalItem(not_null<HistoryItem*> item) {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::sendShortcutMessages(
|
||||
not_null<PeerData*> peer,
|
||||
BusinessShortcutId id) {
|
||||
request(MTPmessages_SendQuickReplyMessages(
|
||||
peer->input,
|
||||
MTP_int(id)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
const auto history = message.action.history;
|
||||
const auto peer = history->peer;
|
||||
|
@ -3776,18 +3808,20 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
|
||||
}
|
||||
const auto viaBotId = UserId();
|
||||
lastMessage = history->addNewLocalMessage(
|
||||
newId.msg,
|
||||
flags,
|
||||
viaBotId,
|
||||
action.replyTo,
|
||||
HistoryItem::NewMessageDate(action.options.scheduled),
|
||||
messageFromId,
|
||||
messagePostAuthor,
|
||||
sending,
|
||||
media,
|
||||
HistoryMessageMarkupData());
|
||||
if (action.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
|
||||
}
|
||||
lastMessage = history->addNewLocalMessage({
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = action.replyTo,
|
||||
.date = HistoryItem::NewMessageDate(action.options),
|
||||
.shortcutId = action.options.shortcutId,
|
||||
.postAuthor = messagePostAuthor,
|
||||
}, sending, media);
|
||||
const auto done = [=](
|
||||
const MTPUpdates &result,
|
||||
const MTP::Response &response) {
|
||||
|
@ -3813,6 +3847,9 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
UnixtimeFromMsgId(response.outerMsgId));
|
||||
}
|
||||
};
|
||||
const auto mtpShortcut = Data::ShortcutIdToMTP(
|
||||
_session,
|
||||
action.options.shortcutId);
|
||||
if (exactWebPage
|
||||
&& !ignoreWebPage
|
||||
&& (manualWebPage || sending.empty())) {
|
||||
|
@ -3829,8 +3866,9 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(message.action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
mtpShortcut
|
||||
), done, fail);
|
||||
} else {
|
||||
histories.sendPreparedMessage(
|
||||
|
@ -3846,7 +3884,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
mtpShortcut
|
||||
), done, fail);
|
||||
}
|
||||
isFirst = false;
|
||||
|
@ -3937,6 +3976,10 @@ void ApiWrap::sendInlineResult(
|
|||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
sendFlags |= SendFlag::f_schedule_date;
|
||||
}
|
||||
if (action.options.shortcutId) {
|
||||
flags |= MessageFlag::ShortcutMessage;
|
||||
sendFlags |= SendFlag::f_quick_reply_shortcut;
|
||||
}
|
||||
if (action.options.hideViaBot) {
|
||||
sendFlags |= SendFlag::f_hide_via;
|
||||
}
|
||||
|
@ -3955,15 +3998,18 @@ void ApiWrap::sendInlineResult(
|
|||
|
||||
_session->data().registerMessageRandomId(randomId, newId);
|
||||
|
||||
data->addToHistory(
|
||||
history,
|
||||
flags,
|
||||
newId.msg,
|
||||
messageFromId,
|
||||
HistoryItem::NewMessageDate(action.options.scheduled),
|
||||
(bot && !action.options.hideViaBot) ? peerToUser(bot->id) : 0,
|
||||
action.replyTo,
|
||||
messagePostAuthor);
|
||||
data->addToHistory(history, {
|
||||
.id = newId.msg,
|
||||
.flags = flags,
|
||||
.from = messageFromId,
|
||||
.replyTo = action.replyTo,
|
||||
.date = HistoryItem::NewMessageDate(action.options),
|
||||
.shortcutId = action.options.shortcutId,
|
||||
.viaBotId = ((bot && !action.options.hideViaBot)
|
||||
? peerToUser(bot->id)
|
||||
: UserId()),
|
||||
.postAuthor = messagePostAuthor,
|
||||
});
|
||||
|
||||
history->clearCloudDraft(topicRootId);
|
||||
history->startSavingCloudDraft(topicRootId);
|
||||
|
@ -3981,7 +4027,8 @@ void ApiWrap::sendInlineResult(
|
|||
MTP_long(data->getQueryId()),
|
||||
MTP_string(data->getId()),
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, action.options.shortcutId)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
history->finishSavingCloudDraft(
|
||||
topicRootId,
|
||||
|
@ -4118,7 +4165,8 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
: Flag(0))
|
||||
| (!sentEntities.v.isEmpty() ? Flag::f_entities : Flag(0))
|
||||
| (options.scheduled ? Flag::f_schedule_date : Flag(0))
|
||||
| (options.sendAs ? Flag::f_send_as : Flag(0));
|
||||
| (options.sendAs ? Flag::f_send_as : Flag(0))
|
||||
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0));
|
||||
|
||||
auto &histories = history->owner().histories();
|
||||
const auto peer = history->peer;
|
||||
|
@ -4137,7 +4185,8 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(options.scheduled),
|
||||
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty())
|
||||
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, options.shortcutId)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
if (done) done(true);
|
||||
if (updateRecentStickers) {
|
||||
|
@ -4233,7 +4282,10 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
|
|||
? Flag::f_silent
|
||||
: Flag(0))
|
||||
| (album->options.scheduled ? Flag::f_schedule_date : Flag(0))
|
||||
| (sendAs ? Flag::f_send_as : Flag(0));
|
||||
| (sendAs ? Flag::f_send_as : Flag(0))
|
||||
| (album->options.shortcutId
|
||||
? Flag::f_quick_reply_shortcut
|
||||
: Flag(0));
|
||||
auto &histories = history->owner().histories();
|
||||
const auto peer = history->peer;
|
||||
histories.sendPreparedMessage(
|
||||
|
@ -4246,7 +4298,8 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
|
|||
Data::Histories::ReplyToPlaceholder(),
|
||||
MTP_vector<MTPInputSingleMedia>(medias),
|
||||
MTP_int(album->options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, album->options.shortcutId)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
_sendingAlbums.remove(groupId);
|
||||
|
||||
|
|
|
@ -337,6 +337,9 @@ public:
|
|||
|
||||
void cancelLocalItem(not_null<HistoryItem*> item);
|
||||
|
||||
void sendShortcutMessages(
|
||||
not_null<PeerData*> peer,
|
||||
BusinessShortcutId id);
|
||||
void sendMessage(MessageToSend &&message);
|
||||
void sendBotStart(
|
||||
not_null<UserData*> bot,
|
||||
|
|
|
@ -1018,7 +1018,7 @@ void SetupChannelBox::prepare() {
|
|||
cancel);
|
||||
|
||||
connect(_link, &Ui::MaskedInputField::changed, [=] { handleChange(); });
|
||||
_link->setVisible(_privacyGroup->value() == Privacy::Public);
|
||||
_link->setVisible(_privacyGroup->current() == Privacy::Public);
|
||||
|
||||
_privacyGroup->setChangedCallback([=](Privacy value) {
|
||||
privacyChanged(value);
|
||||
|
@ -1063,7 +1063,7 @@ void SetupChannelBox::updateMaxHeight() {
|
|||
: 0)
|
||||
+ st::newGroupPadding.bottom();
|
||||
if (!_channel->isMegagroup()
|
||||
|| _privacyGroup->value() == Privacy::Public) {
|
||||
|| _privacyGroup->current() == Privacy::Public) {
|
||||
newHeight += st::newGroupLinkPadding.top()
|
||||
+ _link->height()
|
||||
+ st::newGroupLinkPadding.bottom();
|
||||
|
@ -1264,7 +1264,7 @@ void SetupChannelBox::save() {
|
|||
};
|
||||
if (_saveRequestId) {
|
||||
return;
|
||||
} else if (_privacyGroup->value() == Privacy::Private) {
|
||||
} else if (_privacyGroup->current() == Privacy::Private) {
|
||||
closeBox();
|
||||
} else {
|
||||
const auto link = _link->text().trimmed();
|
||||
|
|
|
@ -81,9 +81,9 @@ void AutoLockBox::prepare() {
|
|||
|
||||
const auto timeInput = Ui::CreateChild<Ui::TimeInput>(
|
||||
this,
|
||||
(group->value() == kCustom)
|
||||
(group->current() == kCustom
|
||||
? TimeString(currentTime)
|
||||
: kDefaultCustom.utf8(),
|
||||
: kDefaultCustom.utf8()),
|
||||
st::autolockTimeField,
|
||||
st::autolockDateField,
|
||||
st::scheduleTimeSeparator,
|
||||
|
@ -115,7 +115,9 @@ void AutoLockBox::prepare() {
|
|||
});
|
||||
|
||||
rpl::merge(
|
||||
boxClosing() | rpl::filter([=] { return group->value() == kCustom; }),
|
||||
boxClosing() | rpl::filter(
|
||||
[=] { return group->current() == kCustom; }
|
||||
),
|
||||
timeInput->submitRequests()
|
||||
) | rpl::start_with_next([=] {
|
||||
if (const auto result = collect()) {
|
||||
|
|
|
@ -31,8 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item.h"
|
||||
#include "history/history_item_helpers.h"
|
||||
#include "history/view/history_view_message.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -42,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_document_resolver.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_premium_limits.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "storage/localimageloader.h"
|
||||
|
@ -82,11 +81,11 @@ constexpr auto kMaxWallPaperSlugLength = 255;
|
|||
const auto flags = MessageFlag::FakeHistoryItem
|
||||
| MessageFlag::HasFromId
|
||||
| (out ? MessageFlag::Outgoing : MessageFlag(0));
|
||||
const auto item = history->makeMessage(
|
||||
history->owner().nextLocalMessageId(),
|
||||
flags,
|
||||
base::unixtime::now(),
|
||||
PreparedServiceText{ { text } });
|
||||
const auto item = history->makeMessage({
|
||||
.id = history->owner().nextLocalMessageId(),
|
||||
.flags = flags,
|
||||
.date = base::unixtime::now(),
|
||||
}, PreparedServiceText{ { text } });
|
||||
return AdminLog::OwnedItem(delegate, item);
|
||||
}
|
||||
|
||||
|
@ -97,24 +96,16 @@ constexpr auto kMaxWallPaperSlugLength = 255;
|
|||
bool out) {
|
||||
Expects(history->peer->isUser());
|
||||
|
||||
const auto flags = MessageFlag::FakeHistoryItem
|
||||
| MessageFlag::HasFromId
|
||||
| (out ? MessageFlag::Outgoing : MessageFlag(0));
|
||||
const auto replyTo = FullReplyTo();
|
||||
const auto viaBotId = UserId();
|
||||
const auto groupedId = uint64();
|
||||
const auto item = history->makeMessage(
|
||||
history->nextNonHistoryEntryId(),
|
||||
flags,
|
||||
replyTo,
|
||||
viaBotId,
|
||||
base::unixtime::now(),
|
||||
out ? history->session().userId() : peerToUser(history->peer->id),
|
||||
QString(),
|
||||
TextWithEntities{ text },
|
||||
MTP_messageMediaEmpty(),
|
||||
HistoryMessageMarkupData(),
|
||||
groupedId);
|
||||
const auto item = history->makeMessage({
|
||||
.id = history->nextNonHistoryEntryId(),
|
||||
.flags = (MessageFlag::FakeHistoryItem
|
||||
| MessageFlag::HasFromId
|
||||
| (out ? MessageFlag::Outgoing : MessageFlag(0))),
|
||||
.from = (out
|
||||
? history->session().userId()
|
||||
: peerToUser(history->peer->id)),
|
||||
.date = base::unixtime::now(),
|
||||
}, TextWithEntities{ text }, MTP_messageMediaEmpty());
|
||||
return AdminLog::OwnedItem(delegate, item);
|
||||
}
|
||||
|
||||
|
@ -699,16 +690,10 @@ void BackgroundPreviewBox::checkLevelForChannel() {
|
|||
if (!weak) {
|
||||
return std::optional<Ui::AskBoostReason>();
|
||||
}
|
||||
const auto appConfig = &_forPeer->session().account().appConfig();
|
||||
const auto defaultRequired = appConfig->get<int>(
|
||||
"channel_wallpaper_level_min",
|
||||
9);
|
||||
const auto customRequired = appConfig->get<int>(
|
||||
"channel_custom_wallpaper_level_min",
|
||||
10);
|
||||
const auto limits = Data::LevelLimits(&_forPeer->session());
|
||||
const auto required = _paperEmojiId.isEmpty()
|
||||
? customRequired
|
||||
: defaultRequired;
|
||||
? limits.channelCustomWallpaperLevelMin()
|
||||
: limits.channelWallpaperLevelMin();
|
||||
if (level >= required) {
|
||||
applyForPeer(false);
|
||||
return std::optional<Ui::AskBoostReason>();
|
||||
|
@ -791,7 +776,7 @@ void BackgroundPreviewBox::applyForPeer() {
|
|||
} else {
|
||||
ShowPremiumPreviewBox(
|
||||
_controller->uiShow(),
|
||||
PremiumPreview::Wallpapers);
|
||||
PremiumFeature::Wallpapers);
|
||||
}
|
||||
});
|
||||
const auto cancel = CreateChild<RoundButton>(
|
||||
|
|
|
@ -717,7 +717,7 @@ void ProxiesBox::refreshProxyForCalls() {
|
|||
return;
|
||||
}
|
||||
_proxyForCalls->toggle(
|
||||
(_proxySettings->value() == ProxyData::Settings::Enabled
|
||||
(_proxySettings->current() == ProxyData::Settings::Enabled
|
||||
&& _currentProxySupportsCallsId != 0),
|
||||
anim::type::normal);
|
||||
}
|
||||
|
@ -864,7 +864,7 @@ void ProxyBox::refreshButtons() {
|
|||
addButton(tr::lng_settings_save(), [=] { save(); });
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
|
||||
const auto type = _type->value();
|
||||
const auto type = _type->current();
|
||||
if (type == Type::Socks5 || type == Type::Mtproto) {
|
||||
addLeftButton(tr::lng_proxy_share(), [=] { share(); });
|
||||
}
|
||||
|
@ -885,7 +885,7 @@ void ProxyBox::share() {
|
|||
|
||||
ProxyData ProxyBox::collectData() {
|
||||
auto result = ProxyData();
|
||||
result.type = _type->value();
|
||||
result.type = _type->current();
|
||||
result.host = _host->getLastText().trimmed();
|
||||
result.port = _port->getLastText().trimmed().toInt();
|
||||
result.user = (result.type == Type::Mtproto)
|
||||
|
@ -1053,7 +1053,7 @@ void ProxyBox::setupControls(const ProxyData &data) {
|
|||
handleType(type);
|
||||
refreshButtons();
|
||||
});
|
||||
handleType(_type->value());
|
||||
handleType(_type->current());
|
||||
}
|
||||
|
||||
void ProxyBox::addLabel(
|
||||
|
|
|
@ -44,7 +44,9 @@ void DownloadPathBox::prepare() {
|
|||
|
||||
setTitle(tr::lng_download_path_header());
|
||||
|
||||
_group->setChangedCallback([this](Directory value) { radioChanged(value); });
|
||||
_group->setChangedCallback([this](Directory value) {
|
||||
radioChanged(value);
|
||||
});
|
||||
|
||||
_pathLink->addClickHandler([=] { editPath(); });
|
||||
if (!_path.isEmpty() && _path != FileDialog::Tmp()) {
|
||||
|
@ -54,7 +56,7 @@ void DownloadPathBox::prepare() {
|
|||
}
|
||||
|
||||
void DownloadPathBox::updateControlsVisibility() {
|
||||
auto custom = (_group->value() == Directory::Custom);
|
||||
auto custom = (_group->current() == Directory::Custom);
|
||||
_pathLink->setVisible(custom);
|
||||
|
||||
auto newHeight = st::boxOptionListPadding.top() + (_default ? _default->getMargins().top() + _default->heightNoMargins() : 0) + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
|
||||
|
@ -122,7 +124,7 @@ void DownloadPathBox::editPath() {
|
|||
|
||||
void DownloadPathBox::save() {
|
||||
#ifndef OS_WIN_STORE
|
||||
auto value = _group->value();
|
||||
auto value = _group->current();
|
||||
auto computePath = [this, value] {
|
||||
if (value == Directory::Custom) {
|
||||
return _path;
|
||||
|
|
|
@ -682,7 +682,7 @@ void EditCaptionBox::setupEmojiPanel() {
|
|||
&& !_controller->session().premium()) {
|
||||
ShowPremiumPreviewBox(
|
||||
_controller,
|
||||
PremiumPreview::AnimatedEmoji);
|
||||
PremiumFeature::AnimatedEmoji);
|
||||
} else {
|
||||
Data::InsertCustomEmoji(_field.get(), data.document);
|
||||
}
|
||||
|
@ -895,6 +895,7 @@ void EditCaptionBox::save() {
|
|||
|
||||
auto options = Api::SendOptions();
|
||||
options.scheduled = item->isScheduled() ? item->date() : 0;
|
||||
options.shortcutId = item->shortcutId();
|
||||
|
||||
if (!_preparedList.files.empty()) {
|
||||
if ((_albumType != Ui::AlbumType::None)
|
||||
|
|
|
@ -10,28 +10,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_global_privacy.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "history/history.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "settings/settings_privacy_security.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "base/binary_guard.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "apiwrap.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
@ -67,6 +63,32 @@ void CreateRadiobuttonLock(
|
|||
}, lock->lifetime());
|
||||
}
|
||||
|
||||
void AddPremiumRequiredRow(
|
||||
not_null<Ui::RpWidget*> widget,
|
||||
not_null<Main::Session*> session,
|
||||
Fn<void()> clickedCallback,
|
||||
Fn<void()> setDefaultOption,
|
||||
const style::Checkbox &st) {
|
||||
const auto row = Ui::CreateChild<Ui::AbstractButton>(widget.get());
|
||||
|
||||
widget->sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
row->resize(s);
|
||||
}, row->lifetime());
|
||||
row->setClickedCallback(std::move(clickedCallback));
|
||||
|
||||
CreateRadiobuttonLock(row, st);
|
||||
|
||||
Data::AmPremiumValue(
|
||||
session
|
||||
) | rpl::start_with_next([=](bool premium) {
|
||||
row->setVisible(!premium);
|
||||
if (!premium) {
|
||||
setDefaultOption();
|
||||
}
|
||||
}, row->lifetime());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class PrivacyExceptionsBoxController : public ChatsListBoxController {
|
||||
|
@ -363,10 +385,29 @@ void EditPrivacyBox::setupContent() {
|
|||
content,
|
||||
_controller->optionsTitleKey(),
|
||||
{ 0, st::settingsPrivacySkipTop, 0, 0 });
|
||||
addOptionRow(Option::Everyone);
|
||||
addOptionRow(Option::Contacts);
|
||||
addOptionRow(Option::CloseFriends);
|
||||
addOptionRow(Option::Nobody);
|
||||
|
||||
const auto options = {
|
||||
Option::Everyone,
|
||||
Option::Contacts,
|
||||
Option::CloseFriends,
|
||||
Option::Nobody,
|
||||
};
|
||||
for (const auto &option : options) {
|
||||
if (const auto row = addOptionRow(option)) {
|
||||
const auto premiumCallback = _controller->premiumClickedCallback(
|
||||
option,
|
||||
_window);
|
||||
if (premiumCallback) {
|
||||
AddPremiumRequiredRow(
|
||||
row,
|
||||
&_window->session(),
|
||||
premiumCallback,
|
||||
[=] { group->setValue(Option::Everyone); },
|
||||
st::messagePrivacyCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto warning = addLabelOrDivider(
|
||||
content,
|
||||
_controller->warning(),
|
||||
|
@ -541,7 +582,7 @@ void EditMessagesPrivacyBox(
|
|||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
if (controller->session().premium()) {
|
||||
privacy->updateNewRequirePremium(
|
||||
group->value() == kOptionPremium);
|
||||
group->current() == kOptionPremium);
|
||||
box->closeBox();
|
||||
} else {
|
||||
showToast();
|
||||
|
|
|
@ -88,6 +88,12 @@ public:
|
|||
virtual void saveAdditional() {
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual Fn<void()> premiumClickedCallback(
|
||||
Option option,
|
||||
not_null<Window::SessionController*> controller) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual ~EditPrivacyController() = default;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/filters/edit_filter_box.h"
|
||||
|
||||
#include "boxes/filters/edit_filter_chats_list.h"
|
||||
#include "boxes/filters/edit_filter_chats_preview.h"
|
||||
#include "boxes/filters/edit_filter_links.h"
|
||||
#include "boxes/premium_limits_box.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
|
@ -26,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_peer_values.h" // Data::AmPremiumValue.
|
||||
#include "data/data_premium_limits.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "core/application.h"
|
||||
|
@ -56,60 +58,6 @@ using Flags = Data::ChatFilter::Flags;
|
|||
using ExceptionPeersRef = const base::flat_set<not_null<History*>> &;
|
||||
using ExceptionPeersGetter = ExceptionPeersRef(Data::ChatFilter::*)() const;
|
||||
|
||||
constexpr auto kAllTypes = {
|
||||
Flag::Contacts,
|
||||
Flag::NonContacts,
|
||||
Flag::Groups,
|
||||
Flag::Channels,
|
||||
Flag::Bots,
|
||||
Flag::NoMuted,
|
||||
Flag::NoRead,
|
||||
Flag::NoArchived,
|
||||
};
|
||||
|
||||
class FilterChatsPreview final : public Ui::RpWidget {
|
||||
public:
|
||||
FilterChatsPreview(
|
||||
not_null<QWidget*> parent,
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers);
|
||||
|
||||
[[nodiscard]] rpl::producer<Flag> flagRemoved() const;
|
||||
[[nodiscard]] rpl::producer<not_null<History*>> peerRemoved() const;
|
||||
|
||||
void updateData(
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers);
|
||||
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
private:
|
||||
using Button = base::unique_qptr<Ui::IconButton>;
|
||||
struct FlagButton {
|
||||
Flag flag = Flag();
|
||||
Button button;
|
||||
};
|
||||
struct PeerButton {
|
||||
not_null<History*> history;
|
||||
Ui::PeerUserpicView userpic;
|
||||
Ui::Text::String name;
|
||||
Button button;
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void refresh();
|
||||
void removeFlag(Flag flag);
|
||||
void removePeer(not_null<History*> history);
|
||||
|
||||
std::vector<FlagButton> _removeFlag;
|
||||
std::vector<PeerButton> _removePeer;
|
||||
|
||||
rpl::event_stream<Flag> _flagRemoved;
|
||||
rpl::event_stream<not_null<History*>> _peerRemoved;
|
||||
|
||||
};
|
||||
|
||||
struct NameEditing {
|
||||
not_null<Ui::InputField*> field;
|
||||
bool custom = false;
|
||||
|
@ -167,167 +115,6 @@ not_null<FilterChatsPreview*> SetupChatsPreview(
|
|||
return preview;
|
||||
}
|
||||
|
||||
FilterChatsPreview::FilterChatsPreview(
|
||||
not_null<QWidget*> parent,
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers)
|
||||
: RpWidget(parent) {
|
||||
updateData(flags, peers);
|
||||
}
|
||||
|
||||
void FilterChatsPreview::refresh() {
|
||||
resizeToWidth(width());
|
||||
}
|
||||
|
||||
void FilterChatsPreview::updateData(
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers) {
|
||||
_removeFlag.clear();
|
||||
_removePeer.clear();
|
||||
const auto makeButton = [&](Fn<void()> handler) {
|
||||
auto result = base::make_unique_q<Ui::IconButton>(
|
||||
this,
|
||||
st::windowFilterSmallRemove);
|
||||
result->setClickedCallback(std::move(handler));
|
||||
return result;
|
||||
};
|
||||
for (const auto flag : kAllTypes) {
|
||||
if (flags & flag) {
|
||||
_removeFlag.push_back({
|
||||
flag,
|
||||
makeButton([=] { removeFlag(flag); }) });
|
||||
}
|
||||
}
|
||||
for (const auto &history : peers) {
|
||||
_removePeer.push_back(PeerButton{
|
||||
.history = history,
|
||||
.button = makeButton([=] { removePeer(history); })
|
||||
});
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
int FilterChatsPreview::resizeGetHeight(int newWidth) {
|
||||
const auto right = st::windowFilterSmallRemoveRight;
|
||||
const auto add = (st::windowFilterSmallItem.height
|
||||
- st::windowFilterSmallRemove.height) / 2;
|
||||
auto top = 0;
|
||||
const auto moveNextButton = [&](not_null<Ui::IconButton*> button) {
|
||||
button->moveToRight(right, top + add, newWidth);
|
||||
top += st::windowFilterSmallItem.height;
|
||||
};
|
||||
for (const auto &[flag, button] : _removeFlag) {
|
||||
moveNextButton(button.get());
|
||||
}
|
||||
for (const auto &[history, userpic, name, button] : _removePeer) {
|
||||
moveNextButton(button.get());
|
||||
}
|
||||
return top;
|
||||
}
|
||||
|
||||
void FilterChatsPreview::paintEvent(QPaintEvent *e) {
|
||||
auto p = Painter(this);
|
||||
auto top = 0;
|
||||
const auto &st = st::windowFilterSmallItem;
|
||||
const auto iconLeft = st.photoPosition.x();
|
||||
const auto iconTop = st.photoPosition.y();
|
||||
const auto nameLeft = st.namePosition.x();
|
||||
p.setFont(st::windowFilterSmallItem.nameStyle.font);
|
||||
const auto nameTop = st.namePosition.y();
|
||||
for (const auto &[flag, button] : _removeFlag) {
|
||||
PaintFilterChatsTypeIcon(
|
||||
p,
|
||||
flag,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
p.drawTextLeft(
|
||||
nameLeft,
|
||||
top + nameTop,
|
||||
width(),
|
||||
FilterChatsTypeName(flag));
|
||||
top += st.height;
|
||||
}
|
||||
for (auto &[history, userpic, name, button] : _removePeer) {
|
||||
const auto savedMessages = history->peer->isSelf();
|
||||
const auto repliesMessages = history->peer->isRepliesChat();
|
||||
if (savedMessages || repliesMessages) {
|
||||
if (savedMessages) {
|
||||
Ui::EmptyUserpic::PaintSavedMessages(
|
||||
p,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
} else {
|
||||
Ui::EmptyUserpic::PaintRepliesMessages(
|
||||
p,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
}
|
||||
p.setPen(st::contactsNameFg);
|
||||
p.drawTextLeft(
|
||||
nameLeft,
|
||||
top + nameTop,
|
||||
width(),
|
||||
(savedMessages
|
||||
? tr::lng_saved_messages(tr::now)
|
||||
: tr::lng_replies_messages(tr::now)));
|
||||
} else {
|
||||
history->peer->paintUserpicLeft(
|
||||
p,
|
||||
userpic,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
p.setPen(st::contactsNameFg);
|
||||
if (name.isEmpty()) {
|
||||
name.setText(
|
||||
st::msgNameStyle,
|
||||
history->peer->name(),
|
||||
Ui::NameTextOptions());
|
||||
}
|
||||
name.drawLeftElided(
|
||||
p,
|
||||
nameLeft,
|
||||
top + nameTop,
|
||||
button->x() - nameLeft,
|
||||
width());
|
||||
}
|
||||
top += st.height;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterChatsPreview::removeFlag(Flag flag) {
|
||||
const auto i = ranges::find(_removeFlag, flag, &FlagButton::flag);
|
||||
Assert(i != end(_removeFlag));
|
||||
_removeFlag.erase(i);
|
||||
refresh();
|
||||
_flagRemoved.fire_copy(flag);
|
||||
}
|
||||
|
||||
void FilterChatsPreview::removePeer(not_null<History*> history) {
|
||||
const auto i = ranges::find(_removePeer, history, &PeerButton::history);
|
||||
Assert(i != end(_removePeer));
|
||||
_removePeer.erase(i);
|
||||
refresh();
|
||||
_peerRemoved.fire_copy(history);
|
||||
}
|
||||
|
||||
rpl::producer<Flag> FilterChatsPreview::flagRemoved() const {
|
||||
return _flagRemoved.events();
|
||||
}
|
||||
|
||||
rpl::producer<not_null<History*>> FilterChatsPreview::peerRemoved() const {
|
||||
return _peerRemoved.events();
|
||||
}
|
||||
|
||||
void EditExceptions(
|
||||
not_null<Window::SessionController*> window,
|
||||
not_null<QObject*> context,
|
||||
|
@ -338,6 +125,12 @@ void EditExceptions(
|
|||
const auto include = (options & Flag::Contacts) != Flags(0);
|
||||
const auto rules = data->current();
|
||||
const auto session = &window->session();
|
||||
const auto limit = Data::PremiumLimits(
|
||||
session
|
||||
).dialogFiltersChatsCurrent();
|
||||
const auto showLimitReached = [=] {
|
||||
window->show(Box(FilterChatsLimitBox, session, limit, include));
|
||||
};
|
||||
auto controller = std::make_unique<EditFilterChatsListController>(
|
||||
session,
|
||||
(include
|
||||
|
@ -346,9 +139,8 @@ void EditExceptions(
|
|||
options,
|
||||
rules.flags() & options,
|
||||
include ? rules.always() : rules.never(),
|
||||
[=](int count) {
|
||||
return Box(FilterChatsLimitBox, session, count, include);
|
||||
});
|
||||
limit,
|
||||
showLimitReached);
|
||||
const auto rawController = controller.get();
|
||||
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||
box->setCloseByOutsideClick(false);
|
||||
|
|
|
@ -28,6 +28,8 @@ using Flag = Data::ChatFilter::Flag;
|
|||
using Flags = Data::ChatFilter::Flags;
|
||||
|
||||
constexpr auto kAllTypes = {
|
||||
Flag::NewChats,
|
||||
Flag::ExistingChats,
|
||||
Flag::Contacts,
|
||||
Flag::NonContacts,
|
||||
Flag::Groups,
|
||||
|
@ -119,7 +121,7 @@ PaintRoundImageCallback TypeRow::generatePaintUserpicCallback(
|
|||
}
|
||||
|
||||
Flag TypeRow::flag() const {
|
||||
return static_cast<Flag>(id() & 0xFF);
|
||||
return static_cast<Flag>(id() & 0xFFFF);
|
||||
}
|
||||
|
||||
ExceptionRow::ExceptionRow(not_null<History*> history) : Row(history) {
|
||||
|
@ -219,6 +221,8 @@ auto TypeController::rowSelectionChanges() const
|
|||
|
||||
[[nodiscard]] QString FilterChatsTypeName(Flag flag) {
|
||||
switch (flag) {
|
||||
case Flag::NewChats: return tr::lng_filters_type_new(tr::now);
|
||||
case Flag::ExistingChats: return tr::lng_filters_type_existing(tr::now);
|
||||
case Flag::Contacts: return tr::lng_filters_type_contacts(tr::now);
|
||||
case Flag::NonContacts:
|
||||
return tr::lng_filters_type_non_contacts(tr::now);
|
||||
|
@ -241,6 +245,8 @@ void PaintFilterChatsTypeIcon(
|
|||
int size) {
|
||||
const auto &color1 = [&]() -> const style::color& {
|
||||
switch (flag) {
|
||||
case Flag::NewChats: return st::historyPeer5UserpicBg;
|
||||
case Flag::ExistingChats: return st::historyPeer8UserpicBg;
|
||||
case Flag::Contacts: return st::historyPeer4UserpicBg;
|
||||
case Flag::NonContacts: return st::historyPeer7UserpicBg;
|
||||
case Flag::Groups: return st::historyPeer2UserpicBg;
|
||||
|
@ -254,6 +260,8 @@ void PaintFilterChatsTypeIcon(
|
|||
}();
|
||||
const auto &color2 = [&]() -> const style::color& {
|
||||
switch (flag) {
|
||||
case Flag::NewChats: return st::historyPeer5UserpicBg2;
|
||||
case Flag::ExistingChats: return st::historyPeer8UserpicBg2;
|
||||
case Flag::Contacts: return st::historyPeer4UserpicBg2;
|
||||
case Flag::NonContacts: return st::historyPeer7UserpicBg2;
|
||||
case Flag::Groups: return st::historyPeer2UserpicBg2;
|
||||
|
@ -267,6 +275,8 @@ void PaintFilterChatsTypeIcon(
|
|||
}();
|
||||
const auto &icon = [&]() -> const style::icon& {
|
||||
switch (flag) {
|
||||
case Flag::NewChats: return st::windowFilterTypeNewChats;
|
||||
case Flag::ExistingChats: return st::windowFilterTypeExistingChats;
|
||||
case Flag::Contacts: return st::windowFilterTypeContacts;
|
||||
case Flag::NonContacts: return st::windowFilterTypeNonContacts;
|
||||
case Flag::Groups: return st::windowFilterTypeGroups;
|
||||
|
@ -323,17 +333,17 @@ EditFilterChatsListController::EditFilterChatsListController(
|
|||
Flags options,
|
||||
Flags selected,
|
||||
const base::flat_set<not_null<History*>> &peers,
|
||||
LimitBoxFactory limitBox)
|
||||
int limit,
|
||||
Fn<void()> showLimitReached)
|
||||
: ChatsListBoxController(session)
|
||||
, _session(session)
|
||||
, _limitBox(std::move(limitBox))
|
||||
, _showLimitReached(std::move(showLimitReached))
|
||||
, _title(std::move(title))
|
||||
, _peers(peers)
|
||||
, _options(options & ~Flag::Chatlist)
|
||||
, _selected(selected)
|
||||
, _limit(Data::PremiumLimits(session).dialogFiltersChatsCurrent())
|
||||
, _limit(limit)
|
||||
, _chatlist(options & Flag::Chatlist) {
|
||||
Expects(_limitBox != nullptr);
|
||||
}
|
||||
|
||||
Main::Session &EditFilterChatsListController::session() const {
|
||||
|
@ -361,8 +371,8 @@ void EditFilterChatsListController::rowClicked(not_null<PeerListRow*> row) {
|
|||
if (count < _limit || row->checked()) {
|
||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||
updateTitle();
|
||||
} else {
|
||||
delegate()->peerListUiShow()->showBox(_limitBox(count));
|
||||
} else if (const auto copy = _showLimitReached) {
|
||||
copy();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,6 +479,10 @@ object_ptr<Ui::RpWidget> EditFilterChatsListController::prepareTypesList() {
|
|||
|
||||
auto EditFilterChatsListController::createRow(not_null<History*> history)
|
||||
-> std::unique_ptr<Row> {
|
||||
const auto business = _options & (Flag::NewChats | Flag::ExistingChats);
|
||||
if (business && (history->peer->isSelf() || !history->peer->isUser())) {
|
||||
return nullptr;
|
||||
}
|
||||
return history->inChatList()
|
||||
? std::make_unique<ExceptionRow>(history)
|
||||
: nullptr;
|
||||
|
|
|
@ -43,7 +43,6 @@ class EditFilterChatsListController final : public ChatsListBoxController {
|
|||
public:
|
||||
using Flag = Data::ChatFilter::Flag;
|
||||
using Flags = Data::ChatFilter::Flags;
|
||||
using LimitBoxFactory = Fn<object_ptr<Ui::BoxContent>(int)>;
|
||||
|
||||
EditFilterChatsListController(
|
||||
not_null<Main::Session*> session,
|
||||
|
@ -51,7 +50,8 @@ public:
|
|||
Flags options,
|
||||
Flags selected,
|
||||
const base::flat_set<not_null<History*>> &peers,
|
||||
LimitBoxFactory limitBox);
|
||||
int limit,
|
||||
Fn<void()> showLimitReached);
|
||||
|
||||
[[nodiscard]] Main::Session &session() const override;
|
||||
[[nodiscard]] Flags chosenOptions() const {
|
||||
|
@ -72,7 +72,7 @@ private:
|
|||
void updateTitle();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
const LimitBoxFactory _limitBox;
|
||||
const Fn<void()> _showLimitReached;
|
||||
rpl::producer<QString> _title;
|
||||
base::flat_set<not_null<History*>> _peers;
|
||||
Flags _options;
|
||||
|
|
199
Telegram/SourceFiles/boxes/filters/edit_filter_chats_preview.cpp
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "boxes/filters/edit_filter_chats_preview.h"
|
||||
|
||||
#include "boxes/filters/edit_filter_chats_list.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "history/history.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/painter.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using Flag = Data::ChatFilter::Flag;
|
||||
|
||||
constexpr auto kAllTypes = {
|
||||
Flag::NewChats,
|
||||
Flag::ExistingChats,
|
||||
Flag::Contacts,
|
||||
Flag::NonContacts,
|
||||
Flag::Groups,
|
||||
Flag::Channels,
|
||||
Flag::Bots,
|
||||
Flag::NoMuted,
|
||||
Flag::NoRead,
|
||||
Flag::NoArchived,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
FilterChatsPreview::FilterChatsPreview(
|
||||
not_null<QWidget*> parent,
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers)
|
||||
: RpWidget(parent) {
|
||||
updateData(flags, peers);
|
||||
}
|
||||
|
||||
void FilterChatsPreview::refresh() {
|
||||
resizeToWidth(width());
|
||||
}
|
||||
|
||||
void FilterChatsPreview::updateData(
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers) {
|
||||
_removeFlag.clear();
|
||||
_removePeer.clear();
|
||||
const auto makeButton = [&](Fn<void()> handler) {
|
||||
auto result = base::make_unique_q<Ui::IconButton>(
|
||||
this,
|
||||
st::windowFilterSmallRemove);
|
||||
result->setClickedCallback(std::move(handler));
|
||||
result->show();
|
||||
return result;
|
||||
};
|
||||
for (const auto flag : kAllTypes) {
|
||||
if (flags & flag) {
|
||||
_removeFlag.push_back({
|
||||
flag,
|
||||
makeButton([=] { removeFlag(flag); }) });
|
||||
}
|
||||
}
|
||||
for (const auto &history : peers) {
|
||||
_removePeer.push_back(PeerButton{
|
||||
.history = history,
|
||||
.button = makeButton([=] { removePeer(history); })
|
||||
});
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
int FilterChatsPreview::resizeGetHeight(int newWidth) {
|
||||
const auto right = st::windowFilterSmallRemoveRight;
|
||||
const auto add = (st::windowFilterSmallItem.height
|
||||
- st::windowFilterSmallRemove.height) / 2;
|
||||
auto top = 0;
|
||||
const auto moveNextButton = [&](not_null<Ui::IconButton*> button) {
|
||||
button->moveToRight(right, top + add, newWidth);
|
||||
top += st::windowFilterSmallItem.height;
|
||||
};
|
||||
for (const auto &[flag, button] : _removeFlag) {
|
||||
moveNextButton(button.get());
|
||||
}
|
||||
for (const auto &[history, userpic, name, button] : _removePeer) {
|
||||
moveNextButton(button.get());
|
||||
}
|
||||
return top;
|
||||
}
|
||||
|
||||
void FilterChatsPreview::paintEvent(QPaintEvent *e) {
|
||||
auto p = Painter(this);
|
||||
auto top = 0;
|
||||
const auto &st = st::windowFilterSmallItem;
|
||||
const auto iconLeft = st.photoPosition.x();
|
||||
const auto iconTop = st.photoPosition.y();
|
||||
const auto nameLeft = st.namePosition.x();
|
||||
p.setFont(st::windowFilterSmallItem.nameStyle.font);
|
||||
const auto nameTop = st.namePosition.y();
|
||||
for (const auto &[flag, button] : _removeFlag) {
|
||||
PaintFilterChatsTypeIcon(
|
||||
p,
|
||||
flag,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
p.drawTextLeft(
|
||||
nameLeft,
|
||||
top + nameTop,
|
||||
width(),
|
||||
FilterChatsTypeName(flag));
|
||||
top += st.height;
|
||||
}
|
||||
for (auto &[history, userpic, name, button] : _removePeer) {
|
||||
const auto savedMessages = history->peer->isSelf();
|
||||
const auto repliesMessages = history->peer->isRepliesChat();
|
||||
if (savedMessages || repliesMessages) {
|
||||
if (savedMessages) {
|
||||
Ui::EmptyUserpic::PaintSavedMessages(
|
||||
p,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
} else {
|
||||
Ui::EmptyUserpic::PaintRepliesMessages(
|
||||
p,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
}
|
||||
p.setPen(st::contactsNameFg);
|
||||
p.drawTextLeft(
|
||||
nameLeft,
|
||||
top + nameTop,
|
||||
width(),
|
||||
(savedMessages
|
||||
? tr::lng_saved_messages(tr::now)
|
||||
: tr::lng_replies_messages(tr::now)));
|
||||
} else {
|
||||
history->peer->paintUserpicLeft(
|
||||
p,
|
||||
userpic,
|
||||
iconLeft,
|
||||
top + iconTop,
|
||||
width(),
|
||||
st.photoSize);
|
||||
p.setPen(st::contactsNameFg);
|
||||
if (name.isEmpty()) {
|
||||
name.setText(
|
||||
st::msgNameStyle,
|
||||
history->peer->name(),
|
||||
Ui::NameTextOptions());
|
||||
}
|
||||
name.drawLeftElided(
|
||||
p,
|
||||
nameLeft,
|
||||
top + nameTop,
|
||||
button->x() - nameLeft,
|
||||
width());
|
||||
}
|
||||
top += st.height;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterChatsPreview::removeFlag(Flag flag) {
|
||||
const auto i = ranges::find(_removeFlag, flag, &FlagButton::flag);
|
||||
Assert(i != end(_removeFlag));
|
||||
_removeFlag.erase(i);
|
||||
refresh();
|
||||
_flagRemoved.fire_copy(flag);
|
||||
}
|
||||
|
||||
void FilterChatsPreview::removePeer(not_null<History*> history) {
|
||||
const auto i = ranges::find(_removePeer, history, &PeerButton::history);
|
||||
Assert(i != end(_removePeer));
|
||||
_removePeer.erase(i);
|
||||
refresh();
|
||||
_peerRemoved.fire_copy(history);
|
||||
}
|
||||
|
||||
rpl::producer<Flag> FilterChatsPreview::flagRemoved() const {
|
||||
return _flagRemoved.events();
|
||||
}
|
||||
|
||||
rpl::producer<not_null<History*>> FilterChatsPreview::peerRemoved() const {
|
||||
return _peerRemoved.events();
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/userpic_view.h"
|
||||
|
||||
class History;
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
} // namespace Ui
|
||||
|
||||
class FilterChatsPreview final : public Ui::RpWidget {
|
||||
public:
|
||||
using Flag = Data::ChatFilter::Flag;
|
||||
using Flags = Data::ChatFilter::Flags;
|
||||
|
||||
FilterChatsPreview(
|
||||
not_null<QWidget*> parent,
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers);
|
||||
|
||||
[[nodiscard]] rpl::producer<Flag> flagRemoved() const;
|
||||
[[nodiscard]] rpl::producer<not_null<History*>> peerRemoved() const;
|
||||
|
||||
void updateData(
|
||||
Flags flags,
|
||||
const base::flat_set<not_null<History*>> &peers);
|
||||
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
private:
|
||||
using Button = base::unique_qptr<Ui::IconButton>;
|
||||
struct FlagButton {
|
||||
Flag flag = Flag();
|
||||
Button button;
|
||||
};
|
||||
struct PeerButton {
|
||||
not_null<History*> history;
|
||||
Ui::PeerUserpicView userpic;
|
||||
Ui::Text::String name;
|
||||
Button button;
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void refresh();
|
||||
void removeFlag(Flag flag);
|
||||
void removePeer(not_null<History*> history);
|
||||
|
||||
std::vector<FlagButton> _removeFlag;
|
||||
std::vector<PeerButton> _removePeer;
|
||||
|
||||
rpl::event_stream<Flag> _flagRemoved;
|
||||
rpl::event_stream<not_null<History*>> _peerRemoved;
|
||||
|
||||
};
|
|
@ -982,8 +982,7 @@ bool GoodForExportFilterLink(
|
|||
not_null<Window::SessionController*> window,
|
||||
const Data::ChatFilter &filter) {
|
||||
using Flag = Data::ChatFilter::Flag;
|
||||
const auto listflags = Flag::Chatlist | Flag::HasMyLinks;
|
||||
if (!filter.never().empty() || (filter.flags() & ~listflags)) {
|
||||
if (!filter.never().empty() || (filter.flags() & Flag::RulesMask)) {
|
||||
window->showToast(tr::lng_filters_link_cant(tr::now));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -386,7 +386,7 @@ void GiftBox(
|
|||
state->buttonText.events(),
|
||||
Ui::Premium::GiftGradientStops(),
|
||||
[=] {
|
||||
const auto value = group->value();
|
||||
const auto value = group->current();
|
||||
return (value < options.size() && value >= 0)
|
||||
? options[value].botUrl
|
||||
: QString();
|
||||
|
@ -587,7 +587,7 @@ void GiftsBox(
|
|||
const auto content = box->addRow(
|
||||
object_ptr<Ui::VerticalLayout>(box),
|
||||
{});
|
||||
auto buttonCallback = [=](PremiumPreview section) {
|
||||
auto buttonCallback = [=](PremiumFeature section) {
|
||||
stars->setPaused(true);
|
||||
const auto previewBoxShown = [=](
|
||||
not_null<Ui::BoxContent*> previewBox) {
|
||||
|
@ -665,7 +665,7 @@ void GiftsBox(
|
|||
}
|
||||
auto invoice = api->invoice(
|
||||
users.size(),
|
||||
api->monthsFromPreset(group->value()));
|
||||
api->monthsFromPreset(group->current()));
|
||||
invoice.purpose = Payments::InvoicePremiumGiftCodeUsers{ users };
|
||||
|
||||
state->confirmButtonBusy = true;
|
||||
|
|
|
@ -1216,7 +1216,7 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
|
|||
if (checked && !premium) {
|
||||
ShowPremiumPreviewToBuy(
|
||||
_controller,
|
||||
PremiumPreview::RealTimeTranslation);
|
||||
PremiumFeature::RealTimeTranslation);
|
||||
_translateChatTurnOff.fire(false);
|
||||
}
|
||||
return premium
|
||||
|
|
|
@ -260,11 +260,11 @@ void Controller::choose(not_null<ChatData*> chat) {
|
|||
|
||||
const auto init = [=](not_null<ListBox*> box) {
|
||||
auto above = object_ptr<Ui::VerticalLayout>(box);
|
||||
Settings::AddDividerTextWithLottie(
|
||||
above,
|
||||
box->showFinishes(),
|
||||
About(channel, chat),
|
||||
u"discussion"_q);
|
||||
Settings::AddDividerTextWithLottie(above, {
|
||||
.lottie = u"discussion"_q,
|
||||
.showFinished = box->showFinishes(),
|
||||
.about = About(channel, chat),
|
||||
});
|
||||
if (!chat) {
|
||||
Assert(channel->isBroadcast());
|
||||
|
||||
|
|
|
@ -216,6 +216,9 @@ ChatAdminRightsInfo EditAdminBox::defaultRights() const {
|
|||
: peer()->isMegagroup()
|
||||
? ChatAdminRightsInfo{ (Flag::ChangeInfo
|
||||
| Flag::DeleteMessages
|
||||
| Flag::PostStories
|
||||
| Flag::EditStories
|
||||
| Flag::DeleteStories
|
||||
| Flag::BanUsers
|
||||
| Flag::InviteByLinkOrAdd
|
||||
| Flag::ManageTopics
|
||||
|
@ -225,6 +228,9 @@ ChatAdminRightsInfo EditAdminBox::defaultRights() const {
|
|||
| Flag::PostMessages
|
||||
| Flag::EditMessages
|
||||
| Flag::DeleteMessages
|
||||
| Flag::PostStories
|
||||
| Flag::EditStories
|
||||
| Flag::DeleteStories
|
||||
| Flag::InviteByLinkOrAdd
|
||||
| Flag::ManageCall) };
|
||||
}
|
||||
|
@ -840,7 +846,7 @@ void EditRestrictedBox::createUntilGroup() {
|
|||
|
||||
void EditRestrictedBox::createUntilVariants() {
|
||||
auto addVariant = [&](int value, const QString &text) {
|
||||
if (!canSave() && _untilGroup->value() != value) {
|
||||
if (!canSave() && _untilGroup->current() != value) {
|
||||
return;
|
||||
}
|
||||
_untilVariants.emplace_back(
|
||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/background_box.h"
|
||||
#include "boxes/stickers_box.h"
|
||||
#include "chat_helpers/compose/compose_show.h"
|
||||
#include "core/ui_integration.h" // Core::MarkedTextContext.
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "data/data_changes.h"
|
||||
|
@ -23,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_emoji_statuses.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_premium_limits.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
|
@ -34,8 +36,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lang/lang_keys.h"
|
||||
#include "lottie/lottie_icon.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "settings/settings_premium.h"
|
||||
|
@ -43,10 +43,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "window/section_widget.h"
|
||||
|
@ -146,6 +148,28 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class LevelBadge final : public Ui::RpWidget {
|
||||
public:
|
||||
LevelBadge(
|
||||
not_null<QWidget*> parent,
|
||||
uint32 level,
|
||||
not_null<Main::Session*> session);
|
||||
|
||||
void setMinimal(bool value);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void updateText();
|
||||
|
||||
const uint32 _level;
|
||||
const TextWithEntities _icon;
|
||||
const Core::MarkedTextContext _context;
|
||||
Ui::Text::String _text;
|
||||
bool _minimal = false;
|
||||
|
||||
};
|
||||
|
||||
ColorSample::ColorSample(
|
||||
not_null<QWidget*> parent,
|
||||
std::shared_ptr<Ui::ChatStyle> style,
|
||||
|
@ -295,47 +319,36 @@ PreviewWrap::PreviewWrap(
|
|||
, _delegate(std::make_unique<PreviewDelegate>(box, _style.get(), [=] {
|
||||
update();
|
||||
}))
|
||||
, _replyToItem(_history->addNewLocalMessage(
|
||||
_history->nextNonHistoryEntryId(),
|
||||
(MessageFlag::FakeHistoryItem
|
||||
, _replyToItem(_history->addNewLocalMessage({
|
||||
.id = _history->nextNonHistoryEntryId(),
|
||||
.flags = (MessageFlag::FakeHistoryItem
|
||||
| MessageFlag::HasFromId
|
||||
| MessageFlag::Post),
|
||||
UserId(), // via
|
||||
FullReplyTo(),
|
||||
base::unixtime::now(), // date
|
||||
_fake->id,
|
||||
QString(), // postAuthor
|
||||
TextWithEntities{ _peer->isSelf()
|
||||
? tr::lng_settings_color_reply(tr::now)
|
||||
: tr::lng_settings_color_reply_channel(tr::now),
|
||||
},
|
||||
MTP_messageMediaEmpty(),
|
||||
HistoryMessageMarkupData(),
|
||||
uint64(0)))
|
||||
, _replyItem(_history->addNewLocalMessage(
|
||||
_history->nextNonHistoryEntryId(),
|
||||
(MessageFlag::FakeHistoryItem
|
||||
.from = _fake->id,
|
||||
.date = base::unixtime::now(),
|
||||
}, TextWithEntities{ _peer->isSelf()
|
||||
? tr::lng_settings_color_reply(tr::now)
|
||||
: tr::lng_settings_color_reply_channel(tr::now),
|
||||
}, MTP_messageMediaEmpty()))
|
||||
, _replyItem(_history->addNewLocalMessage({
|
||||
.id = _history->nextNonHistoryEntryId(),
|
||||
.flags = (MessageFlag::FakeHistoryItem
|
||||
| MessageFlag::HasFromId
|
||||
| MessageFlag::HasReplyInfo
|
||||
| MessageFlag::Post),
|
||||
UserId(), // via
|
||||
FullReplyTo{ .messageId = _replyToItem->fullId() },
|
||||
base::unixtime::now(), // date
|
||||
_fake->id,
|
||||
QString(), // postAuthor
|
||||
TextWithEntities{ _peer->isSelf()
|
||||
? tr::lng_settings_color_text(tr::now)
|
||||
: tr::lng_settings_color_text_channel(tr::now),
|
||||
},
|
||||
MTP_messageMediaWebPage(
|
||||
.from = _fake->id,
|
||||
.replyTo = FullReplyTo{.messageId = _replyToItem->fullId() },
|
||||
.date = base::unixtime::now(),
|
||||
}, TextWithEntities{ _peer->isSelf()
|
||||
? tr::lng_settings_color_text(tr::now)
|
||||
: tr::lng_settings_color_text_channel(tr::now),
|
||||
}, MTP_messageMediaWebPage(
|
||||
MTP_flags(0),
|
||||
MTP_webPagePending(
|
||||
MTP_flags(0),
|
||||
MTP_webPagePending(
|
||||
MTP_flags(0),
|
||||
MTP_long(_webpage->id),
|
||||
MTPstring(),
|
||||
MTP_int(0))),
|
||||
HistoryMessageMarkupData(),
|
||||
uint64(0)))
|
||||
MTP_long(_webpage->id),
|
||||
MTPstring(),
|
||||
MTP_int(0)))))
|
||||
, _element(_replyItem->createView(_delegate.get()))
|
||||
, _position(0, st::msgMargin.bottom()) {
|
||||
_style->apply(_theme.get());
|
||||
|
@ -437,6 +450,108 @@ HistoryView::Context PreviewDelegate::elementContext() {
|
|||
return HistoryView::Context::AdminLog;
|
||||
}
|
||||
|
||||
LevelBadge::LevelBadge(
|
||||
not_null<QWidget*> parent,
|
||||
uint32 level,
|
||||
not_null<Main::Session*> session)
|
||||
: Ui::RpWidget(parent)
|
||||
, _level(level)
|
||||
, _icon(Ui::Text::SingleCustomEmoji(
|
||||
session->data().customEmojiManager().registerInternalEmoji(
|
||||
st::settingsLevelBadgeLock,
|
||||
QMargins(0, st::settingsLevelBadgeLockSkip, 0, 0),
|
||||
false)))
|
||||
, _context({ .session = session }) {
|
||||
updateText();
|
||||
}
|
||||
|
||||
void LevelBadge::updateText() {
|
||||
auto text = _icon;
|
||||
text.append(' ');
|
||||
if (!_minimal) {
|
||||
text.append(tr::lng_boost_level(
|
||||
tr::now,
|
||||
lt_count,
|
||||
_level,
|
||||
Ui::Text::WithEntities));
|
||||
} else {
|
||||
text.append(QString::number(_level));
|
||||
}
|
||||
const auto &st = st::settingsPremiumNewBadge.style;
|
||||
_text.setMarkedText(
|
||||
st,
|
||||
text,
|
||||
kMarkupTextOptions,
|
||||
_context);
|
||||
const auto &padding = st::settingsColorSamplePadding;
|
||||
QWidget::resize(
|
||||
_text.maxWidth() + rect::m::sum::h(padding),
|
||||
st.font->height + rect::m::sum::v(padding));
|
||||
}
|
||||
|
||||
void LevelBadge::setMinimal(bool value) {
|
||||
if ((value != _minimal) && value) {
|
||||
_minimal = value;
|
||||
updateText();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void LevelBadge::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
|
||||
const auto radius = height() / 2;
|
||||
p.setPen(Qt::NoPen);
|
||||
auto gradient = QLinearGradient(QPointF(0, 0), QPointF(width(), 0));
|
||||
gradient.setStops(Ui::Premium::ButtonGradientStops());
|
||||
p.setBrush(gradient);
|
||||
p.drawRoundedRect(rect(), radius, radius);
|
||||
|
||||
p.setPen(st::premiumButtonFg);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
const auto context = Ui::Text::PaintContext{
|
||||
.position = rect::m::pos::tl(st::settingsColorSamplePadding),
|
||||
.outerWidth = width(),
|
||||
.availableWidth = width(),
|
||||
};
|
||||
_text.draw(p, context);
|
||||
}
|
||||
|
||||
void AddLevelBadge(
|
||||
int level,
|
||||
not_null<Ui::SettingsButton*> button,
|
||||
Ui::RpWidget *right,
|
||||
not_null<ChannelData*> channel,
|
||||
const QMargins &padding,
|
||||
rpl::producer<QString> text) {
|
||||
if (channel->levelHint() >= level) {
|
||||
return;
|
||||
}
|
||||
const auto badge = Ui::CreateChild<LevelBadge>(
|
||||
button.get(),
|
||||
level,
|
||||
&channel->session());
|
||||
badge->show();
|
||||
const auto sampleLeft = st::settingsColorSamplePadding.left();
|
||||
const auto badgeLeft = padding.left() + sampleLeft;
|
||||
rpl::combine(
|
||||
button->sizeValue(),
|
||||
std::move(text)
|
||||
) | rpl::start_with_next([=](const QSize &s, const QString &) {
|
||||
if (s.isNull()) {
|
||||
return;
|
||||
}
|
||||
badge->moveToLeft(
|
||||
button->fullTextWidth() + badgeLeft,
|
||||
(s.height() - badge->height()) / 2);
|
||||
const auto rightEdge = right ? right->pos().x() : button->width();
|
||||
badge->setMinimal((rect::right(badge) + sampleLeft) > rightEdge);
|
||||
badge->setVisible((rect::right(badge) + sampleLeft) < rightEdge);
|
||||
}, badge->lifetime());
|
||||
}
|
||||
|
||||
struct SetValues {
|
||||
uint8 colorIndex = 0;
|
||||
DocumentId backgroundEmojiId = 0;
|
||||
|
@ -541,16 +656,13 @@ void Apply(
|
|||
: peerColors->requiredChannelLevelFor(
|
||||
peer->id,
|
||||
values.colorIndex);
|
||||
const auto limits = Data::LevelLimits(&peer->session());
|
||||
const auto iconRequired = values.backgroundEmojiId
|
||||
? session->account().appConfig().get<int>(
|
||||
"channel_bg_icon_level_min",
|
||||
5)
|
||||
? limits.channelBgIconLevelMin()
|
||||
: 0;
|
||||
const auto statusRequired = (values.statusChanged
|
||||
&& values.statusId)
|
||||
? session->account().appConfig().get<int>(
|
||||
"channel_emoji_status_level_min",
|
||||
8)
|
||||
? limits.channelEmojiStatusLevelMin()
|
||||
: 0;
|
||||
const auto required = std::max({
|
||||
colorRequired,
|
||||
|
@ -726,6 +838,7 @@ struct ButtonWithEmoji {
|
|||
not_null<Ui::RpWidget*> parent,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
std::shared_ptr<Ui::ChatStyle> style,
|
||||
not_null<PeerData*> peer,
|
||||
rpl::producer<uint8> colorIndexValue,
|
||||
rpl::producer<DocumentId> emojiIdValue,
|
||||
Fn<void(DocumentId)> emojiIdChosen) {
|
||||
|
@ -827,21 +940,33 @@ struct ButtonWithEmoji {
|
|||
}
|
||||
});
|
||||
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
AddLevelBadge(
|
||||
Data::LevelLimits(&channel->session()).channelBgIconLevelMin(),
|
||||
raw,
|
||||
right,
|
||||
channel,
|
||||
button.st->padding,
|
||||
tr::lng_settings_color_emoji());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::SettingsButton> CreateEmojiStatusButton(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
not_null<ChannelData*> channel,
|
||||
rpl::producer<DocumentId> statusIdValue,
|
||||
Fn<void(DocumentId,TimeId)> statusIdChosen,
|
||||
bool group) {
|
||||
const auto button = ButtonStyleWithRightEmoji(parent);
|
||||
const auto &phrase = group
|
||||
? tr::lng_edit_channel_status_group
|
||||
: tr::lng_edit_channel_status;
|
||||
auto result = Settings::CreateButtonWithIcon(
|
||||
parent,
|
||||
(group
|
||||
? tr::lng_edit_channel_status_group()
|
||||
: tr::lng_edit_channel_status()),
|
||||
phrase(),
|
||||
*button.st,
|
||||
{ &st::menuBlueIconEmojiStatus });
|
||||
const auto raw = result.data();
|
||||
|
@ -926,6 +1051,17 @@ struct ButtonWithEmoji {
|
|||
}
|
||||
});
|
||||
|
||||
const auto limits = Data::LevelLimits(&channel->session());
|
||||
AddLevelBadge(
|
||||
(group
|
||||
? limits.groupEmojiStatusLevelMin()
|
||||
: limits.channelEmojiStatusLevelMin()),
|
||||
raw,
|
||||
right,
|
||||
channel,
|
||||
button.st->padding,
|
||||
phrase());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1036,6 +1172,14 @@ struct ButtonWithEmoji {
|
|||
}
|
||||
}, right->lifetime());
|
||||
|
||||
AddLevelBadge(
|
||||
Data::LevelLimits(&channel->session()).groupEmojiStickersLevelMin(),
|
||||
raw,
|
||||
right,
|
||||
channel,
|
||||
button.st->padding,
|
||||
tr::lng_group_emoji());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1068,38 +1212,15 @@ void EditPeerColorBox(
|
|||
state->index = peer->colorIndex();
|
||||
state->emojiId = peer->backgroundEmojiId();
|
||||
state->statusId = peer->emojiStatusId();
|
||||
|
||||
if (group) {
|
||||
const auto divider = Ui::CreateChild<Ui::BoxContentDivider>(
|
||||
box.get());
|
||||
const auto verticalLayout = box->verticalLayout()->add(
|
||||
object_ptr<Ui::VerticalLayout>(box.get()));
|
||||
|
||||
auto icon = CreateLottieIcon(
|
||||
verticalLayout,
|
||||
{
|
||||
.name = u"palette"_q,
|
||||
.sizeOverride = {
|
||||
st::settingsCloudPasswordIconSize,
|
||||
st::settingsCloudPasswordIconSize,
|
||||
},
|
||||
},
|
||||
st::peerAppearanceIconPadding);
|
||||
box->setShowFinishedCallback([animate = std::move(icon.animate)] {
|
||||
animate(anim::repeat::once);
|
||||
Settings::AddDividerTextWithLottie(box->verticalLayout(), {
|
||||
.lottie = u"palette"_q,
|
||||
.lottieSize = st::settingsCloudPasswordIconSize,
|
||||
.lottieMargins = st::peerAppearanceIconPadding,
|
||||
.showFinished = box->showFinishes(),
|
||||
.about = tr::lng_boost_group_about(Ui::Text::WithEntities),
|
||||
.aboutMargins = st::peerAppearanceCoverLabelMargin,
|
||||
});
|
||||
verticalLayout->add(std::move(icon.widget));
|
||||
verticalLayout->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
verticalLayout,
|
||||
tr::lng_boost_group_about(),
|
||||
st::peerAppearanceCoverLabel),
|
||||
st::peerAppearanceCoverLabelMargin);
|
||||
|
||||
verticalLayout->geometryValue(
|
||||
) | rpl::start_with_next([=](const QRect &r) {
|
||||
divider->setGeometry(r);
|
||||
}, divider->lifetime());
|
||||
} else {
|
||||
box->addRow(object_ptr<PreviewWrap>(
|
||||
box,
|
||||
|
@ -1135,6 +1256,7 @@ void EditPeerColorBox(
|
|||
container,
|
||||
show,
|
||||
style,
|
||||
peer,
|
||||
state->index.value(),
|
||||
state->emojiId.value(),
|
||||
[=](DocumentId id) { state->emojiId = id; }));
|
||||
|
@ -1150,20 +1272,35 @@ void EditPeerColorBox(
|
|||
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
Ui::AddSkip(container, st::settingsColorSampleSkip);
|
||||
Settings::AddButtonWithIcon(
|
||||
const auto &phrase = group
|
||||
? tr::lng_edit_channel_wallpaper_group
|
||||
: tr::lng_edit_channel_wallpaper;
|
||||
const auto button = Settings::AddButtonWithIcon(
|
||||
container,
|
||||
(group
|
||||
? tr::lng_edit_channel_wallpaper_group()
|
||||
: tr::lng_edit_channel_wallpaper()),
|
||||
phrase(),
|
||||
st::peerAppearanceButton,
|
||||
{ &st::menuBlueIconWallpaper }
|
||||
)->setClickedCallback([=] {
|
||||
);
|
||||
button->setClickedCallback([=] {
|
||||
const auto usage = ChatHelpers::WindowUsage::PremiumPromo;
|
||||
if (const auto strong = show->resolveWindow(usage)) {
|
||||
show->show(Box<BackgroundBox>(strong, channel));
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
const auto limits = Data::LevelLimits(&channel->session());
|
||||
AddLevelBadge(
|
||||
group
|
||||
? limits.groupCustomWallpaperLevelMin()
|
||||
: limits.channelCustomWallpaperLevelMin(),
|
||||
button,
|
||||
nullptr,
|
||||
channel,
|
||||
st::peerAppearanceButton.padding,
|
||||
phrase());
|
||||
}
|
||||
|
||||
Ui::AddSkip(container, st::settingsColorSampleSkip);
|
||||
Ui::AddDividerText(
|
||||
container,
|
||||
|
@ -1201,6 +1338,7 @@ void EditPeerColorBox(
|
|||
container->add(CreateEmojiStatusButton(
|
||||
container,
|
||||
show,
|
||||
channel,
|
||||
state->statusId.value(),
|
||||
[=](DocumentId id, TimeId until) {
|
||||
state->statusId = id;
|
||||
|
|
|
@ -25,7 +25,7 @@ void EditPeerHistoryVisibilityBox(
|
|||
|
||||
box->setTitle(tr::lng_manage_history_visibility_title());
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
savedCallback(historyVisibility->value());
|
||||
savedCallback(historyVisibility->current());
|
||||
box->closeBox();
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
}
|
||||
|
||||
[[nodiscard]] Privacy getPrivacy() const {
|
||||
return _controls.privacy->value();
|
||||
return _controls.privacy->current();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool noForwards() const {
|
||||
|
@ -238,7 +238,7 @@ void Controller::createContent() {
|
|||
}, wrap->lifetime());
|
||||
} else {
|
||||
_controls.whoSendWrap->toggle(
|
||||
(_controls.privacy->value() == Privacy::HasUsername),
|
||||
(_controls.privacy->current() == Privacy::HasUsername),
|
||||
anim::type::instant);
|
||||
}
|
||||
auto joinToWrite = _controls.joinToWrite
|
||||
|
@ -299,7 +299,7 @@ void Controller::createContent() {
|
|||
if (_linkOnly) {
|
||||
_controls.inviteLinkWrap->show(anim::type::instant);
|
||||
} else {
|
||||
if (_controls.privacy->value() == Privacy::NoUsername) {
|
||||
if (_controls.privacy->current() == Privacy::NoUsername) {
|
||||
checkUsernameAvailability();
|
||||
}
|
||||
const auto forShowing = _dataSavedValue
|
||||
|
@ -474,7 +474,7 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
|
|||
&Ui::UsernameInput::changed,
|
||||
[this] { usernameChanged(); });
|
||||
|
||||
const auto shown = (_controls.privacy->value() == Privacy::HasUsername);
|
||||
const auto shown = (_controls.privacy->current() == Privacy::HasUsername);
|
||||
result->toggle(shown, anim::type::instant);
|
||||
|
||||
return result;
|
||||
|
@ -539,7 +539,7 @@ void Controller::checkUsernameAvailability() {
|
|||
if (!_controls.usernameInput) {
|
||||
return;
|
||||
}
|
||||
const auto initial = (_controls.privacy->value() != Privacy::HasUsername);
|
||||
const auto initial = (_controls.privacy->current() != Privacy::HasUsername);
|
||||
const auto checking = initial
|
||||
? u".bad."_q
|
||||
: getUsernameInput();
|
||||
|
@ -573,11 +573,11 @@ void Controller::checkUsernameAvailability() {
|
|||
_controls.privacy->setValue(Privacy::NoUsername);
|
||||
} else if (type == u"CHANNELS_ADMIN_PUBLIC_TOO_MUCH"_q) {
|
||||
_usernameState = UsernameState::TooMany;
|
||||
if (_controls.privacy->value() == Privacy::HasUsername) {
|
||||
if (_controls.privacy->current() == Privacy::HasUsername) {
|
||||
askUsernameRevoke();
|
||||
}
|
||||
} else if (initial) {
|
||||
if (_controls.privacy->value() == Privacy::HasUsername) {
|
||||
if (_controls.privacy->current() == Privacy::HasUsername) {
|
||||
showUsernameEmpty();
|
||||
setFocusUsername();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "apiwrap.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "data/data_premium_limits.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_cloud_themes.h"
|
||||
|
@ -424,14 +425,9 @@ Ui::BoostCounters ParseBoostCounters(
|
|||
}
|
||||
|
||||
Ui::BoostFeatures LookupBoostFeatures(not_null<ChannelData*> channel) {
|
||||
const auto group = channel->isMegagroup();
|
||||
const auto appConfig = &channel->session().account().appConfig();
|
||||
const auto get = [&](const QString &key, int fallback, bool ok = true) {
|
||||
return ok ? appConfig->get<int>(key, fallback) : 0;
|
||||
};
|
||||
|
||||
auto nameColorsByLevel = base::flat_map<int, int>();
|
||||
auto linkStylesByLevel = base::flat_map<int, int>();
|
||||
const auto group = channel->isMegagroup();
|
||||
const auto peerColors = &channel->session().api().peerColors();
|
||||
const auto &list = group
|
||||
? peerColors->requiredLevelsGroup()
|
||||
|
@ -447,22 +443,23 @@ Ui::BoostFeatures LookupBoostFeatures(not_null<ChannelData*> channel) {
|
|||
if (themes.empty()) {
|
||||
channel->owner().cloudThemes().refreshChatThemes();
|
||||
}
|
||||
const auto levelLimits = Data::LevelLimits(&channel->session());
|
||||
return Ui::BoostFeatures{
|
||||
.nameColorsByLevel = std::move(nameColorsByLevel),
|
||||
.linkStylesByLevel = std::move(linkStylesByLevel),
|
||||
.linkLogoLevel = get(u"channel_bg_icon_level_min"_q, 4, !group),
|
||||
.transcribeLevel = get(u"group_transcribe_level_min"_q, 6, group),
|
||||
.emojiPackLevel = get(u"group_emoji_stickers_level_min"_q, 4, group),
|
||||
.emojiStatusLevel = get(group
|
||||
? u"group_emoji_status_level_min"_q
|
||||
: u"channel_emoji_status_level_min"_q, 8),
|
||||
.wallpaperLevel = get(group
|
||||
? u"group_wallpaper_level_min"_q
|
||||
: u"channel_wallpaper_level_min"_q, 9),
|
||||
.linkLogoLevel = group ? 0 : levelLimits.channelBgIconLevelMin(),
|
||||
.transcribeLevel = group ? levelLimits.groupTranscribeLevelMin() : 0,
|
||||
.emojiPackLevel = group ? levelLimits.groupEmojiStickersLevelMin() : 0,
|
||||
.emojiStatusLevel = group
|
||||
? levelLimits.groupEmojiStatusLevelMin()
|
||||
: levelLimits.channelEmojiStatusLevelMin(),
|
||||
.wallpaperLevel = group
|
||||
? levelLimits.groupWallpaperLevelMin()
|
||||
: levelLimits.channelWallpaperLevelMin(),
|
||||
.wallpapersCount = themes.empty() ? 8 : int(themes.size()),
|
||||
.customWallpaperLevel = get(group
|
||||
? u"channel_custom_wallpaper_level_min"_q
|
||||
: u"group_custom_wallpaper_level_min"_q, 10),
|
||||
.customWallpaperLevel = group
|
||||
? levelLimits.groupCustomWallpaperLevelMin()
|
||||
: levelLimits.channelCustomWallpaperLevelMin(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1142,7 +1142,7 @@ void AccountsLimitBox(
|
|||
const auto ref = QString();
|
||||
|
||||
const auto wasAccount = &session->account();
|
||||
const auto nowAccount = accounts[group->value()];
|
||||
const auto nowAccount = accounts[group->current()];
|
||||
if (wasAccount == nowAccount) {
|
||||
Settings::ShowPremium(session, ref);
|
||||
return;
|
||||
|
|
|
@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "settings/settings_business.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "history/view/media/history_view_sticker.h"
|
||||
|
@ -59,7 +60,7 @@ constexpr auto kStarPeriod = 3 * crl::time(1000);
|
|||
using Data::ReactionId;
|
||||
|
||||
struct Descriptor {
|
||||
PremiumPreview section = PremiumPreview::Stickers;
|
||||
PremiumFeature section = PremiumFeature::Stickers;
|
||||
DocumentData *requestedSticker = nullptr;
|
||||
bool fromSettings = false;
|
||||
Fn<void()> hiddenCallback;
|
||||
|
@ -90,88 +91,118 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
|||
media->videoThumbnailWanted(origin);
|
||||
}
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> SectionTitle(PremiumPreview section) {
|
||||
[[nodiscard]] rpl::producer<QString> SectionTitle(PremiumFeature section) {
|
||||
switch (section) {
|
||||
case PremiumPreview::Wallpapers:
|
||||
case PremiumFeature::Wallpapers:
|
||||
return tr::lng_premium_summary_subtitle_wallpapers();
|
||||
case PremiumPreview::Stories:
|
||||
case PremiumFeature::Stories:
|
||||
return tr::lng_premium_summary_subtitle_stories();
|
||||
case PremiumPreview::DoubleLimits:
|
||||
case PremiumFeature::DoubleLimits:
|
||||
return tr::lng_premium_summary_subtitle_double_limits();
|
||||
case PremiumPreview::MoreUpload:
|
||||
case PremiumFeature::MoreUpload:
|
||||
return tr::lng_premium_summary_subtitle_more_upload();
|
||||
case PremiumPreview::FasterDownload:
|
||||
case PremiumFeature::FasterDownload:
|
||||
return tr::lng_premium_summary_subtitle_faster_download();
|
||||
case PremiumPreview::VoiceToText:
|
||||
case PremiumFeature::VoiceToText:
|
||||
return tr::lng_premium_summary_subtitle_voice_to_text();
|
||||
case PremiumPreview::NoAds:
|
||||
case PremiumFeature::NoAds:
|
||||
return tr::lng_premium_summary_subtitle_no_ads();
|
||||
case PremiumPreview::EmojiStatus:
|
||||
case PremiumFeature::EmojiStatus:
|
||||
return tr::lng_premium_summary_subtitle_emoji_status();
|
||||
case PremiumPreview::InfiniteReactions:
|
||||
case PremiumFeature::InfiniteReactions:
|
||||
return tr::lng_premium_summary_subtitle_infinite_reactions();
|
||||
case PremiumPreview::TagsForMessages:
|
||||
case PremiumFeature::TagsForMessages:
|
||||
return tr::lng_premium_summary_subtitle_tags_for_messages();
|
||||
case PremiumPreview::LastSeen:
|
||||
case PremiumFeature::LastSeen:
|
||||
return tr::lng_premium_summary_subtitle_last_seen();
|
||||
case PremiumPreview::MessagePrivacy:
|
||||
case PremiumFeature::MessagePrivacy:
|
||||
return tr::lng_premium_summary_subtitle_message_privacy();
|
||||
case PremiumPreview::Stickers:
|
||||
case PremiumFeature::Stickers:
|
||||
return tr::lng_premium_summary_subtitle_premium_stickers();
|
||||
case PremiumPreview::AnimatedEmoji:
|
||||
case PremiumFeature::AnimatedEmoji:
|
||||
return tr::lng_premium_summary_subtitle_animated_emoji();
|
||||
case PremiumPreview::AdvancedChatManagement:
|
||||
case PremiumFeature::AdvancedChatManagement:
|
||||
return tr::lng_premium_summary_subtitle_advanced_chat_management();
|
||||
case PremiumPreview::ProfileBadge:
|
||||
case PremiumFeature::ProfileBadge:
|
||||
return tr::lng_premium_summary_subtitle_profile_badge();
|
||||
case PremiumPreview::AnimatedUserpics:
|
||||
case PremiumFeature::AnimatedUserpics:
|
||||
return tr::lng_premium_summary_subtitle_animated_userpics();
|
||||
case PremiumPreview::RealTimeTranslation:
|
||||
case PremiumFeature::RealTimeTranslation:
|
||||
return tr::lng_premium_summary_subtitle_translation();
|
||||
case PremiumFeature::Business:
|
||||
return tr::lng_premium_summary_subtitle_business();
|
||||
|
||||
case PremiumFeature::BusinessLocation:
|
||||
return tr::lng_business_subtitle_location();
|
||||
case PremiumFeature::BusinessHours:
|
||||
return tr::lng_business_subtitle_opening_hours();
|
||||
case PremiumFeature::QuickReplies:
|
||||
return tr::lng_business_subtitle_quick_replies();
|
||||
case PremiumFeature::GreetingMessage:
|
||||
return tr::lng_business_subtitle_greeting_messages();
|
||||
case PremiumFeature::AwayMessage:
|
||||
return tr::lng_business_subtitle_away_messages();
|
||||
case PremiumFeature::BusinessBots:
|
||||
return tr::lng_business_subtitle_chatbots();
|
||||
}
|
||||
Unexpected("PremiumPreview in SectionTitle.");
|
||||
Unexpected("PremiumFeature in SectionTitle.");
|
||||
}
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> SectionAbout(PremiumPreview section) {
|
||||
[[nodiscard]] rpl::producer<QString> SectionAbout(PremiumFeature section) {
|
||||
switch (section) {
|
||||
case PremiumPreview::Wallpapers:
|
||||
case PremiumFeature::Wallpapers:
|
||||
return tr::lng_premium_summary_about_wallpapers();
|
||||
case PremiumPreview::Stories:
|
||||
case PremiumFeature::Stories:
|
||||
return tr::lng_premium_summary_about_stories();
|
||||
case PremiumPreview::DoubleLimits:
|
||||
case PremiumFeature::DoubleLimits:
|
||||
return tr::lng_premium_summary_about_double_limits();
|
||||
case PremiumPreview::MoreUpload:
|
||||
case PremiumFeature::MoreUpload:
|
||||
return tr::lng_premium_summary_about_more_upload();
|
||||
case PremiumPreview::FasterDownload:
|
||||
case PremiumFeature::FasterDownload:
|
||||
return tr::lng_premium_summary_about_faster_download();
|
||||
case PremiumPreview::VoiceToText:
|
||||
case PremiumFeature::VoiceToText:
|
||||
return tr::lng_premium_summary_about_voice_to_text();
|
||||
case PremiumPreview::NoAds:
|
||||
case PremiumFeature::NoAds:
|
||||
return tr::lng_premium_summary_about_no_ads();
|
||||
case PremiumPreview::EmojiStatus:
|
||||
case PremiumFeature::EmojiStatus:
|
||||
return tr::lng_premium_summary_about_emoji_status();
|
||||
case PremiumPreview::InfiniteReactions:
|
||||
case PremiumFeature::InfiniteReactions:
|
||||
return tr::lng_premium_summary_about_infinite_reactions();
|
||||
case PremiumPreview::TagsForMessages:
|
||||
case PremiumFeature::TagsForMessages:
|
||||
return tr::lng_premium_summary_about_tags_for_messages();
|
||||
case PremiumPreview::LastSeen:
|
||||
case PremiumFeature::LastSeen:
|
||||
return tr::lng_premium_summary_about_last_seen();
|
||||
case PremiumPreview::MessagePrivacy:
|
||||
case PremiumFeature::MessagePrivacy:
|
||||
return tr::lng_premium_summary_about_message_privacy();
|
||||
case PremiumPreview::Stickers:
|
||||
case PremiumFeature::Stickers:
|
||||
return tr::lng_premium_summary_about_premium_stickers();
|
||||
case PremiumPreview::AnimatedEmoji:
|
||||
case PremiumFeature::AnimatedEmoji:
|
||||
return tr::lng_premium_summary_about_animated_emoji();
|
||||
case PremiumPreview::AdvancedChatManagement:
|
||||
case PremiumFeature::AdvancedChatManagement:
|
||||
return tr::lng_premium_summary_about_advanced_chat_management();
|
||||
case PremiumPreview::ProfileBadge:
|
||||
case PremiumFeature::ProfileBadge:
|
||||
return tr::lng_premium_summary_about_profile_badge();
|
||||
case PremiumPreview::AnimatedUserpics:
|
||||
case PremiumFeature::AnimatedUserpics:
|
||||
return tr::lng_premium_summary_about_animated_userpics();
|
||||
case PremiumPreview::RealTimeTranslation:
|
||||
case PremiumFeature::RealTimeTranslation:
|
||||
return tr::lng_premium_summary_about_translation();
|
||||
case PremiumFeature::Business:
|
||||
return tr::lng_premium_summary_about_business();
|
||||
|
||||
case PremiumFeature::BusinessLocation:
|
||||
return tr::lng_business_about_location();
|
||||
case PremiumFeature::BusinessHours:
|
||||
return tr::lng_business_about_opening_hours();
|
||||
case PremiumFeature::QuickReplies:
|
||||
return tr::lng_business_about_quick_replies();
|
||||
case PremiumFeature::GreetingMessage:
|
||||
return tr::lng_business_about_greeting_messages();
|
||||
case PremiumFeature::AwayMessage:
|
||||
return tr::lng_business_about_away_messages();
|
||||
case PremiumFeature::BusinessBots:
|
||||
return tr::lng_business_about_chatbots();
|
||||
}
|
||||
Unexpected("PremiumPreview in SectionTitle.");
|
||||
Unexpected("PremiumFeature in SectionTitle.");
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> ChatBackPreview(
|
||||
|
@ -463,33 +494,40 @@ struct VideoPreviewDocument {
|
|||
RectPart align = RectPart::Bottom;
|
||||
};
|
||||
|
||||
[[nodiscard]] bool VideoAlignToTop(PremiumPreview section) {
|
||||
return (section == PremiumPreview::MoreUpload)
|
||||
|| (section == PremiumPreview::NoAds)
|
||||
|| (section == PremiumPreview::AnimatedEmoji);
|
||||
[[nodiscard]] bool VideoAlignToTop(PremiumFeature section) {
|
||||
return (section == PremiumFeature::MoreUpload)
|
||||
|| (section == PremiumFeature::NoAds)
|
||||
|| (section == PremiumFeature::AnimatedEmoji);
|
||||
}
|
||||
|
||||
[[nodiscard]] DocumentData *LookupVideo(
|
||||
not_null<Main::Session*> session,
|
||||
PremiumPreview section) {
|
||||
PremiumFeature section) {
|
||||
const auto name = [&] {
|
||||
switch (section) {
|
||||
case PremiumPreview::MoreUpload: return "more_upload";
|
||||
case PremiumPreview::FasterDownload: return "faster_download";
|
||||
case PremiumPreview::VoiceToText: return "voice_to_text";
|
||||
case PremiumPreview::NoAds: return "no_ads";
|
||||
case PremiumPreview::AnimatedEmoji: return "animated_emoji";
|
||||
case PremiumPreview::AdvancedChatManagement:
|
||||
case PremiumFeature::MoreUpload: return "more_upload";
|
||||
case PremiumFeature::FasterDownload: return "faster_download";
|
||||
case PremiumFeature::VoiceToText: return "voice_to_text";
|
||||
case PremiumFeature::NoAds: return "no_ads";
|
||||
case PremiumFeature::AnimatedEmoji: return "animated_emoji";
|
||||
case PremiumFeature::AdvancedChatManagement:
|
||||
return "advanced_chat_management";
|
||||
case PremiumPreview::EmojiStatus: return "emoji_status";
|
||||
case PremiumPreview::InfiniteReactions: return "infinite_reactions";
|
||||
case PremiumPreview::TagsForMessages: return "saved_tags";
|
||||
case PremiumPreview::ProfileBadge: return "profile_badge";
|
||||
case PremiumPreview::AnimatedUserpics: return "animated_userpics";
|
||||
case PremiumPreview::RealTimeTranslation: return "translations";
|
||||
case PremiumPreview::Wallpapers: return "wallpapers";
|
||||
case PremiumPreview::LastSeen: return "last_seen";
|
||||
case PremiumPreview::MessagePrivacy: return "message_privacy";
|
||||
case PremiumFeature::EmojiStatus: return "emoji_status";
|
||||
case PremiumFeature::InfiniteReactions: return "infinite_reactions";
|
||||
case PremiumFeature::TagsForMessages: return "saved_tags";
|
||||
case PremiumFeature::ProfileBadge: return "profile_badge";
|
||||
case PremiumFeature::AnimatedUserpics: return "animated_userpics";
|
||||
case PremiumFeature::RealTimeTranslation: return "translations";
|
||||
case PremiumFeature::Wallpapers: return "wallpapers";
|
||||
case PremiumFeature::LastSeen: return "last_seen";
|
||||
case PremiumFeature::MessagePrivacy: return "message_privacy";
|
||||
|
||||
case PremiumFeature::BusinessLocation: return "business_location";
|
||||
case PremiumFeature::BusinessHours: return "business_hours";
|
||||
case PremiumFeature::QuickReplies: return "quick_replies";
|
||||
case PremiumFeature::GreetingMessage: return "greeting_message";
|
||||
case PremiumFeature::AwayMessage: return "away_message";
|
||||
case PremiumFeature::BusinessBots: return "business_bots";
|
||||
}
|
||||
return "";
|
||||
}();
|
||||
|
@ -716,7 +754,7 @@ struct VideoPreviewDocument {
|
|||
[[nodiscard]] not_null<Ui::RpWidget*> GenericPreview(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void()> readyCallback) {
|
||||
const auto result = Ui::CreateChild<Ui::RpWidget>(parent.get());
|
||||
result->show();
|
||||
|
@ -757,10 +795,10 @@ struct VideoPreviewDocument {
|
|||
[[nodiscard]] not_null<Ui::RpWidget*> GenerateDefaultPreview(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void()> readyCallback) {
|
||||
switch (section) {
|
||||
case PremiumPreview::Stickers:
|
||||
case PremiumFeature::Stickers:
|
||||
return StickersPreview(parent, std::move(show), readyCallback);
|
||||
default:
|
||||
return GenericPreview(
|
||||
|
@ -784,8 +822,8 @@ struct VideoPreviewDocument {
|
|||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> CreateSwitch(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<rpl::variable<PremiumPreview>*> selected,
|
||||
std::vector<PremiumPreview> order) {
|
||||
not_null<rpl::variable<PremiumFeature>*> selected,
|
||||
std::vector<PremiumFeature> order) {
|
||||
const auto padding = st::premiumDotPadding;
|
||||
const auto width = padding.left() + st::premiumDot + padding.right();
|
||||
const auto height = padding.top() + st::premiumDot + padding.bottom();
|
||||
|
@ -856,14 +894,20 @@ void PreviewBox(
|
|||
Ui::Animations::Simple animation;
|
||||
Fn<void()> preload;
|
||||
std::vector<Hiding> hiding;
|
||||
rpl::variable<PremiumPreview> selected;
|
||||
std::vector<PremiumPreview> order;
|
||||
rpl::variable<PremiumFeature> selected;
|
||||
std::vector<PremiumFeature> order;
|
||||
};
|
||||
const auto state = outer->lifetime().make_state<State>();
|
||||
state->selected = descriptor.section;
|
||||
state->order = Settings::PremiumPreviewOrder(&show->session());
|
||||
auto premiumOrder = Settings::PremiumFeaturesOrder(&show->session());
|
||||
auto businessOrder = Settings::BusinessFeaturesOrder(&show->session());
|
||||
state->order = ranges::contains(businessOrder, descriptor.section)
|
||||
? std::move(businessOrder)
|
||||
: ranges::contains(businessOrder, descriptor.section)
|
||||
? std::move(premiumOrder)
|
||||
: std::vector{ descriptor.section };
|
||||
|
||||
const auto index = [=](PremiumPreview section) {
|
||||
const auto index = [=](PremiumFeature section) {
|
||||
const auto it = ranges::find(state->order, section);
|
||||
return (it == end(state->order))
|
||||
? 0
|
||||
|
@ -906,7 +950,7 @@ void PreviewBox(
|
|||
return;
|
||||
}
|
||||
const auto now = state->selected.current();
|
||||
if (now != PremiumPreview::Stickers && !state->stickersPreload) {
|
||||
if (now != PremiumFeature::Stickers && !state->stickersPreload) {
|
||||
const auto ready = [=] {
|
||||
if (state->stickersPreload) {
|
||||
state->stickersPreloadReady = true;
|
||||
|
@ -917,14 +961,14 @@ void PreviewBox(
|
|||
state->stickersPreload = GenerateDefaultPreview(
|
||||
outer,
|
||||
show,
|
||||
PremiumPreview::Stickers,
|
||||
PremiumFeature::Stickers,
|
||||
ready);
|
||||
state->stickersPreload->hide();
|
||||
}
|
||||
};
|
||||
|
||||
switch (descriptor.section) {
|
||||
case PremiumPreview::Stickers:
|
||||
case PremiumFeature::Stickers:
|
||||
state->content = media
|
||||
? StickerPreview(outer, show, media, state->preload)
|
||||
: StickersPreview(outer, show, state->preload);
|
||||
|
@ -940,7 +984,7 @@ void PreviewBox(
|
|||
|
||||
state->selected.value(
|
||||
) | rpl::combine_previous(
|
||||
) | rpl::start_with_next([=](PremiumPreview was, PremiumPreview now) {
|
||||
) | rpl::start_with_next([=](PremiumFeature was, PremiumFeature now) {
|
||||
const auto animationCallback = [=] {
|
||||
if (!state->animation.animating()) {
|
||||
for (const auto &hiding : base::take(state->hiding)) {
|
||||
|
@ -982,7 +1026,7 @@ void PreviewBox(
|
|||
.leftTill = state->content->x() - start,
|
||||
});
|
||||
state->leftFrom = start;
|
||||
if (now == PremiumPreview::Stickers && state->stickersPreload) {
|
||||
if (now == PremiumFeature::Stickers && state->stickersPreload) {
|
||||
state->content = base::take(state->stickersPreload);
|
||||
state->content->show();
|
||||
if (base::take(state->stickersPreloadReady)) {
|
||||
|
@ -1053,14 +1097,14 @@ void PreviewBox(
|
|||
return Settings::LookupPremiumRef(state->selected.current());
|
||||
};
|
||||
auto unlock = state->selected.value(
|
||||
) | rpl::map([=](PremiumPreview section) {
|
||||
return (section == PremiumPreview::InfiniteReactions)
|
||||
) | rpl::map([=](PremiumFeature section) {
|
||||
return (section == PremiumFeature::InfiniteReactions)
|
||||
? tr::lng_premium_unlock_reactions()
|
||||
: (section == PremiumPreview::Stickers)
|
||||
: (section == PremiumFeature::Stickers)
|
||||
? tr::lng_premium_unlock_stickers()
|
||||
: (section == PremiumPreview::AnimatedEmoji)
|
||||
: (section == PremiumFeature::AnimatedEmoji)
|
||||
? tr::lng_premium_unlock_emoji()
|
||||
: (section == PremiumPreview::EmojiStatus)
|
||||
: (section == PremiumFeature::EmojiStatus)
|
||||
? tr::lng_premium_unlock_status()
|
||||
: tr::lng_premium_more_about();
|
||||
}) | rpl::flatten_latest();
|
||||
|
@ -1207,18 +1251,25 @@ void Show(
|
|||
descriptor.shownCallback(raw);
|
||||
}
|
||||
return;
|
||||
} else if (descriptor.section == PremiumPreview::DoubleLimits) {
|
||||
} else if (descriptor.section == PremiumFeature::DoubleLimits) {
|
||||
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
DoubledLimitsPreviewBox(box, &show->session());
|
||||
DecorateListPromoBox(box, show, descriptor);
|
||||
}));
|
||||
return;
|
||||
} else if (descriptor.section == PremiumPreview::Stories) {
|
||||
} else if (descriptor.section == PremiumFeature::Stories) {
|
||||
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
UpgradedStoriesPreviewBox(box, &show->session());
|
||||
DecorateListPromoBox(box, show, descriptor);
|
||||
}));
|
||||
return;
|
||||
} else if (descriptor.section == PremiumFeature::Business) {
|
||||
const auto window = show->resolveWindow(
|
||||
ChatHelpers::WindowUsage::PremiumPromo);
|
||||
if (window) {
|
||||
Settings::ShowBusiness(window);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto &list = Preloads();
|
||||
for (auto i = begin(list); i != end(list);) {
|
||||
|
@ -1286,21 +1337,21 @@ void ShowStickerPreviewBox(
|
|||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
not_null<DocumentData*> document) {
|
||||
Show(std::move(show), Descriptor{
|
||||
.section = PremiumPreview::Stickers,
|
||||
.section = PremiumFeature::Stickers,
|
||||
.requestedSticker = document,
|
||||
});
|
||||
}
|
||||
|
||||
void ShowPremiumPreviewBox(
|
||||
not_null<Window::SessionController*> controller,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void(not_null<Ui::BoxContent*>)> shown) {
|
||||
ShowPremiumPreviewBox(controller->uiShow(), section, std::move(shown));
|
||||
}
|
||||
|
||||
void ShowPremiumPreviewBox(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void(not_null<Ui::BoxContent*>)> shown,
|
||||
bool hideSubscriptionButton) {
|
||||
Show(std::move(show), Descriptor{
|
||||
|
@ -1312,7 +1363,7 @@ void ShowPremiumPreviewBox(
|
|||
|
||||
void ShowPremiumPreviewToBuy(
|
||||
not_null<Window::SessionController*> controller,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void()> hiddenCallback) {
|
||||
Show(controller->uiShow(), Descriptor{
|
||||
.section = section,
|
||||
|
|
|
@ -45,7 +45,8 @@ void UpgradedStoriesPreviewBox(
|
|||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session);
|
||||
|
||||
enum class PremiumPreview {
|
||||
enum class PremiumFeature {
|
||||
// Premium features.
|
||||
Stories,
|
||||
DoubleLimits,
|
||||
MoreUpload,
|
||||
|
@ -64,24 +65,33 @@ enum class PremiumPreview {
|
|||
TagsForMessages,
|
||||
LastSeen,
|
||||
MessagePrivacy,
|
||||
Business,
|
||||
|
||||
// Business features.
|
||||
BusinessLocation,
|
||||
BusinessHours,
|
||||
QuickReplies,
|
||||
GreetingMessage,
|
||||
AwayMessage,
|
||||
BusinessBots,
|
||||
|
||||
kCount,
|
||||
};
|
||||
|
||||
void ShowPremiumPreviewBox(
|
||||
not_null<Window::SessionController*> controller,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void(not_null<Ui::BoxContent*>)> shown = nullptr);
|
||||
|
||||
void ShowPremiumPreviewBox(
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void(not_null<Ui::BoxContent*>)> shown = nullptr,
|
||||
bool hideSubscriptionButton = false);
|
||||
|
||||
void ShowPremiumPreviewToBuy(
|
||||
not_null<Window::SessionController*> controller,
|
||||
PremiumPreview section,
|
||||
PremiumFeature section,
|
||||
Fn<void()> hiddenCallback = nullptr);
|
||||
|
||||
void PremiumUnavailableBox(not_null<Ui::GenericBox*> box);
|
||||
|
|
|
@ -77,20 +77,15 @@ AdminLog::OwnedItem GenerateItem(
|
|||
const QString &text) {
|
||||
Expects(history->peer->isUser());
|
||||
|
||||
const auto item = history->addNewLocalMessage(
|
||||
history->nextNonHistoryEntryId(),
|
||||
(MessageFlag::FakeHistoryItem
|
||||
const auto item = history->addNewLocalMessage({
|
||||
.id = history->nextNonHistoryEntryId(),
|
||||
.flags = (MessageFlag::FakeHistoryItem
|
||||
| MessageFlag::HasFromId
|
||||
| MessageFlag::HasReplyInfo),
|
||||
UserId(), // via
|
||||
FullReplyTo{ .messageId = replyTo },
|
||||
base::unixtime::now(), // date
|
||||
from,
|
||||
QString(), // postAuthor
|
||||
TextWithEntities{ .text = text },
|
||||
MTP_messageMediaEmpty(),
|
||||
HistoryMessageMarkupData(),
|
||||
uint64(0)); // groupedId
|
||||
.from = from,
|
||||
.replyTo = FullReplyTo{ .messageId = replyTo },
|
||||
.date = base::unixtime::now(),
|
||||
}, TextWithEntities{ .text = text }, MTP_messageMediaEmpty());
|
||||
|
||||
return AdminLog::OwnedItem(delegate, item);
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ void RingtonesBox(
|
|||
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
const auto value = state->group->value();
|
||||
const auto value = state->group->current();
|
||||
auto sound = (value == kDefaultValue)
|
||||
? Data::NotifySound()
|
||||
: (value == kNoSoundValue)
|
||||
|
|
|
@ -95,7 +95,7 @@ void SelfDestructionBox::showContent() {
|
|||
|
||||
clearButtons();
|
||||
addButton(tr::lng_settings_save(), [=] {
|
||||
const auto value = _ttlGroup->value();
|
||||
const auto value = _ttlGroup->current();
|
||||
switch (_type) {
|
||||
case Type::Account:
|
||||
_session->api().selfDestruct().updateAccountTTL(value);
|
||||
|
|
|
@ -1172,7 +1172,7 @@ void SendFilesBox::setupEmojiPanel() {
|
|||
_captionToPeer,
|
||||
data.document)
|
||||
: (_limits & SendFilesAllow::EmojiWithoutPremium))) {
|
||||
ShowPremiumPreviewBox(_show, PremiumPreview::AnimatedEmoji);
|
||||
ShowPremiumPreviewBox(_show, PremiumFeature::AnimatedEmoji);
|
||||
} else {
|
||||
Data::InsertCustomEmoji(_caption.data(), data.document);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/peer_list_controllers.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "chat_helpers/share_message_phrase_factory.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_game.h"
|
||||
#include "data/data_histories.h"
|
||||
|
@ -1543,11 +1544,15 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
|||
const auto threadHistory = thread->owningHistory();
|
||||
histories.sendRequest(threadHistory, requestType, [=](
|
||||
Fn<void()> finish) {
|
||||
auto &api = threadHistory->session().api();
|
||||
const auto session = &threadHistory->session();
|
||||
auto &api = session->api();
|
||||
const auto sendFlags = commonSendFlags
|
||||
| (topMsgId ? Flag::f_top_msg_id : Flag(0))
|
||||
| (ShouldSendSilent(peer, options)
|
||||
? Flag::f_silent
|
||||
: Flag(0))
|
||||
| (options.shortcutId
|
||||
? Flag::f_quick_reply_shortcut
|
||||
: Flag(0));
|
||||
threadHistory->sendRequestId = api.request(
|
||||
MTPmessages_ForwardMessages(
|
||||
|
@ -1558,7 +1563,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
|||
peer->input,
|
||||
MTP_int(topMsgId),
|
||||
MTP_int(options.scheduled),
|
||||
MTP_inputPeerEmpty() // send_as
|
||||
MTP_inputPeerEmpty(), // send_as
|
||||
Data::ShortcutIdToMTP(session, options.shortcutId)
|
||||
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {
|
||||
threadHistory->session().api().applyUpdates(updates);
|
||||
state->requests.remove(reqId);
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_premium_limits.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "core/application.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
@ -40,8 +41,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/painter.h"
|
||||
#include "ui/unread_badge_paint.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -2050,10 +2049,8 @@ void StickersBox::Inner::checkGroupLevel(Fn<void()> done) {
|
|||
return std::optional<Ui::AskBoostReason>();
|
||||
}
|
||||
_checkingGroupLevel = false;
|
||||
const auto appConfig = &peer->session().account().appConfig();
|
||||
const auto required = appConfig->get<int>(
|
||||
"group_emoji_stickers_level_min",
|
||||
4);
|
||||
const auto required = Data::LevelLimits(
|
||||
&peer->session()).groupEmojiStickersLevelMin();
|
||||
if (level >= required) {
|
||||
save();
|
||||
return std::optional<Ui::AskBoostReason>();
|
||||
|
|
|
@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/power_save_blocker.h"
|
||||
#include "media/streaming/media_streaming_utility.h"
|
||||
|
@ -147,17 +148,18 @@ void Panel::initWindow() {
|
|||
window()->setTitle(_user->name());
|
||||
window()->setTitleStyle(st::callTitle);
|
||||
|
||||
window()->events(
|
||||
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::Close) {
|
||||
handleClose();
|
||||
base::install_event_filter(window().get(), [=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::Close && handleClose()) {
|
||||
e->ignore();
|
||||
return base::EventFilterResult::Cancel;
|
||||
} else if (e->type() == QEvent::KeyPress) {
|
||||
if ((static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Escape)
|
||||
&& window()->isFullScreen()) {
|
||||
window()->showNormal();
|
||||
}
|
||||
}
|
||||
}, window()->lifetime());
|
||||
return base::EventFilterResult::Continue;
|
||||
});
|
||||
|
||||
window()->setBodyTitleArea([=](QPoint widgetPoint) {
|
||||
using Flag = Ui::WindowTitleHitTestFlag;
|
||||
|
@ -828,10 +830,12 @@ void Panel::paint(QRect clip) {
|
|||
}
|
||||
}
|
||||
|
||||
void Panel::handleClose() {
|
||||
bool Panel::handleClose() const {
|
||||
if (_call) {
|
||||
_call->hangup();
|
||||
window()->hide();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
not_null<Ui::RpWindow*> Panel::window() const {
|
||||
|
|
|
@ -106,7 +106,7 @@ private:
|
|||
void initLayout();
|
||||
void initGeometry();
|
||||
|
||||
void handleClose();
|
||||
[[nodiscard]] bool handleClose() const;
|
||||
|
||||
void updateControlsGeometry();
|
||||
void updateHangupGeometry();
|
||||
|
|
|
@ -608,7 +608,7 @@ defaultComposeIcons: ComposeIcons {
|
|||
|
||||
stripBubble: icon{
|
||||
{ "chat/reactions_bubble_shadow", windowShadowFg },
|
||||
{ "chat/reactions_bubble", windowBg },
|
||||
{ "chat/reactions_bubble", emojiPanBg },
|
||||
};
|
||||
stripExpandPanel: icon{
|
||||
{ "chat/reactions_round_big", windowBgRipple },
|
||||
|
|
|
@ -23,6 +23,7 @@ struct ComposeFeatures {
|
|||
bool autocompleteHashtags = true;
|
||||
bool autocompleteMentions = true;
|
||||
bool autocompleteCommands = true;
|
||||
bool commonTabbedPanel = true;
|
||||
};
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|