Merge tag 'v4.10.0' into dev
# Conflicts: # README.md # Telegram/Resources/winrc/Telegram.rc # Telegram/Resources/winrc/Updater.rc # Telegram/SourceFiles/apiwrap.cpp # Telegram/SourceFiles/core/version.h # Telegram/SourceFiles/data/data_stories.cpp # Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp # Telegram/lib_ui # snap/snapcraft.yaml
4
.github/workflows/linux.yml
vendored
|
@ -41,7 +41,7 @@ on:
|
|||
jobs:
|
||||
|
||||
linux:
|
||||
name: CentOS 7
|
||||
name: Rocky Linux 8
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/${{ github.repository }}/centos_env
|
||||
|
@ -51,7 +51,7 @@ jobs:
|
|||
|
||||
defaults:
|
||||
run:
|
||||
shell: scl enable rh-python38 -- scl enable llvm-toolset-7.0 -- scl enable devtoolset-10 -- bash --noprofile --norc -eo pipefail {0}
|
||||
shell: scl enable gcc-toolset-12 -- bash --noprofile --norc -eo pipefail {0}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
2
.github/workflows/win.yml
vendored
|
@ -124,7 +124,7 @@ jobs:
|
|||
echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV
|
||||
|
||||
API="-D TDESKTOP_API_TEST=ON"
|
||||
if [ ${{ github.ref == 'refs/heads/nightly' }} ]; then
|
||||
if [ $GITHUB_REF == 'refs/heads/nightly' ]; then
|
||||
echo "Use the open credentials."
|
||||
API="-D TDESKTOP_API_ID=611335 -D TDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c"
|
||||
fi
|
||||
|
|
3
.gitmodules
vendored
|
@ -58,9 +58,6 @@
|
|||
[submodule "Telegram/ThirdParty/range-v3"]
|
||||
path = Telegram/ThirdParty/range-v3
|
||||
url = https://github.com/ericniebler/range-v3.git
|
||||
[submodule "Telegram/ThirdParty/fcitx-qt5"]
|
||||
path = Telegram/ThirdParty/fcitx-qt5
|
||||
url = https://github.com/fcitx/fcitx-qt5.git
|
||||
[submodule "Telegram/ThirdParty/nimf"]
|
||||
path = Telegram/ThirdParty/nimf
|
||||
url = https://github.com/hamonikr/nimf.git
|
||||
|
|
|
@ -61,7 +61,7 @@ if (NOT DESKTOP_APP_USE_PACKAGED)
|
|||
if (WIN32)
|
||||
set(qt_version 5.15.10)
|
||||
elseif (APPLE)
|
||||
set(qt_version 6.3.2)
|
||||
set(qt_version 6.2.5)
|
||||
endif()
|
||||
endif()
|
||||
include(cmake/external/qt/package.cmake)
|
||||
|
|
|
@ -478,6 +478,7 @@ PRIVATE
|
|||
core/crash_report_window.h
|
||||
core/crash_reports.cpp
|
||||
core/crash_reports.h
|
||||
core/deadlock_detector.h
|
||||
core/file_utilities.cpp
|
||||
core/file_utilities.h
|
||||
core/launcher.cpp
|
||||
|
@ -1541,6 +1542,7 @@ PRIVATE
|
|||
qrc/emoji_5.qrc
|
||||
qrc/emoji_6.qrc
|
||||
qrc/emoji_7.qrc
|
||||
qrc/emoji_8.qrc
|
||||
qrc/emoji_preview.qrc
|
||||
qrc/telegram/animations.qrc
|
||||
qrc/telegram/export.qrc
|
||||
|
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1 MiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 821 KiB After Width: | Height: | Size: 832 KiB |
BIN
Telegram/Resources/emoji/emoji_8.webp
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
Telegram/Resources/icons/limits/boost.png
Normal file
After Width: | Height: | Size: 464 B |
BIN
Telegram/Resources/icons/limits/boost@2x.png
Normal file
After Width: | Height: | Size: 796 B |
BIN
Telegram/Resources/icons/limits/boost@3x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/mediaview/views.png
Normal file
After Width: | Height: | Size: 476 B |
BIN
Telegram/Resources/icons/mediaview/views@2x.png
Normal file
After Width: | Height: | Size: 884 B |
BIN
Telegram/Resources/icons/mediaview/views@3x.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 319 B |
Before Width: | Height: | Size: 527 B After Width: | Height: | Size: 539 B |
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 777 B |
Before Width: | Height: | Size: 563 B After Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/stories/boost_mini.png
Normal file
After Width: | Height: | Size: 366 B |
BIN
Telegram/Resources/icons/stories/boost_mini@2x.png
Normal file
After Width: | Height: | Size: 589 B |
BIN
Telegram/Resources/icons/stories/boost_mini@3x.png
Normal file
After Width: | Height: | Size: 863 B |
|
@ -548,6 +548,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_settings_title_account_name" = "Show active account";
|
||||
"lng_settings_title_total_count" = "Total unread count";
|
||||
"lng_settings_native_frame" = "Use system window frame";
|
||||
"lng_settings_qt_frame" = "Use Qt window frame";
|
||||
"lng_settings_auto_start" = "Launch Telegram when system starts";
|
||||
"lng_settings_start_min" = "Launch minimized";
|
||||
"lng_settings_auto_start_disabled_uwp" = "Starting with the system was disabled in Windows Settings.\n\nPlease enable Telegram Desktop in the Startup Apps Settings.";
|
||||
|
@ -1182,6 +1183,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_profile_loading" = "Loading...";
|
||||
"lng_profile_saved_stories#one" = "{count} saved story";
|
||||
"lng_profile_saved_stories#other" = "{count} saved stories";
|
||||
"lng_profile_posts#one" = "{count} post";
|
||||
"lng_profile_posts#other" = "{count} posts";
|
||||
"lng_profile_photos#one" = "{count} photo";
|
||||
"lng_profile_photos#other" = "{count} photos";
|
||||
"lng_profile_gifs#one" = "{count} GIF";
|
||||
|
@ -1611,6 +1614,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_action_suggested_video" = "{user} suggests you to use this profile video.";
|
||||
"lng_action_suggested_video_button" = "View Video";
|
||||
"lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu.";
|
||||
"lng_action_webapp_bot_allowed" = "You allowed this bot to message you in his web-app.";
|
||||
"lng_action_set_wallpaper_me" = "You set a new wallpaper for this chat";
|
||||
"lng_action_set_wallpaper" = "{user} set a new wallpaper for this chat";
|
||||
"lng_action_set_wallpaper_button" = "View Wallpaper";
|
||||
|
@ -1799,6 +1803,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_bot_share_location_unavailable" = "Sorry, location sharing is currently unavailable in Telegram Desktop.";
|
||||
"lng_bot_share_phone" = "Do you want to share your phone number with this bot?";
|
||||
"lng_bot_share_phone_confirm" = "Share";
|
||||
"lng_bot_allow_write_title" = "Allow messaging";
|
||||
"lng_bot_allow_write" = "Do you want to allow this bot writing you?";
|
||||
"lng_bot_allow_write_confirm" = "Allow";
|
||||
|
||||
"lng_attach_failed" = "Failed";
|
||||
"lng_attach_file" = "File";
|
||||
|
@ -1995,6 +2002,38 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_premium_gift_terms" = "You can review the list of features and terms of use for Telegram Premium {link}.";
|
||||
"lng_premium_gift_terms_link" = "here";
|
||||
|
||||
"lng_boost_channel_button" = "Boost Channel";
|
||||
"lng_boost_level#one" = "Level {count}";
|
||||
"lng_boost_level#other" = "Level {count}";
|
||||
"lng_boost_channel_title_first" = "Enable stories for channel";
|
||||
"lng_boost_channel_needs_first#one" = "{channel} needs **{count}** more boost to enable posting stories. Help make it possible!";
|
||||
"lng_boost_channel_needs_first#other" = "{channel} needs **{count}** more boosts to enable posting stories. Help make it possible!";
|
||||
"lng_boost_channel_title_more" = "Help upgrade channel";
|
||||
"lng_boost_channel_needs_more#one" = "{channel} needs **{count}** more boost to be able to {post}.";
|
||||
"lng_boost_channel_needs_more#other" = "{channel} needs **{count}** more boosts to be able to {post}.";
|
||||
"lng_boost_channel_title_max" = "Maximum level reached";
|
||||
"lng_boost_channel_you_title" = "You boosted {channel}!";
|
||||
"lng_boost_channel_you_first#one" = "This channel needs **{count}** more boost\nto enable stories.";
|
||||
"lng_boost_channel_you_first#other" = "This channel needs **{count}** more boosts\nto enable stories.";
|
||||
"lng_boost_channel_you_more#one" = "This channel needs **{count}** more boost\nto be able to {post}.";
|
||||
"lng_boost_channel_you_more#other" = "This channel needs **{count}** more boosts\nto be able to {post}.";
|
||||
"lng_boost_channel_reached_first" = "This channel reached **Level 1** and can now post stories.";
|
||||
"lng_boost_channel_reached_more#one" = "This channel reached **Level {count}** and can now {post}.";
|
||||
"lng_boost_channel_reached_more#other" = "This channel reached **Level {count}** and can now {post}.";
|
||||
"lng_boost_channel_post_stories#one" = "post **{count} story** per day";
|
||||
"lng_boost_channel_post_stories#other" = "post **{count} stories** per day";
|
||||
"lng_boost_error_gifted_title" = "Can't boost with gifted Premium!";
|
||||
"lng_boost_error_gifted_text" = "Because your **Telegram Premium** subscription was gifted to you, you can't use it to boost channels.";
|
||||
"lng_boost_error_already_title" = "Already Boosted!";
|
||||
"lng_boost_error_already_text" = "You are already boosting this channel.";
|
||||
"lng_boost_error_premium_title" = "Premium needed!";
|
||||
"lng_boost_error_premium_text" = "Only **Telegram Premium** subscribers can boost channels. Do you want to subscribe to **Telegram Premium**?";
|
||||
"lng_boost_error_premium_yes" = "Yes";
|
||||
"lng_boost_error_flood_title" = "Can't boost too often!";
|
||||
"lng_boost_error_flood_text" = "You can change the channel you boost only once a day. Next time you can boost is in {left}.";
|
||||
"lng_boost_now_instead" = "You currently boost {channel}. Do you want to boost {other} instead?";
|
||||
"lng_boost_now_replace" = "Replace";
|
||||
|
||||
"lng_accounts_limit_title" = "Limit Reached";
|
||||
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected accounts.";
|
||||
"lng_accounts_limit1#other" = "You have reached the limit of **{count}** connected accounts.";
|
||||
|
@ -2256,17 +2295,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_bot_remove_from_menu" = "Remove From Menu";
|
||||
"lng_bot_remove_from_menu_sure" = "Remove {bot} from the attachment menu?";
|
||||
"lng_bot_remove_from_menu_done" = "Bot removed from the menu.";
|
||||
"lng_bot_remove_from_side_menu" = "Remove From Menu";
|
||||
"lng_bot_remove_from_side_menu_sure" = "Remove {bot} from the main menu?";
|
||||
"lng_bot_remove_from_side_menu_done" = "Bot removed from the main menu.";
|
||||
"lng_bot_settings" = "Settings";
|
||||
"lng_bot_open" = "Open Bot";
|
||||
"lng_bot_reload_page" = "Reload Page";
|
||||
"lng_bot_add_to_menu" = "{bot} asks your permission to be added as an option to your attachments menu so you can access it from any chat.";
|
||||
"lng_bot_add_to_menu_done" = "Bot added to the menu.";
|
||||
"lng_bot_will_be_added" = "{bot} shortcuts will be added to the attachment options and the main menu.";
|
||||
"lng_bot_side_menu_new" = "NEW";
|
||||
"lng_bot_menu_not_supported" = "This bot isn't supported in the attach menu.";
|
||||
"lng_bot_menu_already_added" = "This bot is already added in your attach menu.";
|
||||
"lng_bot_menu_button" = "Menu";
|
||||
"lng_bot_close_warning_title" = "Warning";
|
||||
"lng_bot_close_warning" = "Changes that you made may not be saved.";
|
||||
"lng_bot_close_warning_sure" = "Close anyway";
|
||||
"lng_bot_add_to_side_menu" = "{bot} asks your permission to be added as an option to your main menu so you can access it any time.";
|
||||
"lng_bot_add_to_side_menu_done" = "Bot added to the main menu.";
|
||||
|
||||
"lng_typing" = "typing";
|
||||
"lng_user_typing" = "{user} is typing";
|
||||
|
@ -2370,6 +2416,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_context_open_gif" = "Open GIF";
|
||||
"lng_context_save_gif" = "Save GIF";
|
||||
"lng_context_delete_gif" = "Delete GIF";
|
||||
"lng_context_open_channel" = "Open Channel";
|
||||
"lng_context_attached_stickers" = "Attached Stickers";
|
||||
"lng_context_to_msg" = "Go To Message";
|
||||
"lng_context_reply_msg" = "Reply";
|
||||
|
@ -2747,6 +2794,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
"lng_payments_terms_title" = "Terms of Service";
|
||||
"lng_payments_terms_text" = "Subscribe and accept terms of service of {bot}?";
|
||||
"lng_payments_terms_text_once" = "Are you accepting terms of service of {bot}?";
|
||||
"lng_payments_terms_agree" = "I agree to {link}";
|
||||
"lng_payments_terms_link" = "Terms of Service";
|
||||
"lng_payments_terms_accept" = "Accept";
|
||||
|
@ -3079,9 +3127,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_gigagroup_suggest_more" = "Learn more";
|
||||
|
||||
"lng_rights_channel_info" = "Change channel info";
|
||||
"lng_rights_channel_manage" = "Manage messages";
|
||||
"lng_rights_channel_post" = "Post messages";
|
||||
"lng_rights_channel_edit" = "Edit messages of others";
|
||||
"lng_rights_channel_delete" = "Delete messages of others";
|
||||
"lng_rights_channel_manage_stories" = "Manage stories";
|
||||
"lng_rights_channel_post_stories" = "Post stories";
|
||||
"lng_rights_channel_edit_stories" = "Edit stories of others";
|
||||
"lng_rights_channel_delete_stories" = "Delete stories of others";
|
||||
"lng_rights_channel_manage_calls" = "Manage live streams";
|
||||
"lng_rights_group_info" = "Change group info";
|
||||
"lng_rights_group_ban" = "Ban users";
|
||||
|
@ -3340,6 +3393,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_admin_log_admin_post_messages" = "Post messages";
|
||||
"lng_admin_log_admin_edit_messages" = "Edit messages";
|
||||
"lng_admin_log_admin_delete_messages" = "Delete messages";
|
||||
"lng_admin_log_admin_post_stories" = "Post stories";
|
||||
"lng_admin_log_admin_edit_stories" = "Edit stories";
|
||||
"lng_admin_log_admin_delete_stories" = "Delete stories";
|
||||
"lng_admin_log_admin_remain_anonymous" = "Remain anonymous";
|
||||
"lng_admin_log_admin_ban_users" = "Ban users";
|
||||
"lng_admin_log_admin_invite_users" = "Add members";
|
||||
|
@ -3555,6 +3611,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_export_option_choose_format" = "Choose export format";
|
||||
"lng_export_option_html" = "Human-readable HTML";
|
||||
"lng_export_option_json" = "Machine-readable JSON";
|
||||
"lng_export_option_html_and_json" = "Both";
|
||||
"lng_export_limits" = "From: {from}, to: {till}";
|
||||
"lng_export_beginning" = "the oldest message";
|
||||
"lng_export_end" = "present";
|
||||
|
@ -3819,6 +3876,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_view_button_voice_chat_channel" = "Live stream";
|
||||
"lng_view_button_request_join" = "Request to Join";
|
||||
"lng_view_button_external_link" = "Open link";
|
||||
"lng_view_button_boost" = "Boost";
|
||||
|
||||
"lng_sponsored_hide_ads" = "Hide";
|
||||
"lng_sponsored_title" = "What are sponsored messages?";
|
||||
|
@ -3829,6 +3887,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
"lng_telegram_features_url" = "https://t.me/TelegramTips";
|
||||
|
||||
"lng_mini_apps_disclaimer_title" = "Warning";
|
||||
"lng_mini_apps_disclaimer_text" = "You are about to use a mini app operated by an independent party **not affiliated with Telegram**. You must agree to the Terms of Use of mini apps to continue.";
|
||||
"lng_mini_apps_disclaimer_button" = "I agree to the {link}";
|
||||
"lng_mini_apps_disclaimer_link" = "Terms of Use";
|
||||
"lng_mini_apps_tos_url" = "https://telegram.org/tos/mini-apps";
|
||||
|
||||
"lng_ringtones_box_title" = "Notification Sound";
|
||||
"lng_ringtones_box_cloud_subtitle" = "Choose your tone";
|
||||
"lng_ringtones_box_upload_choose" = "Choose ringtone";
|
||||
|
@ -3946,6 +4010,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_stories_recent_button" = "Recent Stories";
|
||||
"lng_stories_archive_title" = "Stories Archive";
|
||||
"lng_stories_archive_about" = "Only you can see archived stories unless you choose to save them to your profile.";
|
||||
"lng_stories_channel_archive_about" = "Only admins of the channel can see archived stories unless they are saved to the channel page.";
|
||||
"lng_stories_reply_sent" = "Message Sent";
|
||||
"lng_stories_hidden_to_contacts" = "Stories from {user} will now be shown in **Archived Chats**.";
|
||||
"lng_stories_shown_in_chats" = "Stories from {user} will now be shown in the **Chats List**.";
|
||||
|
@ -3965,6 +4030,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_stories_archive_done" = "This story is hidden from your profile.";
|
||||
"lng_stories_archive_done_many#one" = "{count} story is hidden from your profile.";
|
||||
"lng_stories_archive_done_many#other" = "{count} stories are hidden from your profile.";
|
||||
"lng_stories_channel_save_sure" = "Do you want to save this story to the channel page?";
|
||||
"lng_stories_channel_save_sure_many#one" = "Do you want to save {count} story to the channel page?";
|
||||
"lng_stories_channel_save_sure_many#other" = "Do you want to save {count} stories to the channel page?";
|
||||
"lng_stories_channel_save_done" = "This story is saved to the channel page.";
|
||||
"lng_stories_channel_save_done_many#one" = "{count} story is saved to the channel page.";
|
||||
"lng_stories_channel_save_done_many#other" = "{count} stories are saved to the channel page.";
|
||||
"lng_stories_channel_save_done_about" = "Saved stories can be viewed by others on the channel page until they are removed.";
|
||||
"lng_stories_channel_archive_sure" = "Do you want to hide this story from the channel page?";
|
||||
"lng_stories_channel_archive_sure_many#one" = "Do you want to hide {count} story from the channel page?";
|
||||
"lng_stories_channel_archive_sure_many#other" = "Do you want to hide {count} stories from the channel page?";
|
||||
"lng_stories_channel_archive_done" = "This story is hidden from the channel page.";
|
||||
"lng_stories_channel_archive_done_many#one" = "{count} story is hidden from the channel page.";
|
||||
"lng_stories_channel_archive_done_many#other" = "{count} stories are hidden from the channel page.";
|
||||
"lng_stories_save_promo" = "Subscribe to {link} to download other people's unprotected stories to disk.";
|
||||
|
||||
"lng_stealth_mode_menu_item" = "Stealth Mode";
|
||||
|
|
5
Telegram/Resources/qrc/emoji_8.qrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/gui">
|
||||
<file alias="emoji/emoji_8.webp">../emoji/emoji_8.webp</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -10,7 +10,7 @@
|
|||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="4.9.4.0" />
|
||||
Version="4.10.0.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,9,4,0
|
||||
PRODUCTVERSION 4,9,4,0
|
||||
FILEVERSION 4,10,0,0
|
||||
PRODUCTVERSION 4,10,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -62,10 +62,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop"
|
||||
VALUE "FileVersion", "4.9.4.0"
|
||||
VALUE "FileVersion", "4.10.0.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.9.4.0"
|
||||
VALUE "ProductVersion", "4.10.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,9,4,0
|
||||
PRODUCTVERSION 4,9,4,0
|
||||
FILEVERSION 4,10,0,0
|
||||
PRODUCTVERSION 4,10,0,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.9.4.0"
|
||||
VALUE "FileVersion", "4.10.0.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.9.4.0"
|
||||
VALUE "ProductVersion", "4.10.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -267,7 +267,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
QByteArray inner = f.readAll();
|
||||
stream << name << quint32(inner.size()) << inner;
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifndef Q_OS_WIN
|
||||
stream << (QFileInfo(fullName).isExecutable() ? true : false);
|
||||
#endif
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ int main(int argc, char *argv[])
|
|||
cout << "Compression start, size: " << resultSize << "\n";
|
||||
|
||||
QByteArray compressed, resultCheck;
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined TDESKTOP_USE_PACKAGED // use Lzma SDK for win
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
|
||||
|
||||
compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size
|
||||
|
@ -496,10 +496,8 @@ int main(int argc, char *argv[])
|
|||
QString outName((targetwin64 ? QString("tx64upd%1") : QString("tupdate%1")).arg(AlphaVersion ? AlphaVersion : version));
|
||||
#elif defined Q_OS_MAC
|
||||
QString outName((targetarmac ? QString("tarmacupd%1") : QString("tmacupd%1")).arg(AlphaVersion ? AlphaVersion : version));
|
||||
#elif defined Q_OS_UNIX
|
||||
QString outName(QString("tlinuxupd%1").arg(AlphaVersion ? AlphaVersion : version));
|
||||
#else
|
||||
#error Unknown platform!
|
||||
QString outName(QString("tlinuxupd%1").arg(AlphaVersion ? AlphaVersion : version));
|
||||
#endif
|
||||
if (AlphaVersion) {
|
||||
outName += "_" + AlphaSignature;
|
||||
|
|
|
@ -27,7 +27,7 @@ extern "C" {
|
|||
#include <openssl/evp.h>
|
||||
} // extern "C"
|
||||
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined TDESKTOP_USE_PACKAGED // use Lzma SDK for win
|
||||
#include <LzmaLib.h>
|
||||
#else
|
||||
#include <lzma.h>
|
||||
|
|
|
@ -41,6 +41,7 @@ bool do_mkdir(const char *path) { // from http://stackoverflow.com/questions/675
|
|||
}
|
||||
|
||||
bool _debug = false;
|
||||
bool writeprotected = false;
|
||||
string updaterDir;
|
||||
string updaterName;
|
||||
string workDir;
|
||||
|
@ -88,7 +89,7 @@ void writeLog(const char *format, ...) {
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
bool copyFile(const char *from, const char *to, bool writeprotected) {
|
||||
bool copyFile(const char *from, const char *to) {
|
||||
FILE *ffrom = fopen(from, "rb"), *fto = fopen(to, "wb");
|
||||
if (!ffrom) {
|
||||
if (fto) fclose(fto);
|
||||
|
@ -211,7 +212,7 @@ void delFolder() {
|
|||
rmdir(delFolder.c_str());
|
||||
}
|
||||
|
||||
bool update(bool writeprotected) {
|
||||
bool update() {
|
||||
writeLog("Update started..");
|
||||
|
||||
string updDir = workDir + "tupdates/temp", readyFilePath = workDir + "tupdates/temp/ready", tdataDir = workDir + "tupdates/temp/tdata";
|
||||
|
@ -324,7 +325,7 @@ bool update(bool writeprotected) {
|
|||
writeLog("Copying file '%s' to '%s'..", fname.c_str(), tofname.c_str());
|
||||
int copyTries = 0, triesLimit = 30;
|
||||
do {
|
||||
if (!copyFile(fname.c_str(), tofname.c_str(), writeprotected)) {
|
||||
if (!copyFile(fname.c_str(), tofname.c_str())) {
|
||||
++copyTries;
|
||||
usleep(100000);
|
||||
} else {
|
||||
|
@ -359,10 +360,10 @@ int main(int argc, char *argv[]) {
|
|||
bool needupdate = true;
|
||||
bool autostart = false;
|
||||
bool debug = false;
|
||||
bool writeprotected = false;
|
||||
bool tosettings = false;
|
||||
bool startintray = false;
|
||||
bool customWorkingDir = false;
|
||||
bool justUpdate = false;
|
||||
|
||||
char *key = 0;
|
||||
char *workdir = 0;
|
||||
|
@ -381,6 +382,9 @@ int main(int argc, char *argv[]) {
|
|||
customWorkingDir = true;
|
||||
} else if (equal(argv[i], "-writeprotected")) {
|
||||
writeprotected = true;
|
||||
justUpdate = true;
|
||||
} else if (equal(argv[i], "-justupdate")) {
|
||||
justUpdate = true;
|
||||
} else if (equal(argv[i], "-key") && ++i < argc) {
|
||||
key = argv[i];
|
||||
} else if (equal(argv[i], "-workpath") && ++i < argc) {
|
||||
|
@ -455,7 +459,7 @@ int main(int argc, char *argv[]) {
|
|||
} else {
|
||||
writeLog("Passed workpath is '%s'", workDir.c_str());
|
||||
}
|
||||
update(writeprotected);
|
||||
update();
|
||||
}
|
||||
} else {
|
||||
writeLog("Error: bad exe name!");
|
||||
|
@ -464,36 +468,38 @@ int main(int argc, char *argv[]) {
|
|||
writeLog("Error: short exe name!");
|
||||
}
|
||||
|
||||
const auto fullBinaryPath = exePath + exeName;
|
||||
|
||||
auto values = vector<string>();
|
||||
const auto push = [&](string arg) {
|
||||
// Force null-terminated .data() call result.
|
||||
values.push_back(arg + char(0));
|
||||
};
|
||||
push(!argv0.empty() ? argv0 : fullBinaryPath);
|
||||
push("-noupdate");
|
||||
if (autostart) push("-autostart");
|
||||
if (debug) push("-debug");
|
||||
if (startintray) push("-startintray");
|
||||
if (tosettings) push("-tosettings");
|
||||
if (key) {
|
||||
push("-key");
|
||||
push(key);
|
||||
}
|
||||
if (customWorkingDir && workdir) {
|
||||
push("-workdir");
|
||||
push(workdir);
|
||||
}
|
||||
|
||||
auto args = vector<char*>();
|
||||
for (auto &arg : values) {
|
||||
args.push_back(arg.data());
|
||||
}
|
||||
args.push_back(nullptr);
|
||||
|
||||
// let the parent launch instead
|
||||
if (!writeprotected) {
|
||||
if (justUpdate) {
|
||||
writeLog("Closing log and quitting..");
|
||||
} else {
|
||||
const auto fullBinaryPath = exePath + exeName;
|
||||
|
||||
auto values = vector<string>();
|
||||
const auto push = [&](string arg) {
|
||||
// Force null-terminated .data() call result.
|
||||
values.push_back(arg + char(0));
|
||||
};
|
||||
push(!argv0.empty() ? argv0 : fullBinaryPath);
|
||||
push("-noupdate");
|
||||
if (autostart) push("-autostart");
|
||||
if (debug) push("-debug");
|
||||
if (startintray) push("-startintray");
|
||||
if (tosettings) push("-tosettings");
|
||||
if (key) {
|
||||
push("-key");
|
||||
push(key);
|
||||
}
|
||||
if (customWorkingDir && workdir) {
|
||||
push("-workdir");
|
||||
push(workdir);
|
||||
}
|
||||
|
||||
auto args = vector<char*>();
|
||||
for (auto &arg : values) {
|
||||
args.push_back(arg.data());
|
||||
}
|
||||
args.push_back(nullptr);
|
||||
|
||||
pid_t pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
|
@ -503,9 +509,10 @@ int main(int argc, char *argv[]) {
|
|||
execv(fullBinaryPath.c_str(), args.data());
|
||||
return 1;
|
||||
}
|
||||
|
||||
writeLog("Executed Telegram, closing log and quitting..");
|
||||
}
|
||||
|
||||
writeLog("Executed Telegram, closing log and quitting..");
|
||||
closeLog();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -77,45 +77,59 @@ void BlockedPeers::block(not_null<PeerData*> peer) {
|
|||
_session->changes().peerUpdated(
|
||||
peer,
|
||||
Data::PeerUpdate::Flag::IsBlocked);
|
||||
} else if (_blockRequests.find(peer) == end(_blockRequests)) {
|
||||
const auto requestId = _api.request(MTPcontacts_Block(
|
||||
MTP_flags(0),
|
||||
peer->input
|
||||
)).done([=] {
|
||||
_blockRequests.erase(peer);
|
||||
peer->setIsBlocked(true);
|
||||
if (_slice) {
|
||||
_slice->list.insert(
|
||||
_slice->list.begin(),
|
||||
{ peer->id, base::unixtime::now() });
|
||||
++_slice->total;
|
||||
_changes.fire_copy(*_slice);
|
||||
}
|
||||
}).fail([=] {
|
||||
_blockRequests.erase(peer);
|
||||
}).send();
|
||||
|
||||
_blockRequests.emplace(peer, requestId);
|
||||
return;
|
||||
} else if (blockAlreadySent(peer, true)) {
|
||||
return;
|
||||
}
|
||||
const auto requestId = _api.request(MTPcontacts_Block(
|
||||
MTP_flags(0),
|
||||
peer->input
|
||||
)).done([=] {
|
||||
const auto data = _blockRequests.take(peer);
|
||||
peer->setIsBlocked(true);
|
||||
if (_slice) {
|
||||
_slice->list.insert(
|
||||
_slice->list.begin(),
|
||||
{ peer->id, base::unixtime::now() });
|
||||
++_slice->total;
|
||||
_changes.fire_copy(*_slice);
|
||||
}
|
||||
if (data) {
|
||||
for (const auto &callback : data->callbacks) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
}).fail([=] {
|
||||
if (const auto data = _blockRequests.take(peer)) {
|
||||
for (const auto &callback : data->callbacks) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
|
||||
_blockRequests.emplace(peer, Request{
|
||||
.requestId = requestId,
|
||||
.blocking = true,
|
||||
});
|
||||
}
|
||||
|
||||
void BlockedPeers::unblock(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> onDone,
|
||||
Fn<void(bool success)> done,
|
||||
bool force) {
|
||||
if (!force && !peer->isBlocked()) {
|
||||
_session->changes().peerUpdated(
|
||||
peer,
|
||||
Data::PeerUpdate::Flag::IsBlocked);
|
||||
return;
|
||||
} else if (_blockRequests.find(peer) != end(_blockRequests)) {
|
||||
} else if (blockAlreadySent(peer, false, done)) {
|
||||
return;
|
||||
}
|
||||
const auto requestId = _api.request(MTPcontacts_Unblock(
|
||||
MTP_flags(0),
|
||||
peer->input
|
||||
)).done([=] {
|
||||
_blockRequests.erase(peer);
|
||||
const auto data = _blockRequests.take(peer);
|
||||
peer->setIsBlocked(false);
|
||||
if (_slice) {
|
||||
auto &list = _slice->list;
|
||||
|
@ -130,13 +144,46 @@ void BlockedPeers::unblock(
|
|||
}
|
||||
_changes.fire_copy(*_slice);
|
||||
}
|
||||
if (onDone) {
|
||||
onDone();
|
||||
if (data) {
|
||||
for (const auto &callback : data->callbacks) {
|
||||
callback(true);
|
||||
}
|
||||
}
|
||||
}).fail([=] {
|
||||
_blockRequests.erase(peer);
|
||||
if (const auto data = _blockRequests.take(peer)) {
|
||||
for (const auto &callback : data->callbacks) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
_blockRequests.emplace(peer, requestId);
|
||||
const auto i = _blockRequests.emplace(peer, Request{
|
||||
.requestId = requestId,
|
||||
.blocking = false,
|
||||
}).first;
|
||||
if (done) {
|
||||
i->second.callbacks.push_back(std::move(done));
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockedPeers::blockAlreadySent(
|
||||
not_null<PeerData*> peer,
|
||||
bool blocking,
|
||||
Fn<void(bool success)> done) {
|
||||
const auto i = _blockRequests.find(peer);
|
||||
if (i == end(_blockRequests)) {
|
||||
return false;
|
||||
} else if (i->second.blocking == blocking) {
|
||||
if (done) {
|
||||
i->second.callbacks.push_back(std::move(done));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const auto callbacks = base::take(i->second.callbacks);
|
||||
_blockRequests.erase(i);
|
||||
for (const auto &callback : callbacks) {
|
||||
callback(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BlockedPeers::reload() {
|
||||
|
@ -160,7 +207,7 @@ auto BlockedPeers::slice() -> rpl::producer<BlockedPeers::Slice> {
|
|||
: (_changes.events() | rpl::type_erased());
|
||||
}
|
||||
|
||||
void BlockedPeers::request(int offset, Fn<void(BlockedPeers::Slice)> onDone) {
|
||||
void BlockedPeers::request(int offset, Fn<void(BlockedPeers::Slice)> done) {
|
||||
if (_requestId) {
|
||||
return;
|
||||
}
|
||||
|
@ -170,7 +217,7 @@ void BlockedPeers::request(int offset, Fn<void(BlockedPeers::Slice)> onDone) {
|
|||
MTP_int(offset ? kBlockedPerPage : kBlockedFirstSlice)
|
||||
)).done([=](const MTPcontacts_Blocked &result) {
|
||||
_requestId = 0;
|
||||
onDone(TLToSlice(result, _session->data()));
|
||||
done(TLToSlice(result, _session->data()));
|
||||
}).fail([=] {
|
||||
_requestId = 0;
|
||||
}).send();
|
||||
|
|
|
@ -39,20 +39,31 @@ public:
|
|||
|
||||
void reload();
|
||||
rpl::producer<Slice> slice();
|
||||
void request(int offset, Fn<void(Slice)> onDone);
|
||||
void request(int offset, Fn<void(Slice)> done);
|
||||
|
||||
void block(not_null<PeerData*> peer);
|
||||
void unblock(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> onDone = nullptr,
|
||||
Fn<void(bool success)> done = nullptr,
|
||||
bool force = false);
|
||||
|
||||
private:
|
||||
struct Request {
|
||||
std::vector<Fn<void(bool success)>> callbacks;
|
||||
mtpRequestId requestId = 0;
|
||||
bool blocking = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] bool blockAlreadySent(
|
||||
not_null<PeerData*> peer,
|
||||
bool blocking,
|
||||
Fn<void(bool success)> done = nullptr);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
|
||||
MTP::Sender _api;
|
||||
|
||||
base::flat_map<not_null<PeerData*>, mtpRequestId> _blockRequests;
|
||||
base::flat_map<not_null<PeerData*>, Request> _blockRequests;
|
||||
mtpRequestId _requestId = 0;
|
||||
std::optional<Slice> _slice;
|
||||
rpl::event_stream<Slice> _changes;
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "apiwrap.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "info/profile/info_profile_badge.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
|
@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/toast/toast.h"
|
||||
#include "boxes/premium_limits_box.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_info.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
namespace Api {
|
||||
|
@ -195,6 +197,13 @@ ConfirmInviteBox::ConfirmInviteBox(
|
|||
: _session(session)
|
||||
, _submit(std::move(submit))
|
||||
, _title(this, st::confirmInviteTitle)
|
||||
, _badge(std::make_unique<Info::Profile::Badge>(
|
||||
this,
|
||||
st::infoPeerBadge,
|
||||
_session,
|
||||
rpl::single(Info::Profile::Badge::Content{ BadgeForInvite(invite) }),
|
||||
nullptr,
|
||||
[=] { return false; }))
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _about(this, st::confirmInviteAbout)
|
||||
, _aboutRequests(this, st::confirmInviteStatus)
|
||||
|
@ -275,9 +284,24 @@ ConfirmInviteBox::ChatInvite ConfirmInviteBox::Parse(
|
|||
.isMegagroup = data.is_megagroup(),
|
||||
.isBroadcast = data.is_broadcast(),
|
||||
.isRequestNeeded = data.is_request_needed(),
|
||||
.isFake = data.is_fake(),
|
||||
.isScam = data.is_scam(),
|
||||
.isVerified = data.is_verified(),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Info::Profile::BadgeType ConfirmInviteBox::BadgeForInvite(
|
||||
const ChatInvite &invite) {
|
||||
using Type = Info::Profile::BadgeType;
|
||||
return invite.isVerified
|
||||
? Type::Verified
|
||||
: invite.isScam
|
||||
? Type::Scam
|
||||
: invite.isFake
|
||||
? Type::Fake
|
||||
: Type::None;
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::prepare() {
|
||||
addButton(
|
||||
(_requestApprove
|
||||
|
@ -326,8 +350,26 @@ void ConfirmInviteBox::prepare() {
|
|||
|
||||
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
|
||||
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
|
||||
|
||||
const auto padding = st::boxRowPadding;
|
||||
auto nameWidth = width() - padding.left() - padding.right();
|
||||
auto badgeWidth = 0;
|
||||
if (const auto widget = _badge->widget()) {
|
||||
badgeWidth = st::infoVerifiedCheckPosition.x() + widget->width();
|
||||
nameWidth -= badgeWidth;
|
||||
}
|
||||
_title->resizeToWidth(std::min(nameWidth, _title->textMaxWidth()));
|
||||
_title->moveToLeft(
|
||||
(width() - _title->width() - badgeWidth) / 2,
|
||||
st::confirmInviteTitleTop);
|
||||
const auto badgeLeft = _title->x() + _title->width();
|
||||
const auto badgeTop = _title->y();
|
||||
const auto badgeBottom = _title->y() + _title->height();
|
||||
_badge->move(badgeLeft, badgeTop, badgeBottom);
|
||||
|
||||
_status->move(
|
||||
(width() - _status->width()) / 2,
|
||||
st::confirmInviteStatusTop);
|
||||
auto bottom = _status->y()
|
||||
+ _status->height()
|
||||
+ st::boxPadding.bottom()
|
||||
|
|
|
@ -12,6 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
class UserData;
|
||||
class ChannelData;
|
||||
|
||||
namespace Info::Profile {
|
||||
class Badge;
|
||||
enum class BadgeType;
|
||||
} // namespace Info::Profile
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
@ -66,10 +71,15 @@ private:
|
|||
bool isMegagroup = false;
|
||||
bool isBroadcast = false;
|
||||
bool isRequestNeeded = false;
|
||||
bool isFake = false;
|
||||
bool isScam = false;
|
||||
bool isVerified = false;
|
||||
};
|
||||
[[nodiscard]] static ChatInvite Parse(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data);
|
||||
[[nodiscard]] Info::Profile::BadgeType BadgeForInvite(
|
||||
const ChatInvite &invite);
|
||||
|
||||
ConfirmInviteBox(
|
||||
not_null<Main::Session*> session,
|
||||
|
@ -81,12 +91,14 @@ private:
|
|||
|
||||
Fn<void()> _submit;
|
||||
object_ptr<Ui::FlatLabel> _title;
|
||||
std::unique_ptr<Info::Profile::Badge> _badge;
|
||||
object_ptr<Ui::FlatLabel> _status;
|
||||
object_ptr<Ui::FlatLabel> _about;
|
||||
object_ptr<Ui::FlatLabel> _aboutRequests;
|
||||
std::shared_ptr<Data::PhotoMedia> _photo;
|
||||
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
|
||||
std::vector<Participant> _participants;
|
||||
|
||||
bool _isChannel = false;
|
||||
bool _requestApprove = false;
|
||||
|
||||
|
|
|
@ -78,12 +78,8 @@ void SendReport(
|
|||
MTP_string(comment)
|
||||
)).done(std::move(done)).send();
|
||||
}, [&](StoryId id) {
|
||||
const auto user = peer->asUser();
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
peer->session().api().request(MTPstories_Report(
|
||||
user->inputUser,
|
||||
peer->input,
|
||||
MTP_vector<MTPint>(1, MTP_int(id)),
|
||||
ReasonToTL(reason),
|
||||
MTP_string(comment)
|
||||
|
|
|
@ -17,11 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Api {
|
||||
namespace {
|
||||
|
||||
constexpr auto TestApiId = 17349;
|
||||
constexpr auto SnapApiId = 611335;
|
||||
constexpr auto DesktopApiId = 2040;
|
||||
|
||||
Websites::Entry ParseEntry(
|
||||
[[nodiscard]] Websites::Entry ParseEntry(
|
||||
not_null<Data::Session*> owner,
|
||||
const MTPDwebAuthorization &data) {
|
||||
auto result = Websites::Entry{
|
||||
|
|
|
@ -100,8 +100,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "storage/storage_media_prepare.h"
|
||||
#include "storage/storage_account.h"
|
||||
|
||||
// AyuGram includes
|
||||
#include "ayu/ayu_settings.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Save draft to the cloud with 1 sec extra delay.
|
||||
|
@ -791,7 +793,7 @@ QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
|||
? i->second
|
||||
: fallback();
|
||||
request(MTPstories_ExportStoryLink(
|
||||
story->peer()->asUser()->inputUser,
|
||||
story->peer()->input,
|
||||
MTP_int(story->id())
|
||||
)).done([=](const MTPExportedStoryLink &result) {
|
||||
const auto link = qs(result.data().vlink());
|
||||
|
@ -2535,14 +2537,9 @@ void ApiWrap::refreshFileReference(
|
|||
}, [&](Data::FileOriginPremiumPreviews data) {
|
||||
request(MTPhelp_GetPremiumPromo());
|
||||
}, [&](Data::FileOriginStory data) {
|
||||
const auto user = _session->data().peer(data.peerId)->asUser();
|
||||
if (user) {
|
||||
request(MTPstories_GetStoriesByID(
|
||||
user->inputUser,
|
||||
MTP_vector<MTPint>(1, MTP_int(data.storyId))));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
request(MTPstories_GetStoriesByID(
|
||||
_session->data().peer(data.peerId)->input,
|
||||
MTP_vector<MTPint>(1, MTP_int(data.storyId))));
|
||||
}, [&](v::null_t) {
|
||||
fail();
|
||||
});
|
||||
|
@ -3322,25 +3319,37 @@ void ApiWrap::shareContact(
|
|||
const QString &phone,
|
||||
const QString &firstName,
|
||||
const QString &lastName,
|
||||
const SendAction &action) {
|
||||
const SendAction &action,
|
||||
Fn<void(bool)> done) {
|
||||
const auto userId = UserId(0);
|
||||
sendSharedContact(phone, firstName, lastName, userId, action);
|
||||
sendSharedContact(
|
||||
phone,
|
||||
firstName,
|
||||
lastName,
|
||||
userId,
|
||||
action,
|
||||
std::move(done));
|
||||
}
|
||||
|
||||
void ApiWrap::shareContact(
|
||||
not_null<UserData*> user,
|
||||
const SendAction &action) {
|
||||
const SendAction &action,
|
||||
Fn<void(bool)> done) {
|
||||
const auto userId = peerToUser(user->id);
|
||||
const auto phone = _session->data().findContactPhone(user);
|
||||
if (phone.isEmpty()) {
|
||||
if (done) {
|
||||
done(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
sendSharedContact(
|
||||
return sendSharedContact(
|
||||
phone,
|
||||
user->firstName,
|
||||
user->lastName,
|
||||
userId,
|
||||
action);
|
||||
action,
|
||||
std::move(done));
|
||||
}
|
||||
|
||||
void ApiWrap::sendSharedContact(
|
||||
|
@ -3348,7 +3357,8 @@ void ApiWrap::sendSharedContact(
|
|||
const QString &firstName,
|
||||
const QString &lastName,
|
||||
UserId userId,
|
||||
const SendAction &action) {
|
||||
const SendAction &action,
|
||||
Fn<void(bool)> done) {
|
||||
sendAction(action);
|
||||
|
||||
const auto history = action.history;
|
||||
|
@ -3399,7 +3409,7 @@ void ApiWrap::sendSharedContact(
|
|||
MTP_string(firstName),
|
||||
MTP_string(lastName),
|
||||
MTP_string()); // vcard
|
||||
sendMedia(item, media, action.options);
|
||||
sendMedia(item, media, action.options, std::move(done));
|
||||
|
||||
_session->data().sendHistoryChangeNotifications();
|
||||
_session->changes().historyUpdated(
|
||||
|
@ -3949,18 +3959,20 @@ void ApiWrap::uploadAlbumMedia(
|
|||
void ApiWrap::sendMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPInputMedia &media,
|
||||
Api::SendOptions options) {
|
||||
Api::SendOptions options,
|
||||
Fn<void(bool)> done) {
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
_session->data().registerMessageRandomId(randomId, item->fullId());
|
||||
|
||||
sendMediaWithRandomId(item, media, options, randomId);
|
||||
sendMediaWithRandomId(item, media, options, randomId, std::move(done));
|
||||
}
|
||||
|
||||
void ApiWrap::sendMediaWithRandomId(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPInputMedia &media,
|
||||
Api::SendOptions options,
|
||||
uint64 randomId) {
|
||||
uint64 randomId,
|
||||
Fn<void(bool)> done) {
|
||||
// AyuGram useScheduledMessages
|
||||
const auto settings = &AyuSettings::getInstance();
|
||||
if (settings->useScheduledMessages && !options.scheduled)
|
||||
|
@ -3969,7 +3981,6 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
auto current = base::unixtime::now();
|
||||
options.scheduled = current + 12;
|
||||
}
|
||||
|
||||
const auto history = item->history();
|
||||
const auto replyTo = item->replyTo();
|
||||
|
||||
|
@ -4011,10 +4022,12 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
MTP_int(options.scheduled),
|
||||
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty())
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
if (done) done(true);
|
||||
if (updateRecentStickers) {
|
||||
requestRecentStickersForce(true);
|
||||
}
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
if (done) done(false);
|
||||
sendMessageFail(error, peer, randomId, itemId);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -294,8 +294,12 @@ public:
|
|||
const QString &phone,
|
||||
const QString &firstName,
|
||||
const QString &lastName,
|
||||
const SendAction &action);
|
||||
void shareContact(not_null<UserData*> user, const SendAction &action);
|
||||
const SendAction &action,
|
||||
Fn<void(bool)> done = nullptr);
|
||||
void shareContact(
|
||||
not_null<UserData*> user,
|
||||
const SendAction &action,
|
||||
Fn<void(bool)> done = nullptr);
|
||||
void applyAffectedMessages(
|
||||
not_null<PeerData*> peer,
|
||||
const MTPmessages_AffectedMessages &result);
|
||||
|
@ -489,7 +493,8 @@ private:
|
|||
const QString &firstName,
|
||||
const QString &lastName,
|
||||
UserId userId,
|
||||
const SendAction &action);
|
||||
const SendAction &action,
|
||||
Fn<void(bool)> done);
|
||||
|
||||
void deleteHistory(
|
||||
not_null<PeerData*> peer,
|
||||
|
@ -516,12 +521,14 @@ private:
|
|||
void sendMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPInputMedia &media,
|
||||
Api::SendOptions options);
|
||||
Api::SendOptions options,
|
||||
Fn<void(bool)> done = nullptr);
|
||||
void sendMediaWithRandomId(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPInputMedia &media,
|
||||
Api::SendOptions options,
|
||||
uint64 randomId);
|
||||
uint64 randomId,
|
||||
Fn<void(bool)> done = nullptr);
|
||||
FileLoadTo fileLoadTaskOptions(const SendAction &action) const;
|
||||
|
||||
void getTopPromotionDelayed(TimeId now, TimeId next);
|
||||
|
|
|
@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/fields/special_fields.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/text/format_values.h"
|
||||
|
@ -297,8 +298,11 @@ void AddContactBox::prepare() {
|
|||
: tr::lng_enter_contact_data());
|
||||
updateButtons();
|
||||
|
||||
connect(_first, &Ui::InputField::submitted, [=] { submit(); });
|
||||
connect(_last, &Ui::InputField::submitted, [=] { submit(); });
|
||||
const auto submitted = [=] { submit(); };
|
||||
_first->submits(
|
||||
) | rpl::start_with_next(submitted, _first->lifetime());
|
||||
_last->submits(
|
||||
) | rpl::start_with_next(submitted, _last->lifetime());
|
||||
connect(_phone, &Ui::PhoneInput::submitted, [=] { submit(); });
|
||||
|
||||
setDimensions(
|
||||
|
@ -567,23 +571,24 @@ void GroupInfoBox::prepare() {
|
|||
_description->setSubmitSettings(
|
||||
Core::App().settings().sendSubmitWay());
|
||||
|
||||
connect(_description, &Ui::InputField::resized, [=] {
|
||||
_description->heightChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
descriptionResized();
|
||||
});
|
||||
connect(_description, &Ui::InputField::submitted, [=] {
|
||||
submit();
|
||||
});
|
||||
connect(_description, &Ui::InputField::cancelled, [=] {
|
||||
}, _description->lifetime());
|
||||
_description->submits(
|
||||
) | rpl::start_with_next([=] { submit(); }, _description->lifetime());
|
||||
_description->cancelled(
|
||||
) | rpl::start_with_next([=] {
|
||||
closeBox();
|
||||
});
|
||||
}, _description->lifetime());
|
||||
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
getDelegate()->outerContainer(),
|
||||
_description,
|
||||
&_navigation->session());
|
||||
}
|
||||
|
||||
connect(_title, &Ui::InputField::submitted, [=] { submitName(); });
|
||||
_title->submits(
|
||||
) | rpl::start_with_next([=] { submitName(); }, _title->lifetime());
|
||||
|
||||
addButton(
|
||||
((_type != Type::Group || _canAddBot)
|
||||
|
@ -1522,20 +1527,22 @@ void EditNameBox::prepare() {
|
|||
_first->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName);
|
||||
_last->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName);
|
||||
|
||||
connect(_first, &Ui::InputField::submitted, [=] { submit(); });
|
||||
connect(_last, &Ui::InputField::submitted, [=] { submit(); });
|
||||
_first->submits(
|
||||
) | rpl::start_with_next([=] { submit(); }, _first->lifetime());
|
||||
_last->submits(
|
||||
) | rpl::start_with_next([=] { submit(); }, _last->lifetime());
|
||||
|
||||
_first->customTab(true);
|
||||
_last->customTab(true);
|
||||
|
||||
QObject::connect(
|
||||
_first,
|
||||
&Ui::InputField::tabbed,
|
||||
[=] { _last->setFocus(); });
|
||||
QObject::connect(
|
||||
_last,
|
||||
&Ui::InputField::tabbed,
|
||||
[=] { _first->setFocus(); });
|
||||
_first->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
_last->setFocus();
|
||||
}, _first->lifetime());
|
||||
_last->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
_first->setFocus();
|
||||
}, _last->lifetime());
|
||||
}
|
||||
|
||||
void EditNameBox::setInnerFocus() {
|
||||
|
|
|
@ -32,27 +32,27 @@ Data::ChatFilter ChangedFilter(
|
|||
auto never = base::duplicate(filter.never());
|
||||
if (add) {
|
||||
never.remove(history);
|
||||
const auto result = Data::ChatFilter(
|
||||
filter.id(),
|
||||
filter.title(),
|
||||
filter.iconEmoji(),
|
||||
filter.flags(),
|
||||
filter.always(),
|
||||
filter.pinned(),
|
||||
std::move(never));
|
||||
if (result.contains(history)) {
|
||||
return result;
|
||||
} else {
|
||||
never = base::duplicate(result.never());
|
||||
always.insert(history);
|
||||
}
|
||||
} else {
|
||||
const auto alwaysIt = always.find(history);
|
||||
if (alwaysIt != end(always)) {
|
||||
always.erase(alwaysIt);
|
||||
} else {
|
||||
never.insert(history);
|
||||
}
|
||||
always.remove(history);
|
||||
}
|
||||
const auto result = Data::ChatFilter(
|
||||
filter.id(),
|
||||
filter.title(),
|
||||
filter.iconEmoji(),
|
||||
filter.flags(),
|
||||
std::move(always),
|
||||
filter.pinned(),
|
||||
std::move(never));
|
||||
const auto in = result.contains(history);
|
||||
if (in == add) {
|
||||
return result;
|
||||
}
|
||||
always = base::duplicate(result.always());
|
||||
never = base::duplicate(result.never());
|
||||
if (add) {
|
||||
always.insert(history);
|
||||
} else {
|
||||
never.insert(history);
|
||||
}
|
||||
return Data::ChatFilter(
|
||||
filter.id(),
|
||||
|
|
|
@ -18,7 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mtproto/facade.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/fields/number_input.h"
|
||||
#include "ui/widgets/fields/password_input.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
|
|
|
@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
@ -184,7 +184,8 @@ not_null<Ui::FlatLabel*> CreateWarningLabel(
|
|||
QString(),
|
||||
st::createPollWarning);
|
||||
result->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
QObject::connect(field, &Ui::InputField::changed, [=] {
|
||||
field->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
Ui::PostponeCall(crl::guard(field, [=] {
|
||||
const auto length = field->getLastText().size();
|
||||
const auto value = valueLimit - length;
|
||||
|
@ -198,7 +199,7 @@ not_null<Ui::FlatLabel*> CreateWarningLabel(
|
|||
}
|
||||
result->setVisible(shown);
|
||||
}));
|
||||
});
|
||||
}, field->lifetime());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -243,13 +244,14 @@ Options::Option::Option(
|
|||
_content->resize(_content->width(), height);
|
||||
}, _field->lifetime());
|
||||
|
||||
QObject::connect(_field, &Ui::InputField::changed, [=] {
|
||||
_field->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
Ui::PostponeCall(crl::guard(_field, [=] {
|
||||
if (_hasCorrect) {
|
||||
_correct->toggle(isGood(), anim::type::normal);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}, _field->lifetime());
|
||||
|
||||
createShadow();
|
||||
createRemove();
|
||||
|
@ -303,10 +305,11 @@ void Options::Option::createRemove() {
|
|||
const auto toggle = lifetime.make_state<rpl::variable<bool>>(false);
|
||||
_removeAlways = lifetime.make_state<rpl::variable<bool>>(false);
|
||||
|
||||
QObject::connect(field, &Ui::InputField::changed, [=] {
|
||||
field->changes(
|
||||
) | rpl::start_with_next([field, toggle] {
|
||||
// Don't capture 'this'! Because Option is a value type.
|
||||
*toggle = !field->getLastText().isEmpty();
|
||||
});
|
||||
}, field->lifetime());
|
||||
rpl::combine(
|
||||
toggle->value(),
|
||||
_removeAlways->value(),
|
||||
|
@ -649,28 +652,32 @@ void Options::addEmptyOption() {
|
|||
_position + _list.size() + _destroyed.size(),
|
||||
_chooseCorrectGroup));
|
||||
const auto field = _list.back()->field();
|
||||
QObject::connect(field, &Ui::InputField::submitted, [=] {
|
||||
field->submits(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto index = findField(field);
|
||||
if (_list[index]->isGood() && index + 1 < _list.size()) {
|
||||
_list[index + 1]->setFocus();
|
||||
}
|
||||
});
|
||||
QObject::connect(field, &Ui::InputField::changed, [=] {
|
||||
}, field->lifetime());
|
||||
field->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
Ui::PostponeCall(crl::guard(field, [=] {
|
||||
validateState();
|
||||
}));
|
||||
});
|
||||
QObject::connect(field, &Ui::InputField::focused, [=] {
|
||||
}, field->lifetime());
|
||||
field->focusedChanges(
|
||||
) | rpl::filter(rpl::mappers::_1) | rpl::start_with_next([=] {
|
||||
_scrollToWidget.fire_copy(field);
|
||||
});
|
||||
QObject::connect(field, &Ui::InputField::tabbed, [=] {
|
||||
}, field->lifetime());
|
||||
field->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto index = findField(field);
|
||||
if (index + 1 < _list.size()) {
|
||||
_list[index + 1]->setFocus();
|
||||
} else {
|
||||
_tabbed.fire({});
|
||||
}
|
||||
});
|
||||
}, field->lifetime());
|
||||
base::install_event_filter(field, [=](not_null<QEvent*> event) {
|
||||
if (event->type() != QEvent::KeyPress
|
||||
|| !field->getLastText().isEmpty()) {
|
||||
|
@ -927,9 +934,10 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
|||
st::boxDividerLabel),
|
||||
st::createPollLimitPadding));
|
||||
|
||||
connect(question, &Ui::InputField::tabbed, [=] {
|
||||
question->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
options->focusFirst();
|
||||
});
|
||||
}, question->lifetime());
|
||||
|
||||
AddSkip(container);
|
||||
AddSubsectionTitle(container, tr::lng_polls_create_settings());
|
||||
|
@ -975,9 +983,10 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
|||
}
|
||||
}, question->lifetime());
|
||||
|
||||
connect(solution, &Ui::InputField::tabbed, [=] {
|
||||
solution->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
question->setFocus();
|
||||
});
|
||||
}, solution->lifetime());
|
||||
|
||||
quiz->setDisabled(_disabled & PollData::Flag::Quiz);
|
||||
if (multiple) {
|
||||
|
@ -1009,12 +1018,12 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
|||
const auto text = question->getLastText().trimmed();
|
||||
return !text.isEmpty() && (text.size() <= kQuestionLimit);
|
||||
};
|
||||
|
||||
connect(question, &Ui::InputField::submitted, [=] {
|
||||
question->submits(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (isValidQuestion()) {
|
||||
options->focusFirst();
|
||||
}
|
||||
});
|
||||
}, question->lifetime());
|
||||
|
||||
_setInnerFocus = [=] {
|
||||
question->setFocusFast();
|
||||
|
|
|
@ -54,7 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/painter.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
|
@ -488,9 +488,16 @@ void EditCaptionBox::setupField() {
|
|||
Core::App().settings().sendSubmitWay());
|
||||
_field->setMaxHeight(st::defaultComposeFiles.caption.heightMax);
|
||||
|
||||
connect(_field, &Ui::InputField::submitted, [=] { save(); });
|
||||
connect(_field, &Ui::InputField::cancelled, [=] { closeBox(); });
|
||||
connect(_field, &Ui::InputField::resized, [=] { captionResized(); });
|
||||
_field->submits(
|
||||
) | rpl::start_with_next([=] { save(); }, _field->lifetime());
|
||||
_field->cancelled(
|
||||
) | rpl::start_with_next([=] {
|
||||
closeBox();
|
||||
}, _field->lifetime());
|
||||
_field->heightChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
captionResized();
|
||||
}, _field->lifetime());
|
||||
_field->setMimeDataHook([=](
|
||||
not_null<const QMimeData*> data,
|
||||
Ui::InputField::MimeAction action) {
|
||||
|
@ -522,10 +529,11 @@ void EditCaptionBox::setInitialText() {
|
|||
setCloseByOutsideClick(true);
|
||||
}
|
||||
});
|
||||
connect(_field, &Ui::InputField::changed, [=] {
|
||||
_field->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
_checkChangedTimer.callOnce(kChangesDebounceTimeout);
|
||||
setCloseByOutsideClick(false);
|
||||
});
|
||||
}, _field->lifetime());
|
||||
}
|
||||
|
||||
void EditCaptionBox::setupControls() {
|
||||
|
|
|
@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/effects/panel_animation.h"
|
||||
#include "ui/filter_icons.h"
|
||||
|
@ -619,11 +619,12 @@ void EditFilterBox(
|
|||
nameEditing->custom = true;
|
||||
}, box->lifetime());
|
||||
|
||||
QObject::connect(name, &Ui::InputField::changed, [=] {
|
||||
name->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (!nameEditing->settingDefault) {
|
||||
nameEditing->custom = true;
|
||||
}
|
||||
});
|
||||
}, name->lifetime());
|
||||
const auto updateDefaultTitle = [=](const Data::ChatFilter &filter) {
|
||||
if (nameEditing->custom) {
|
||||
return;
|
||||
|
|
|
@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/controls/invite_link_label.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
|
|
|
@ -21,10 +21,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/fields/password_input.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/sent_code_field.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/painter.h"
|
||||
#include "passport/passport_encryption.h"
|
||||
|
@ -306,15 +305,26 @@ void PasscodeBox::prepare() {
|
|||
connect(_oldPasscode, &Ui::MaskedInputField::changed, [=] { oldChanged(); });
|
||||
connect(_newPasscode, &Ui::MaskedInputField::changed, [=] { newChanged(); });
|
||||
connect(_reenterPasscode, &Ui::MaskedInputField::changed, [=] { newChanged(); });
|
||||
connect(_passwordHint, &Ui::InputField::changed, [=] { newChanged(); });
|
||||
connect(_recoverEmail, &Ui::InputField::changed, [=] { emailChanged(); });
|
||||
_passwordHint->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
newChanged();
|
||||
}, _passwordHint->lifetime());
|
||||
_recoverEmail->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (!_emailError.isEmpty()) {
|
||||
_emailError = QString();
|
||||
update();
|
||||
}
|
||||
}, _recoverEmail->lifetime());
|
||||
|
||||
const auto fieldSubmit = [=] { submit(); };
|
||||
connect(_oldPasscode, &Ui::MaskedInputField::submitted, fieldSubmit);
|
||||
connect(_newPasscode, &Ui::MaskedInputField::submitted, fieldSubmit);
|
||||
connect(_reenterPasscode, &Ui::MaskedInputField::submitted, fieldSubmit);
|
||||
connect(_passwordHint, &Ui::InputField::submitted, fieldSubmit);
|
||||
connect(_recoverEmail, &Ui::InputField::submitted, fieldSubmit);
|
||||
_passwordHint->submits(
|
||||
) | rpl::start_with_next(fieldSubmit, _passwordHint->lifetime());
|
||||
_recoverEmail->submits(
|
||||
) | rpl::start_with_next(fieldSubmit, _recoverEmail->lifetime());
|
||||
|
||||
_recover->addClickHandler([=] { recoverByEmail(); });
|
||||
|
||||
|
@ -1061,13 +1071,6 @@ void PasscodeBox::newChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::emailChanged() {
|
||||
if (!_emailError.isEmpty()) {
|
||||
_emailError = QString();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::recoverByEmail() {
|
||||
if (!_cloudFields.hasRecovery) {
|
||||
Assert(_session != nullptr);
|
||||
|
@ -1189,8 +1192,12 @@ void RecoverBox::prepare() {
|
|||
+ _recoverCode->height()
|
||||
+ st::passcodeTextLine));
|
||||
|
||||
connect(_recoverCode, &Ui::InputField::changed, [=] { codeChanged(); });
|
||||
connect(_recoverCode, &Ui::InputField::submitted, [=] { submit(); });
|
||||
_recoverCode->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
codeChanged();
|
||||
}, _recoverCode->lifetime());
|
||||
_recoverCode->submits(
|
||||
) | rpl::start_with_next([=] { submit(); }, _recoverCode->lifetime());
|
||||
}
|
||||
|
||||
void RecoverBox::paintEvent(QPaintEvent *e) {
|
||||
|
|
|
@ -90,7 +90,6 @@ private:
|
|||
void closeReplacedBy();
|
||||
void oldChanged();
|
||||
void newChanged();
|
||||
void emailChanged();
|
||||
void save(bool force = false);
|
||||
void badOldPasscode();
|
||||
void recoverByEmail();
|
||||
|
|
|
@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/text/format_values.h" // Ui::FormatPhone
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "info/profile/info_profile_cover.h"
|
||||
|
@ -239,8 +239,8 @@ void Controller::initNameFields(
|
|||
_save();
|
||||
}
|
||||
};
|
||||
QObject::connect(first, &Ui::InputField::submitted, submit);
|
||||
QObject::connect(last, &Ui::InputField::submitted, submit);
|
||||
first->submits() | rpl::start_with_next(submit, first->lifetime());
|
||||
last->submits() | rpl::start_with_next(submit, last->lifetime());
|
||||
first->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName);
|
||||
first->setMaxLength(Ui::EditPeer::kMaxUserFirstLastName);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "boxes/peers/edit_forum_topic_box.h"
|
||||
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/effects/emoji_fly_animation.h"
|
||||
#include "ui/abstract_button.h"
|
||||
|
@ -465,15 +465,13 @@ void EditForumTopicBox(
|
|||
ChooseNextColorId(current.colorId, state->otherColorIds),
|
||||
};
|
||||
});
|
||||
base::qt_signal_producer(
|
||||
title,
|
||||
&Ui::InputField::changed
|
||||
title->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
state->defaultIcon = DefaultIcon{
|
||||
title->getLastText().trimmed(),
|
||||
state->defaultIcon.current().colorId,
|
||||
};
|
||||
}, box->lifetime());
|
||||
}, title->lifetime());
|
||||
|
||||
if (!topic || !topic->isGeneral()) {
|
||||
Settings::AddDividerText(
|
||||
|
|
|
@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/box_content_divider.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/toast/toast.h"
|
||||
|
@ -384,8 +384,11 @@ void EditAdminBox::prepare() {
|
|||
if (!_saveCallback) {
|
||||
return;
|
||||
} else if (_addAsAdmin && !_addAsAdmin->checked()) {
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
AddBotToGroup(user(), peer(), _addingBot->token);
|
||||
getDelegate()->hideLayer();
|
||||
if (const auto strong = weak.data()) {
|
||||
strong->closeBox();
|
||||
}
|
||||
return;
|
||||
} else if (_addingBot && !_addingBot->existing) {
|
||||
const auto phrase = peer()->isBroadcast()
|
||||
|
@ -461,13 +464,14 @@ not_null<Ui::InputField*> EditAdminBox::addRankInput(
|
|||
st::rightsAboutMargin);
|
||||
result->setMaxLength(kAdminRoleLimit);
|
||||
result->setInstantReplaces(Ui::InstantReplaces::TextOnly());
|
||||
connect(result, &Ui::InputField::changed, [=] {
|
||||
result->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto text = result->getLastText();
|
||||
const auto removed = TextUtilities::RemoveEmoji(text);
|
||||
if (removed != text) {
|
||||
result->setText(removed);
|
||||
}
|
||||
});
|
||||
}, result->lifetime());
|
||||
|
||||
container->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
|
|
|
@ -51,7 +51,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/box_content_divider.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
|
@ -519,10 +519,10 @@ object_ptr<Ui::RpWidget> Controller::createTitleEdit() {
|
|||
result->entity(),
|
||||
&_peer->session());
|
||||
|
||||
QObject::connect(
|
||||
result->entity(),
|
||||
&Ui::InputField::submitted,
|
||||
[=] { submitTitle(); });
|
||||
result->entity()->submits(
|
||||
) | rpl::start_with_next([=] {
|
||||
submitTitle();
|
||||
}, result->entity()->lifetime());
|
||||
|
||||
_controls.title = result->entity();
|
||||
return result;
|
||||
|
@ -555,10 +555,10 @@ object_ptr<Ui::RpWidget> Controller::createDescriptionEdit() {
|
|||
result->entity(),
|
||||
&_peer->session());
|
||||
|
||||
QObject::connect(
|
||||
result->entity(),
|
||||
&Ui::InputField::submitted,
|
||||
[=] { submitDescription(); });
|
||||
result->entity()->submits(
|
||||
) | rpl::start_with_next([=] {
|
||||
submitDescription();
|
||||
}, result->entity()->lifetime());
|
||||
|
||||
_controls.description = result->entity();
|
||||
return result;
|
||||
|
|
|
@ -51,13 +51,14 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
|
|||
}
|
||||
|
||||
[[nodiscard]] auto NestedRestrictionLabelsList(
|
||||
Data::RestrictionsSetOptions options) {
|
||||
Data::RestrictionsSetOptions options)
|
||||
-> std::vector<NestedEditFlagsLabels<ChatRestrictions>> {
|
||||
using Flag = ChatRestriction;
|
||||
|
||||
auto first = std::vector<RestrictionLabel>{
|
||||
{ Flag::SendOther, tr::lng_rights_chat_send_text(tr::now) },
|
||||
};
|
||||
auto inner = std::vector<RestrictionLabel>{
|
||||
auto media = std::vector<RestrictionLabel>{
|
||||
{ Flag::SendPhotos, tr::lng_rights_chat_photos(tr::now) },
|
||||
{ Flag::SendVideos, tr::lng_rights_chat_videos(tr::now) },
|
||||
{ Flag::SendVideoMessages, tr::lng_rights_chat_video_messages(tr::now) },
|
||||
|
@ -85,9 +86,64 @@ constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
|
|||
&RestrictionLabel::flags),
|
||||
end(second));
|
||||
}
|
||||
return std::vector<NestedEditFlagsLabels<ChatRestrictions>>{
|
||||
return {
|
||||
{ std::nullopt, std::move(first) },
|
||||
{ tr::lng_rights_chat_send_media(), std::move(inner) },
|
||||
{ tr::lng_rights_chat_send_media(), std::move(media) },
|
||||
{ std::nullopt, std::move(second) },
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] auto NestedAdminRightLabels(
|
||||
Data::AdminRightsSetOptions options)
|
||||
-> std::vector<NestedEditFlagsLabels<ChatAdminRights>> {
|
||||
using Flag = ChatAdminRight;
|
||||
|
||||
if (options.isGroup) {
|
||||
auto result = std::vector<AdminRightLabel>{
|
||||
{ Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) },
|
||||
{ Flag::DeleteMessages, tr::lng_rights_group_delete(tr::now) },
|
||||
{ Flag::BanUsers, tr::lng_rights_group_ban(tr::now) },
|
||||
{ Flag::InviteByLinkOrAdd, options.anyoneCanAddMembers
|
||||
? tr::lng_rights_group_invite_link(tr::now)
|
||||
: tr::lng_rights_group_invite(tr::now) },
|
||||
{ Flag::ManageTopics, tr::lng_rights_group_topics(tr::now) },
|
||||
{ Flag::PinMessages, tr::lng_rights_group_pin(tr::now) },
|
||||
{ Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) },
|
||||
{ Flag::Anonymous, tr::lng_rights_group_anonymous(tr::now) },
|
||||
{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) },
|
||||
};
|
||||
if (!options.isForum) {
|
||||
result.erase(
|
||||
ranges::remove(
|
||||
result,
|
||||
Flag::ManageTopics | Flag(),
|
||||
&AdminRightLabel::flags),
|
||||
end(result));
|
||||
}
|
||||
return { { std::nullopt, std::move(result) } };
|
||||
}
|
||||
auto first = std::vector<AdminRightLabel>{
|
||||
{ Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) },
|
||||
};
|
||||
auto messages = std::vector<AdminRightLabel>{
|
||||
{ Flag::PostMessages, tr::lng_rights_channel_post(tr::now) },
|
||||
{ Flag::EditMessages, tr::lng_rights_channel_edit(tr::now) },
|
||||
{ Flag::DeleteMessages, tr::lng_rights_channel_delete(tr::now) },
|
||||
};
|
||||
auto stories = std::vector<AdminRightLabel>{
|
||||
{ Flag::PostStories, tr::lng_rights_channel_post_stories(tr::now) },
|
||||
{ Flag::EditStories, tr::lng_rights_channel_edit_stories(tr::now) },
|
||||
{ Flag::DeleteStories, tr::lng_rights_channel_delete_stories(tr::now) },
|
||||
};
|
||||
auto second = std::vector<AdminRightLabel>{
|
||||
{ Flag::InviteByLinkOrAdd, tr::lng_rights_group_invite(tr::now) },
|
||||
{ Flag::ManageCall, tr::lng_rights_channel_manage_calls(tr::now) },
|
||||
{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) },
|
||||
};
|
||||
return {
|
||||
{ std::nullopt, std::move(first) },
|
||||
{ tr::lng_rights_channel_manage(), std::move(messages) },
|
||||
{ tr::lng_rights_channel_manage_stories(), std::move(stories) },
|
||||
{ std::nullopt, std::move(second) },
|
||||
};
|
||||
}
|
||||
|
@ -1031,42 +1087,11 @@ std::vector<RestrictionLabel> RestrictionLabels(
|
|||
|
||||
std::vector<AdminRightLabel> AdminRightLabels(
|
||||
Data::AdminRightsSetOptions options) {
|
||||
using Flag = ChatAdminRight;
|
||||
|
||||
if (options.isGroup) {
|
||||
auto result = std::vector<AdminRightLabel>{
|
||||
{ Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) },
|
||||
{ Flag::DeleteMessages, tr::lng_rights_group_delete(tr::now) },
|
||||
{ Flag::BanUsers, tr::lng_rights_group_ban(tr::now) },
|
||||
{ Flag::InviteByLinkOrAdd, options.anyoneCanAddMembers
|
||||
? tr::lng_rights_group_invite_link(tr::now)
|
||||
: tr::lng_rights_group_invite(tr::now) },
|
||||
{ Flag::ManageTopics, tr::lng_rights_group_topics(tr::now) },
|
||||
{ Flag::PinMessages, tr::lng_rights_group_pin(tr::now) },
|
||||
{ Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) },
|
||||
{ Flag::Anonymous, tr::lng_rights_group_anonymous(tr::now) },
|
||||
{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) },
|
||||
};
|
||||
if (!options.isForum) {
|
||||
result.erase(
|
||||
ranges::remove(
|
||||
result,
|
||||
Flag::ManageTopics | Flag(),
|
||||
&AdminRightLabel::flags),
|
||||
end(result));
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return {
|
||||
{ Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) },
|
||||
{ Flag::PostMessages, tr::lng_rights_channel_post(tr::now) },
|
||||
{ Flag::EditMessages, tr::lng_rights_channel_edit(tr::now) },
|
||||
{ Flag::DeleteMessages, tr::lng_rights_channel_delete(tr::now) },
|
||||
{ Flag::InviteByLinkOrAdd, tr::lng_rights_group_invite(tr::now) },
|
||||
{ Flag::ManageCall, tr::lng_rights_channel_manage_calls(tr::now) },
|
||||
{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) }
|
||||
};
|
||||
auto result = std::vector<AdminRightLabel>();
|
||||
for (const auto &[_, r] : NestedAdminRightLabels(options)) {
|
||||
result.insert(result.end(), r.begin(), r.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
|
||||
|
@ -1107,7 +1132,7 @@ EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
|
|||
rights,
|
||||
{
|
||||
.header = std::move(header),
|
||||
.labels = { { std::nullopt, AdminRightLabels(options) } },
|
||||
.labels = NestedAdminRightLabels(options),
|
||||
.disabledMessages = std::move(disabledMessages),
|
||||
});
|
||||
result.widget = std::move(widget);
|
||||
|
|
|
@ -32,7 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/controls/userpic_button.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/box_content_divider.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
|
|
|
@ -48,19 +48,6 @@ struct InfographicDescriptor {
|
|||
bool complexRatio = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] rpl::producer<> BoxShowFinishes(not_null<Ui::GenericBox*> box) {
|
||||
const auto singleShot = box->lifetime().make_state<rpl::lifetime>();
|
||||
const auto showFinishes = singleShot->make_state<rpl::event_stream<>>();
|
||||
|
||||
box->setShowFinishedCallback([=] {
|
||||
showFinishes->fire({});
|
||||
singleShot->destroy();
|
||||
box->setShowFinishedCallback(nullptr);
|
||||
});
|
||||
|
||||
return showFinishes->events();
|
||||
}
|
||||
|
||||
void AddSubsectionTitle(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<QString> text) {
|
||||
|
@ -423,8 +410,9 @@ void SimpleLimitBox(
|
|||
Settings::AddSkip(top, st::premiumInfographicPadding.top());
|
||||
Ui::Premium::AddBubbleRow(
|
||||
top,
|
||||
st::defaultPremiumBubble,
|
||||
BoxShowFinishes(box),
|
||||
descriptor.defaultLimit,
|
||||
0,
|
||||
descriptor.current,
|
||||
descriptor.premiumLimit,
|
||||
premiumPossible,
|
||||
|
@ -783,16 +771,18 @@ void FilterLinksLimitBox(
|
|||
|
||||
void FiltersLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session) {
|
||||
not_null<Main::Session*> session,
|
||||
std::optional<int> filtersCountOverride) {
|
||||
const auto premium = session->premium();
|
||||
const auto premiumPossible = session->premiumPossible();
|
||||
|
||||
const auto limits = Data::PremiumLimits(session);
|
||||
const auto defaultLimit = float64(limits.dialogFiltersDefault());
|
||||
const auto premiumLimit = float64(limits.dialogFiltersPremium());
|
||||
const auto current = float64(ranges::count_if(
|
||||
const auto cloud = int(ranges::count_if(
|
||||
session->data().chatsFilters().list(),
|
||||
[](const Data::ChatFilter &f) { return f.id() != FilterId(); }));
|
||||
const auto current = float64(filtersCountOverride.value_or(cloud));
|
||||
|
||||
auto text = rpl::combine(
|
||||
tr::lng_filters_limit1(
|
||||
|
@ -1092,6 +1082,7 @@ void AccountsLimitBox(
|
|||
Settings::AddSkip(top, st::premiumInfographicPadding.top());
|
||||
Ui::Premium::AddBubbleRow(
|
||||
top,
|
||||
st::defaultPremiumBubble,
|
||||
BoxShowFinishes(box),
|
||||
0,
|
||||
current,
|
||||
|
|
|
@ -42,7 +42,8 @@ void FilterLinksLimitBox(
|
|||
not_null<Main::Session*> session);
|
||||
void FiltersLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session);
|
||||
not_null<Main::Session*> session,
|
||||
std::optional<int> filtersCountOverride);
|
||||
void ShareableFiltersLimitBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Main::Session*> session);
|
||||
|
|
|
@ -31,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/effects/scroll_content_shadow.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
|
@ -1033,17 +1033,21 @@ void SendFilesBox::setupCaption() {
|
|||
Core::App().settings().sendSubmitWay());
|
||||
_caption->setMaxLength(kMaxMessageLength);
|
||||
|
||||
connect(_caption, &Ui::InputField::resized, [=] {
|
||||
_caption->heightChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
captionResized();
|
||||
});
|
||||
connect(_caption, &Ui::InputField::submitted, [=](
|
||||
Qt::KeyboardModifiers modifiers) {
|
||||
}, _caption->lifetime());
|
||||
_caption->submits(
|
||||
) | rpl::start_with_next([=](Qt::KeyboardModifiers modifiers) {
|
||||
const auto ctrlShiftEnter = modifiers.testFlag(Qt::ShiftModifier)
|
||||
&& (modifiers.testFlag(Qt::ControlModifier)
|
||||
|| modifiers.testFlag(Qt::MetaModifier));
|
||||
send({}, ctrlShiftEnter);
|
||||
});
|
||||
connect(_caption, &Ui::InputField::cancelled, [=] { closeBox(); });
|
||||
}, _caption->lifetime());
|
||||
_caption->cancelled(
|
||||
) | rpl::start_with_next([=] {
|
||||
closeBox();
|
||||
}, _caption->lifetime());
|
||||
_caption->setMimeDataHook([=](
|
||||
not_null<const QMimeData*> data,
|
||||
Ui::InputField::MimeAction action) {
|
||||
|
|
|
@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
|
@ -144,7 +144,7 @@ void RenameBox(not_null<Ui::GenericBox*> box) {
|
|||
Core::App().settings().setCustomDeviceModel(result);
|
||||
Core::App().saveSettingsDelayed();
|
||||
};
|
||||
QObject::connect(name, &Ui::InputField::submitted, submit);
|
||||
name->submits() | rpl::start_with_next(submit, name->lifetime());
|
||||
box->addButton(tr::lng_settings_save(), submit);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/text/text_options.h"
|
||||
|
@ -226,9 +226,8 @@ void ShareBox::prepareCommentField() {
|
|||
|
||||
const auto field = _comment->entity();
|
||||
|
||||
connect(field, &Ui::InputField::submitted, [=] {
|
||||
submit({});
|
||||
});
|
||||
field->submits(
|
||||
) | rpl::start_with_next([=] { submit({}); }, field->lifetime());
|
||||
if (const auto show = uiShow(); show->valid()) {
|
||||
InitMessageFieldHandlers(
|
||||
_descriptor.session,
|
||||
|
@ -249,6 +248,8 @@ void ShareBox::prepareCommentField() {
|
|||
void ShareBox::prepare() {
|
||||
prepareCommentField();
|
||||
|
||||
setCloseByOutsideClick(false);
|
||||
|
||||
_select->resizeToWidth(st::boxWideWidth);
|
||||
Ui::SendPendingMoveResizeEvents(_select);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/slide_animation.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "ui/painter.h"
|
||||
|
|
|
@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/menu/menu_action.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/painter.h"
|
||||
|
|
|
@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/call_button.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/tooltip.h"
|
||||
#include "ui/widgets/rp_window.h"
|
||||
#include "ui/chat/group_call_bar.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/continuous_sliders.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
|
|
|
@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
@ -287,7 +287,7 @@ void EditGroupCallTitleBox(
|
|||
box->closeBox();
|
||||
done(result);
|
||||
};
|
||||
QObject::connect(input, &Ui::InputField::submitted, submit);
|
||||
input->submits() | rpl::start_with_next(submit, input->lifetime());
|
||||
box->addButton(tr::lng_settings_save(), submit);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
@ -346,7 +346,7 @@ void AddTitleGroupCallRecordingBox(
|
|||
box->closeBox();
|
||||
done(result);
|
||||
};
|
||||
QObject::connect(input, &Ui::InputField::submitted, submit);
|
||||
input->submits() | rpl::start_with_next(submit, input->lifetime());
|
||||
box->addButton(tr::lng_group_call_recording_start_button(), submit);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ inline auto PreviewPath(int i) {
|
|||
|
||||
const auto kSets = {
|
||||
Set{ { 0, 0, 0, "Mac" }, PreviewPath(0) },
|
||||
Set{ { 1, 1392, 8'184'590, "Android" }, PreviewPath(1) },
|
||||
Set{ { 2, 1393, 5'413'219, "Twemoji" }, PreviewPath(2) },
|
||||
Set{ { 3, 1394, 6'967'218, "JoyPixels" }, PreviewPath(3) },
|
||||
Set{ { 1, 1804, 8'115'639, "Android" }, PreviewPath(1) },
|
||||
Set{ { 2, 1805, 5'481'197, "Twemoji" }, PreviewPath(2) },
|
||||
Set{ { 3, 1806, 7'047'594, "JoyPixels" }, PreviewPath(3) },
|
||||
};
|
||||
|
||||
using Loading = MTP::DedicatedLoader::Progress;
|
||||
|
|
|
@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/inner_dropdown.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
|
|
|
@ -31,7 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/clip/media_clip_reader.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
|
|
|
@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/click_handler_types.h"
|
||||
#include "ui/controls/tabbed_search.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/image/image.h"
|
||||
|
|
|
@ -190,16 +190,18 @@ void EditLinkBox(
|
|||
}
|
||||
};
|
||||
|
||||
QObject::connect(text, &Ui::InputField::submitted, [=] {
|
||||
text->submits(
|
||||
) | rpl::start_with_next([=] {
|
||||
url->setFocusFast();
|
||||
});
|
||||
QObject::connect(url, &Ui::InputField::submitted, [=] {
|
||||
}, text->lifetime());
|
||||
url->submits(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (text->getLastText().isEmpty()) {
|
||||
text->setFocusFast();
|
||||
} else {
|
||||
submit();
|
||||
}
|
||||
});
|
||||
}, url->lifetime());
|
||||
|
||||
box->setTitle(url->getLastText().isEmpty()
|
||||
? tr::lng_formatting_link_create_title()
|
||||
|
@ -223,8 +225,14 @@ void EditLinkBox(
|
|||
url->customTab(true);
|
||||
text->customTab(true);
|
||||
|
||||
QObject::connect(url, &Ui::InputField::tabbed, [=] { text->setFocus(); });
|
||||
QObject::connect(text, &Ui::InputField::tabbed, [=] { url->setFocus(); });
|
||||
url->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
text->setFocus();
|
||||
}, url->lifetime());
|
||||
text->tabbed(
|
||||
) | rpl::start_with_next([=] {
|
||||
url->setFocus();
|
||||
}, text->lifetime());
|
||||
}
|
||||
|
||||
TextWithEntities StripSupportHashtag(TextWithEntities text) {
|
||||
|
@ -590,7 +598,8 @@ AutocompleteQuery ParseMentionHashtagBotCommandQuery(
|
|||
MessageLinksParser::MessageLinksParser(not_null<Ui::InputField*> field)
|
||||
: _field(field)
|
||||
, _timer([=] { parse(); }) {
|
||||
_connection = QObject::connect(_field, &Ui::InputField::changed, [=] {
|
||||
_lifetime = _field->changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto length = _field->getTextWithTags().text.size();
|
||||
const auto timeout = (std::abs(length - _lastLength) > 2)
|
||||
? 0
|
||||
|
|
|
@ -7,9 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/qt_connection.h"
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_SPELLCHECK
|
||||
|
@ -132,7 +131,7 @@ private:
|
|||
int _lastLength = 0;
|
||||
bool _disabled = false;
|
||||
base::Timer _timer;
|
||||
base::qt_connection _connection;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lottie/lottie_single_player.h"
|
||||
#include "ui/dpr/dpr_icon.h"
|
||||
#include "ui/dpr/dpr_image.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect_part.h"
|
||||
|
|
|
@ -22,110 +22,6 @@ namespace {
|
|||
|
||||
std::map<int, const char*> BetaLogs() {
|
||||
return {
|
||||
{
|
||||
4005004,
|
||||
"- Allow wide range of interface scale options.\n"
|
||||
|
||||
"- Show opened chat name in the window title.\n"
|
||||
|
||||
"- Bug fixes and other minor improvements.\n"
|
||||
|
||||
"- Fix updating on macOS older than 10.14.\n"
|
||||
},
|
||||
{
|
||||
4005006,
|
||||
"- Try enabling non-fractional scale "
|
||||
"High DPI support on Windows and Linux.\n"
|
||||
|
||||
"- Experimental setting for fractional scale "
|
||||
"High DPI support on Windows and Linux.\n"
|
||||
|
||||
"- Fix navigation to bottom problems in groups you didn't join.\n"
|
||||
|
||||
"- Fix a crash in chat export settings changes.\n"
|
||||
|
||||
"- Fix a crash in sending some of JPEG images.\n"
|
||||
|
||||
"- Fix CJK fonts on Windows.\n"
|
||||
},
|
||||
{
|
||||
4005007,
|
||||
"- Fix glitches after moving window to another screen.\n",
|
||||
},
|
||||
{
|
||||
4005008,
|
||||
"- Allow opening another account in a new window "
|
||||
"(see Settings > Advanced > Experimental Settings).\n"
|
||||
|
||||
"- A lot of bugfixes for working with more than one window.\n"
|
||||
},
|
||||
{
|
||||
4006004,
|
||||
"- Allow media viewer to exit fullscreen and become a normal window."
|
||||
},
|
||||
{
|
||||
4006006,
|
||||
"- Confirmation window before starting a call.\n"
|
||||
|
||||
"- New \"Battery and Animations\" settings section.\n"
|
||||
|
||||
"- \"Save Power on Low Battery\" option for laptops.\n"
|
||||
|
||||
"- Improved windowed mode support for media viewer.\n"
|
||||
|
||||
"- Hardware accelerated video playback fix on macOS.\n"
|
||||
|
||||
"- New application icon on macOS following the system guidelines.\n"
|
||||
},
|
||||
{
|
||||
4006007,
|
||||
"- Fix crash when accepting incoming calls.\n"
|
||||
|
||||
"- Remove sound when cancelling an unconfirmed call.\n"
|
||||
},
|
||||
{
|
||||
4006008,
|
||||
"- Improve quality of voice messages with changed playback speed.\n"
|
||||
|
||||
"- Show when your message was read in small groups.\n"
|
||||
|
||||
"- Fix pasting images from Firefox on Windows.\n"
|
||||
|
||||
"- Improve memory usage for custom emoji.\n"
|
||||
},
|
||||
{
|
||||
4006010,
|
||||
"- Suggest sending an invite link if user forbids "
|
||||
"inviting him to groups.\n"
|
||||
|
||||
"- Show when a reaction was left on your message in small groups.\n"
|
||||
|
||||
"- Fix a crash in video chats on Windows.\n"
|
||||
|
||||
"- Fix a crash in audio speed change.\n"
|
||||
},
|
||||
{
|
||||
4006011,
|
||||
"- Allow larger interface scale values on high-dpi screens.\n"
|
||||
|
||||
"- Implement new voice and video speed change interface (up to 2.5x).\n"
|
||||
|
||||
"- Support global Fn+F shortcut to toggle fullscreen on macOS.\n"
|
||||
|
||||
"- Silent notification sound in Focus Mode on macOS.\n"
|
||||
|
||||
"- Fix media viewer on macOS with several screens.\n"
|
||||
|
||||
"- Fix a crash in connection type box.\n"
|
||||
|
||||
"- Fix possible crash on quit.\n"
|
||||
},
|
||||
{
|
||||
4006012,
|
||||
"- Fix several possible crashes.\n"
|
||||
|
||||
"- Deprecate macOS 10.12, Ubuntu 18.04 and CentOS 7 in July.\n"
|
||||
},
|
||||
{
|
||||
4008011,
|
||||
"- Fix initial video playback speed.\n"
|
||||
|
|
|
@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "boxes/send_files_box.h"
|
||||
#include "history/view/history_view_quick_action.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "storage/serialize_common.h"
|
||||
#include "window/section_widget.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
|
|
|
@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <new>
|
||||
#include <mutex>
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <new.h>
|
||||
|
@ -25,7 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <client/windows/handler/exception_handler.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#elif defined Q_OS_UNIX // Q_OS_WIN
|
||||
#else // Q_OS_WIN
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <sys/syscall.h>
|
||||
|
@ -48,7 +48,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#endif // Q_OS_MAC
|
||||
|
||||
#endif // Q_OS_WIN
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
namespace CrashReports {
|
||||
namespace {
|
||||
|
@ -59,7 +59,7 @@ using AnnotationRefs = std::map<std::string, const QString*>;
|
|||
Annotations ProcessAnnotations;
|
||||
AnnotationRefs ProcessAnnotationRefs;
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
QString ReportPath;
|
||||
FILE *ReportFile = nullptr;
|
||||
|
@ -197,13 +197,15 @@ const int HandledSignals[] = {
|
|||
SIGABRT,
|
||||
SIGFPE,
|
||||
SIGILL,
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifndef Q_OS_WIN
|
||||
SIGBUS,
|
||||
SIGTRAP,
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // !Q_OS_WIN
|
||||
};
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifdef Q_OS_WIN
|
||||
void SignalHandler(int signum) {
|
||||
#else // Q_OS_WIN
|
||||
struct sigaction OldSigActions[32]/* = { 0 }*/;
|
||||
|
||||
void RestoreSignalHandlers() {
|
||||
|
@ -229,9 +231,7 @@ void InvokeOldSignalHandler(int signum, siginfo_t *info, void *ucontext) {
|
|||
void SignalHandler(int signum, siginfo_t *info, void *ucontext) {
|
||||
RestoreSignalHandlers();
|
||||
|
||||
#else // Q_OS_UNIX
|
||||
void SignalHandler(int signum) {
|
||||
#endif // else for Q_OS_UNIX
|
||||
#endif // else for Q_OS_WIN
|
||||
|
||||
const char* name = 0;
|
||||
switch (signum) {
|
||||
|
@ -253,9 +253,9 @@ void SignalHandler(int signum) {
|
|||
ReportingThreadId = nullptr;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifndef Q_OS_WIN
|
||||
InvokeOldSignalHandler(signum, info, ucontext);
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // !Q_OS_WIN
|
||||
}
|
||||
|
||||
bool SetSignalHandlers = true;
|
||||
|
@ -267,9 +267,9 @@ google_breakpad::ExceptionHandler* BreakpadExceptionHandler = 0;
|
|||
bool DumpCallback(const wchar_t* _dump_dir, const wchar_t* _minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool success)
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
bool DumpCallback(const char* _dump_dir, const char* _minidump_id, void *context, bool success)
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#else // Q_OS_MAC
|
||||
bool DumpCallback(const google_breakpad::MinidumpDescriptor &md, void *context, bool success)
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // else for Q_OS_WIN || Q_OS_MAC
|
||||
{
|
||||
if (CrashLogged) return success;
|
||||
CrashLogged = true;
|
||||
|
@ -290,7 +290,7 @@ bool DumpCallback(const google_breakpad::MinidumpDescriptor &md, void *context,
|
|||
}
|
||||
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
|
||||
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -314,7 +314,7 @@ QString PlatformString() {
|
|||
}
|
||||
|
||||
void StartCatching() {
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
ProcessAnnotations["Binary"] = cExeName().toUtf8().constData();
|
||||
ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData();
|
||||
ProcessAnnotations["Version"] = (cAlphaVersion()
|
||||
|
@ -370,7 +370,7 @@ void StartCatching() {
|
|||
false)) { // asynchronous_start
|
||||
}
|
||||
#endif // else for MAC_USE_BREAKPAD
|
||||
#elif defined Q_OS_UNIX
|
||||
#else
|
||||
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()),
|
||||
/*FilterCallback*/ 0,
|
||||
|
@ -379,22 +379,22 @@ void StartCatching() {
|
|||
true,
|
||||
-1
|
||||
);
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // else for Q_OS_WIN || Q_OS_MAC
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
}
|
||||
|
||||
void FinishCatching() {
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
|
||||
|
||||
delete base::take(BreakpadExceptionHandler);
|
||||
|
||||
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
}
|
||||
|
||||
StartResult Start() {
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
ReportPath = cWorkingDir() + u"tdata/working"_q;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -420,12 +420,12 @@ StartResult Start() {
|
|||
return lastdump;
|
||||
}
|
||||
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
return Restart();
|
||||
}
|
||||
|
||||
Status Restart() {
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
if (ReportFile) {
|
||||
return Started;
|
||||
}
|
||||
|
@ -470,13 +470,13 @@ Status Restart() {
|
|||
LOG(("FATAL: Could not open '%1' for writing!").arg(ReportPath));
|
||||
|
||||
return CantOpen;
|
||||
#else // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#else // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
return Started;
|
||||
#endif // else for !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // else for !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
}
|
||||
|
||||
void Finish() {
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
FinishCatching();
|
||||
|
||||
if (ReportFile) {
|
||||
|
@ -489,7 +489,7 @@ void Finish() {
|
|||
unlink(ReportPath.toUtf8().constData());
|
||||
#endif // else for Q_OS_WIN
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
}
|
||||
|
||||
void SetAnnotation(const std::string &key, const QString &value) {
|
||||
|
@ -539,7 +539,7 @@ void SetAnnotationRef(const std::string &key, const QString *valuePtr) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
dump::~dump() {
|
||||
if (ReportFile) {
|
||||
|
@ -604,6 +604,6 @@ const dump &operator<<(const dump &stream, double num) {
|
|||
return stream;
|
||||
}
|
||||
|
||||
#endif // DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
} // namespace CrashReports
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace CrashReports {
|
|||
|
||||
QString PlatformString();
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
struct dump {
|
||||
~dump();
|
||||
|
@ -24,7 +24,7 @@ const dump &operator<<(const dump &stream, unsigned long num);
|
|||
const dump &operator<<(const dump &stream, unsigned long long num);
|
||||
const dump &operator<<(const dump &stream, double num);
|
||||
|
||||
#endif // DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
#endif // TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
enum Status {
|
||||
CantOpen,
|
||||
|
|
83
Telegram/SourceFiles/core/deadlock_detector.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace Core::DeadlockDetector {
|
||||
|
||||
class PingPongEvent : public QEvent {
|
||||
public:
|
||||
static auto Type() {
|
||||
static const auto Result = QEvent::Type(QEvent::registerEventType());
|
||||
return Result;
|
||||
}
|
||||
|
||||
PingPongEvent(not_null<QObject*> sender)
|
||||
: QEvent(Type())
|
||||
, _sender(sender) {
|
||||
}
|
||||
|
||||
[[nodiscard]] not_null<QObject*> sender() const {
|
||||
return _sender;
|
||||
}
|
||||
|
||||
private:
|
||||
not_null<QObject*> _sender;
|
||||
|
||||
};
|
||||
|
||||
class Pinger : public QObject {
|
||||
public:
|
||||
Pinger(not_null<QObject*> receiver)
|
||||
: _receiver(receiver)
|
||||
, _abortTimer([] { Unexpected("Deadlock found!"); }) {
|
||||
const auto callback = [=] {
|
||||
QCoreApplication::postEvent(_receiver, new PingPongEvent(this));
|
||||
_abortTimer.callOnce(30000);
|
||||
};
|
||||
_pingTimer.setCallback(callback);
|
||||
_pingTimer.callEach(60000);
|
||||
callback();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e) override {
|
||||
if (e->type() == PingPongEvent::Type()
|
||||
&& static_cast<PingPongEvent*>(e)->sender() == _receiver) {
|
||||
_abortTimer.cancel();
|
||||
}
|
||||
return QObject::event(e);
|
||||
}
|
||||
|
||||
private:
|
||||
not_null<QObject*> _receiver;
|
||||
base::Timer _pingTimer;
|
||||
base::Timer _abortTimer;
|
||||
|
||||
};
|
||||
|
||||
class PingThread : public QThread {
|
||||
public:
|
||||
PingThread(not_null<QObject*> parent)
|
||||
: QThread(parent) {
|
||||
start();
|
||||
}
|
||||
|
||||
~PingThread() {
|
||||
quit();
|
||||
wait();
|
||||
}
|
||||
|
||||
protected:
|
||||
void run() override {
|
||||
Pinger pinger(parent());
|
||||
QThread::run();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace Core::DeadlockDetector
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/options.h"
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QStandardPaths>
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
|
@ -115,16 +116,26 @@ void ComputeDebugMode() {
|
|||
}
|
||||
|
||||
void ComputeExternalUpdater() {
|
||||
QFile file(u"/etc/tdesktop/externalupdater"_q);
|
||||
|
||||
if (file.exists() && file.open(QIODevice::ReadOnly)) {
|
||||
QTextStream fileStream(&file);
|
||||
while (!fileStream.atEnd()) {
|
||||
const auto path = fileStream.readLine();
|
||||
|
||||
if (path == (cExeDir() + cExeName())) {
|
||||
SetUpdaterDisabledAtStartup();
|
||||
return;
|
||||
auto locations = QStandardPaths::standardLocations(
|
||||
QStandardPaths::AppDataLocation);
|
||||
if (locations.isEmpty()) {
|
||||
locations << QString();
|
||||
}
|
||||
locations[0] = QDir::cleanPath(cWorkingDir());
|
||||
locations << QDir::cleanPath(cExeDir());
|
||||
for (const auto &location : locations) {
|
||||
const auto dir = location + u"/externalupdater.d"_q;
|
||||
for (const auto &info : QDir(dir).entryInfoList(QDir::Files)) {
|
||||
QFile file(info.absoluteFilePath());
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QTextStream fileStream(&file);
|
||||
while (!fileStream.atEnd()) {
|
||||
const auto path = fileStream.readLine();
|
||||
if (path == (cExeDir() + cExeName())) {
|
||||
SetUpdaterDisabledAtStartup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +234,7 @@ bool CheckPortableVersionFolder() {
|
|||
if (cAlphaVersion()) {
|
||||
Assert(*AlphaPrivateKey != 0);
|
||||
|
||||
cForceWorkingDir(portable + '/');
|
||||
cForceWorkingDir(portable);
|
||||
QDir().mkpath(cWorkingDir() + u"tdata"_q);
|
||||
cSetAlphaPrivateKey(QByteArray(AlphaPrivateKey));
|
||||
if (!key.open(QIODevice::WriteOnly)) {
|
||||
|
@ -239,7 +250,7 @@ bool CheckPortableVersionFolder() {
|
|||
if (!QDir(portable).exists()) {
|
||||
return true;
|
||||
}
|
||||
cForceWorkingDir(portable + '/');
|
||||
cForceWorkingDir(portable);
|
||||
if (!key.exists()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -291,7 +302,8 @@ Launcher::Launcher(int argc, char *argv[])
|
|||
: _argc(argc)
|
||||
, _argv(argv)
|
||||
, _arguments(readArguments(_argc, _argv))
|
||||
, _baseIntegration(_argc, _argv) {
|
||||
, _baseIntegration(_argc, _argv)
|
||||
, _initialWorkingDir(QDir::currentPath() + '/') {
|
||||
crl::toggle_fp_exceptions(true);
|
||||
|
||||
base::Integration::Set(&_baseIntegration);
|
||||
|
@ -446,6 +458,10 @@ const QStringList &Launcher::arguments() const {
|
|||
return _arguments;
|
||||
}
|
||||
|
||||
QString Launcher::initialWorkingDir() const {
|
||||
return _initialWorkingDir;
|
||||
}
|
||||
|
||||
bool Launcher::customWorkingDir() const {
|
||||
return !_customWorkingDir.isEmpty();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
virtual int exec();
|
||||
|
||||
const QStringList &arguments() const;
|
||||
QString initialWorkingDir() const;
|
||||
bool customWorkingDir() const;
|
||||
|
||||
uint64 installationTag() const;
|
||||
|
@ -84,6 +85,7 @@ private:
|
|||
QStringList _arguments;
|
||||
BaseIntegration _baseIntegration;
|
||||
|
||||
QString _initialWorkingDir;
|
||||
QString _customWorkingDir;
|
||||
|
||||
};
|
||||
|
|
|
@ -378,6 +378,8 @@ bool ResolveUsernameOrPhone(
|
|||
startToken = params.value(u"startgroup"_q);
|
||||
} else if (params.contains(u"startchannel"_q)) {
|
||||
resolveType = ResolveType::AddToChannel;
|
||||
} else if (params.contains(u"boost"_q)) {
|
||||
resolveType = ResolveType::Boost;
|
||||
}
|
||||
auto post = ShowAtUnreadMsgId;
|
||||
auto adminRights = ChatAdminRights();
|
||||
|
@ -392,7 +394,6 @@ bool ResolveUsernameOrPhone(
|
|||
const auto storyParam = params.value(u"story"_q);
|
||||
const auto storyId = storyParam.toInt();
|
||||
const auto appname = webChannelPreviewLink ? QString() : appnameParam;
|
||||
const auto appstart = params.value(u"startapp"_q);
|
||||
const auto commentParam = params.value(u"comment"_q);
|
||||
const auto commentId = commentParam.toInt();
|
||||
const auto topicParam = params.value(u"topic"_q);
|
||||
|
@ -404,11 +405,11 @@ bool ResolveUsernameOrPhone(
|
|||
startToken = gameParam;
|
||||
resolveType = ResolveType::ShareGame;
|
||||
}
|
||||
if (startToken.isEmpty() && params.contains(u"startapp"_q)) {
|
||||
startToken = params.value(u"startapp"_q);
|
||||
}
|
||||
if (!appname.isEmpty()) {
|
||||
resolveType = ResolveType::BotApp;
|
||||
if (startToken.isEmpty() && params.contains(u"startapp"_q)) {
|
||||
startToken = params.value(u"startapp"_q);
|
||||
}
|
||||
}
|
||||
const auto myContext = context.value<ClickHandlerContext>();
|
||||
using Navigation = Window::SessionNavigation;
|
||||
|
@ -436,7 +437,11 @@ bool ResolveUsernameOrPhone(
|
|||
.attachBotUsername = params.value(u"attach"_q),
|
||||
.attachBotToggleCommand = (params.contains(u"startattach"_q)
|
||||
? params.value(u"startattach"_q)
|
||||
: (appname.isEmpty() && params.contains(u"startapp"_q))
|
||||
? params.value(u"startapp"_q)
|
||||
: std::optional<QString>()),
|
||||
.attachBotMenuOpen = (appname.isEmpty()
|
||||
&& params.contains(u"startapp"_q)),
|
||||
.attachBotChooseTypes = InlineBots::ParseChooseTypes(
|
||||
params.value(u"choose"_q)),
|
||||
.voicechatHash = (params.contains(u"livestream"_q)
|
||||
|
@ -839,6 +844,32 @@ bool ResolveLoginCode(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ResolveBoost(
|
||||
Window::SessionController *controller,
|
||||
const Match &match,
|
||||
const QVariant &context) {
|
||||
if (!controller) {
|
||||
return false;
|
||||
}
|
||||
const auto params = url_parse_params(
|
||||
match->captured(1),
|
||||
qthelp::UrlParamNameTransform::ToLower);
|
||||
const auto domainParam = params.value(u"domain"_q);
|
||||
const auto channelParam = params.value(u"channel"_q);
|
||||
|
||||
const auto myContext = context.value<ClickHandlerContext>();
|
||||
using Navigation = Window::SessionNavigation;
|
||||
controller->window().activate();
|
||||
controller->showPeerByLink(Navigation::PeerByLinkInfo{
|
||||
.usernameOrId = (!domainParam.isEmpty()
|
||||
? std::variant<QString, ChannelId>(domainParam)
|
||||
: ChannelId(BareId(channelParam.toULongLong()))),
|
||||
.resolveType = Window::ResolveType::Boost,
|
||||
.clickFromMessageId = myContext.itemId,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
||||
|
@ -919,6 +950,10 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
|||
u"^login/?(\\?code=([0-9]+))(&|$)"_q,
|
||||
ResolveLoginCode
|
||||
},
|
||||
{
|
||||
u"^boost/?\\?(.+)(#|$)"_q,
|
||||
ResolveBoost,
|
||||
},
|
||||
{
|
||||
u"^([^\\?]+)(\\?|#|$)"_q,
|
||||
HandleUnknown
|
||||
|
@ -1022,8 +1057,13 @@ QString TryConvertUrlToLocal(QString url) {
|
|||
"/\\d+/?(\\?|$)|"
|
||||
"/\\d+/\\d+/?(\\?|$)"
|
||||
")"_q, query, matchOptions)) {
|
||||
const auto channel = privateMatch->captured(1);
|
||||
const auto params = query.mid(privateMatch->captured(0).size()).toString();
|
||||
const auto base = u"tg://privatepost?channel="_q + privateMatch->captured(1);
|
||||
if (params.indexOf("boost", 0, Qt::CaseInsensitive) >= 0
|
||||
&& params.toLower().split('&').contains(u"boost"_q)) {
|
||||
return u"tg://boost?channel="_q + channel;
|
||||
}
|
||||
const auto base = u"tg://privatepost?channel="_q + channel;
|
||||
auto added = QString();
|
||||
if (const auto threadPostMatch = regex_match(u"^/(\\d+)/(\\d+)(/?\\?|/?$)"_q, privateMatch->captured(2))) {
|
||||
added = u"&topic=%1&post=%2"_q.arg(threadPostMatch->captured(1)).arg(threadPostMatch->captured(2));
|
||||
|
@ -1041,7 +1081,12 @@ QString TryConvertUrlToLocal(QString url) {
|
|||
"/s/\\d+/?(\\?|$)|"
|
||||
"/\\d+/\\d+/?(\\?|$)"
|
||||
")"_q, query, matchOptions)) {
|
||||
const auto domain = usernameMatch->captured(1);
|
||||
const auto params = query.mid(usernameMatch->captured(0).size()).toString();
|
||||
if (params.indexOf("boost", 0, Qt::CaseInsensitive) >= 0
|
||||
&& params.toLower().split('&').contains(u"boost"_q)) {
|
||||
return u"tg://boost?domain="_q + domain;
|
||||
}
|
||||
const auto base = u"tg://resolve?domain="_q + url_encode(usernameMatch->captured(1));
|
||||
auto added = QString();
|
||||
if (const auto threadPostMatch = regex_match(u"^/(\\d+)/(\\d+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) {
|
||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/launcher.h"
|
||||
#include "core/local_url_handlers.h"
|
||||
#include "core/update_checker.h"
|
||||
#include "core/deadlock_detector.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/concurrent_timer.h"
|
||||
#include "base/invoke_queued.h"
|
||||
|
@ -202,6 +203,13 @@ void Sandbox::launchApplication() {
|
|||
}
|
||||
setupScreenScale();
|
||||
|
||||
#ifndef _DEBUG
|
||||
if (Logs::DebugEnabled()) {
|
||||
using DeadlockDetector::PingThread;
|
||||
_deadlockDetector = std::make_unique<PingThread>(this);
|
||||
}
|
||||
#endif // !_DEBUG
|
||||
|
||||
_application = std::make_unique<Application>();
|
||||
|
||||
// Ideally this should go to constructor.
|
||||
|
@ -271,6 +279,10 @@ bool Sandbox::event(QEvent *e) {
|
|||
return false;
|
||||
} else if (e->type() == QEvent::Close) {
|
||||
Quit();
|
||||
} else if (e->type() == DeadlockDetector::PingPongEvent::Type()) {
|
||||
postEvent(
|
||||
static_cast<DeadlockDetector::PingPongEvent*>(e)->sender(),
|
||||
new DeadlockDetector::PingPongEvent(this));
|
||||
}
|
||||
return QApplication::event(e);
|
||||
}
|
||||
|
|
|
@ -131,6 +131,8 @@ private:
|
|||
|
||||
rpl::event_stream<> _widgetUpdateRequests;
|
||||
|
||||
std::unique_ptr<QThread> _deadlockDetector;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -370,7 +370,6 @@ QString UiIntegration::phrasePanelCloseAnyway() {
|
|||
return tr::lng_bot_close_warning_sure(tr::now);
|
||||
}
|
||||
|
||||
#if 0 // disabled for now
|
||||
QString UiIntegration::phraseBotSharePhone() {
|
||||
return tr::lng_bot_share_phone(tr::now);
|
||||
}
|
||||
|
@ -382,7 +381,18 @@ QString UiIntegration::phraseBotSharePhoneTitle() {
|
|||
QString UiIntegration::phraseBotSharePhoneConfirm() {
|
||||
return tr::lng_bot_share_phone_confirm(tr::now);
|
||||
}
|
||||
#endif
|
||||
|
||||
QString UiIntegration::phraseBotAllowWrite() {
|
||||
return tr::lng_bot_allow_write(tr::now);
|
||||
}
|
||||
|
||||
QString UiIntegration::phraseBotAllowWriteTitle() {
|
||||
return tr::lng_bot_allow_write_title(tr::now);
|
||||
}
|
||||
|
||||
QString UiIntegration::phraseBotAllowWriteConfirm() {
|
||||
return tr::lng_bot_allow_write_confirm(tr::now);
|
||||
}
|
||||
|
||||
bool OpenGLLastCheckFailed() {
|
||||
return QFile::exists(OpenGLCheckFilePath());
|
||||
|
|
|
@ -84,11 +84,12 @@ public:
|
|||
QString phrasePanelCloseWarning() override;
|
||||
QString phrasePanelCloseUnsaved() override;
|
||||
QString phrasePanelCloseAnyway() override;
|
||||
#if 0 // disabled for now
|
||||
QString phraseBotSharePhone() override;
|
||||
QString phraseBotSharePhoneTitle() override;
|
||||
QString phraseBotSharePhoneConfirm() override;
|
||||
#endif
|
||||
QString phraseBotAllowWrite() override;
|
||||
QString phraseBotAllowWriteTitle() override;
|
||||
QString phraseBotAllowWriteConfirm() override;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -42,16 +42,16 @@ extern "C" {
|
|||
} // extern "C"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined TDESKTOP_USE_PACKAGED // use Lzma SDK for win
|
||||
#include <LzmaLib.h>
|
||||
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#else // Q_OS_WIN && !TDESKTOP_USE_PACKAGED
|
||||
#include <lzma.h>
|
||||
#endif // else of Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#endif // else of Q_OS_WIN && !TDESKTOP_USE_PACKAGED
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifndef Q_OS_WIN
|
||||
#include <unistd.h>
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // !Q_OS_WIN
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
|
@ -275,11 +275,11 @@ bool UnpackUpdate(const QString &filepath) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined TDESKTOP_USE_PACKAGED // use Lzma SDK for win
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
|
||||
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#else // Q_OS_WIN && !TDESKTOP_USE_PACKAGED
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
|
||||
#endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#endif // Q_OS_WIN && !TDESKTOP_USE_PACKAGED
|
||||
|
||||
QByteArray compressed = input.readAll();
|
||||
int32 compressedLen = compressed.size() - hSize;
|
||||
|
@ -330,14 +330,14 @@ bool UnpackUpdate(const QString &filepath) {
|
|||
uncompressed.resize(uncompressedLen);
|
||||
|
||||
size_t resultLen = uncompressed.size();
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined TDESKTOP_USE_PACKAGED // use Lzma SDK for win
|
||||
SizeT srcLen = compressedLen;
|
||||
int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
|
||||
if (uncompressRes != SZ_OK) {
|
||||
LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
|
||||
return false;
|
||||
}
|
||||
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#else // Q_OS_WIN && !TDESKTOP_USE_PACKAGED
|
||||
lzma_stream stream = LZMA_STREAM_INIT;
|
||||
|
||||
lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
|
||||
|
@ -380,7 +380,7 @@ bool UnpackUpdate(const QString &filepath) {
|
|||
LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res));
|
||||
return false;
|
||||
}
|
||||
#endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#endif // Q_OS_WIN && !TDESKTOP_USE_PACKAGED
|
||||
|
||||
tempDir.mkdir(tempDir.absolutePath());
|
||||
|
||||
|
@ -428,9 +428,9 @@ bool UnpackUpdate(const QString &filepath) {
|
|||
bool executable = false;
|
||||
|
||||
stream >> relativeName >> fileSize >> fileInnerData;
|
||||
#ifdef Q_OS_UNIX
|
||||
#ifndef Q_OS_WIN
|
||||
stream >> executable;
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // !Q_OS_WIN
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read file from downloaded stream, status: %1").arg(stream.status()));
|
||||
return false;
|
||||
|
@ -1539,10 +1539,10 @@ bool checkReadyUpdate() {
|
|||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
QString curUpdater = (cExeDir() + cExeName() + u"/Contents/Frameworks/Updater"_q);
|
||||
QFileInfo updater(cWorkingDir() + u"tupdates/temp/Telegram.app/Contents/Frameworks/Updater"_q);
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#else // Q_OS_MAC
|
||||
QString curUpdater = (cExeDir() + u"Updater"_q);
|
||||
QFileInfo updater(cWorkingDir() + u"tupdates/temp/Updater"_q);
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // else for Q_OS_WIN || Q_OS_MAC
|
||||
if (!updater.exists()) {
|
||||
QFileInfo current(curUpdater);
|
||||
if (!current.exists()) {
|
||||
|
@ -1576,7 +1576,7 @@ bool checkReadyUpdate() {
|
|||
ClearAll();
|
||||
return false;
|
||||
}
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#else // Q_OS_MAC
|
||||
// if the files in the directory are owned by user, while the directory is not,
|
||||
// update will still fail since it's not possible to remove files
|
||||
if (QFile::exists(curUpdater)
|
||||
|
@ -1604,7 +1604,7 @@ bool checkReadyUpdate() {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // else for Q_OS_WIN || Q_OS_MAC
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
base::Platform::RemoveQuarantine(QFileInfo(curUpdater).absolutePath());
|
||||
|
|
|
@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
|
|||
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
|
||||
constexpr auto AppName = "AyuGram Desktop"_cs;
|
||||
constexpr auto AppFile = "AyuGram"_cs;
|
||||
constexpr auto AppVersion = 4009004;
|
||||
constexpr auto AppVersionStr = "4.9.4";
|
||||
constexpr auto AppVersion = 4010000;
|
||||
constexpr auto AppVersionStr = "4.10";
|
||||
constexpr auto AppBetaVersion = false;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
|
|
@ -24,4 +24,5 @@ struct BotAppData {
|
|||
|
||||
uint64 accessHash = 0;
|
||||
uint64 hash = 0;
|
||||
bool hasSettings = false;
|
||||
};
|
||||
|
|
|
@ -221,14 +221,14 @@ struct StoryUpdate {
|
|||
enum class Flag : uint32 {
|
||||
None = 0,
|
||||
|
||||
Edited = (1U << 0),
|
||||
Destroyed = (1U << 1),
|
||||
NewAdded = (1U << 2),
|
||||
ViewsAdded = (1U << 3),
|
||||
MarkRead = (1U << 4),
|
||||
Reaction = (1U << 5),
|
||||
Edited = (1U << 0),
|
||||
Destroyed = (1U << 1),
|
||||
NewAdded = (1U << 2),
|
||||
ViewsChanged = (1U << 3),
|
||||
MarkRead = (1U << 4),
|
||||
Reaction = (1U << 5),
|
||||
|
||||
LastUsedBit = (1U << 5),
|
||||
LastUsedBit = (1U << 5),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_user.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_stories.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_forum_icons.h"
|
||||
|
@ -530,6 +531,11 @@ bool ChannelData::canBanMembers() const {
|
|||
|| (adminRights() & AdminRight::BanUsers);
|
||||
}
|
||||
|
||||
bool ChannelData::canPostMessages() const {
|
||||
return amCreator()
|
||||
|| (adminRights() & AdminRight::PostMessages);
|
||||
}
|
||||
|
||||
bool ChannelData::canEditMessages() const {
|
||||
return amCreator()
|
||||
|| (adminRights() & AdminRight::EditMessages);
|
||||
|
@ -540,6 +546,30 @@ bool ChannelData::canDeleteMessages() const {
|
|||
|| (adminRights() & AdminRight::DeleteMessages);
|
||||
}
|
||||
|
||||
bool ChannelData::canPostStories() const {
|
||||
if (!isBroadcast()) {
|
||||
return false;
|
||||
}
|
||||
return amCreator()
|
||||
|| (adminRights() & AdminRight::PostStories);
|
||||
}
|
||||
|
||||
bool ChannelData::canEditStories() const {
|
||||
if (!isBroadcast()) {
|
||||
return false;
|
||||
}
|
||||
return amCreator()
|
||||
|| (adminRights() & AdminRight::EditStories);
|
||||
}
|
||||
|
||||
bool ChannelData::canDeleteStories() const {
|
||||
if (!isBroadcast()) {
|
||||
return false;
|
||||
}
|
||||
return amCreator()
|
||||
|| (adminRights() & AdminRight::DeleteStories);
|
||||
}
|
||||
|
||||
bool ChannelData::anyoneCanAddMembers() const {
|
||||
return !(defaultRestrictions() & Restriction::AddParticipants);
|
||||
}
|
||||
|
@ -559,11 +589,6 @@ bool ChannelData::canAddAdmins() const {
|
|||
|| (adminRights() & AdminRight::AddAdmins);
|
||||
}
|
||||
|
||||
bool ChannelData::canPublish() const {
|
||||
return amCreator()
|
||||
|| (adminRights() & AdminRight::PostMessages);
|
||||
}
|
||||
|
||||
bool ChannelData::allowsForwarding() const {
|
||||
return !(flags() & Flag::NoForwards);
|
||||
}
|
||||
|
@ -877,6 +902,38 @@ const Data::AllowedReactions &ChannelData::allowedReactions() const {
|
|||
return _allowedReactions;
|
||||
}
|
||||
|
||||
bool ChannelData::hasActiveStories() const {
|
||||
return flags() & Flag::HasActiveStories;
|
||||
}
|
||||
|
||||
bool ChannelData::hasUnreadStories() const {
|
||||
return flags() & Flag::HasUnreadStories;
|
||||
}
|
||||
|
||||
void ChannelData::setStoriesState(StoriesState state) {
|
||||
Expects(state != StoriesState::Unknown);
|
||||
|
||||
const auto was = flags();
|
||||
switch (state) {
|
||||
case StoriesState::None:
|
||||
_flags.remove(Flag::HasActiveStories | Flag::HasUnreadStories);
|
||||
break;
|
||||
case StoriesState::HasRead:
|
||||
_flags.set(
|
||||
(flags() & ~Flag::HasUnreadStories) | Flag::HasActiveStories);
|
||||
break;
|
||||
case StoriesState::HasUnread:
|
||||
_flags.add(Flag::HasActiveStories | Flag::HasUnreadStories);
|
||||
break;
|
||||
}
|
||||
if (flags() != was) {
|
||||
if (const auto history = owner().historyLoaded(this)) {
|
||||
history->updateChatListEntryPostponed();
|
||||
}
|
||||
session().changes().peerUpdated(this, UpdateFlag::StoriesState);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelData::processTopics(const MTPVector<MTPForumTopic> &topics) {
|
||||
if (const auto forum = this->forum()) {
|
||||
forum->applyReceivedTopics(topics);
|
||||
|
@ -1046,6 +1103,7 @@ void ApplyChannelUpdate(
|
|||
} else {
|
||||
channel->setAllowedReactions({});
|
||||
}
|
||||
channel->owner().stories().apply(channel, update.vstories());
|
||||
channel->fullUpdated();
|
||||
channel->setPendingRequestsCount(
|
||||
update.vrequests_pending().value_or_empty(),
|
||||
|
|
|
@ -59,6 +59,9 @@ enum class ChannelDataFlag {
|
|||
Forum = (1 << 23),
|
||||
AntiSpam = (1 << 24),
|
||||
ParticipantsHidden = (1 << 25),
|
||||
StoriesHidden = (1 << 26),
|
||||
HasActiveStories = (1 << 27),
|
||||
HasUnreadStories = (1 << 28),
|
||||
};
|
||||
inline constexpr bool is_flag_type(ChannelDataFlag) { return true; };
|
||||
using ChannelDataFlags = base::flags<ChannelDataFlag>;
|
||||
|
@ -226,6 +229,9 @@ public:
|
|||
[[nodiscard]] bool isFake() const {
|
||||
return flags() & Flag::Fake;
|
||||
}
|
||||
[[nodiscard]] bool hasStoriesHidden() const {
|
||||
return flags() & Flag::StoriesHidden;
|
||||
}
|
||||
|
||||
[[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights(
|
||||
not_null<PeerData*> participant);
|
||||
|
@ -329,10 +335,13 @@ public:
|
|||
[[nodiscard]] bool canBanMembers() const;
|
||||
[[nodiscard]] bool anyoneCanAddMembers() const;
|
||||
|
||||
[[nodiscard]] bool canPostMessages() const;
|
||||
[[nodiscard]] bool canEditMessages() const;
|
||||
[[nodiscard]] bool canDeleteMessages() const;
|
||||
[[nodiscard]] bool canPostStories() const;
|
||||
[[nodiscard]] bool canEditStories() const;
|
||||
[[nodiscard]] bool canDeleteStories() const;
|
||||
[[nodiscard]] bool hiddenPreHistory() const;
|
||||
[[nodiscard]] bool canPublish() const;
|
||||
[[nodiscard]] bool canViewMembers() const;
|
||||
[[nodiscard]] bool canViewAdmins() const;
|
||||
[[nodiscard]] bool canViewBanned() const;
|
||||
|
@ -437,6 +446,10 @@ public:
|
|||
void setAllowedReactions(Data::AllowedReactions value);
|
||||
[[nodiscard]] const Data::AllowedReactions &allowedReactions() const;
|
||||
|
||||
[[nodiscard]] bool hasActiveStories() const;
|
||||
[[nodiscard]] bool hasUnreadStories() const;
|
||||
void setStoriesState(StoriesState state);
|
||||
|
||||
[[nodiscard]] Data::Forum *forum() const {
|
||||
return mgInfo ? mgInfo->forum() : nullptr;
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ bool CanSendAnyOf(
|
|||
&& !(channel->flags() & Flag::JoinToWrite));
|
||||
if (!allowed || (forbidInForums && channel->isForum())) {
|
||||
return false;
|
||||
} else if (channel->canPublish()) {
|
||||
} else if (channel->canPostMessages()) {
|
||||
return true;
|
||||
} else if (channel->isBroadcast()) {
|
||||
return false;
|
||||
|
|
|
@ -25,6 +25,9 @@ enum class ChatAdminRight {
|
|||
ManageCall = (1 << 11),
|
||||
Other = (1 << 12),
|
||||
ManageTopics = (1 << 13),
|
||||
PostStories = (1 << 14),
|
||||
EditStories = (1 << 15),
|
||||
DeleteStories = (1 << 16),
|
||||
};
|
||||
inline constexpr bool is_flag_type(ChatAdminRight) { return true; }
|
||||
using ChatAdminRights = base::flags<ChatAdminRight>;
|
||||
|
|
|
@ -159,14 +159,7 @@ wv xm xml ym yuv").split(' ');
|
|||
bool IsExecutableName(const QString &filepath) {
|
||||
static const auto kExtensions = [] {
|
||||
const auto joined =
|
||||
#ifdef Q_OS_MAC
|
||||
u"\
|
||||
applescript action app bin command csh osx workflow terminal url caction \
|
||||
mpkg pkg scpt scptd xhtm webarchive"_q;
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
u"bin csh deb desktop ksh out pet pkg pup rpm run sh shar \
|
||||
slp zsh"_q;
|
||||
#else // Q_OS_MAC || Q_OS_UNIX
|
||||
#ifdef Q_OS_WIN
|
||||
u"\
|
||||
ad ade adp app application appref-ms asp asx bas bat bin cab cdxml cer cfg \
|
||||
chi chm cmd cnt com cpl crt csh der diagcab dll drv eml exe fon fxp gadget \
|
||||
|
@ -179,7 +172,14 @@ psd1 psm1 pssc pst py py3 pyc pyd pyi pyo pyw pywz pyz rb reg rgs scf scr \
|
|||
sct search-ms settingcontent-ms sh shb shs slk sys t tmp u3p url vb vbe vbp \
|
||||
vbs vbscript vdx vsmacros vsd vsdm vsdx vss vssm vssx vst vstm vstx vsw vsx \
|
||||
vtx website ws wsc wsf wsh xbap xll xnk xs"_q;
|
||||
#endif // !Q_OS_MAC && !Q_OS_UNIX
|
||||
#elif defined Q_OS_MAC // Q_OS_MAC
|
||||
u"\
|
||||
applescript action app bin command csh osx workflow terminal url caction \
|
||||
mpkg pkg scpt scptd xhtm webarchive"_q;
|
||||
#else // Q_OS_WIN || Q_OS_MAC
|
||||
u"bin csh deb desktop ksh out pet pkg pup rpm run sh shar \
|
||||
slp zsh"_q;
|
||||
#endif // !Q_OS_WIN && !Q_OS_MAC
|
||||
const auto list = joined.split(' ');
|
||||
return base::flat_set<QString>(list.begin(), list.end());
|
||||
}();
|
||||
|
|
|
@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_drafts.h"
|
||||
|
||||
#include "api/api_text_entities.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_widget.h"
|
||||
|
|
|
@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lang/lang_keys.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "storage/storage_facade.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
|
|
@ -73,7 +73,7 @@ struct FullReplyTo {
|
|||
FullStoryId storyId;
|
||||
|
||||
[[nodiscard]] bool valid() const {
|
||||
return msgId || storyId;
|
||||
return msgId || (storyId && peerIsUser(storyId.peer));
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return valid();
|
||||
|
|