Merge tag 'v4.12.2' into dev

# Conflicts:
#	.github/workflows/win.yml
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/SourceFiles/settings/settings_advanced.cpp
#	Telegram/SourceFiles/settings/settings_main.cpp
#	Telegram/lib_ui
#	snap/snapcraft.yaml
This commit is contained in:
ZavaruKitsu 2023-12-01 15:38:13 +03:00
commit 0f8187fa36
556 changed files with 27811 additions and 3566 deletions

View file

@ -40,7 +40,7 @@ jobs:
macos: macos:
name: MacOS name: MacOS
runs-on: macos-latest runs-on: macos-13
strategy: strategy:
matrix: matrix:
@ -67,6 +67,8 @@ jobs:
- name: First set up. - name: First set up.
run: | run: |
brew update
brew upgrade || true
brew install autoconf automake boost cmake ffmpeg openal-soft openssl opus ninja pkg-config python qt yasm xz brew install autoconf automake boost cmake ffmpeg openal-soft openssl opus ninja pkg-config python qt yasm xz
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

View file

@ -1,7 +1,6 @@
name: Windows. name: Windows.
on: on:
workflow_dispatch:
push: push:
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'
@ -47,10 +46,11 @@ jobs:
strategy: strategy:
matrix: matrix:
arch: [Win32] arch: [Win32, x64]
generator: ["", "Ninja Multi-Config"]
env: env:
UPLOAD_ARTIFACT: "true" UPLOAD_ARTIFACT: "false"
ONLY_CACHE: "false" ONLY_CACHE: "false"
PREPARE_PATH: "Telegram/build/prepare/prepare.py" PREPARE_PATH: "Telegram/build/prepare/prepare.py"
@ -110,19 +110,42 @@ jobs:
cd %TBUILD% cd %TBUILD%
%REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent %REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent
- name: Read defines. - name: Read configuration matrix.
shell: bash shell: bash
run: | run: |
ARTIFACT_NAME="Telegram"
ARCH=""
if [ -n "${{ matrix.arch }}" ]; then
case "${{ matrix.arch }}" in
Win32) ARCH="x86";;
*) ARCH="${{ matrix.arch }}";;
esac
echo "Architecture from matrix: $ARCH"
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.arch }}"
fi
GENERATOR=""
if [ -n "${{ matrix.generator }}" ]; then
GENERATOR="-G \"${{ matrix.generator }}\""
echo "Generator from matrix: $GENERATOR"
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.generator }}"
fi
echo "TDESKTOP_BUILD_GENERATOR=$GENERATOR" >> $GITHUB_ENV
[ -n "$GENERATOR" ] && ARCH=""
echo "TDESKTOP_BUILD_ARCH=$ARCH" >> $GITHUB_ENV
DEFINE="" DEFINE=""
if [ -n "${{ matrix.defines }}" ]; then if [ -n "${{ matrix.defines }}" ]; then
DEFINE="-D ${{ matrix.defines }}=ON" DEFINE="-D ${{ matrix.defines }}=ON"
echo "Define from matrix: $DEFINE" echo "Define from matrix: $DEFINE"
echo "ARTIFACT_NAME=Telegram_${{ matrix.arch }}_${{ matrix.defines }}" >> $GITHUB_ENV ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.defines }}"
else
echo "ARTIFACT_NAME=Telegram_${{ matrix.arch }}" >> $GITHUB_ENV
fi fi
echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV
echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> $GITHUB_ENV
API="-D TDESKTOP_API_TEST=ON" 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." echo "Use the open credentials."
@ -143,50 +166,23 @@ jobs:
cd %TBUILD%\%REPO_NAME%\Telegram cd %TBUILD%\%REPO_NAME%\Telegram
call configure.bat ^ call configure.bat ^
${{ matrix.arch }} ^ %TDESKTOP_BUILD_GENERATOR% ^
%TDESKTOP_BUILD_ARCH% ^
%TDESKTOP_BUILD_API% ^ %TDESKTOP_BUILD_API% ^
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^ -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^
-D DESKTOP_APP_NO_PDB=ON ^ -D DESKTOP_APP_NO_PDB=ON ^
%TDESKTOP_BUILD_DEFINE% ^ %TDESKTOP_BUILD_DEFINE%
-DCMAKE_SYSTEM_VERSION=%SDK%
cd ..\out cmake --build ..\out --config Debug --parallel
msbuild -m Telegram.sln /p:Configuration=Debug,Platform=${{ matrix.arch }},DebugSymbols=false,DebugType=none
- name: Move artifact. - name: Move artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || ${{ github.ref == 'refs/heads/nightly' }} if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
run: | run: |
mkdir artifact mkdir artifact
move %TBUILD%\%REPO_NAME%\out\Debug\AyuGram.exe artifact/ move %TBUILD%\%REPO_NAME%\out\Debug\Telegram.exe artifact/
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@master
name: Upload artifact. name: Upload artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || ${{ github.ref == 'refs/heads/nightly' }} if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
with: with:
name: ${{ env.ARTIFACT_NAME }} name: ${{ env.ARTIFACT_NAME }}
path: artifact\ path: artifact\
release:
name: Release
needs: [windows]
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- uses: actions/checkout@v2
- name: Merge Releases
uses: actions/download-artifact@v2
with:
name: Telegram_Win32
path: artifact
- name: Upload release
uses: Hs1r1us/Release-AIO@v1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# The name of the tag
tag_name: prelease-${{ github.run_number }}
prerelease: true
release_name: Ayugram CI
asset_files: './artifact'

3
.gitmodules vendored
View file

@ -76,9 +76,6 @@
[submodule "Telegram/lib_webview"] [submodule "Telegram/lib_webview"]
path = Telegram/lib_webview path = Telegram/lib_webview
url = https://github.com/desktop-app/lib_webview.git url = https://github.com/desktop-app/lib_webview.git
[submodule "Telegram/ThirdParty/jemalloc"]
path = Telegram/ThirdParty/jemalloc
url = https://github.com/jemalloc/jemalloc
[submodule "Telegram/ThirdParty/dispatch"] [submodule "Telegram/ThirdParty/dispatch"]
path = Telegram/ThirdParty/dispatch path = Telegram/ThirdParty/dispatch
url = https://github.com/apple/swift-corelibs-libdispatch url = https://github.com/apple/swift-corelibs-libdispatch

View file

@ -10,8 +10,9 @@ if (APPLE)
else() else()
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
endif() endif()
cmake_policy(SET CMP0076 NEW) if (POLICY CMP0149)
cmake_policy(SET CMP0091 NEW) cmake_policy(SET CMP0149 NEW)
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)

View file

@ -197,6 +197,8 @@ PRIVATE
api/api_messages_search.h api/api_messages_search.h
api/api_messages_search_merged.cpp api/api_messages_search_merged.cpp
api/api_messages_search_merged.h api/api_messages_search_merged.h
api/api_peer_colors.cpp
api/api_peer_colors.h
api/api_peer_photo.cpp api/api_peer_photo.cpp
api/api_peer_photo.h api/api_peer_photo.h
api/api_polls.cpp api/api_polls.cpp
@ -447,16 +449,18 @@ PRIVATE
chat_helpers/gifs_list_widget.h chat_helpers/gifs_list_widget.h
chat_helpers/message_field.cpp chat_helpers/message_field.cpp
chat_helpers/message_field.h chat_helpers/message_field.h
chat_helpers/share_message_phrase_factory.cpp
chat_helpers/share_message_phrase_factory.h
chat_helpers/spellchecker_common.cpp chat_helpers/spellchecker_common.cpp
chat_helpers/spellchecker_common.h chat_helpers/spellchecker_common.h
chat_helpers/stickers_dice_pack.cpp
chat_helpers/stickers_dice_pack.h
chat_helpers/stickers_emoji_image_loader.cpp chat_helpers/stickers_emoji_image_loader.cpp
chat_helpers/stickers_emoji_image_loader.h chat_helpers/stickers_emoji_image_loader.h
chat_helpers/stickers_emoji_pack.cpp chat_helpers/stickers_emoji_pack.cpp
chat_helpers/stickers_emoji_pack.h chat_helpers/stickers_emoji_pack.h
chat_helpers/stickers_gift_box_pack.cpp chat_helpers/stickers_gift_box_pack.cpp
chat_helpers/stickers_gift_box_pack.h chat_helpers/stickers_gift_box_pack.h
chat_helpers/stickers_dice_pack.cpp
chat_helpers/stickers_dice_pack.h
chat_helpers/stickers_list_footer.cpp chat_helpers/stickers_list_footer.cpp
chat_helpers/stickers_list_footer.h chat_helpers/stickers_list_footer.h
chat_helpers/stickers_list_widget.cpp chat_helpers/stickers_list_widget.cpp
@ -778,6 +782,8 @@ PRIVATE
history/view/media/history_view_premium_gift.h history/view/media/history_view_premium_gift.h
history/view/media/history_view_service_box.cpp history/view/media/history_view_service_box.cpp
history/view/media/history_view_service_box.h history/view/media/history_view_service_box.h
history/view/media/history_view_similar_channels.cpp
history/view/media/history_view_similar_channels.h
history/view/media/history_view_slot_machine.cpp history/view/media/history_view_slot_machine.cpp
history/view/media/history_view_slot_machine.h history/view/media/history_view_slot_machine.h
history/view/media/history_view_sticker.cpp history/view/media/history_view_sticker.cpp
@ -853,6 +859,8 @@ PRIVATE
history/view/history_view_service_message.h history/view/history_view_service_message.h
history/view/history_view_spoiler_click_handler.cpp history/view/history_view_spoiler_click_handler.cpp
history/view/history_view_spoiler_click_handler.h history/view/history_view_spoiler_click_handler.h
history/view/history_view_sponsored_click_handler.cpp
history/view/history_view_sponsored_click_handler.h
history/view/history_view_sticker_toast.cpp history/view/history_view_sticker_toast.cpp
history/view/history_view_sticker_toast.h history/view/history_view_sticker_toast.h
history/view/history_view_transcribe_button.cpp history/view/history_view_transcribe_button.cpp
@ -958,6 +966,8 @@ PRIVATE
info/profile/info_profile_widget.h info/profile/info_profile_widget.h
info/settings/info_settings_widget.cpp info/settings/info_settings_widget.cpp
info/settings/info_settings_widget.h info/settings/info_settings_widget.h
info/similar_channels/info_similar_channels_widget.cpp
info/similar_channels/info_similar_channels_widget.h
info/statistics/info_statistics_common.h info/statistics/info_statistics_common.h
info/statistics/info_statistics_inner_widget.cpp info/statistics/info_statistics_inner_widget.cpp
info/statistics/info_statistics_inner_widget.h info/statistics/info_statistics_inner_widget.h
@ -1095,6 +1105,8 @@ PRIVATE
media/stories/media_stories_recent_views.h media/stories/media_stories_recent_views.h
media/stories/media_stories_reply.cpp media/stories/media_stories_reply.cpp
media/stories/media_stories_reply.h media/stories/media_stories_reply.h
media/stories/media_stories_repost_view.cpp
media/stories/media_stories_repost_view.h
media/stories/media_stories_share.cpp media/stories/media_stories_share.cpp
media/stories/media_stories_share.h media/stories/media_stories_share.h
media/stories/media_stories_sibling.cpp media/stories/media_stories_sibling.cpp
@ -1345,8 +1357,8 @@ PRIVATE
settings/settings_calls.h settings/settings_calls.h
settings/settings_codes.cpp settings/settings_codes.cpp
settings/settings_codes.h settings/settings_codes.h
settings/settings_common.cpp settings/settings_common_session.cpp
settings/settings_common.h settings/settings_common_session.h
settings/settings_experimental.cpp settings/settings_experimental.cpp
settings/settings_experimental.h settings/settings_experimental.h
settings/settings_folders.cpp settings/settings_folders.cpp
@ -1506,6 +1518,7 @@ PRIVATE
window/window_section_common.h window/window_section_common.h
window/window_session_controller.cpp window/window_session_controller.cpp
window/window_session_controller.h window/window_session_controller.h
window/window_session_controller_link_info.h
window/window_slide_animation.cpp window/window_slide_animation.cpp
window/window_slide_animation.h window/window_slide_animation.h
window/window_top_bar_wrap.h window/window_top_bar_wrap.h
@ -1798,6 +1811,10 @@ endif()
set_target_properties(Telegram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder}) set_target_properties(Telegram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
if (WIN32) if (WIN32)
target_link_libraries(Telegram
PRIVATE
delayimp
)
target_link_options(Telegram target_link_options(Telegram
PRIVATE PRIVATE
/DELAYLOAD:secur32.dll /DELAYLOAD:secur32.dll
@ -1854,6 +1871,10 @@ if (NOT DESKTOP_APP_DISABLE_AUTOUPDATE AND NOT build_macstore AND NOT build_wins
) )
target_include_directories(Updater PRIVATE ${lib_base_loc}) target_include_directories(Updater PRIVATE ${lib_base_loc})
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_link_libraries(Updater
PRIVATE
delayimp
)
target_link_options(Updater target_link_options(Updater
PRIVATE PRIVATE
/DELAYLOAD:user32.dll /DELAYLOAD:user32.dll

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -839,6 +839,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_background_dimming" = "Background dimming"; "lng_background_dimming" = "Background dimming";
"lng_background_sure_reset_default" = "Are you sure you want to reset the wallpaper?"; "lng_background_sure_reset_default" = "Are you sure you want to reset the wallpaper?";
"lng_background_reset_default" = "Reset"; "lng_background_reset_default" = "Reset";
"lng_background_apply_me" = "Apply for me";
"lng_background_apply_both" = "Apply for me and {user}";
"lng_download_path_ask" = "Ask download path for each file"; "lng_download_path_ask" = "Ask download path for each file";
"lng_download_path" = "Download path"; "lng_download_path" = "Download path";
@ -1175,6 +1177,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_bot_privacy" = "Bot Privacy Policy"; "lng_profile_bot_privacy" = "Bot Privacy Policy";
"lng_profile_common_groups#one" = "{count} group in common"; "lng_profile_common_groups#one" = "{count} group in common";
"lng_profile_common_groups#other" = "{count} groups in common"; "lng_profile_common_groups#other" = "{count} groups in common";
"lng_profile_similar_channels#one" = "{count} similar channel";
"lng_profile_similar_channels#other" = "{count} similar channels";
"lng_profile_participants_section" = "Members"; "lng_profile_participants_section" = "Members";
"lng_profile_subscribers_section" = "Subscribers"; "lng_profile_subscribers_section" = "Subscribers";
"lng_profile_add_contact" = "Add Contact"; "lng_profile_add_contact" = "Add Contact";
@ -1347,6 +1351,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_peer_reactions_none_about" = "Members of the group can't add any reactions to messages."; "lng_manage_peer_reactions_none_about" = "Members of the group can't add any reactions to messages.";
"lng_manage_peer_reactions_some_title" = "Only allow these reactions"; "lng_manage_peer_reactions_some_title" = "Only allow these reactions";
"lng_manage_peer_reactions_available" = "Available reactions"; "lng_manage_peer_reactions_available" = "Available reactions";
"lng_manage_peer_reactions_own" = "You can also {link} emoji packs and use them as reactions.";
"lng_manage_peer_reactions_own_link" = "create your own";
"lng_manage_peer_reactions_level#one" = "Your channel needs to reach level **{count}** to use **{same_count}** custom reaction.";
"lng_manage_peer_reactions_level#other" = "Your channel needs to reach level **{count}** to use **{same_count}** custom reactions.";
"lng_manage_peer_reactions_boost" = "Boost your channel {link}.";
"lng_manage_peer_reactions_boost_link" = "here";
"lng_manage_peer_reactions_limit" = "Channels can't have more custom reactions.";
"lng_manage_peer_antispam" = "Aggressive Anti-Spam"; "lng_manage_peer_antispam" = "Aggressive Anti-Spam";
"lng_manage_peer_antispam_about" = "Telegram will filter more spam but may occasionally affect ordinary messages. You can report False Positives in Recent Actions."; "lng_manage_peer_antispam_about" = "Telegram will filter more spam but may occasionally affect ordinary messages. You can report False Positives in Recent Actions.";
@ -1641,11 +1652,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_suggested_video_button" = "View 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_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_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_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" = "{user} set a new wallpaper for this chat.";
"lng_action_set_wallpaper_both_me" = "You set a new wallpaper for {user} and you.";
"lng_action_set_wallpaper_button" = "View Wallpaper"; "lng_action_set_wallpaper_button" = "View Wallpaper";
"lng_action_set_same_wallpaper_me" = "You set the same wallpaper for this chat"; "lng_action_set_wallpaper_remove" = "Remove";
"lng_action_set_same_wallpaper" = "{user} set the same wallpaper for this chat"; "lng_action_set_same_wallpaper_me" = "You set the same wallpaper for this chat.";
"lng_action_set_same_wallpaper" = "{user} set the same wallpaper for this chat.";
"lng_action_topic_created_inside" = "Topic created"; "lng_action_topic_created_inside" = "Topic created";
"lng_action_topic_closed_inside" = "Topic closed"; "lng_action_topic_closed_inside" = "Topic closed";
"lng_action_topic_reopened_inside" = "Topic reopened"; "lng_action_topic_reopened_inside" = "Topic reopened";
@ -1667,6 +1680,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available."; "lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available.";
"lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available."; "lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available.";
"lng_action_giveaway_started" = "{from} just started a giveaway of Telegram Premium subscriptions to its followers."; "lng_action_giveaway_started" = "{from} just started a giveaway of Telegram Premium subscriptions to its followers.";
"lng_action_giveaway_results#one" = "{count} winner of the giveaway was randomly selected by Telegram and received private messages with giftcodes.";
"lng_action_giveaway_results#other" = "{count} winners of the giveaway were randomly selected by Telegram and received private messages with giftcodes.";
"lng_action_giveaway_results_some" = "Some winners of the giveaway was randomly selected by Telegram and received private messages with giftcodes.";
"lng_action_giveaway_results_none" = "No winners of the giveaway could be selected.";
"lng_similar_channels_title" = "Similar channels";
"lng_similar_channels_view_all" = "View all";
"lng_similar_channels_more" = "More Channels";
"lng_similar_channels_premium_all#one" = "Subscribe to {link} to unlock up to **{count}** similar channel.";
"lng_similar_channels_premium_all#other" = "Subscribe to {link} to unlock up to **{count}** similar channels.";
"lng_similar_channels_premium_all_link" = "Telegram Premium";
"lng_similar_channels_show_more" = "Show more channels";
"lng_premium_gift_duration_months#one" = "for {count} month"; "lng_premium_gift_duration_months#one" = "for {count} month";
"lng_premium_gift_duration_months#other" = "for {count} months"; "lng_premium_gift_duration_months#other" = "for {count} months";
@ -1808,8 +1833,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_forwarded_hidden" = "The account was hidden by the user."; "lng_forwarded_hidden" = "The account was hidden by the user.";
"lng_forwarded_imported" = "This message was imported from another app. It may not be real."; "lng_forwarded_imported" = "This message was imported from another app. It may not be real.";
"lng_signed_author" = "Author: {user}"; "lng_signed_author" = "Author: {user}";
"lng_sponsored" = "sponsored"; "lng_sponsored_message_title" = "Sponsored";
"lng_recommended" = "recommended"; "lng_recommended_message_title" = "Recommended";
"lng_edited" = "edited"; "lng_edited" = "edited";
"lng_edited_date" = "Edited: {date}"; "lng_edited_date" = "Edited: {date}";
"lng_sent_date" = "Sent: {date}"; "lng_sent_date" = "Sent: {date}";
@ -1921,6 +1946,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_summary_subtitle_gift#other" = "{user} has gifted you a {count}-months subscription for Telegram Premium."; "lng_premium_summary_subtitle_gift#other" = "{user} has gifted you a {count}-months subscription for Telegram Premium.";
"lng_premium_summary_subtitle_gift_me#one" = "You gifted {user} a {count}-month subscription for Telegram Premium."; "lng_premium_summary_subtitle_gift_me#one" = "You gifted {user} a {count}-month subscription for Telegram Premium.";
"lng_premium_summary_subtitle_gift_me#other" = "You gifted {user} a {count}-months subscription for Telegram Premium."; "lng_premium_summary_subtitle_gift_me#other" = "You gifted {user} a {count}-months subscription for Telegram Premium.";
"lng_premium_summary_subtitle_wallpapers" = "Wallpapers for Both Sides";
"lng_premium_summary_about_wallpapers" = "Set custom wallpapers for you and your chat partner.";
"lng_premium_summary_subtitle_stories" = "Upgraded Stories"; "lng_premium_summary_subtitle_stories" = "Upgraded Stories";
"lng_premium_summary_about_stories" = "Priority order, stealth mode, permanent views history and more."; "lng_premium_summary_about_stories" = "Priority order, stealth mode, permanent views history and more.";
"lng_premium_summary_subtitle_double_limits" = "Doubled Limits"; "lng_premium_summary_subtitle_double_limits" = "Doubled Limits";
@ -2083,6 +2110,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boost_channel_title_color" = "Enable colors"; "lng_boost_channel_title_color" = "Enable colors";
"lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color."; "lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color.";
"lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color."; "lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color.";
"lng_boost_channel_title_reactions" = "Custom reactions";
"lng_boost_channel_needs_level_reactions#one" = "Your channel needs to reach **Level {count}** to add **{same_count}** custom emoji as a reaction.";
"lng_boost_channel_needs_level_reactions#other" = "Your channel needs to reach **Level {count}** to add **{same_count}** custom emoji as reactions.";
"lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:"; "lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:";
"lng_boost_channel_ask_button" = "Copy Link"; "lng_boost_channel_ask_button" = "Copy Link";
"lng_boost_channel_or" = "or"; "lng_boost_channel_or" = "or";
@ -2746,6 +2778,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_share_wrong_user" = "This game was opened from a different user."; "lng_share_wrong_user" = "This game was opened from a different user.";
"lng_share_game_link_copied" = "Game link copied to clipboard."; "lng_share_game_link_copied" = "Game link copied to clipboard.";
"lng_share_done" = "Done!"; "lng_share_done" = "Done!";
"lng_share_message_to_saved_messages" = "Message forwarded to **Saved Messages**.";
"lng_share_messages_to_saved_messages" = "Messages forwarded to **Saved Messages**.";
"lng_share_message_to_chat" = "Message forwarded to **{chat}**.";
"lng_share_messages_to_chat" = "Messages forwarded to **{chat}**.";
"lng_share_message_to_two_chats" = "Message forwarded to **{user}** and **{chat}**.";
"lng_share_messages_to_two_chats" = "Messages forwarded to **{user}** and **{chat}**.";
"lng_share_message_to_many_chats#one" = "Message forwarded to **{count} chat**.";
"lng_share_message_to_many_chats#other" = "Message forwarded to **{count} chats**.";
"lng_share_messages_to_many_chats#one" = "Messages forwarded to **{count} chat**.";
"lng_share_messages_to_many_chats#other" = "Messages forwarded to **{count} chats**.";
"lng_contact_phone" = "Phone Number"; "lng_contact_phone" = "Phone Number";
"lng_enter_contact_data" = "New Contact"; "lng_enter_contact_data" = "New Contact";
@ -3294,6 +3336,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_audio_player_reverse" = "Reverse order"; "lng_audio_player_reverse" = "Reverse order";
"lng_audio_player_shuffle" = "Shuffle"; "lng_audio_player_shuffle" = "Shuffle";
"lng_audio_transcribe_long" = "This voice message is too long."; "lng_audio_transcribe_long" = "This voice message is too long.";
"lng_audio_transcribe_trials_left#one" = "You have {count} free transcription left until {date}.";
"lng_audio_transcribe_trials_left#other" = "You have {count} free transcriptions left until {date}.";
"lng_audio_transcribe_trials_over" = "You have used all your free transcriptions this week. Wait until {date} to use it again or subscribe to {link} now.";
"lng_rights_edit_admin" = "Manage permissions"; "lng_rights_edit_admin" = "Manage permissions";
"lng_rights_edit_admin_header" = "What can this admin do?"; "lng_rights_edit_admin_header" = "What can this admin do?";
@ -4096,6 +4141,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_view_button_request_join" = "Request to Join"; "lng_view_button_request_join" = "Request to Join";
"lng_view_button_external_link" = "Open link"; "lng_view_button_external_link" = "Open link";
"lng_view_button_boost" = "Boost"; "lng_view_button_boost" = "Boost";
"lng_view_button_giftcode" = "Open";
"lng_sponsored_hide_ads" = "Hide"; "lng_sponsored_hide_ads" = "Hide";
"lng_sponsored_title" = "What are sponsored messages?"; "lng_sponsored_title" = "What are sponsored messages?";
@ -4141,10 +4187,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_forum_topics_no_discussion" = "Topics can't be enabled in discussion groups at the moment."; "lng_forum_topics_no_discussion" = "Topics can't be enabled in discussion groups at the moment.";
"lng_forum_choose_title_and_icon" = "Choose title and icon for your topic"; "lng_forum_choose_title_and_icon" = "Choose title and icon for your topic";
"lng_forum_replies_only" = "You can reply to messages in topics."; "lng_forum_replies_only" = "You can reply to messages in topics.";
"lng_forum_message_in" = "Message in {topic}";
"lng_forum_reply_in" = "Reply in {topic}";
"lng_forum_no_topics" = "No topics currently created in this forum."; "lng_forum_no_topics" = "No topics currently created in this forum.";
"lng_forum_create_topic" = "Create topic"; "lng_forum_create_topic" = "Create topic";
"lng_forum_discard_sure" = "Are you sure you want to discard this topic?"; "lng_forum_discard_sure" = "Are you sure you want to discard this topic?";
"lng_forum_view_as_messages" = "View as Messages"; "lng_forum_view_as_messages" = "View as Messages";
"lng_forum_view_as_topics" = "View as Topics";
"lng_forum_no_messages" = "No messages"; "lng_forum_no_messages" = "No messages";
"lng_forum_messages#one" = "{count} message"; "lng_forum_messages#one" = "{count} message";
"lng_forum_messages#other" = "{count} messages"; "lng_forum_messages#other" = "{count} messages";
@ -4286,12 +4335,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stats_title" = "Statistics"; "lng_stats_title" = "Statistics";
"lng_stats_message_title" = "Message Statistic"; "lng_stats_message_title" = "Message Statistic";
"lng_stats_story_title" = "Story Statistic";
"lng_stats_zoom_out" = "Zoom Out"; "lng_stats_zoom_out" = "Zoom Out";
"lng_stats_day_month_year" = "{days_count} {month} {year}";
"lng_stats_day_month" = "{days_count} {month}";
"lng_stats_weekday_day_month_year" = "{day}, {days_count} {month} {year}";
"lng_stats_weekday_day_month_time" = "{day}, {days_count} {month} {time}";
"lng_stats_overview_title" = "Overview"; "lng_stats_overview_title" = "Overview";
"lng_stats_overview_member_count" = "Followers"; "lng_stats_overview_member_count" = "Followers";
"lng_stats_overview_mean_view_count" = "Views Per Post"; "lng_stats_overview_mean_view_count" = "Views Per Post";
"lng_stats_overview_mean_share_count" = "Shared Per Post"; "lng_stats_overview_mean_share_count" = "Shared Per Post";
"lng_stats_overview_mean_reactions_count" = "Reactions Per Post";
"lng_stats_overview_mean_story_view_count" = "Views Per Story";
"lng_stats_overview_mean_story_share_count" = "Shared Per Story";
"lng_stats_overview_mean_story_reactions_count" = "Reactions Per Story";
"lng_stats_overview_enabled_notifications" = "Enabled Notifications"; "lng_stats_overview_enabled_notifications" = "Enabled Notifications";
"lng_stats_overview_messages" = "Messages"; "lng_stats_overview_messages" = "Messages";
"lng_stats_overview_group_mean_view_count" = "Viewing Members"; "lng_stats_overview_group_mean_view_count" = "Viewing Members";
@ -4321,8 +4380,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stats_recent_messages_title" = "Recent posts"; "lng_stats_recent_messages_title" = "Recent posts";
"lng_stats_recent_messages_views#one" = "{count} view"; "lng_stats_recent_messages_views#one" = "{count} view";
"lng_stats_recent_messages_views#other" = "{count} views"; "lng_stats_recent_messages_views#other" = "{count} views";
"lng_stats_recent_messages_shares#one" = "{count} share";
"lng_stats_recent_messages_shares#other" = "{count} shares";
"lng_stats_loading" = "Loading stats..."; "lng_stats_loading" = "Loading stats...";
"lng_stats_loading_subtext" = "Please wait a few moments while we generate your stats."; "lng_stats_loading_subtext" = "Please wait a few moments while we generate your stats.";
@ -4336,6 +4393,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_chart_title_language" = "Languages"; "lng_chart_title_language" = "Languages";
"lng_chart_title_message_interaction" = "Interactions"; "lng_chart_title_message_interaction" = "Interactions";
"lng_chart_title_instant_view_interaction" = "IV Interactions"; "lng_chart_title_instant_view_interaction" = "IV Interactions";
"lng_chart_title_reactions_by_emotion" = "Reactions";
"lng_chart_title_story_interactions" = "Story Interactions";
"lng_chart_title_story_reactions_by_emotion" = "Story reactions";
"lng_chart_title_group_join" = "Group members"; "lng_chart_title_group_join" = "Group members";
"lng_chart_title_group_join_by_source" = "New members by source"; "lng_chart_title_group_join_by_source" = "New members by source";

View file

@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.11.7.0" /> Version="4.12.2.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName> <PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,11,7,0 FILEVERSION 4,12,2,0
PRODUCTVERSION 4,11,7,0 PRODUCTVERSION 4,12,2,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop" VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "4.11.7.0" VALUE "FileVersion", "4.12.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.11.7.0" VALUE "ProductVersion", "4.12.2.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,11,7,0 FILEVERSION 4,12,2,0
PRODUCTVERSION 4,11,7,0 PRODUCTVERSION 4,12,2,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater" VALUE "FileDescription", "AyuGram Desktop Updater"
VALUE "FileVersion", "4.11.7.0" VALUE "FileVersion", "4.12.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.11.7.0" VALUE "ProductVersion", "4.12.2.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -20,12 +20,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h" #include "history/history.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/controls/filter_link_header.h" #include "ui/controls/filter_link_header.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/filter_icons.h" #include "ui/filter_icons.h"
#include "ui/vertical_list.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_filter_icons.h" #include "styles/style_filter_icons.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -341,7 +341,7 @@ void ToggleChatsController::setupAboveWidget() {
_addedTopWidget = container->add(object_ptr<Ui::RpWidget>(container)); _addedTopWidget = container->add(object_ptr<Ui::RpWidget>(container));
const auto realAbove = container->add( const auto realAbove = container->add(
object_ptr<Ui::VerticalLayout>(container)); object_ptr<Ui::VerticalLayout>(container));
AddDivider(realAbove); Ui::AddDivider(realAbove);
const auto totalCount = [&] { const auto totalCount = [&] {
if (_chats.empty()) { if (_chats.empty()) {
return _additional.size(); return _additional.size();
@ -422,7 +422,7 @@ void ToggleChatsController::setupBelowWidget() {
auto widget = object_ptr<Ui::DividerLabel>( auto widget = object_ptr<Ui::DividerLabel>(
(QWidget*)nullptr, (QWidget*)nullptr,
std::move(layout), std::move(layout),
st::settingsDividerLabelPadding); st::defaultBoxDividerLabelPadding);
raw->add(object_ptr<Ui::FlatLabel>( raw->add(object_ptr<Ui::FlatLabel>(
raw, raw,
(_action == ToggleAction::Removing (_action == ToggleAction::Removing

View file

@ -211,6 +211,29 @@ void ApplyBotsList(
Data::PeerUpdate::Flag::FullInfo); Data::PeerUpdate::Flag::FullInfo);
} }
[[nodiscard]] ChatParticipants::Channels ParseSimilar(
not_null<ChannelData*> channel,
const MTPmessages_Chats &chats) {
auto result = ChatParticipants::Channels();
std::vector<not_null<ChannelData*>>();
chats.match([&](const auto &data) {
const auto &list = data.vchats().v;
result.list.reserve(list.size());
for (const auto &chat : list) {
const auto peer = channel->owner().processChat(chat);
if (const auto channel = peer->asChannel()) {
result.list.push_back(channel);
}
}
if constexpr (MTPDmessages_chatsSlice::Is<decltype(data)>()) {
if (channel->session().premiumPossible()) {
result.more = data.vcount().v - data.vchats().v.size();
}
}
});
return result;
}
} // namespace } // namespace
ChatParticipant::ChatParticipant( ChatParticipant::ChatParticipant(
@ -685,4 +708,50 @@ void ChatParticipants::unblock(
_kickRequests.emplace(kick, requestId); _kickRequests.emplace(kick, requestId);
} }
void ChatParticipants::loadSimilarChannels(not_null<ChannelData*> channel) {
if (!channel->isBroadcast()) {
return;
} else if (const auto i = _similar.find(channel); i != end(_similar)) {
if (i->second.requestId
|| !i->second.channels.more
|| !channel->session().premium()) {
return;
}
}
_similar[channel].requestId = _api.request(
MTPchannels_GetChannelRecommendations(channel->inputChannel)
).done([=](const MTPmessages_Chats &result) {
auto &similar = _similar[channel];
similar.requestId = 0;
auto parsed = ParseSimilar(channel, result);
if (similar.channels == parsed) {
return;
}
similar.channels = std::move(parsed);
if (const auto history = channel->owner().historyLoaded(channel)) {
if (const auto item = history->joinedMessageInstance()) {
history->owner().requestItemResize(item);
}
}
_similarLoaded.fire_copy(channel);
}).send();
}
auto ChatParticipants::similar(not_null<ChannelData*> channel)
-> const Channels & {
const auto i = channel->isBroadcast()
? _similar.find(channel)
: end(_similar);
if (i != end(_similar)) {
return i->second.channels;
}
static const auto empty = Channels();
return empty;
}
auto ChatParticipants::similarLoaded() const
-> rpl::producer<not_null<ChannelData*>> {
return _similarLoaded.events();
}
} // namespace Api } // namespace Api

View file

@ -120,7 +120,26 @@ public:
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<PeerData*> participant); not_null<PeerData*> participant);
void loadSimilarChannels(not_null<ChannelData*> channel);
struct Channels {
std::vector<not_null<ChannelData*>> list;
int more = 0;
friend inline bool operator==(
const Channels &,
const Channels &) = default;
};
[[nodiscard]] const Channels &similar(not_null<ChannelData*> channel);
[[nodiscard]] auto similarLoaded() const
-> rpl::producer<not_null<ChannelData*>>;
private: private:
struct SimilarChannels {
Channels channels;
mtpRequestId requestId = 0;
};
MTP::Sender _api; MTP::Sender _api;
using PeerRequests = base::flat_map<PeerData*, mtpRequestId>; using PeerRequests = base::flat_map<PeerData*, mtpRequestId>;
@ -143,6 +162,9 @@ private:
not_null<PeerData*>>; not_null<PeerData*>>;
base::flat_map<KickRequest, mtpRequestId> _kickRequests; base::flat_map<KickRequest, mtpRequestId> _kickRequests;
base::flat_map<not_null<ChannelData*>, SimilarChannels> _similar;
rpl::event_stream<not_null<ChannelData*>> _similarLoaded;
}; };
} // namespace Api } // namespace Api

View file

@ -0,0 +1,126 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "api/api_peer_colors.h"
#include "apiwrap.h"
#include "ui/chat/chat_style.h"
namespace Api {
namespace {
constexpr auto kRequestEach = 3600 * crl::time(1000);
} // namespace
PeerColors::PeerColors(not_null<ApiWrap*> api)
: _api(&api->instance())
, _timer([=] { request(); }) {
request();
_timer.callEach(kRequestEach);
}
PeerColors::~PeerColors() = default;
void PeerColors::request() {
if (_requestId) {
return;
}
_requestId = _api.request(MTPhelp_GetPeerColors(
MTP_int(_hash)
)).done([=](const MTPhelp_PeerColors &result) {
_requestId = 0;
result.match([&](const MTPDhelp_peerColors &data) {
_hash = data.vhash().v;
apply(data);
}, [](const MTPDhelp_peerColorsNotModified &) {
});
}).fail([=] {
_requestId = 0;
}).send();
}
std::vector<uint8> PeerColors::suggested() const {
return _suggested.current();
}
rpl::producer<std::vector<uint8>> PeerColors::suggestedValue() const {
return _suggested.value();
}
auto PeerColors::indicesValue() const
-> rpl::producer<Ui::ColorIndicesCompressed> {
return rpl::single(_colorIndicesCurrent
? *_colorIndicesCurrent
: Ui::ColorIndicesCompressed()
) | rpl::then(_colorIndicesChanged.events() | rpl::map([=] {
return *_colorIndicesCurrent;
}));
}
void PeerColors::apply(const MTPDhelp_peerColors &data) {
auto suggested = std::vector<uint8>();
auto colors = std::make_shared<
std::array<Ui::ColorIndexData, Ui::kColorIndexCount>>();
using ParsedColor = std::array<uint32, Ui::kColorPatternsCount>;
const auto parseColors = [](const MTPhelp_PeerColorSet &set) {
return set.match([&](const MTPDhelp_peerColorSet &data) {
auto result = ParsedColor();
const auto &list = data.vcolors().v;
if (list.empty() || list.size() > Ui::kColorPatternsCount) {
LOG(("API Error: Bad count for PeerColorSet.colors: %1"
).arg(list.size()));
return ParsedColor();
}
auto fill = result.data();
for (const auto &color : list) {
*fill++ = (uint32(1) << 24) | uint32(color.v);
}
return result;
}, [](const MTPDhelp_peerColorProfileSet &) {
LOG(("API Error: peerColorProfileSet in colors result!"));
return ParsedColor();
});
};
const auto &list = data.vcolors().v;
suggested.reserve(list.size());
for (const auto &color : list) {
const auto &data = color.data();
const auto colorIndexBare = data.vcolor_id().v;
if (colorIndexBare < 0 || colorIndexBare >= Ui::kColorIndexCount) {
LOG(("API Error: Bad color index: %1").arg(colorIndexBare));
continue;
}
const auto colorIndex = uint8(colorIndexBare);
if (!data.is_hidden()) {
suggested.push_back(colorIndex);
}
if (const auto light = data.vcolors()) {
auto &fields = (*colors)[colorIndex];
fields.light = parseColors(*light);
if (const auto dark = data.vdark_colors()) {
fields.dark = parseColors(*dark);
} else {
fields.dark = fields.light;
}
}
}
if (!_colorIndicesCurrent) {
_colorIndicesCurrent = std::make_unique<Ui::ColorIndicesCompressed>(
Ui::ColorIndicesCompressed{ std::move(colors) });
_colorIndicesChanged.fire({});
} else if (*_colorIndicesCurrent->colors != *colors) {
_colorIndicesCurrent->colors = std::move(colors);
_colorIndicesChanged.fire({});
}
_suggested = std::move(suggested);
}
} // namespace Api

View file

@ -0,0 +1,46 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/timer.h"
#include "mtproto/sender.h"
class ApiWrap;
namespace Ui {
struct ColorIndicesCompressed;
} // namespace Ui
namespace Api {
class PeerColors final {
public:
explicit PeerColors(not_null<ApiWrap*> api);
~PeerColors();
[[nodiscard]] std::vector<uint8> suggested() const;
[[nodiscard]] rpl::producer<std::vector<uint8>> suggestedValue() const;
[[nodiscard]] auto indicesValue() const
-> rpl::producer<Ui::ColorIndicesCompressed>;
private:
void request();
void apply(const MTPDhelp_peerColors &data);
MTP::Sender _api;
int32 _hash = 0;
mtpRequestId _requestId = 0;
base::Timer _timer;
rpl::variable<std::vector<uint8>> _suggested;
rpl::event_stream<> _colorIndicesChanged;
std::unique_ptr<Ui::ColorIndicesCompressed> _colorIndicesCurrent;
};
} // namespace Api

View file

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_peer.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/history.h" #include "history/history.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -62,15 +61,25 @@ constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
tlUnmuted.vpart().v / tlUnmuted.vtotal().v * 100., tlUnmuted.vpart().v / tlUnmuted.vtotal().v * 100.,
0., 0.,
100.); 100.);
using Recent = MTPMessageInteractionCounters; using Recent = MTPPostInteractionCounters;
auto recentMessages = ranges::views::all( auto recentMessages = ranges::views::all(
data.vrecent_message_interactions().v data.vrecent_posts_interactions().v
) | ranges::views::transform([&](const Recent &tl) { ) | ranges::views::transform([&](const Recent &tl) {
return Data::StatisticsMessageInteractionInfo{ return tl.match([&](const MTPDpostInteractionCountersStory &data) {
.messageId = tl.data().vmsg_id().v, return Data::StatisticsMessageInteractionInfo{
.viewsCount = tl.data().vviews().v, .storyId = data.vstory_id().v,
.forwardsCount = tl.data().vforwards().v, .viewsCount = data.vviews().v,
}; .forwardsCount = data.vforwards().v,
.reactionsCount = data.vreactions().v,
};
}, [&](const MTPDpostInteractionCountersMessage &data) {
return Data::StatisticsMessageInteractionInfo{
.messageId = data.vmsg_id().v,
.viewsCount = data.vviews().v,
.forwardsCount = data.vforwards().v,
.reactionsCount = data.vreactions().v,
};
});
}) | ranges::to_vector; }) | ranges::to_vector;
return { return {
@ -80,6 +89,15 @@ constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
.memberCount = StatisticalValueFromTL(data.vfollowers()), .memberCount = StatisticalValueFromTL(data.vfollowers()),
.meanViewCount = StatisticalValueFromTL(data.vviews_per_post()), .meanViewCount = StatisticalValueFromTL(data.vviews_per_post()),
.meanShareCount = StatisticalValueFromTL(data.vshares_per_post()), .meanShareCount = StatisticalValueFromTL(data.vshares_per_post()),
.meanReactionCount = StatisticalValueFromTL(
data.vreactions_per_post()),
.meanStoryViewCount = StatisticalValueFromTL(
data.vviews_per_story()),
.meanStoryShareCount = StatisticalValueFromTL(
data.vshares_per_story()),
.meanStoryReactionCount = StatisticalValueFromTL(
data.vreactions_per_story()),
.enabledNotificationsPercentage = unmuted, .enabledNotificationsPercentage = unmuted,
@ -110,6 +128,15 @@ constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
.instantViewInteractionGraph = StatisticalGraphFromTL( .instantViewInteractionGraph = StatisticalGraphFromTL(
data.viv_interactions_graph()), data.viv_interactions_graph()),
.reactionsByEmotionGraph = StatisticalGraphFromTL(
data.vreactions_by_emotion_graph()),
.storyInteractionsGraph = StatisticalGraphFromTL(
data.vstory_interactions_graph()),
.storyReactionsByEmotionGraph = StatisticalGraphFromTL(
data.vstory_reactions_by_emotion_graph()),
.recentMessageInteractions = std::move(recentMessages), .recentMessageInteractions = std::move(recentMessages),
}; };
} }
@ -324,7 +351,7 @@ Data::SupergroupStatistics Statistics::supergroupStats() const {
PublicForwards::PublicForwards( PublicForwards::PublicForwards(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
FullMsgId fullId) Data::RecentPostId fullId)
: StatisticsRequestSender(channel) : StatisticsRequestSender(channel)
, _fullId(fullId) { , _fullId(fullId) {
} }
@ -332,9 +359,20 @@ PublicForwards::PublicForwards(
void PublicForwards::request( void PublicForwards::request(
const Data::PublicForwardsSlice::OffsetToken &token, const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done) { Fn<void(Data::PublicForwardsSlice)> done) {
if (_requestId) { if (!_requestId) {
return; if (_fullId.messageId) {
requestMessage(token, std::move(done));
} else if (_fullId.storyId) {
requestStory(token, std::move(done));
}
} }
}
void PublicForwards::requestMessage(
const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done) {
Expects(_fullId.messageId);
const auto offsetPeer = channel()->owner().peer(token.fullId.peer); const auto offsetPeer = channel()->owner().peer(token.fullId.peer);
const auto tlOffsetPeer = offsetPeer const auto tlOffsetPeer = offsetPeer
? offsetPeer->input ? offsetPeer->input
@ -342,13 +380,13 @@ void PublicForwards::request(
constexpr auto kLimit = tl::make_int(100); constexpr auto kLimit = tl::make_int(100);
_requestId = makeRequest(MTPstats_GetMessagePublicForwards( _requestId = makeRequest(MTPstats_GetMessagePublicForwards(
channel()->inputChannel, channel()->inputChannel,
MTP_int(_fullId.msg), MTP_int(_fullId.messageId.msg),
MTP_int(token.rate), MTP_int(token.rate),
tlOffsetPeer, tlOffsetPeer,
MTP_int(token.fullId.msg), MTP_int(token.fullId.msg),
kLimit kLimit
)).done([=, channel = channel()](const MTPmessages_Messages &result) { )).done([=, channel = channel()](const MTPmessages_Messages &result) {
using Messages = QVector<FullMsgId>; using Messages = QVector<Data::RecentPostId>;
_requestId = 0; _requestId = 0;
auto nextToken = Data::PublicForwardsSlice::OffsetToken(); auto nextToken = Data::PublicForwardsSlice::OffsetToken();
@ -365,7 +403,7 @@ void PublicForwards::request(
MessageFlags(), MessageFlags(),
NewMessageType::Existing); NewMessageType::Existing);
nextToken.fullId = { peerId, msgId }; nextToken.fullId = { peerId, msgId };
result.push_back(nextToken.fullId); result.push_back({ .messageId = nextToken.fullId });
} }
} }
} }
@ -420,14 +458,90 @@ void PublicForwards::request(
}).send(); }).send();
} }
void PublicForwards::requestStory(
const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done) {
Expects(_fullId.storyId);
constexpr auto kLimit = tl::make_int(100);
_requestId = makeRequest(MTPstats_GetStoryPublicForwards(
channel()->input,
MTP_int(_fullId.storyId.story),
MTP_string(token.storyOffset),
kLimit
)).done([=, channel = channel()](
const MTPstats_PublicForwards &tlForwards) {
using Messages = QVector<Data::RecentPostId>;
_requestId = 0;
const auto &data = tlForwards.data();
channel->owner().processUsers(data.vusers());
channel->owner().processChats(data.vchats());
const auto nextToken = Data::PublicForwardsSlice::OffsetToken({
.storyOffset = data.vnext_offset().value_or_empty(),
});
const auto allLoaded = nextToken.storyOffset.isEmpty()
|| (nextToken.storyOffset == token.storyOffset);
const auto fullCount = data.vcount().v;
auto recentList = Messages();
for (const auto &tlForward : data.vforwards().v) {
tlForward.match([&](const MTPDpublicForwardMessage &data) {
const auto &message = data.vmessage();
const auto msgId = IdFromMessage(message);
const auto peerId = PeerFromMessage(message);
const auto lastDate = DateFromMessage(message);
if (const auto peer = channel->owner().peerLoaded(peerId)) {
if (!lastDate) {
return;
}
channel->owner().addNewMessage(
message,
MessageFlags(),
NewMessageType::Existing);
recentList.push_back({ .messageId = { peerId, msgId } });
}
}, [&](const MTPDpublicForwardStory &data) {
data.vstory().match([&](const MTPDstoryItem &d) {
recentList.push_back({
.storyId = { peerFromMTP(data.vpeer()), d.vid().v }
});
}, [](const auto &) {
});
});
}
_lastTotal = std::max(_lastTotal, fullCount);
done({
.list = std::move(recentList),
.total = _lastTotal,
.allLoaded = allLoaded,
.token = nextToken,
});
}).fail([=] {
_requestId = 0;
}).send();
}
MessageStatistics::MessageStatistics( MessageStatistics::MessageStatistics(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
FullMsgId fullId) FullMsgId fullId)
: StatisticsRequestSender(channel) : StatisticsRequestSender(channel)
, _publicForwards(channel, fullId) , _publicForwards(channel, { .messageId = fullId })
, _fullId(fullId) { , _fullId(fullId) {
} }
MessageStatistics::MessageStatistics(
not_null<ChannelData*> channel,
FullStoryId storyId)
: StatisticsRequestSender(channel)
, _publicForwards(channel, { .storyId = storyId })
, _storyId(storyId) {
}
Data::PublicForwardsSlice MessageStatistics::firstSlice() const { Data::PublicForwardsSlice MessageStatistics::firstSlice() const {
return _firstSlice; return _firstSlice;
} }
@ -438,21 +552,26 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
} }
const auto requestFirstPublicForwards = [=]( const auto requestFirstPublicForwards = [=](
const Data::StatisticalGraph &messageGraph, const Data::StatisticalGraph &messageGraph,
const Data::StatisticalGraph &reactionsGraph,
const Data::StatisticsMessageInteractionInfo &info) { const Data::StatisticsMessageInteractionInfo &info) {
_publicForwards.request({}, [=](Data::PublicForwardsSlice slice) { const auto callback = [=](Data::PublicForwardsSlice slice) {
const auto total = slice.total; const auto total = slice.total;
_firstSlice = std::move(slice); _firstSlice = std::move(slice);
done({ done({
.messageInteractionGraph = messageGraph, .messageInteractionGraph = messageGraph,
.reactionsByEmotionGraph = reactionsGraph,
.publicForwards = total, .publicForwards = total,
.privateForwards = info.forwardsCount - total, .privateForwards = info.forwardsCount - total,
.views = info.viewsCount, .views = info.viewsCount,
.reactions = info.reactionsCount,
}); });
}); };
_publicForwards.request({}, callback);
}; };
const auto requestPrivateForwards = [=]( const auto requestPrivateForwards = [=](
const Data::StatisticalGraph &messageGraph) { const Data::StatisticalGraph &messageGraph,
const Data::StatisticalGraph &reactionsGraph) {
api().request(MTPchannels_GetMessages( api().request(MTPchannels_GetMessages(
channel()->inputChannel, channel()->inputChannel,
MTP_vector<MTPInputMessage>( MTP_vector<MTPInputMessage>(
@ -462,6 +581,13 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
const auto process = [&](const MTPVector<MTPMessage> &messages) { const auto process = [&](const MTPVector<MTPMessage> &messages) {
const auto &message = messages.v.front(); const auto &message = messages.v.front();
return message.match([&](const MTPDmessage &data) { return message.match([&](const MTPDmessage &data) {
auto reactionsCount = 0;
if (const auto tlReactions = data.vreactions()) {
const auto &tlCounts = tlReactions->data().vresults();
for (const auto &tlCount : tlCounts.v) {
reactionsCount += tlCount.data().vcount().v;
}
}
return Data::StatisticsMessageInteractionInfo{ return Data::StatisticsMessageInteractionInfo{
.messageId = IdFromMessage(message), .messageId = IdFromMessage(message),
.viewsCount = data.vviews() .viewsCount = data.vviews()
@ -470,6 +596,7 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
.forwardsCount = data.vforwards() .forwardsCount = data.vforwards()
? data.vforwards()->v ? data.vforwards()->v
: 0, : 0,
.reactionsCount = reactionsCount,
}; };
}, [](const MTPDmessageEmpty &) { }, [](const MTPDmessageEmpty &) {
return Data::StatisticsMessageInteractionInfo(); return Data::StatisticsMessageInteractionInfo();
@ -488,22 +615,74 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
return Data::StatisticsMessageInteractionInfo(); return Data::StatisticsMessageInteractionInfo();
}); });
requestFirstPublicForwards(messageGraph, std::move(info)); requestFirstPublicForwards(
messageGraph,
reactionsGraph,
std::move(info));
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
requestFirstPublicForwards(messageGraph, {}); requestFirstPublicForwards(messageGraph, reactionsGraph, {});
}).send(); }).send();
}; };
makeRequest(MTPstats_GetMessageStats( const auto requestStoryPrivateForwards = [=](
MTP_flags(MTPstats_GetMessageStats::Flags(0)), const Data::StatisticalGraph &messageGraph,
channel()->inputChannel, const Data::StatisticalGraph &reactionsGraph) {
MTP_int(_fullId.msg.bare) api().request(MTPstories_GetStoriesByID(
)).done([=](const MTPstats_MessageStats &result) { channel()->input,
requestPrivateForwards( MTP_vector<MTPint>(1, MTP_int(_storyId.story)))
StatisticalGraphFromTL(result.data().vviews_graph())); ).done([=](const MTPstories_Stories &result) {
}).fail([=](const MTP::Error &error) { const auto &storyItem = result.data().vstories().v.front();
requestPrivateForwards({}); auto info = storyItem.match([&](const MTPDstoryItem &data) {
}).send(); if (!data.vviews()) {
return Data::StatisticsMessageInteractionInfo();
}
const auto &tlViews = data.vviews()->data();
return Data::StatisticsMessageInteractionInfo{
.storyId = data.vid().v,
.viewsCount = tlViews.vviews_count().v,
.forwardsCount = tlViews.vforwards_count().value_or(0),
.reactionsCount = tlViews.vreactions_count().value_or(0),
};
}, [](const auto &) {
return Data::StatisticsMessageInteractionInfo();
});
requestFirstPublicForwards(
messageGraph,
reactionsGraph,
std::move(info));
}).fail([=](const MTP::Error &error) {
requestFirstPublicForwards(messageGraph, reactionsGraph, {});
}).send();
};
if (_storyId) {
makeRequest(MTPstats_GetStoryStats(
MTP_flags(MTPstats_GetStoryStats::Flags(0)),
channel()->input,
MTP_int(_storyId.story)
)).done([=](const MTPstats_StoryStats &result) {
const auto &data = result.data();
requestStoryPrivateForwards(
StatisticalGraphFromTL(data.vviews_graph()),
StatisticalGraphFromTL(data.vreactions_by_emotion_graph()));
}).fail([=](const MTP::Error &error) {
requestStoryPrivateForwards({}, {});
}).send();
} else {
makeRequest(MTPstats_GetMessageStats(
MTP_flags(MTPstats_GetMessageStats::Flags(0)),
channel()->inputChannel,
MTP_int(_fullId.msg.bare)
)).done([=](const MTPstats_MessageStats &result) {
const auto &data = result.data();
requestPrivateForwards(
StatisticalGraphFromTL(data.vviews_graph()),
StatisticalGraphFromTL(data.vreactions_by_emotion_graph()));
}).fail([=](const MTP::Error &error) {
requestPrivateForwards({}, {});
}).send();
}
} }
Boosts::Boosts(not_null<PeerData*> peer) Boosts::Boosts(not_null<PeerData*> peer)

View file

@ -68,14 +68,23 @@ private:
class PublicForwards final : public StatisticsRequestSender { class PublicForwards final : public StatisticsRequestSender {
public: public:
PublicForwards(not_null<ChannelData*> channel, FullMsgId fullId); PublicForwards(
not_null<ChannelData*> channel,
Data::RecentPostId fullId);
void request( void request(
const Data::PublicForwardsSlice::OffsetToken &token, const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done); Fn<void(Data::PublicForwardsSlice)> done);
private: private:
const FullMsgId _fullId; void requestMessage(
const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done);
void requestStory(
const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done);
const Data::RecentPostId _fullId;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
int _lastTotal = 0; int _lastTotal = 0;
@ -86,6 +95,9 @@ public:
explicit MessageStatistics( explicit MessageStatistics(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
FullMsgId fullId); FullMsgId fullId);
explicit MessageStatistics(
not_null<ChannelData*> channel,
FullStoryId storyId);
void request(Fn<void(Data::MessageStatistics)> done); void request(Fn<void(Data::MessageStatistics)> done);
@ -94,6 +106,7 @@ public:
private: private:
PublicForwards _publicForwards; PublicForwards _publicForwards;
const FullMsgId _fullId; const FullMsgId _fullId;
const FullStoryId _storyId;
Data::PublicForwardsSlice _firstSlice; Data::PublicForwardsSlice _firstSlice;

View file

@ -7,13 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "api/api_transcribes.h" #include "api/api_transcribes.h"
#include "history/history_item.h"
#include "history/history.h"
#include "main/main_session.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_peer.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "data/data_document.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
namespace Api { namespace Api {
@ -22,6 +25,44 @@ Transcribes::Transcribes(not_null<ApiWrap*> api)
, _api(&api->instance()) { , _api(&api->instance()) {
} }
bool Transcribes::trialsSupport() {
if (!_trialsSupport) {
const auto count = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_weekly_number"_q,
0);
const auto until = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_cooldown_until"_q,
0);
_trialsSupport = (count > 0) || (until > 0);
}
return *_trialsSupport;
}
TimeId Transcribes::trialsRefreshAt() {
if (_trialsRefreshAt < 0) {
_trialsRefreshAt = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_cooldown_until"_q,
0);
}
return _trialsRefreshAt;
}
int Transcribes::trialsCount() {
if (_trialsCount < 0) {
_trialsCount = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_weekly_number"_q,
-1);
return std::max(_trialsCount, 0);
}
return _trialsCount;
}
crl::time Transcribes::trialsMaxLengthMs() const {
return 1000 * _session->account().appConfig().get<int>(
u"transcribe_audio_trial_duration_max"_q,
300);
}
void Transcribes::toggle(not_null<HistoryItem*> item) { void Transcribes::toggle(not_null<HistoryItem*> item) {
const auto id = item->fullId(); const auto id = item->fullId();
auto i = _map.find(id); auto i = _map.find(id);
@ -86,6 +127,23 @@ void Transcribes::load(not_null<HistoryItem*> item) {
MTP_int(item->id) MTP_int(item->id)
)).done([=](const MTPmessages_TranscribedAudio &result) { )).done([=](const MTPmessages_TranscribedAudio &result) {
const auto &data = result.data(); const auto &data = result.data();
{
const auto trialsCountChanged = data.vtrial_remains_num()
&& (_trialsCount != data.vtrial_remains_num()->v);
if (trialsCountChanged) {
_trialsCount = data.vtrial_remains_num()->v;
}
const auto refreshAtChanged = data.vtrial_remains_until_date()
&& (_trialsRefreshAt != data.vtrial_remains_until_date()->v);
if (refreshAtChanged) {
_trialsRefreshAt = data.vtrial_remains_until_date()->v;
}
if (trialsCountChanged) {
ShowTrialTranscribesToast(_trialsCount, _trialsRefreshAt);
}
}
auto &entry = _map[id]; auto &entry = _map[id];
entry.requestId = 0; entry.requestId = 0;
entry.pending = data.is_pending(); entry.pending = data.is_pending();

View file

@ -36,12 +36,21 @@ public:
void apply(const MTPDupdateTranscribedAudio &update); void apply(const MTPDupdateTranscribedAudio &update);
[[nodiscard]] bool trialsSupport();
[[nodiscard]] TimeId trialsRefreshAt();
[[nodiscard]] int trialsCount();
[[nodiscard]] crl::time trialsMaxLengthMs() const;
private: private:
void load(not_null<HistoryItem*> item); void load(not_null<HistoryItem*> item);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
MTP::Sender _api; MTP::Sender _api;
int _trialsCount = -1;
std::optional<bool> _trialsSupport;
TimeId _trialsRefreshAt = -1;
base::flat_map<FullMsgId, Entry> _map; base::flat_map<FullMsgId, Entry> _map;
base::flat_map<uint64, FullMsgId> _ids; base::flat_map<uint64, FullMsgId> _ids;

View file

@ -2023,6 +2023,19 @@ void Updates::feedUpdate(const MTPUpdate &update) {
} }
} break; } break;
case mtpc_updatePeerWallpaper: {
const auto &d = update.c_updatePeerWallpaper();
if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) {
if (const auto paper = d.vwallpaper()) {
peer->setWallPaper(
Data::WallPaper::Create(&session(), *paper),
d.is_wallpaper_overridden());
} else {
peer->setWallPaper({});
}
}
} break;
case mtpc_updateBotCommands: { case mtpc_updateBotCommands: {
const auto &d = update.c_updateBotCommands(); const auto &d = update.c_updateBotCommands();
if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) { if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) {
@ -2358,6 +2371,14 @@ void Updates::feedUpdate(const MTPUpdate &update) {
} }
} break; } break;
case mtpc_updateChannelViewForumAsMessages: {
const auto &d = update.c_updateChannelViewForumAsMessages();
const auto id = ChannelId(d.vchannel_id());
if (const auto channel = session().data().channelLoaded(id)) {
channel->setViewAsMessagesFlag(mtpIsTrue(d.venabled()));
}
} break;
// Pinned message. // Pinned message.
case mtpc_updatePinnedMessages: { case mtpc_updatePinnedMessages: {
const auto &d = update.c_updatePinnedMessages(); const auto &d = update.c_updatePinnedMessages();

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_hash.h" #include "api/api_hash.h"
#include "api/api_invite_links.h" #include "api/api_invite_links.h"
#include "api/api_media.h" #include "api/api_media.h"
#include "api/api_peer_colors.h"
#include "api/api_peer_photo.h" #include "api/api_peer_photo.h"
#include "api/api_polls.h" #include "api/api_polls.h"
#include "api/api_sending.h" #include "api/api_sending.h"
@ -33,50 +34,35 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_user_names.h" #include "api/api_user_names.h"
#include "api/api_websites.h" #include "api/api_websites.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_photo.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_media_types.h"
#include "data/data_sparse_ids.h"
#include "data/data_search_controller.h" #include "data/data_search_controller.h"
#include "data/data_scheduled_messages.h" #include "data/data_scheduled_messages.h"
#include "data/data_channel_admins.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_stories.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_cloud_themes.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_wall_paper.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/dialogs_key.h"
#include "core/core_cloud_password.h" #include "core/core_cloud_password.h"
#include "core/application.h" #include "core/application.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/random.h" #include "base/random.h"
#include "base/qt/qt_common_adapters.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "mtproto/mtproto_config.h" #include "mtproto/mtproto_config.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/history_item_helpers.h" #include "history/history_item_helpers.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_session_settings.h" #include "main/main_session_settings.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "boxes/stickers_box.h"
#include "boxes/sticker_set_box.h" #include "boxes/sticker_set_box.h"
#include "boxes/premium_limits_box.h" #include "boxes/premium_limits_box.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
@ -87,7 +73,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "ui/item_text_options.h" #include "ui/item_text_options.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/emoji_config.h"
#include "ui/chat/attach/attach_prepare.h" #include "ui/chat/attach/attach_prepare.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "support/support_helper.h" #include "support/support_helper.h"
@ -95,9 +80,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "storage/download_manager_mtproto.h" #include "storage/download_manager_mtproto.h"
#include "storage/file_upload.h" #include "storage/file_upload.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "storage/storage_media_prepare.h"
#include "storage/storage_account.h" #include "storage/storage_account.h"
// AyuGram includes // AyuGram includes
@ -151,6 +133,15 @@ void ShowChannelsLimitBox(not_null<PeerData*> peer) {
} }
} }
[[nodiscard]] FileLoadTo FileLoadTaskOptions(const Api::SendAction &action) {
const auto peer = action.history->peer;
return FileLoadTo(
peer->id,
action.options,
action.replyTo,
action.replaceMediaOf);
}
} // namespace } // namespace
ApiWrap::ApiWrap(not_null<Main::Session*> session) ApiWrap::ApiWrap(not_null<Main::Session*> session)
@ -184,7 +175,8 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
, _transcribes(std::make_unique<Api::Transcribes>(this)) , _transcribes(std::make_unique<Api::Transcribes>(this))
, _premium(std::make_unique<Api::Premium>(this)) , _premium(std::make_unique<Api::Premium>(this))
, _usernames(std::make_unique<Api::Usernames>(this)) , _usernames(std::make_unique<Api::Usernames>(this))
, _websites(std::make_unique<Api::Websites>(this)) { , _websites(std::make_unique<Api::Websites>(this))
, _peerColors(std::make_unique<Api::PeerColors>(this)) {
crl::on_main(session, [=] { crl::on_main(session, [=] {
// You can't use _session->lifetime() in the constructor, // You can't use _session->lifetime() in the constructor,
// only queued, because it is not constructed yet. // only queued, because it is not constructed yet.
@ -1754,6 +1746,10 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
}).send(); }).send();
_channelAmInRequests.emplace(channel, requestId); _channelAmInRequests.emplace(channel, requestId);
using Flag = ChannelDataFlag;
chatParticipants().loadSimilarChannels(channel);
channel->setFlags(channel->flags() | Flag::SimilarExpanded);
} }
} }
@ -2070,13 +2066,13 @@ void ApiWrap::deleteHistory(
void ApiWrap::applyUpdates( void ApiWrap::applyUpdates(
const MTPUpdates &updates, const MTPUpdates &updates,
uint64 sentMessageRandomId) { uint64 sentMessageRandomId) const {
this->updates().applyUpdates(updates, sentMessageRandomId); this->updates().applyUpdates(updates, sentMessageRandomId);
} }
int ApiWrap::applyAffectedHistory( int ApiWrap::applyAffectedHistory(
PeerData *peer, PeerData *peer,
const MTPmessages_AffectedHistory &result) { const MTPmessages_AffectedHistory &result) const {
const auto &data = result.c_messages_affectedHistory(); const auto &data = result.c_messages_affectedHistory();
if (const auto channel = peer ? peer->asChannel() : nullptr) { if (const auto channel = peer ? peer->asChannel() : nullptr) {
channel->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v); channel->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v);
@ -2098,7 +2094,7 @@ void ApiWrap::applyAffectedMessages(
} }
void ApiWrap::applyAffectedMessages( void ApiWrap::applyAffectedMessages(
const MTPmessages_AffectedMessages &result) { const MTPmessages_AffectedMessages &result) const {
const auto &data = result.c_messages_affectedMessages(); const auto &data = result.c_messages_affectedMessages();
updates().updateAndApply(data.vpts().v, data.vpts_count().v); updates().updateAndApply(data.vpts().v, data.vpts_count().v);
} }
@ -2557,8 +2553,8 @@ void ApiWrap::refreshFileReference(
request(MTPhelp_GetPremiumPromo()); request(MTPhelp_GetPremiumPromo());
}, [&](Data::FileOriginStory data) { }, [&](Data::FileOriginStory data) {
request(MTPstories_GetStoriesByID( request(MTPstories_GetStoriesByID(
_session->data().peer(data.peerId)->input, _session->data().peer(data.peer)->input,
MTP_vector<MTPint>(1, MTP_int(data.storyId)))); MTP_vector<MTPint>(1, MTP_int(data.story))));
}, [&](v::null_t) { }, [&](v::null_t) {
fail(); fail();
}); });
@ -3444,7 +3440,7 @@ void ApiWrap::sendVoiceMessage(
crl::time duration, crl::time duration,
const SendAction &action) { const SendAction &action) {
const auto caption = TextWithTags(); const auto caption = TextWithTags();
const auto to = fileLoadTaskOptions(action); const auto to = FileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>( _fileLoader->addTask(std::make_unique<FileLoadTask>(
&session(), &session(),
result, result,
@ -3462,7 +3458,7 @@ void ApiWrap::editMedia(
if (list.files.empty()) return; if (list.files.empty()) return;
auto &file = list.files.front(); auto &file = list.files.front();
const auto to = fileLoadTaskOptions(action); const auto to = FileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>( _fileLoader->addTask(std::make_unique<FileLoadTask>(
&session(), &session(),
file.path, file.path,
@ -3491,7 +3487,7 @@ void ApiWrap::sendFiles(
sendMessage(std::move(message)); sendMessage(std::move(message));
} }
const auto to = fileLoadTaskOptions(action); const auto to = FileLoadTaskOptions(action);
if (album) { if (album) {
album->options = to.options; album->options = to.options;
} }
@ -3530,7 +3526,7 @@ void ApiWrap::sendFile(
const QByteArray &fileContent, const QByteArray &fileContent,
SendMediaType type, SendMediaType type,
const SendAction &action) { const SendAction &action) {
const auto to = fileLoadTaskOptions(action); const auto to = FileLoadTaskOptions(action);
auto caption = TextWithTags(); auto caption = TextWithTags();
const auto spoiler = false; const auto spoiler = false;
const auto information = nullptr; const auto information = nullptr;
@ -4227,15 +4223,6 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
}); });
} }
FileLoadTo ApiWrap::fileLoadTaskOptions(const SendAction &action) const {
const auto peer = action.history->peer;
return FileLoadTo(
peer->id,
action.options,
action.replyTo,
action.replaceMediaOf);
}
void ApiWrap::reloadContactSignupSilent() { void ApiWrap::reloadContactSignupSilent() {
if (_contactSignupSilentRequestId) { if (_contactSignupSilentRequestId) {
return; return;
@ -4451,3 +4438,7 @@ Api::Usernames &ApiWrap::usernames() {
Api::Websites &ApiWrap::websites() { Api::Websites &ApiWrap::websites() {
return *_websites; return *_websites;
} }
Api::PeerColors &ApiWrap::peerColors() {
return *_peerColors;
}

View file

@ -9,8 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_common.h" #include "api/api_common.h"
#include "base/timer.h" #include "base/timer.h"
#include "base/flat_map.h"
#include "base/flat_set.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "data/stickers/data_stickers_set.h" #include "data/stickers/data_stickers_set.h"
#include "data/data_messages.h" #include "data/data_messages.h"
@ -73,6 +71,7 @@ class InviteLinks;
class ViewsManager; class ViewsManager;
class ConfirmPhone; class ConfirmPhone;
class PeerPhoto; class PeerPhoto;
class PeerColors;
class Polls; class Polls;
class ChatParticipants; class ChatParticipants;
class UnreadThings; class UnreadThings;
@ -141,10 +140,10 @@ public:
void applyUpdates( void applyUpdates(
const MTPUpdates &updates, const MTPUpdates &updates,
uint64 sentMessageRandomId = 0); uint64 sentMessageRandomId = 0) const;
int applyAffectedHistory( int applyAffectedHistory(
PeerData *peer, // May be nullptr, like for deletePhoneCallHistory. PeerData *peer, // May be nullptr, like for deletePhoneCallHistory.
const MTPmessages_AffectedHistory &result); const MTPmessages_AffectedHistory &result) const;
void registerModifyRequest(const QString &key, mtpRequestId requestId); void registerModifyRequest(const QString &key, mtpRequestId requestId);
void clearModifyRequest(const QString &key); void clearModifyRequest(const QString &key);
@ -392,6 +391,7 @@ public:
[[nodiscard]] Api::Premium &premium(); [[nodiscard]] Api::Premium &premium();
[[nodiscard]] Api::Usernames &usernames(); [[nodiscard]] Api::Usernames &usernames();
[[nodiscard]] Api::Websites &websites(); [[nodiscard]] Api::Websites &websites();
[[nodiscard]] Api::PeerColors &peerColors();
void updatePrivacyLastSeens(); void updatePrivacyLastSeens();
@ -503,7 +503,7 @@ private:
not_null<PeerData*> peer, not_null<PeerData*> peer,
bool justClear, bool justClear,
bool revoke); bool revoke);
void applyAffectedMessages(const MTPmessages_AffectedMessages &result); void applyAffectedMessages(const MTPmessages_AffectedMessages &result) const;
void deleteAllFromParticipantSend( void deleteAllFromParticipantSend(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
@ -532,7 +532,6 @@ private:
Api::SendOptions options, Api::SendOptions options,
uint64 randomId, uint64 randomId,
Fn<void(bool)> done = nullptr); Fn<void(bool)> done = nullptr);
FileLoadTo fileLoadTaskOptions(const SendAction &action) const;
void getTopPromotionDelayed(TimeId now, TimeId next); void getTopPromotionDelayed(TimeId now, TimeId next);
void topPromotionDone(const MTPhelp_PromoData &proxy); void topPromotionDone(const MTPhelp_PromoData &proxy);
@ -711,6 +710,7 @@ private:
const std::unique_ptr<Api::Premium> _premium; const std::unique_ptr<Api::Premium> _premium;
const std::unique_ptr<Api::Usernames> _usernames; const std::unique_ptr<Api::Usernames> _usernames;
const std::unique_ptr<Api::Websites> _websites; const std::unique_ptr<Api::Websites> _websites;
const std::unique_ptr<Api::PeerColors> _peerColors;
mtpRequestId _wallPaperRequestId = 0; mtpRequestId _wallPaperRequestId = 0;
QString _wallPaperSlug; QString _wallPaperSlug;

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
namespace Ui { namespace Ui {
class LinkButton; class LinkButton;

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "base/random.h" #include "base/random.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "boxes/abstract_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h" #include "boxes/premium_limits_box.h"
#include "boxes/peers/add_participants_box.h" #include "boxes/peers/add_participants_box.h"

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "base/timer.h" #include "base/timer.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h" #include "main/main_session_settings.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_auto_download.h" #include "data/data_auto_download.h"
#include "ui/vertical_list.h"
#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/continuous_sliders.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
@ -35,7 +36,6 @@ not_null<int64*> AddSizeLimitSlider(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
const base::flat_map<Type, int64> &values, const base::flat_map<Type, int64> &values,
int64 defaultValue) { int64 defaultValue) {
using namespace Settings;
using Pair = base::flat_map<Type, int64>::value_type; using Pair = base::flat_map<Type, int64>::value_type;
const auto limits = Ui::CreateChild<rpl::event_stream<int64>>( const auto limits = Ui::CreateChild<rpl::event_stream<int64>>(
@ -46,7 +46,7 @@ not_null<int64*> AddSizeLimitSlider(
[](Pair pair) { return pair.second; })->second; [](Pair pair) { return pair.second; })->second;
const auto startLimit = currentLimit ? currentLimit : defaultValue; const auto startLimit = currentLimit ? currentLimit : defaultValue;
const auto result = Ui::CreateChild<int64>(container.get(), startLimit); const auto result = Ui::CreateChild<int64>(container.get(), startLimit);
AddButtonWithLabel( Settings::AddButtonWithLabel(
container, container,
tr::lng_media_size_limit(), tr::lng_media_size_limit(),
limits->events_starting_with_copy( limits->events_starting_with_copy(
@ -109,11 +109,11 @@ void AutoDownloadBox::setupContent() {
Type type, Type type,
rpl::producer<QString> label) { rpl::producer<QString> label) {
const auto value = settings->bytesLimit(_source, type); const auto value = settings->bytesLimit(_source, type);
AddButton( content->add(object_ptr<Ui::SettingsButton>(
content, content,
std::move(label), std::move(label),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( ))->toggleOn(
rpl::single(value > 0) rpl::single(value > 0)
)->toggledChanges( )->toggledChanges(
) | rpl::start_with_next([=](bool enabled) { ) | rpl::start_with_next([=](bool enabled) {

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
namespace Main { namespace Main {
class Session; class Session;

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
namespace Ui { namespace Ui {
class Radiobutton; class Radiobutton;

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/attach/attach_extensions.h" #include "ui/chat/attach/attach_extensions.h"
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "ui/vertical_list.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
@ -24,7 +25,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "boxes/background_preview_box.h" #include "boxes/background_preview_box.h"
#include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_icon.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -165,9 +165,9 @@ void BackgroundBox::prepare() {
auto wrap = object_ptr<Ui::VerticalLayout>(this); auto wrap = object_ptr<Ui::VerticalLayout>(this);
const auto container = wrap.data(); const auto container = wrap.data();
Settings::AddSkip(container); Ui::AddSkip(container);
const auto button = container->add(Settings::CreateButton( const auto button = container->add(object_ptr<Ui::SettingsButton>(
container, container,
tr::lng_settings_bg_from_file(), tr::lng_settings_bg_from_file(),
st::infoProfileButton)); st::infoProfileButton));
@ -180,8 +180,8 @@ void BackgroundBox::prepare() {
chooseFromFile(); chooseFromFile();
}); });
Settings::AddSkip(container); Ui::AddSkip(container);
Settings::AddDivider(container); Ui::AddDivider(container);
_inner = container->add( _inner = container->add(
object_ptr<Inner>(this, &_controller->session(), _forPeer)); object_ptr<Inner>(this, &_controller->session(), _forPeer));
@ -310,7 +310,7 @@ void BackgroundBox::resetForPeer() {
}).send(); }).send();
const auto weak = Ui::MakeWeak(this); const auto weak = Ui::MakeWeak(this);
_forPeer->setWallPaper(std::nullopt); _forPeer->setWallPaper({});
if (weak) { if (weak) {
_controller->finishChatThemeEdit(_forPeer); _controller->finishChatThemeEdit(_forPeer);
} }

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
class PeerData; class PeerData;

View file

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "boxes/background_preview_box.h" #include "boxes/background_preview_box.h"
#include "base/unixtime.h"
#include "boxes/premium_preview_box.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
@ -18,8 +20,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/continuous_sliders.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
@ -33,17 +37,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/data_document_resolver.h" #include "data/data_document_resolver.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "base/unixtime.h" #include "data/data_peer_values.h"
#include "boxes/background_preview_box.h" #include "settings/settings_premium.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
#include "settings/settings_common.h"
#include "storage/file_upload.h" #include "storage/file_upload.h"
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_settings.h"
#include <QtGui/QClipboard> #include <QtGui/QClipboard>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
@ -293,10 +295,10 @@ void BackgroundPreviewBox::createDimmingSlider(bool dark) {
const auto equals = (dark == Window::Theme::IsNightMode()); const auto equals = (dark == Window::Theme::IsNightMode());
const auto inner = Ui::CreateChild<Ui::VerticalLayout>(_dimmingContent); const auto inner = Ui::CreateChild<Ui::VerticalLayout>(_dimmingContent);
inner->show(); inner->show();
Settings::AddSubsectionTitle( Ui::AddSubsectionTitle(
inner, inner,
tr::lng_background_dimming(), tr::lng_background_dimming(),
style::margins(0, st::settingsSectionSkip, 0, 0), style::margins(0, st::defaultVerticalListSkip, 0, 0),
equals ? nullptr : dark ? &_dark->subtitle : &_light->subtitle); equals ? nullptr : dark ? &_dark->subtitle : &_light->subtitle);
_dimmingSlider = inner->add( _dimmingSlider = inner->add(
object_ptr<Ui::MediaSlider>( object_ptr<Ui::MediaSlider>(
@ -378,7 +380,7 @@ auto BackgroundPreviewBox::prepareOverridenStyle(bool dark)
.box = st::defaultBox, .box = st::defaultBox,
.toggle = toggle, .toggle = toggle,
.slider = st::defaultContinuousSlider, .slider = st::defaultContinuousSlider,
.subtitle = st::settingsSubsectionTitle, .subtitle = st::defaultSubsectionTitle,
}; };
result.box.button.textFg = p->lightButtonFg(); result.box.button.textFg = p->lightButtonFg();
result.box.button.textFgOver = p->lightButtonFgOver(); result.box.button.textFgOver = p->lightButtonFgOver();
@ -510,6 +512,10 @@ void BackgroundPreviewBox::recreateBlurCheckbox() {
}, _blur->lifetime()); }, _blur->lifetime());
_blur->setDisabled(_paper.document() && _full.isNull()); _blur->setDisabled(_paper.document() && _full.isNull());
if (_forBothOverlay) {
_forBothOverlay->raise();
}
} }
void BackgroundPreviewBox::apply() { void BackgroundPreviewBox::apply() {
@ -520,7 +526,7 @@ void BackgroundPreviewBox::apply() {
} }
} }
void BackgroundPreviewBox::uploadForPeer() { void BackgroundPreviewBox::uploadForPeer(bool both) {
Expects(_forPeer != nullptr); Expects(_forPeer != nullptr);
if (_uploadId) { if (_uploadId) {
@ -579,7 +585,7 @@ void BackgroundPreviewBox::uploadForPeer() {
"Got wallPaperNoFile after account.UploadWallPaper.")); "Got wallPaperNoFile after account.UploadWallPaper."));
}); });
if (const auto paper = Data::WallPaper::Create(session, result)) { if (const auto paper = Data::WallPaper::Create(session, result)) {
setExistingForPeer(*paper); setExistingForPeer(*paper, both);
} }
}).send(); }).send();
}, _uploadLifetime); }, _uploadLifetime);
@ -588,7 +594,9 @@ void BackgroundPreviewBox::uploadForPeer() {
_radial.start(_uploadProgress); _radial.start(_uploadProgress);
} }
void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) { void BackgroundPreviewBox::setExistingForPeer(
const Data::WallPaper &paper,
bool both) {
Expects(_forPeer != nullptr); Expects(_forPeer != nullptr);
if (const auto already = _forPeer->wallPaper()) { if (const auto already = _forPeer->wallPaper()) {
@ -602,6 +610,7 @@ void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
api->request(MTPmessages_SetChatWallPaper( api->request(MTPmessages_SetChatWallPaper(
MTP_flags((_fromMessageId ? Flag::f_id : Flag()) MTP_flags((_fromMessageId ? Flag::f_id : Flag())
| (_fromMessageId ? Flag() : Flag::f_wallpaper) | (_fromMessageId ? Flag() : Flag::f_wallpaper)
| (both ? Flag::f_for_both : Flag())
| Flag::f_settings), | Flag::f_settings),
_forPeer->input, _forPeer->input,
paper.mtpInput(&_controller->session()), paper.mtpInput(&_controller->session()),
@ -618,10 +627,117 @@ void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
void BackgroundPreviewBox::applyForPeer() { void BackgroundPreviewBox::applyForPeer() {
Expects(_forPeer != nullptr); Expects(_forPeer != nullptr);
if (Data::IsCustomWallPaper(_paper)) { if (!Data::IsCustomWallPaper(_paper)) {
uploadForPeer(); if (const auto already = _forPeer->wallPaper()) {
if (already->equals(_paper)) {
_controller->finishChatThemeEdit(_forPeer);
return;
}
}
}
if (!_fromMessageId && _forPeer->session().premiumPossible()) {
if (_forBothOverlay) {
return;
}
const auto size = this->size() * style::DevicePixelRatio();
const auto bg = Images::DitherImage(
Images::BlurLargeImage(
Ui::GrabWidgetToImage(this).scaled(
size / style::ConvertScale(4),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation),
24).scaled(
size,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
_forBothOverlay = std::make_unique<Ui::FadeWrap<>>(
this,
object_ptr<Ui::RpWidget>(this));
const auto overlay = _forBothOverlay->entity();
sizeValue() | rpl::start_with_next([=](QSize size) {
_forBothOverlay->setGeometry({ QPoint(), size });
overlay->setGeometry({ QPoint(), size });
}, _forBothOverlay->lifetime());
overlay->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(overlay);
p.drawImage(0, 0, bg);
p.fillRect(clip, QColor(0, 0, 0, 64));
}, overlay->lifetime());
using namespace Ui;
const auto forMe = CreateChild<RoundButton>(
overlay,
tr::lng_background_apply_me(),
st::backgroundConfirm);
forMe->setClickedCallback([=] {
applyForPeer(false);
});
using namespace rpl::mappers;
const auto forBoth = ::Settings::CreateLockedButton(
overlay,
tr::lng_background_apply_both(
lt_user,
rpl::single(_forPeer->shortName())),
st::backgroundConfirm,
Data::AmPremiumValue(&_forPeer->session()) | rpl::map(!_1));
forBoth->setClickedCallback([=] {
if (_forPeer->session().premium()) {
applyForPeer(true);
} else {
ShowPremiumPreviewBox(
_controller->uiShow(),
PremiumPreview::Wallpapers);
}
});
const auto cancel = CreateChild<RoundButton>(
overlay,
tr::lng_cancel(),
st::backgroundConfirmCancel);
cancel->setClickedCallback([=] {
const auto raw = _forBothOverlay.release();
raw->shownValue() | rpl::filter(
!rpl::mappers::_1
) | rpl::take(1) | rpl::start_with_next(crl::guard(raw, [=] {
delete raw;
}), raw->lifetime());
raw->toggle(false, anim::type::normal);
});
forMe->setTextTransform(RoundButton::TextTransform::NoTransform);
forBoth->setTextTransform(RoundButton::TextTransform::NoTransform);
cancel->setTextTransform(RoundButton::TextTransform::NoTransform);
overlay->sizeValue(
) | rpl::start_with_next([=](QSize size) {
const auto padding = st::backgroundConfirmPadding;
const auto width = size.width()
- padding.left()
- padding.right();
const auto height = cancel->height();
auto top = size.height() - padding.bottom() - height;
cancel->setGeometry(padding.left(), top, width, height);
top -= height + padding.top();
forBoth->setGeometry(padding.left(), top, width, height);
top -= height + padding.top();
forMe->setGeometry(padding.left(), top, width, height);
}, _forBothOverlay->lifetime());
_forBothOverlay->hide(anim::type::instant);
_forBothOverlay->show(anim::type::normal);
} else { } else {
setExistingForPeer(_paper); applyForPeer(false);
}
}
void BackgroundPreviewBox::applyForPeer(bool both) {
if (Data::IsCustomWallPaper(_paper)) {
uploadForPeer(both);
} else {
setExistingForPeer(_paper, both);
} }
} }

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "base/binary_guard.h" #include "base/binary_guard.h"
#include "history/admin_log/history_admin_log_item.h" #include "history/admin_log/history_admin_log_item.h"
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
@ -29,6 +29,8 @@ class ChatStyle;
class MediaSlider; class MediaSlider;
template <typename Widget> template <typename Widget>
class SlideWrap; class SlideWrap;
template <typename Widget>
class FadeWrap;
} // namespace Ui } // namespace Ui
struct BackgroundPreviewArgs { struct BackgroundPreviewArgs {
@ -66,9 +68,10 @@ private:
void apply(); void apply();
void applyForPeer(); void applyForPeer();
void applyForPeer(bool both);
void applyForEveryone(); void applyForEveryone();
void uploadForPeer(); void uploadForPeer(bool both);
void setExistingForPeer(const Data::WallPaper &paper); void setExistingForPeer(const Data::WallPaper &paper, bool both);
void share(); void share();
void radialAnimationCallback(crl::time now); void radialAnimationCallback(crl::time now);
QRect radialRect() const; QRect radialRect() const;
@ -131,6 +134,8 @@ private:
float64 _uploadProgress = 0.; float64 _uploadProgress = 0.;
rpl::lifetime _uploadLifetime; rpl::lifetime _uploadLifetime;
std::unique_ptr<Ui::FadeWrap<Ui::RpWidget>> _forBothOverlay;
rpl::variable<QColor> _paletteServiceBg; rpl::variable<QColor> _paletteServiceBg;
rpl::lifetime _serviceBgLifetime; rpl::lifetime _serviceBgLifetime;

View file

@ -753,7 +753,28 @@ backgroundCheck: ServiceCheck {
color: msgServiceFg; color: msgServiceFg;
duration: 200; duration: 200;
} }
backgroundConfirmPadding: margins(24px, 16px, 24px, 16px);
backgroundConfirm: RoundButton(defaultActiveButton) {
height: 44px;
textTop: 12px;
font: font(13px semibold);
}
backgroundConfirmCancel: RoundButton(backgroundConfirm) {
textFg: mediaviewSaveMsgFg;
textFgOver: mediaviewSaveMsgFg;
numbersTextFg: mediaviewSaveMsgFg;
numbersTextFgOver: mediaviewSaveMsgFg;
textBg: shadowFg;
textBgOver: shadowFg;
height: 44px;
textTop: 12px;
font: font(13px semibold);
ripple: RippleAnimation(defaultRippleAnimation) {
color: shadowFg;
}
}
urlAuthCheckbox: Checkbox(defaultBoxCheckbox) { urlAuthCheckbox: Checkbox(defaultBoxCheckbox) {
width: 240px; width: 240px;
} }
@ -906,6 +927,14 @@ sponsoredUrlButton: RoundButton(defaultActiveButton) {
} }
} }
requestPeerRestriction: FlatLabel(defaultFlatLabel) {
minWidth: 240px;
textFg: membersAboutLimitFg;
style: TextStyle(boxTextStyle) {
lineHeight: 22px;
}
}
requestsBoxItem: PeerListItem(peerListBoxItem) { requestsBoxItem: PeerListItem(peerListBoxItem) {
height: 99px; height: 99px;
button: OutlineButton(defaultPeerListButton) { button: OutlineButton(defaultPeerListButton) {

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h" #include "base/timer.h"
#include "base/object_ptr.h" #include "base/object_ptr.h"
#include "core/core_settings.h" #include "core/core_settings_proxy.h"
#include "mtproto/connection_abstract.h" #include "mtproto/connection_abstract.h"
#include "mtproto/mtproto_proxy_data.h" #include "mtproto/mtproto_proxy_data.h"

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
@ -26,7 +27,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "menu/menu_send.h" #include "menu/menu_send.h"
#include "history/view/history_view_schedule_box.h" #include "history/view/history_view_schedule_box.h"
#include "settings/settings_common.h"
#include "base/unique_qptr.h" #include "base/unique_qptr.h"
#include "base/event_filter.h" #include "base/event_filter.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
@ -34,7 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_settings.h"
namespace { namespace {
@ -790,7 +789,7 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
using namespace Settings; using namespace Settings;
const auto session = &_controller->session(); const auto session = &_controller->session();
AddSubsectionTitle(container, tr::lng_polls_create_question()); Ui::AddSubsectionTitle(container, tr::lng_polls_create_question());
const auto question = container->add( const auto question = container->add(
object_ptr<Ui::InputField>( object_ptr<Ui::InputField>(
container, container,
@ -818,9 +817,9 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
- st::createPollWarningPosition.x()), - st::createPollWarningPosition.x()),
(geometry.y() (geometry.y()
- st::createPollFieldPadding.top() - st::createPollFieldPadding.top()
- st::settingsSubsectionTitlePadding.bottom() - st::defaultSubsectionTitlePadding.bottom()
- st::settingsSubsectionTitle.style.font->height - st::defaultSubsectionTitle.style.font->height
+ st::settingsSubsectionTitle.style.font->ascent + st::defaultSubsectionTitle.style.font->ascent
- st::createPollWarning.style.font->ascent), - st::createPollWarning.style.font->ascent),
geometry.width()); geometry.width());
}, warning->lifetime()); }, warning->lifetime());
@ -841,8 +840,8 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
const auto inner = outer->entity(); const auto inner = outer->entity();
const auto session = &_controller->session(); const auto session = &_controller->session();
AddSkip(inner); Ui::AddSkip(inner);
AddSubsectionTitle(inner, tr::lng_polls_solution_title()); Ui::AddSubsectionTitle(inner, tr::lng_polls_solution_title());
const auto solution = inner->add( const auto solution = inner->add(
object_ptr<Ui::InputField>( object_ptr<Ui::InputField>(
inner, inner,
@ -875,9 +874,9 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
- st::createPollWarningPosition.x()), - st::createPollWarningPosition.x()),
(geometry.y() (geometry.y()
- st::createPollFieldPadding.top() - st::createPollFieldPadding.top()
- st::settingsSubsectionTitlePadding.bottom() - st::defaultSubsectionTitlePadding.bottom()
- st::settingsSubsectionTitle.style.font->height - st::defaultSubsectionTitle.style.font->height
+ st::settingsSubsectionTitle.style.font->ascent + st::defaultSubsectionTitle.style.font->ascent
- st::createPollWarning.style.font->ascent), - st::createPollWarning.style.font->ascent),
geometry.width()); geometry.width());
}, warning->lifetime()); }, warning->lifetime());
@ -902,13 +901,13 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
const auto container = result.data(); const auto container = result.data();
const auto question = setupQuestion(container); const auto question = setupQuestion(container);
AddDivider(container); Ui::AddDivider(container);
AddSkip(container); Ui::AddSkip(container);
container->add( container->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
container, container,
tr::lng_polls_create_options(), tr::lng_polls_create_options(),
st::settingsSubsectionTitle), st::defaultSubsectionTitle),
st::createPollFieldTitlePadding); st::createPollFieldTitlePadding);
const auto options = lifetime().make_state<Options>( const auto options = lifetime().make_state<Options>(
getDelegate()->outerContainer(), getDelegate()->outerContainer(),
@ -939,8 +938,8 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
options->focusFirst(); options->focusFirst();
}, question->lifetime()); }, question->lifetime());
AddSkip(container); Ui::AddSkip(container);
AddSubsectionTitle(container, tr::lng_polls_create_settings()); Ui::AddSubsectionTitle(container, tr::lng_polls_create_settings());
const auto anonymous = (!(_disabled & PollData::Flag::PublicVotes)) const auto anonymous = (!(_disabled & PollData::Flag::PublicVotes))
? container->add( ? container->add(

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "api/api_common.h" #include "api/api_common.h"
#include "data/data_poll.h" #include "data/data_poll.h"
#include "base/flags.h" #include "base/flags.h"

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#ifndef TDESKTOP_DISABLE_SPELLCHECK #ifndef TDESKTOP_DISABLE_SPELLCHECK
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
namespace Main { namespace Main {
class Session; class Session;

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "ui/chat/attach/attach_prepare.h" #include "ui/chat/attach/attach_prepare.h"
namespace ChatHelpers { namespace ChatHelpers {

View file

@ -13,9 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/vertical_list.h"
#include "history/history.h" #include "history/history.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "settings/settings_common.h"
#include "settings/settings_privacy_security.h" #include "settings/settings_privacy_security.h"
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "base/binary_guard.h" #include "base/binary_guard.h"
@ -233,7 +233,7 @@ Ui::FlatLabel *EditPrivacyBox::addLabel(
object_ptr<Ui::DividerLabel>( object_ptr<Ui::DividerLabel>(
container, container,
std::move(label), std::move(label),
st::settingsDividerLabelPadding), st::defaultBoxDividerLabelPadding),
{ 0, topSkip, 0, 0 }); { 0, topSkip, 0, 0 });
return result; return result;
} }
@ -294,7 +294,7 @@ void EditPrivacyBox::setupContent() {
const auto button = content->add( const auto button = content->add(
object_ptr<Ui::SlideWrap<Button>>( object_ptr<Ui::SlideWrap<Button>>(
content, content,
CreateButton( object_ptr<Button>(
content, content,
rpl::duplicate(text), rpl::duplicate(text),
st::settingsButtonNoIcon))); st::settingsButtonNoIcon)));
@ -321,7 +321,7 @@ void EditPrivacyBox::setupContent() {
content->add(std::move(above)); content->add(std::move(above));
} }
AddSubsectionTitle( Ui::AddSubsectionTitle(
content, content,
_controller->optionsTitleKey(), _controller->optionsTitleKey(),
{ 0, st::settingsPrivacySkipTop, 0, 0 }); { 0, st::settingsPrivacySkipTop, 0, 0 });
@ -332,7 +332,7 @@ void EditPrivacyBox::setupContent() {
const auto warning = addLabelOrDivider( const auto warning = addLabelOrDivider(
content, content,
_controller->warning(), _controller->warning(),
st::settingsSectionSkip + st::settingsPrivacySkipTop); st::defaultVerticalListSkip + st::settingsPrivacySkipTop);
if (warning) { if (warning) {
_controller->prepareWarningLabel(warning); _controller->prepareWarningLabel(warning);
} }
@ -345,8 +345,8 @@ void EditPrivacyBox::setupContent() {
content->add(std::move(middle)); content->add(std::move(middle));
} }
AddSkip(content); Ui::AddSkip(content);
AddSubsectionTitle( Ui::AddSubsectionTitle(
content, content,
tr::lng_edit_privacy_exceptions(), tr::lng_edit_privacy_exceptions(),
{ 0, st::settingsPrivacySkipTop, 0, 0 }); { 0, st::settingsPrivacySkipTop, 0, 0 });
@ -355,7 +355,7 @@ void EditPrivacyBox::setupContent() {
addLabel( addLabel(
content, content,
_controller->exceptionsDescription() | Ui::Text::ToWithEntities(), _controller->exceptionsDescription() | Ui::Text::ToWithEntities(),
st::settingsSectionSkip); st::defaultVerticalListSkip);
if (auto below = _controller->setupBelowWidget(_window, content)) { if (auto below = _controller->setupBelowWidget(_window, content)) {
content->add(std::move(below)); content->add(std::move(below));

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/filter_icons.h" #include "ui/filter_icons.h"
#include "ui/filter_icon_panel.h" #include "ui/filter_icon_panel.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_peer.h" #include "data/data_peer.h"
@ -515,7 +516,7 @@ not_null<Ui::SettingsButton*> AddToggledButton(
const auto toggled = container->add( const auto toggled = container->add(
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>( object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
container, container,
CreateButton( CreateButtonWithIcon(
container, container,
std::move(text), std::move(text),
st, st,
@ -658,12 +659,12 @@ void EditFilterBox(
name->setFocusFast(); name->setFocusFast();
}); });
AddSkip(content); Ui::AddSkip(content);
AddDivider(content); Ui::AddDivider(content);
AddSkip(content); Ui::AddSkip(content);
AddSubsectionTitle(content, tr::lng_filters_include()); Ui::AddSubsectionTitle(content, tr::lng_filters_include());
const auto includeAdd = AddButton( const auto includeAdd = AddButtonWithIcon(
content, content,
tr::lng_filters_add_chats(), tr::lng_filters_add_chats(),
st::settingsButtonActive, st::settingsButtonActive,
@ -676,9 +677,9 @@ void EditFilterBox(
kTypes, kTypes,
&Data::ChatFilter::always); &Data::ChatFilter::always);
AddSkip(content); Ui::AddSkip(content);
AddDividerText(content, tr::lng_filters_include_about()); Ui::AddDividerText(content, tr::lng_filters_include_about());
AddSkip(content); Ui::AddSkip(content);
auto excludeWrap = content->add( auto excludeWrap = content->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>( object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
@ -688,9 +689,9 @@ void EditFilterBox(
excludeWrap->toggleOn(state->chatlist.value() | rpl::map(!_1)); excludeWrap->toggleOn(state->chatlist.value() | rpl::map(!_1));
const auto excludeInner = excludeWrap->entity(); const auto excludeInner = excludeWrap->entity();
AddSubsectionTitle(excludeInner, tr::lng_filters_exclude()); Ui::AddSubsectionTitle(excludeInner, tr::lng_filters_exclude());
const auto excludeAdd = AddButton( const auto excludeAdd = AddButtonWithIcon(
excludeInner, excludeInner,
tr::lng_filters_remove_chats(), tr::lng_filters_remove_chats(),
st::settingsButtonActive, st::settingsButtonActive,
@ -703,9 +704,9 @@ void EditFilterBox(
kExcludeTypes, kExcludeTypes,
&Data::ChatFilter::never); &Data::ChatFilter::never);
AddSkip(excludeInner); Ui::AddSkip(excludeInner);
AddDividerText(excludeInner, tr::lng_filters_exclude_about()); Ui::AddDividerText(excludeInner, tr::lng_filters_exclude_about());
AddSkip(excludeInner); Ui::AddSkip(excludeInner);
const auto collect = [=]() -> std::optional<Data::ChatFilter> { const auto collect = [=]() -> std::optional<Data::ChatFilter> {
const auto title = name->getLastText().trimmed(); const auto title = name->getLastText().trimmed();
@ -726,7 +727,7 @@ void EditFilterBox(
return rules.withTitle(title); return rules.withTitle(title);
}; };
AddSubsectionTitle( Ui::AddSubsectionTitle(
content, content,
rpl::conditional( rpl::conditional(
state->hasLinks.value(), state->hasLinks.value(),
@ -806,8 +807,8 @@ void EditFilterBox(
})); }));
})); }));
}, createLink->lifetime()); }, createLink->lifetime());
AddSkip(content); Ui::AddSkip(content);
AddDividerText( Ui::AddDividerText(
content, content,
rpl::conditional( rpl::conditional(
state->hasLinks.value(), state->hasLinks.value(),

View file

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -140,12 +141,12 @@ void ChatFilterLinkBox(
tr::lng_group_invite_label_header(), tr::lng_group_invite_label_header(),
data.title), data.title),
style::margins( style::margins(
st::settingsSubsectionTitlePadding.left(), st::defaultSubsectionTitlePadding.left(),
st::settingsSectionSkip, st::defaultVerticalListSkip,
st::settingsSubsectionTitlePadding.right(), st::defaultSubsectionTitlePadding.right(),
st::settingsSectionSkip * 2)); st::defaultVerticalListSkip * 2));
labelField->setMaxLength(kMaxLinkTitleLength); labelField->setMaxLength(kMaxLinkTitleLength);
Settings::AddDivider(container); AddDivider(container);
box->setFocusCallback([=] { box->setFocusCallback([=] {
labelField->setFocusFast(); labelField->setFocusFast();
@ -616,7 +617,7 @@ void LinkController::addLinkBlock(not_null<Ui::VerticalLayout*> container) {
&st::menuIconDelete); &st::menuIconDelete);
return result; return result;
}; };
AddSubsectionTitle( Ui::AddSubsectionTitle(
container, container,
tr::lng_filters_link_subtitle(), tr::lng_filters_link_subtitle(),
st::filterLinkSubsectionTitlePadding); st::filterLinkSubsectionTitlePadding);
@ -637,11 +638,11 @@ void LinkController::addLinkBlock(not_null<Ui::VerticalLayout*> container) {
AddCopyShareLinkButtons(container, copyLink, shareLink); AddCopyShareLinkButtons(container, copyLink, shareLink);
AddSkip(container, st::inviteLinkJoinedRowPadding.bottom() * 2); Ui::AddSkip(container, st::inviteLinkJoinedRowPadding.bottom() * 2);
AddSkip(container); Ui::AddSkip(container);
AddDivider(container); Ui::AddDivider(container);
} }
void LinkController::prepare() { void LinkController::prepare() {
@ -788,7 +789,7 @@ void LinkController::setupBelowWidget() {
? tr::lng_filters_link_chats_no_about() ? tr::lng_filters_link_chats_no_about()
: tr::lng_filters_link_chats_about()), : tr::lng_filters_link_chats_about()),
st::boxDividerLabel), st::boxDividerLabel),
st::settingsDividerLabelPadding)); st::defaultBoxDividerLabelPadding));
} }
Main::Session &LinkController::session() const { Main::Session &LinkController::session() const {
@ -1152,7 +1153,7 @@ void AddFilterSubtitleWithToggles(
font->width(tr::lng_filters_by_link_select(tr::now)), font->width(tr::lng_filters_by_link_select(tr::now)),
font->width(tr::lng_filters_by_link_deselect(tr::now)))); font->width(tr::lng_filters_by_link_deselect(tr::now))));
} }
const auto title = Settings::AddSubsectionTitle( const auto title = Ui::AddSubsectionTitle(
container, container,
std::move(text), std::move(text),
padding); padding);

View file

@ -24,7 +24,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/text/text_options.h" #include "ui/text/text_options.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "boxes/abstract_box.h"
#include "boxes/premium_preview_box.h" #include "boxes/premium_preview_box.h"
#include "boxes/translate_box.h" #include "boxes/translate_box.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
@ -1177,12 +1179,12 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
if (!_controller) { if (!_controller) {
return; return;
} }
const auto translateEnabled = Settings::AddButton( const auto translateEnabled = container->add(
container, object_ptr<Ui::SettingsButton>(
tr::lng_translate_settings_show(), container,
st::settingsButtonNoIcon tr::lng_translate_settings_show(),
)->toggleOn( st::settingsButtonNoIcon))->toggleOn(
rpl::single(Core::App().settings().translateButtonEnabled())); rpl::single(Core::App().settings().translateButtonEnabled()));
translateEnabled->toggledValue( translateEnabled->toggledValue(
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
@ -1194,11 +1196,11 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
using namespace rpl::mappers; using namespace rpl::mappers;
auto premium = Data::AmPremiumValue(&_controller->session()); auto premium = Data::AmPremiumValue(&_controller->session());
const auto translateChat = Settings::AddButton( const auto translateChat = container->add(object_ptr<Ui::SettingsButton>(
container, container,
tr::lng_translate_settings_chat(), tr::lng_translate_settings_chat(),
st::settingsButtonNoIconLocked st::settingsButtonNoIconLocked
)->toggleOn(rpl::merge( ))->toggleOn(rpl::merge(
rpl::combine( rpl::combine(
Core::App().settings().translateChatEnabledValue(), Core::App().settings().translateChatEnabledValue(),
rpl::duplicate(premium), rpl::duplicate(premium),
@ -1250,10 +1252,8 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
translateSkip->setClickedCallback([=] { translateSkip->setClickedCallback([=] {
uiShow()->showBox(Ui::EditSkipTranslationLanguages()); uiShow()->showBox(Ui::EditSkipTranslationLanguages());
}); });
Settings::AddSkip(container); Ui::AddSkip(container);
Settings::AddDividerText( Ui::AddDividerText(container, tr::lng_translate_settings_about());
container,
tr::lng_translate_settings_about());
} }
void LanguageBox::keyPressEvent(QKeyEvent *e) { void LanguageBox::keyPressEvent(QKeyEvent *e) {

View file

@ -7,8 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "lang/lang_cloud_manager.h" #include "ui/layers/box_content.h"
#include "boxes/abstract_box.h"
#include "base/binary_guard.h" #include "base/binary_guard.h"
struct LanguageId; struct LanguageId;
@ -37,8 +36,6 @@ protected:
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
private: private:
using Languages = Lang::CloudManager::Languages;
void setupTop(not_null<Ui::VerticalLayout*> container); void setupTop(not_null<Ui::VerticalLayout*> container);
[[nodiscard]] int rowsInPage() const; [[nodiscard]] int rowsInPage() const;

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "boxes/local_storage_box.h" #include "boxes/local_storage_box.h"
#include "boxes/abstract_box.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "storage/cache/storage_cache_database.h" #include "storage/cache/storage_cache_database.h"
namespace Main { namespace Main {

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
class MaxInviteBox final : public Ui::BoxContent { class MaxInviteBox final : public Ui::BoxContent {
public: public:

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "core/core_cloud_password.h" #include "core/core_cloud_password.h"

View file

@ -11,9 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
#include "ui/unread_badge.h" #include "ui/unread_badge.h"
#include "ui/userpic_view.h" #include "ui/userpic_view.h"
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "mtproto/sender.h"
#include "data/data_cloud_file.h"
#include "base/timer.h" #include "base/timer.h"
namespace style { namespace style {

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/flat_set.h" #include "base/flat_set.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "base/timer.h" #include "base/timer.h"
#include "mtproto/sender.h"
class History; class History;

View file

@ -35,7 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_settings.h"
namespace { namespace {

View file

@ -20,15 +20,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_icon.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" // Session::api(). #include "main/main_session.h" // Session::api().
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/vertical_list.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
#include "styles/style_settings.h" #include "styles/style_layers.h"
namespace { namespace {
@ -352,11 +352,11 @@ void ChoosePeerBoxController::prepareRestrictions() {
const auto raw = above.data(); const auto raw = above.data();
auto rows = RestrictionsList(_query); auto rows = RestrictionsList(_query);
if (!rows.empty()) { if (!rows.empty()) {
Settings::AddSubsectionTitle( Ui::AddSubsectionTitle(
raw, raw,
tr::lng_request_peer_requirements(), tr::lng_request_peer_requirements(),
{ 0, st::membersMarginTop, 0, 0 }); { 0, st::membersMarginTop, 0, 0 });
const auto skip = st::settingsSubsectionTitlePadding.left(); const auto skip = st::defaultSubsectionTitlePadding.left();
auto separator = QString::fromUtf8("\n\xE2\x80\xA2 "); auto separator = QString::fromUtf8("\n\xE2\x80\xA2 ");
raw->add( raw->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
@ -364,7 +364,7 @@ void ChoosePeerBoxController::prepareRestrictions() {
separator + rows.join(separator), separator + rows.join(separator),
st::requestPeerRestriction), st::requestPeerRestriction),
{ skip, 0, skip, st::membersMarginTop }); { skip, 0, skip, st::membersMarginTop });
Settings::AddDivider(raw); Ui::AddDivider(raw);
} }
const auto make = [&](tr::phrase<> text, const style::icon &st) { const auto make = [&](tr::phrase<> text, const style::icon &st) {
auto button = raw->add( auto button = raw->add(

View file

@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
#include "ui/effects/emoji_fly_animation.h" #include "ui/effects/emoji_fly_animation.h"
#include "ui/abstract_button.h" #include "ui/abstract_button.h"
#include "ui/color_int_conversion.h" #include "ui/vertical_list.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_forum.h" #include "data/data_forum.h"
@ -32,14 +32,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_emoji_status_panel.h" #include "info/profile/info_profile_emoji_status_panel.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "settings/settings_common.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
namespace {
namespace { namespace {
constexpr auto kDefaultIconId = DocumentId(0x7FFF'FFFF'FFFF'FFFFULL); constexpr auto kDefaultIconId = DocumentId(0x7FFF'FFFF'FFFF'FFFFULL);
@ -114,8 +112,6 @@ bool DefaultIconEmoji::readyInDefaultState() {
return true; return true;
} }
} // namespace
[[nodiscard]] int EditIconSize() { [[nodiscard]] int EditIconSize() {
const auto tag = Data::CustomEmojiManager::SizeTag::Large; const auto tag = Data::CustomEmojiManager::SizeTag::Large;
return Data::FrameSizeFromTag(tag) / style::DevicePixelRatio(); return Data::FrameSizeFromTag(tag) / style::DevicePixelRatio();
@ -479,9 +475,7 @@ void EditForumTopicBox(
}, title->lifetime()); }, title->lifetime());
if (!topic || !topic->isGeneral()) { if (!topic || !topic->isGeneral()) {
Settings::AddDividerText( Ui::AddDividerText(top, tr::lng_forum_choose_title_and_icon());
top,
tr::lng_forum_choose_title_and_icon());
box->setScrollStyle(st::reactPanelScroll); box->setScrollStyle(st::reactPanelScroll);

View file

@ -10,9 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "settings/settings_common.h" #include "settings/settings_common.h" // AddButton.
#include "data/data_changes.h" #include "data/data_changes.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/text/text_utilities.h" // Ui::Text::RichLangValue #include "ui/text/text_utilities.h" // Ui::Text::RichLangValue
@ -267,8 +268,8 @@ void Controller::choose(not_null<ChatData*> chat) {
if (!chat) { if (!chat) {
Assert(channel->isBroadcast()); Assert(channel->isBroadcast());
Settings::AddSkip(above); Ui::AddSkip(above);
Settings::AddButton( Settings::AddButtonWithIcon(
above, above,
tr::lng_manage_discussion_group_create(), tr::lng_manage_discussion_group_create(),
st::infoCreateLinkedChatButton, st::infoCreateLinkedChatButton,
@ -286,7 +287,7 @@ void Controller::choose(not_null<ChatData*> chat) {
auto below = object_ptr<Ui::VerticalLayout>(box); auto below = object_ptr<Ui::VerticalLayout>(box);
if (chat && canEdit) { if (chat && canEdit) {
Settings::AddButton( Settings::AddButtonWithIcon(
below, below,
(channel->isBroadcast() (channel->isBroadcast()
? tr::lng_manage_discussion_group_unlink ? tr::lng_manage_discussion_group_unlink
@ -294,9 +295,9 @@ void Controller::choose(not_null<ChatData*> chat) {
st::infoUnlinkChatButton, st::infoUnlinkChatButton,
{ &st::menuIconRemove } { &st::menuIconRemove }
)->addClickHandler([=] { callback(nullptr); }); )->addClickHandler([=] { callback(nullptr); });
Settings::AddSkip(below); Ui::AddSkip(below);
} }
Settings::AddDividerText( Ui::AddDividerText(
below, below,
(channel->isBroadcast() (channel->isBroadcast()
? tr::lng_manage_discussion_group_posted ? tr::lng_manage_discussion_group_posted

View file

@ -13,7 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "settings/settings_common.h" #include "ui/vertical_list.h"
#include "settings/settings_common.h" // IconDescriptor.
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_app_config.h" #include "main/main_app_config.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -45,7 +46,7 @@ namespace {
struct State { struct State {
rpl::event_stream<bool> toggled; rpl::event_stream<bool> toggled;
}; };
Settings::AddSkip(container); Ui::AddSkip(container);
const auto state = container->lifetime().make_state<State>(); const auto state = container->lifetime().make_state<State>();
const auto button = container->add( const auto button = container->add(
EditPeerInfoBox::CreateButton( EditPeerInfoBox::CreateButton(
@ -58,10 +59,8 @@ namespace {
))->toggleOn(rpl::single( ))->toggleOn(rpl::single(
(megagroup->flags() & ChannelDataFlag::ParticipantsHidden) != 0 (megagroup->flags() & ChannelDataFlag::ParticipantsHidden) != 0
) | rpl::then(state->toggled.events())); ) | rpl::then(state->toggled.events()));
Settings::AddSkip(container); Ui::AddSkip(container);
Settings::AddDividerText( Ui::AddDividerText(container, tr::lng_profile_hide_participants_about());
container,
tr::lng_profile_hide_participants_about());
button->toggledValue( button->toggledValue(
) | rpl::start_with_next([=](bool toggled) { ) | rpl::start_with_next([=](bool toggled) {

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
#include "base/unique_qptr.h" #include "base/unique_qptr.h"
#include "data/data_chat_participant_status.h" #include "data/data_chat_participant_status.h"

View file

@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_participants_box.h" #include "boxes/peers/edit_participants_box.h"
#include "api/api_chat_participants.h" #include "api/api_chat_participants.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/peers/edit_participant_box.h" #include "boxes/peers/edit_participant_box.h"
#include "boxes/peers/add_participants_box.h" #include "boxes/peers/add_participants_box.h"
#include "boxes/peers/prepare_short_info_box.h" // PrepareShortInfoBox #include "boxes/peers/prepare_short_info_box.h" // PrepareShortInfoBox
@ -21,7 +20,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_config.h" #include "mtproto/mtproto_config.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h"
#include "dialogs/dialogs_indexed_list.h" #include "dialogs/dialogs_indexed_list.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_session.h" #include "data/data_session.h"
@ -33,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h" #include "base/unixtime.h"
#include "ui/effects/outline_segments.h" #include "ui/effects/outline_segments.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/ui_utility.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "history/history.h" #include "history/history.h"
@ -426,9 +423,7 @@ bool ParticipantsAdditionalData::isExternal(
bool ParticipantsAdditionalData::isKicked( bool ParticipantsAdditionalData::isKicked(
not_null<PeerData*> participant) const { not_null<PeerData*> participant) const {
return _peer->isChat() return !_peer->isChat() && (_kicked.find(participant) != end(_kicked));
? false
: _kicked.find(participant) != end(_kicked);
} }
UserData *ParticipantsAdditionalData::adminPromotedBy( UserData *ParticipantsAdditionalData::adminPromotedBy(
@ -1645,6 +1640,33 @@ base::unique_qptr<Ui::PopupMenu> ParticipantsBoxController::rowContextMenu(
? &st::menuIconProfile ? &st::menuIconProfile
: &st::menuIconInfo)); : &st::menuIconInfo));
} }
if (const auto by = _additional.restrictedBy(participant)) {
result->addAction(
(_role == Role::Kicked
? tr::lng_channel_banned_status_removed_by
: tr::lng_channel_banned_status_restricted_by)(
tr::now,
lt_user,
by->name()),
crl::guard(this, [=] {
_navigation->parentController()->show(
PrepareShortInfoBox(by, _navigation));
}),
&st::menuIconAdmin);
} else if (user) {
if (const auto by = _additional.adminPromotedBy(user)) {
result->addAction(
tr::lng_channel_admin_status_promoted_by(
tr::now,
lt_user,
by->name()),
crl::guard(this, [=] {
_navigation->parentController()->show(
PrepareShortInfoBox(by, _navigation));
}),
&st::menuIconAdmin);
}
}
if (_role == Role::Kicked) { if (_role == Role::Kicked) {
if (_peer->isMegagroup() if (_peer->isMegagroup()
&& _additional.canRestrictParticipant(participant)) { && _additional.canRestrictParticipant(participant)) {

View file

@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include <rpl/variable.h> #include <rpl/variable.h>
#include "boxes/peer_list_box.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "base/timer.h" #include "base/timer.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_color_box.h" #include "boxes/peers/edit_peer_color_box.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "api/api_peer_colors.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "boxes/peers/replace_boost_box.h" #include "boxes/peers/replace_boost_box.h"
#include "chat_helpers/compose/compose_show.h" #include "chat_helpers/compose/compose_show.h"
@ -37,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/section_widget.h" #include "window/section_widget.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -459,15 +461,15 @@ void Set(
).done(done).fail(fail).send(); ).done(done).fail(fail).send();
}; };
if (peer->isSelf()) { if (peer->isSelf()) {
using Flag = MTPaccount_UpdateColor::Flag;
send(MTPaccount_UpdateColor( send(MTPaccount_UpdateColor(
MTP_flags( MTP_flags(Flag::f_color | Flag::f_background_emoji_id),
MTPaccount_UpdateColor::Flag::f_background_emoji_id),
MTP_int(colorIndex), MTP_int(colorIndex),
MTP_long(backgroundEmojiId))); MTP_long(backgroundEmojiId)));
} else if (const auto channel = peer->asChannel()) { } else if (const auto channel = peer->asChannel()) {
using Flag = MTPchannels_UpdateColor::Flag;
send(MTPchannels_UpdateColor( send(MTPchannels_UpdateColor(
MTP_flags( MTP_flags(Flag::f_background_emoji_id),
MTPchannels_UpdateColor::Flag::f_background_emoji_id),
channel->inputChannel, channel->inputChannel,
MTP_int(colorIndex), MTP_int(colorIndex),
MTP_long(backgroundEmojiId))); MTP_long(backgroundEmojiId)));
@ -526,7 +528,7 @@ void Apply(
show->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{ show->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{
.link = qs(data.vboost_url()), .link = qs(data.vboost_url()),
.boost = counters, .boost = counters,
.requiredLevel = required, .reason = { Ui::AskBoostChannelColor{ required } },
}, openStatistics, nullptr)); }, openStatistics, nullptr));
cancel(); cancel();
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
@ -661,11 +663,10 @@ int ColorSelector::resizeGetHeight(int newWidth) {
const auto st = parent->lifetime().make_state<style::SettingsButton>( const auto st = parent->lifetime().make_state<style::SettingsButton>(
basicSt); basicSt);
st->padding.setRight(rightPadding); st->padding.setRight(rightPadding);
auto result = CreateButton( auto result = object_ptr<Ui::SettingsButton>(
parent, parent,
tr::lng_settings_color_emoji(), tr::lng_settings_color_emoji(),
*st, *st);
{});
const auto raw = result.data(); const auto raw = result.data();
const auto right = Ui::CreateChild<Ui::RpWidget>(raw); const auto right = Ui::CreateChild<Ui::RpWidget>(raw);
@ -787,19 +788,7 @@ void EditPeerColorBox(
state->emojiId.value() state->emojiId.value()
), {}); ), {});
const auto appConfig = &peer->session().account().appConfig(); auto indices = peer->session().api().peerColors().suggestedValue();
auto indices = rpl::single(
rpl::empty
) | rpl::then(
appConfig->refreshed()
) | rpl::map([=] {
const auto list = appConfig->get<std::vector<int>>(
"peer_colors_available",
{ 0, 1, 2, 3, 4, 5, 6 });
return list | ranges::views::transform([](int i) {
return uint8(i);
}) | ranges::to_vector;
});
const auto margin = st::settingsColorRadioMargin; const auto margin = st::settingsColorRadioMargin;
const auto skip = st::settingsColorRadioSkip; const auto skip = st::settingsColorRadioSkip;
box->addRow( box->addRow(
@ -812,11 +801,11 @@ void EditPeerColorBox(
{ margin, skip, margin, skip }); { margin, skip, margin, skip });
const auto container = box->verticalLayout(); const auto container = box->verticalLayout();
AddDividerText(container, peer->isSelf() Ui::AddDividerText(container, peer->isSelf()
? tr::lng_settings_color_about() ? tr::lng_settings_color_about()
: tr::lng_settings_color_about_channel()); : tr::lng_settings_color_about_channel());
AddSkip(container, st::settingsColorSampleSkip); Ui::AddSkip(container, st::settingsColorSampleSkip);
container->add(CreateEmojiIconButton( container->add(CreateEmojiIconButton(
container, container,
@ -826,8 +815,8 @@ void EditPeerColorBox(
state->emojiId.value(), state->emojiId.value(),
[=](DocumentId id) { state->emojiId = id; })); [=](DocumentId id) { state->emojiId = id; }));
AddSkip(container, st::settingsColorSampleSkip); Ui::AddSkip(container, st::settingsColorSampleSkip);
AddDividerText(container, peer->isSelf() Ui::AddDividerText(container, peer->isSelf()
? tr::lng_settings_color_emoji_about() ? tr::lng_settings_color_emoji_about()
: tr::lng_settings_color_emoji_about_channel()); : tr::lng_settings_color_emoji_about_channel());
@ -853,7 +842,7 @@ void AddPeerColorButton(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer) { not_null<PeerData*> peer) {
const auto button = AddButton( const auto button = AddButtonWithIcon(
container, container,
(peer->isSelf() (peer->isSelf()
? tr::lng_settings_theme_name_color() ? tr::lng_settings_theme_name_color()

View file

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_peer_photo.h" #include "api/api_peer_photo.h"
#include "api/api_user_names.h" #include "api/api_user_names.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "boxes/add_contact_box.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "boxes/peers/edit_participants_box.h" #include "boxes/peers/edit_participants_box.h"
#include "boxes/peers/edit_peer_color_box.h" #include "boxes/peers/edit_peer_color_box.h"
@ -23,10 +22,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_linked_chat_box.h" #include "boxes/peers/edit_linked_chat_box.h"
#include "boxes/peers/edit_peer_requests_box.h" #include "boxes/peers/edit_peer_requests_box.h"
#include "boxes/peers/edit_peer_reactions.h" #include "boxes/peers/edit_peer_reactions.h"
#include "boxes/peers/replace_boost_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/stickers_box.h" #include "boxes/stickers_box.h"
#include "boxes/username_box.h" #include "boxes/username_box.h"
#include "ui/boxes/single_choice_box.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
@ -37,35 +36,36 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_message_reactions.h" #include "data/data_message_reactions.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_premium_limits.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "history/admin_log/history_admin_log_section.h" #include "history/admin_log/history_admin_log_section.h"
#include "info/boosts/info_boosts_widget.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "info/info_memento.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "main/main_session.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_app_config.h" #include "main/main_app_config.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "ui/boxes/boost_box.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/vertical_list.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/fields/input_field.h" #include "ui/widgets/fields/input_field.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/box_content_divider.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "info/profile/info_profile_icon.h"
#include "api/api_invite_links.h" #include "api/api_invite_links.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_settings.h"
namespace { namespace {
@ -87,13 +87,9 @@ void AddSkip(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
int top = st::editPeerTopButtonsLayoutSkip, int top = st::editPeerTopButtonsLayoutSkip,
int bottom = st::editPeerTopButtonsLayoutSkipToBottom) { int bottom = st::editPeerTopButtonsLayoutSkipToBottom) {
container->add(object_ptr<Ui::FixedHeightWidget>( Ui::AddSkip(container, top);
container, Ui::AddDivider(container);
top)); Ui::AddSkip(container, bottom);
container->add(object_ptr<Ui::BoxContentDivider>(container));
container->add(object_ptr<Ui::FixedHeightWidget>(
container,
bottom));
} }
void AddButtonWithCount( void AddButtonWithCount(
@ -245,10 +241,6 @@ void ShowEditPermissions(
navigation->parentController()->show(Box(std::move(createBox))); navigation->parentController()->show(Box(std::move(createBox)));
} }
} // namespace
namespace {
class Controller : public base::has_weak_ptr { class Controller : public base::has_weak_ptr {
public: public:
Controller( Controller(
@ -269,6 +261,7 @@ private:
Ui::VerticalLayout *buttonsLayout = nullptr; Ui::VerticalLayout *buttonsLayout = nullptr;
Ui::SettingsButton *forumToggle = nullptr; Ui::SettingsButton *forumToggle = nullptr;
bool forumToggleLocked = false; bool forumToggleLocked = false;
bool levelRequested = false;
Ui::SlideWrap<> *historyVisibilityWrap = nullptr; Ui::SlideWrap<> *historyVisibilityWrap = nullptr;
}; };
struct Saving { struct Saving {
@ -318,6 +311,7 @@ private:
void submitDescription(); void submitDescription();
void deleteWithConfirmation(); void deleteWithConfirmation();
void deleteChannel(); void deleteChannel();
void editReactions();
[[nodiscard]] std::optional<Saving> validate() const; [[nodiscard]] std::optional<Saving> validate() const;
[[nodiscard]] bool validateUsernamesOrder(Saving &to) const; [[nodiscard]] bool validateUsernamesOrder(Saving &to) const;
@ -591,10 +585,10 @@ object_ptr<Ui::RpWidget> Controller::createStickersEdit() {
object_ptr<Ui::VerticalLayout>(_wrap)); object_ptr<Ui::VerticalLayout>(_wrap));
const auto container = result->entity(); const auto container = result->entity();
Settings::AddSubsectionTitle( Ui::AddSubsectionTitle(
container, container,
tr::lng_group_stickers(), tr::lng_group_stickers(),
{ 0, st::settingsSubsectionTitlePadding.top() - bottomSkip, 0, 0 }); { 0, st::defaultSubsectionTitlePadding.top() - bottomSkip, 0, 0 });
AddButtonWithCount( AddButtonWithCount(
container, container,
@ -606,13 +600,13 @@ object_ptr<Ui::RpWidget> Controller::createStickersEdit() {
}, },
{ &st::menuIconStickers }); { &st::menuIconStickers });
Settings::AddSkip(container, bottomSkip); Ui::AddSkip(container, bottomSkip);
Settings::AddDividerText( Ui::AddDividerText(
container, container,
tr::lng_group_stickers_description()); tr::lng_group_stickers_description());
Settings::AddSkip(container, bottomSkip); Ui::AddSkip(container, bottomSkip);
return result; return result;
} }
@ -1002,12 +996,12 @@ void Controller::fillManageSection() {
if (_isBot) { if (_isBot) {
const auto &container = _controls.buttonsLayout; const auto &container = _controls.buttonsLayout;
AddSkip(container, 0); ::AddSkip(container, 0);
fillBotUsernamesButton(); fillBotUsernamesButton();
fillBotEditIntroButton(); fillBotEditIntroButton();
fillBotEditCommandsButton(); fillBotEditCommandsButton();
fillBotEditSettingsButton(); fillBotEditSettingsButton();
Settings::AddSkip( Ui::AddSkip(
container, container,
st::editPeerTopButtonsLayoutSkipCustomBottom); st::editPeerTopButtonsLayoutSkipCustomBottom);
container->add(object_ptr<Ui::DividerLabel>( container->add(object_ptr<Ui::DividerLabel>(
@ -1022,7 +1016,7 @@ void Controller::fillManageSection() {
kBotManagerUsername.utf16()))), kBotManagerUsername.utf16()))),
Ui::Text::RichLangValue), Ui::Text::RichLangValue),
st::boxDividerLabel), st::boxDividerLabel),
st::settingsDividerLabelPadding)); st::defaultBoxDividerLabelPadding));
return; return;
} }
@ -1070,7 +1064,7 @@ void Controller::fillManageSection() {
&& (channel->linkedChat() && (channel->linkedChat()
|| (channel->isBroadcast() && channel->canEditInformation())); || (channel->isBroadcast() && channel->canEditInformation()));
AddSkip(_controls.buttonsLayout, 0); ::AddSkip(_controls.buttonsLayout, 0);
if (canEditType) { if (canEditType) {
fillPrivacyTypeButton(); fillPrivacyTypeButton();
@ -1099,11 +1093,10 @@ void Controller::fillManageSection() {
//|| canEditInviteLinks //|| canEditInviteLinks
|| canViewOrEditLinkedChat || canViewOrEditLinkedChat
|| canEditType) { || canEditType) {
AddSkip(_controls.buttonsLayout); ::AddSkip(_controls.buttonsLayout);
} }
if (canEditReactions()) { if (canEditReactions()) {
const auto session = &_peer->session();
auto allowedReactions = Info::Profile::MigratedOrMeValue( auto allowedReactions = Info::Profile::MigratedOrMeValue(
_peer _peer
) | rpl::map([=](not_null<PeerData*> peer) { ) | rpl::map([=](not_null<PeerData*> peer) {
@ -1114,36 +1107,21 @@ void Controller::fillManageSection() {
return Data::PeerAllowedReactions(peer); return Data::PeerAllowedReactions(peer);
}); });
}) | rpl::flatten_latest(); }) | rpl::flatten_latest();
auto label = rpl::combine( auto label = std::move(
std::move(allowedReactions), allowedReactions
Info::Profile::FullReactionsCountValue(session) ) | rpl::map([=](const Data::AllowedReactions &allowed) {
) | rpl::map([=](const Data::AllowedReactions &allowed, int total) {
const auto some = int(allowed.some.size()); const auto some = int(allowed.some.size());
return (allowed.type != Data::AllowedReactionsType::Some) return (allowed.type != Data::AllowedReactionsType::Some)
? tr::lng_manage_peer_reactions_on(tr::now) ? tr::lng_manage_peer_reactions_on(tr::now)
: some : some
? (QString::number(some) ? QString::number(some)
+ " / "
+ QString::number(std::max(some, total)))
: tr::lng_manage_peer_reactions_off(tr::now); : tr::lng_manage_peer_reactions_off(tr::now);
}); });
const auto done = [=](const Data::AllowedReactions &chosen) {
SaveAllowedReactions(_peer, chosen);
};
AddButtonWithCount( AddButtonWithCount(
_controls.buttonsLayout, _controls.buttonsLayout,
tr::lng_manage_peer_reactions(), tr::lng_manage_peer_reactions(),
std::move(label), std::move(label),
[=] { [=] { editReactions(); },
_navigation->parentController()->show(Box(
EditAllowedReactionsBox,
_navigation,
!_peer->isBroadcast(),
session->data().reactions().list(
Data::Reactions::Type::Active),
Data::PeerAllowedReactions(_peer),
done));
},
{ &st::menuIconGroupReactions }); { &st::menuIconGroupReactions });
} }
if (canEditPermissions) { if (canEditPermissions) {
@ -1269,7 +1247,7 @@ void Controller::fillManageSection() {
} }
if (canEditStickers || canDeleteChannel) { if (canEditStickers || canDeleteChannel) {
AddSkip(_controls.buttonsLayout); ::AddSkip(_controls.buttonsLayout);
} }
if (canEditStickers) { if (canEditStickers) {
@ -1287,10 +1265,67 @@ void Controller::fillManageSection() {
} }
if (canEditStickers || canDeleteChannel) { if (canEditStickers || canDeleteChannel) {
AddSkip(_controls.buttonsLayout); ::AddSkip(_controls.buttonsLayout);
} }
} }
void Controller::editReactions() {
const auto done = [=](const Data::AllowedReactions &chosen) {
SaveAllowedReactions(_peer, chosen);
};
if (!_peer->isBroadcast()) {
_navigation->uiShow()->show(Box(
EditAllowedReactionsBox,
EditAllowedReactionsArgs{
.navigation = _navigation,
.isGroup = true,
.list = _navigation->session().data().reactions().list(
Data::Reactions::Type::Active),
.allowed = Data::PeerAllowedReactions(_peer),
.save = done,
}));
return;
}
if (_controls.levelRequested) {
return;
}
_controls.levelRequested = true;
_api.request(MTPpremium_GetBoostsStatus(
_peer->input
)).done([=](const MTPpremium_BoostsStatus &result) {
_controls.levelRequested = false;
const auto link = qs(result.data().vboost_url());
const auto weak = base::make_weak(_navigation->parentController());
auto counters = ParseBoostCounters(result);
counters.mine = 0; // Don't show current level as just-reached.
const auto askForBoosts = [=](int required) {
if (const auto strong = weak.get()) {
const auto openStatistics = [=, peer = _peer] {
strong->showSection(Info::Boosts::Make(peer));
};
strong->show(Box(Ui::AskBoostBox, Ui::AskBoostBoxData{
.link = link,
.boost = counters,
.reason = { Ui::AskBoostCustomReactions{ required } },
}, openStatistics, nullptr));
}
};
_navigation->uiShow()->show(Box(
EditAllowedReactionsBox,
EditAllowedReactionsArgs{
.navigation = _navigation,
.allowedCustomReactions = counters.level,
.customReactionsHardLimit = Data::PremiumLimits(
&_peer->session()).maxBoostLevel(),
.list = _navigation->session().data().reactions().list(
Data::Reactions::Type::Active),
.allowed = Data::PeerAllowedReactions(_peer),
.askForBoosts = askForBoosts,
.save = done,
}));
}).send();
}
void Controller::fillPendingRequestsButton() { void Controller::fillPendingRequestsButton() {
auto pendingRequestsCount = Info::Profile::MigratedOrMeValue( auto pendingRequestsCount = Info::Profile::MigratedOrMeValue(
_peer _peer

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/boxes/edit_invite_link.h" #include "ui/boxes/edit_invite_link.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "boxes/share_box.h" #include "boxes/share_box.h"
#include "history/view/history_view_group_call_bar.h" // GenerateUserpics... #include "history/view/history_view_group_call_bar.h" // GenerateUserpics...
#include "history/history_item_helpers.h" // GetErrorTextForSending. #include "history/history_item_helpers.h" // GetErrorTextForSending.
@ -39,14 +40,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "settings/settings_common.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "qr/qr_generate.h" #include "qr/qr_generate.h"
#include "intro/intro_qr.h" // TelegramLogoImage #include "intro/intro_qr.h" // TelegramLogoImage
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h" // st::boxDividerLabel. #include "styles/style_layers.h" // st::boxDividerLabel.
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_settings.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
@ -434,7 +433,7 @@ void Controller::addHeaderBlock(not_null<Ui::VerticalLayout*> container) {
AddDeleteLinkButton(container, deleteLink); AddDeleteLinkButton(container, deleteLink);
} }
AddSkip(container, st::inviteLinkJoinedRowPadding.bottom() * 2); Ui::AddSkip(container, st::inviteLinkJoinedRowPadding.bottom() * 2);
auto grayLabelText = dataValue( auto grayLabelText = dataValue(
) | rpl::map([=](const LinkData &data) { ) | rpl::map([=](const LinkData &data) {
@ -457,7 +456,7 @@ void Controller::addHeaderBlock(not_null<Ui::VerticalLayout*> container) {
container, container,
tr::lng_group_invite_expired_about(), tr::lng_group_invite_expired_about(),
st::boxAttentionDividerLabel), st::boxAttentionDividerLabel),
st::settingsDividerLabelPadding))); st::defaultBoxDividerLabelPadding)));
const auto grayLabelWrap = container->add( const auto grayLabelWrap = container->add(
object_ptr<Ui::SlideWrap<Ui::DividerLabel>>( object_ptr<Ui::SlideWrap<Ui::DividerLabel>>(
container, container,
@ -467,12 +466,12 @@ void Controller::addHeaderBlock(not_null<Ui::VerticalLayout*> container) {
container, container,
std::move(grayLabelText), std::move(grayLabelText),
st::boxDividerLabel), st::boxDividerLabel),
st::settingsDividerLabelPadding))); st::defaultBoxDividerLabelPadding)));
const auto justDividerWrap = container->add( const auto justDividerWrap = container->add(
object_ptr<Ui::SlideWrap<>>( object_ptr<Ui::SlideWrap<>>(
container, container,
object_ptr<Ui::BoxContentDivider>(container))); object_ptr<Ui::BoxContentDivider>(container)));
AddSkip(container); Ui::AddSkip(container);
dataValue( dataValue(
) | rpl::start_with_next([=](const LinkData &data) { ) | rpl::start_with_next([=](const LinkData &data) {
@ -509,15 +508,15 @@ not_null<Ui::SlideWrap<>*> Controller::addRequestedListBlock(
const auto wrap = result->entity(); const auto wrap = result->entity();
// Make this container occupy full width. // Make this container occupy full width.
wrap->add(object_ptr<Ui::RpWidget>(wrap)); wrap->add(object_ptr<Ui::RpWidget>(wrap));
AddDivider(wrap); Ui::AddDivider(wrap);
AddSkip(wrap); Ui::AddSkip(wrap);
auto requestedCount = dataValue( auto requestedCount = dataValue(
) | rpl::filter([](const LinkData &data) { ) | rpl::filter([](const LinkData &data) {
return data.requested > 0; return data.requested > 0;
}) | rpl::map([=](const LinkData &data) { }) | rpl::map([=](const LinkData &data) {
return float64(data.requested); return float64(data.requested);
}); });
AddSubsectionTitle( Ui::AddSubsectionTitle(
wrap, wrap,
tr::lng_group_invite_requested_full( tr::lng_group_invite_requested_full(
lt_count_decimal, lt_count_decimal,
@ -588,14 +587,14 @@ void Controller::setupAboveJoinedWidget() {
if (revoked || !current.permanent) { if (revoked || !current.permanent) {
addHeaderBlock(container); addHeaderBlock(container);
} }
AddSubsectionTitle( Ui::AddSubsectionTitle(
container, container,
tr::lng_group_invite_created_by()); tr::lng_group_invite_created_by());
AddSinglePeerRow( AddSinglePeerRow(
container, container,
current.admin, current.admin,
rpl::single(langDateTime(base::unixtime::parse(current.date)))); rpl::single(langDateTime(base::unixtime::parse(current.date))));
AddSkip(container, st::membersMarginBottom); Ui::AddSkip(container, st::membersMarginBottom);
auto requestedWrap = addRequestedListBlock(container); auto requestedWrap = addRequestedListBlock(container);
@ -609,8 +608,8 @@ void Controller::setupAboveJoinedWidget() {
// Make this container occupy full width. // Make this container occupy full width.
listHeader->add(object_ptr<Ui::RpWidget>(listHeader)); listHeader->add(object_ptr<Ui::RpWidget>(listHeader));
AddDivider(listHeader); Ui::AddDivider(listHeader);
AddSkip(listHeader); Ui::AddSkip(listHeader);
auto listHeaderText = dataValue( auto listHeaderText = dataValue(
) | rpl::map([=](const LinkData &data) { ) | rpl::map([=](const LinkData &data) {
@ -665,7 +664,7 @@ void Controller::setupAboveJoinedWidget() {
const auto remaining = Ui::CreateChild<Ui::FlatLabel>( const auto remaining = Ui::CreateChild<Ui::FlatLabel>(
listHeader, listHeader,
std::move(remainingText), std::move(remainingText),
st::settingsSubsectionTitleRight); st::inviteLinkTitleRight);
dataValue( dataValue(
) | rpl::start_with_next([=](const LinkData &data) { ) | rpl::start_with_next([=](const LinkData &data) {
remaining->setTextColorOverride( remaining->setTextColorOverride(

View file

@ -19,17 +19,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/peers/edit_peer_invite_link.h" #include "boxes/peers/edit_peer_invite_link.h"
#include "settings/settings_common.h" // AddDivider.
#include "apiwrap.h" #include "apiwrap.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_layers.h" // st::boxDividerLabel #include "styles/style_layers.h" // st::boxDividerLabel
#include "styles/style_settings.h" // st::settingsDividerLabelPadding
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
namespace { namespace {
@ -875,8 +874,6 @@ void ManageInviteLinksBox(
not_null<UserData*> admin, not_null<UserData*> admin,
int count, int count,
int revokedCount) { int revokedCount) {
using namespace Settings;
const auto show = Main::MakeSessionShow( const auto show = Main::MakeSessionShow(
box->uiShow(), box->uiShow(),
&peer->session()); &peer->session());
@ -901,14 +898,14 @@ void ManageInviteLinksBox(
std::move(status)); std::move(status));
} }
AddSubsectionTitle(container, tr::lng_create_permanent_link_title()); Ui::AddSubsectionTitle(container, tr::lng_create_permanent_link_title());
AddPermanentLinkBlock( AddPermanentLinkBlock(
show, show,
container, container,
peer, peer,
admin, admin,
permanentFromList->events()); permanentFromList->events());
AddDivider(container); Ui::AddDivider(container);
auto otherHeader = (Ui::SlideWrap<>*)nullptr; auto otherHeader = (Ui::SlideWrap<>*)nullptr;
if (admin->isSelf()) { if (admin->isSelf()) {
@ -923,7 +920,7 @@ void ManageInviteLinksBox(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
container, container,
tr::lng_group_invite_other_list(), tr::lng_group_invite_other_list(),
st::settingsSubsectionTitle), st::defaultSubsectionTitle),
st::inviteLinkRevokedTitlePadding)); st::inviteLinkRevokedTitlePadding));
} }
@ -949,7 +946,7 @@ void ManageInviteLinksBox(
container, container,
tr::lng_group_invite_add_about(), tr::lng_group_invite_add_about(),
st::boxDividerLabel), st::boxDividerLabel),
st::settingsDividerLabelPadding)), st::defaultBoxDividerLabelPadding)),
style::margins(0, st::inviteLinkCreateSkip, 0, 0)); style::margins(0, st::inviteLinkCreateSkip, 0, 0));
const auto adminsDivider = container->add(object_ptr<Ui::SlideWrap<>>( const auto adminsDivider = container->add(object_ptr<Ui::SlideWrap<>>(
@ -960,7 +957,7 @@ void ManageInviteLinksBox(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
container, container,
tr::lng_group_invite_other_title(), tr::lng_group_invite_other_title(),
st::settingsSubsectionTitle), st::defaultSubsectionTitle),
st::inviteLinkRevokedTitlePadding)); st::inviteLinkRevokedTitlePadding));
const auto admins = AddAdminsList(show, container, peer, admin); const auto admins = AddAdminsList(show, container, peer, admin);
@ -972,7 +969,7 @@ void ManageInviteLinksBox(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
container, container,
tr::lng_group_invite_revoked_title(), tr::lng_group_invite_revoked_title(),
st::settingsSubsectionTitle), st::defaultSubsectionTitle),
st::inviteLinkRevokedTitlePadding)); st::inviteLinkRevokedTitlePadding));
const auto revoked = AddLinksList( const auto revoked = AddLinksList(
show, show,

View file

@ -611,7 +611,7 @@ template <typename Flags>
return checkView; return checkView;
} else { } else {
const auto button = Settings::AddButton( const auto button = Settings::AddButtonWithIcon(
verticalLayout, verticalLayout,
rpl::single(entry.label), rpl::single(entry.label),
st, st,

View file

@ -7,48 +7,599 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "boxes/peers/edit_peer_reactions.h" #include "boxes/peers/edit_peer_reactions.h"
#include "boxes/reactions_settings_box.h" // AddReactionAnimatedIcon #include "base/event_filter.h"
#include "data/data_message_reactions.h" #include "chat_helpers/tabbed_panel.h"
#include "data/data_peer.h" #include "chat_helpers/tabbed_selector.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_document.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/view/reactions/history_view_reactions_selector.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "ui/boxes/boost_box.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/layers/generic_box.h" #include "ui/layers/generic_box.h"
#include "ui/widgets/buttons.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "settings/settings_common.h" #include "ui/vertical_list.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_settings.h" #include "window/window_session_controller_link_info.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_settings.h"
#include "styles/style_layers.h"
#include <QtWidgets/QTextEdit>
#include <QtGui/QTextBlock>
#include <QtGui/QTextDocumentFragment>
namespace {
constexpr auto kDisabledEmojiOpacity = 0.4;
struct UniqueCustomEmojiContext {
std::vector<DocumentId> ids;
Fn<bool(DocumentId)> applyHardLimit;
int hardLimit = 0;
int hardLimitChecked = 0;
bool hardLimitHit = false;
};
class MaybeDisabledEmoji final : public Ui::Text::CustomEmoji {
public:
MaybeDisabledEmoji(
std::unique_ptr<CustomEmoji> wrapped,
Fn<bool()> enabled);
int width() override;
QString entityData() override;
void paint(QPainter &p, const Context &context) override;
void unload() override;
bool ready() override;
bool readyInDefaultState() override;
private:
const std::unique_ptr<Ui::Text::CustomEmoji> _wrapped;
const Fn<bool()> _enabled;
};
MaybeDisabledEmoji::MaybeDisabledEmoji(
std::unique_ptr<CustomEmoji> wrapped,
Fn<bool()> enabled)
: _wrapped(std::move(wrapped))
, _enabled(std::move(enabled)) {
}
int MaybeDisabledEmoji::width() {
return _wrapped->width();
}
QString MaybeDisabledEmoji::entityData() {
return _wrapped->entityData();
}
void MaybeDisabledEmoji::paint(QPainter &p, const Context &context) {
const auto disabled = !_enabled();
const auto was = disabled ? p.opacity() : 1.;
if (disabled) {
p.setOpacity(kDisabledEmojiOpacity);
}
_wrapped->paint(p, context);
if (disabled) {
p.setOpacity(was);
}
}
void MaybeDisabledEmoji::unload() {
_wrapped->unload();
}
bool MaybeDisabledEmoji::ready() {
return _wrapped->ready();
}
bool MaybeDisabledEmoji::readyInDefaultState() {
return _wrapped->readyInDefaultState();
}
[[nodiscard]] QString AllowOnlyCustomEmojiProcessor(QStringView mimeTag) {
auto all = TextUtilities::SplitTags(mimeTag);
for (auto i = all.begin(); i != all.end();) {
if (Ui::InputField::IsCustomEmojiLink(*i)) {
++i;
} else {
i = all.erase(i);
}
}
return TextUtilities::JoinTag(all);
}
[[nodiscard]] bool AllowOnlyCustomEmojiMimeDataHook(
not_null<const QMimeData*> data,
Ui::InputField::MimeAction action) {
if (action == Ui::InputField::MimeAction::Check) {
const auto textMime = TextUtilities::TagsTextMimeType();
const auto tagsMime = TextUtilities::TagsMimeType();
if (!data->hasFormat(textMime) || !data->hasFormat(tagsMime)) {
return false;
}
auto text = QString::fromUtf8(data->data(textMime));
auto tags = TextUtilities::DeserializeTags(
data->data(tagsMime),
text.size());
auto checkedTill = 0;
ranges::sort(tags, ranges::less(), &TextWithTags::Tag::offset);
for (const auto &tag : tags) {
if (tag.offset != checkedTill
|| AllowOnlyCustomEmojiProcessor(tag.id) != tag.id) {
return false;
}
checkedTill += tag.length;
}
return true;
} else if (action == Ui::InputField::MimeAction::Insert) {
return false;
}
Unexpected("Action in MimeData hook.");
}
[[nodiscard]] std::vector<Data::ReactionId> DefaultSelected() {
const auto like = QString::fromUtf8("\xf0\x9f\x91\x8d");
const auto dislike = QString::fromUtf8("\xf0\x9f\x91\x8e");
return { Data::ReactionId{ like }, Data::ReactionId{ dislike } };
}
[[nodiscard]] bool RemoveNonCustomEmojiFragment(
not_null<QTextDocument*> document,
UniqueCustomEmojiContext &context) {
context.ids.clear();
context.hardLimitChecked = 0;
auto removeFrom = 0;
auto removeTill = 0;
auto block = document->begin();
for (auto j = block.begin(); !j.atEnd(); ++j) {
const auto fragment = j.fragment();
Assert(fragment.isValid());
removeTill = removeFrom = fragment.position();
const auto format = fragment.charFormat();
if (format.objectType() != Ui::InputField::kCustomEmojiFormat) {
removeTill += fragment.length();
break;
}
const auto id = format.property(Ui::InputField::kCustomEmojiId);
const auto documentId = id.toULongLong();
const auto applyHardLimit = context.applyHardLimit(documentId);
if (ranges::contains(context.ids, documentId)) {
removeTill += fragment.length();
break;
} else if (applyHardLimit
&& context.hardLimitChecked >= context.hardLimit) {
context.hardLimitHit = true;
removeTill += fragment.length();
break;
}
context.ids.push_back(documentId);
if (applyHardLimit) {
++context.hardLimitChecked;
}
}
while (removeTill == removeFrom) {
block = block.next();
if (block == document->end()) {
return false;
}
removeTill = block.position();
}
Ui::PrepareFormattingOptimization(document);
auto cursor = QTextCursor(document);
cursor.setPosition(removeFrom);
cursor.setPosition(removeTill, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
return true;
}
bool RemoveNonCustomEmoji(
not_null<QTextDocument*> document,
UniqueCustomEmojiContext &context) {
if (!RemoveNonCustomEmojiFragment(document, context)) {
return false;
}
while (RemoveNonCustomEmojiFragment(document, context)) {
}
return true;
}
void SetupOnlyCustomEmojiField(
not_null<Ui::InputField*> field,
Fn<void(std::vector<DocumentId>, bool)> callback,
Fn<bool(DocumentId)> applyHardLimit,
int customHardLimit) {
field->setTagMimeProcessor(AllowOnlyCustomEmojiProcessor);
field->setMimeDataHook(AllowOnlyCustomEmojiMimeDataHook);
struct State {
bool processing = false;
bool pending = false;
};
const auto state = field->lifetime().make_state<State>();
field->changes(
) | rpl::start_with_next([=] {
state->pending = true;
if (state->processing) {
return;
}
auto context = UniqueCustomEmojiContext{
.applyHardLimit = applyHardLimit,
.hardLimit = customHardLimit,
};
auto changed = false;
state->processing = true;
while (state->pending) {
state->pending = false;
const auto document = field->rawTextEdit()->document();
const auto pageSize = document->pageSize();
QTextCursor(document).joinPreviousEditBlock();
if (RemoveNonCustomEmoji(document, context)) {
changed = true;
}
state->processing = false;
QTextCursor(document).endEditBlock();
if (document->pageSize() != pageSize) {
document->setPageSize(pageSize);
}
}
callback(context.ids, context.hardLimitHit);
if (changed) {
field->forceProcessContentsChanges();
}
}, field->lifetime());
}
[[nodiscard]] TextWithTags ComposeEmojiList(
not_null<Data::Reactions*> reactions,
const std::vector<Data::ReactionId> &list) {
auto result = TextWithTags();
const auto size = [&] {
return int(result.text.size());
};
auto added = base::flat_set<Data::ReactionId>();
const auto &all = reactions->list(Data::Reactions::Type::All);
const auto add = [&](Data::ReactionId id) {
if (!added.emplace(id).second) {
return;
}
auto unifiedId = id.custom();
const auto offset = size();
if (unifiedId) {
result.text.append('@');
} else {
result.text.append(id.emoji());
const auto i = ranges::find(all, id, &Data::Reaction::id);
if (i == end(all)) {
return;
}
unifiedId = i->selectAnimation->id;
}
const auto data = Data::SerializeCustomEmojiId(unifiedId);
const auto tag = Ui::InputField::CustomEmojiLink(data);
result.tags.append({ offset, size() - offset, tag });
};
for (const auto &id : list) {
add(id);
}
return result;
}
enum class ReactionsSelectorState {
Active,
Disabled,
Hidden,
};
struct ReactionsSelectorArgs {
not_null<QWidget*> outer;
not_null<Window::SessionController*> controller;
rpl::producer<QString> title;
std::vector<Data::Reaction> list;
std::vector<Data::ReactionId> selected;
Fn<void(std::vector<Data::ReactionId>, bool)> callback;
rpl::producer<ReactionsSelectorState> stateValue;
int customAllowed = 0;
int customHardLimit = 0;
bool all = false;
};
object_ptr<Ui::RpWidget> AddReactionsSelector(
not_null<Ui::RpWidget*> parent,
ReactionsSelectorArgs &&args) {
using namespace ChatHelpers;
using HistoryView::Reactions::UnifiedFactoryOwner;
auto result = object_ptr<Ui::InputField>(
parent,
st::manageGroupReactionsField,
Ui::InputField::Mode::MultiLine,
std::move(args.title));
const auto raw = result.data();
const auto session = &args.controller->session();
const auto owner = &session->data();
const auto reactions = &owner->reactions();
const auto customAllowed = args.customAllowed;
struct State {
std::unique_ptr<Ui::RpWidget> overlay;
std::unique_ptr<UnifiedFactoryOwner> unifiedFactoryOwner;
UnifiedFactoryOwner::RecentFactory factory;
base::flat_set<DocumentId> allowed;
rpl::lifetime focusLifetime;
};
const auto state = raw->lifetime().make_state<State>();
state->unifiedFactoryOwner = std::make_unique<UnifiedFactoryOwner>(
session,
reactions->list(Data::Reactions::Type::Active));
state->factory = state->unifiedFactoryOwner->factory();
const auto customEmojiPaused = [controller = args.controller] {
return controller->isGifPausedAtLeastFor(PauseReason::Layer);
};
raw->setCustomEmojiFactory([=](QStringView data, Fn<void()> update)
-> std::unique_ptr<Ui::Text::CustomEmoji> {
const auto id = Data::ParseCustomEmojiData(data);
auto result = owner->customEmojiManager().create(
data,
std::move(update));
if (state->unifiedFactoryOwner->lookupReactionId(id).custom()) {
return std::make_unique<MaybeDisabledEmoji>(
std::move(result),
[=] { return state->allowed.contains(id); });
}
using namespace Ui::Text;
return std::make_unique<FirstFrameEmoji>(std::move(result));
}, std::move(customEmojiPaused));
const auto callback = args.callback;
const auto isCustom = [=](DocumentId id) {
return state->unifiedFactoryOwner->lookupReactionId(id).custom();
};
SetupOnlyCustomEmojiField(raw, [=](
std::vector<DocumentId> ids,
bool hardLimitHit) {
auto allowed = base::flat_set<DocumentId>();
auto reactions = std::vector<Data::ReactionId>();
reactions.reserve(ids.size());
allowed.reserve(std::min(customAllowed, int(ids.size())));
const auto owner = state->unifiedFactoryOwner.get();
for (const auto id : ids) {
const auto reactionId = owner->lookupReactionId(id);
if (reactionId.custom() && allowed.size() < customAllowed) {
allowed.emplace(id);
}
reactions.push_back(reactionId);
}
if (state->allowed != allowed) {
state->allowed = std::move(allowed);
raw->rawTextEdit()->update();
}
callback(std::move(reactions), hardLimitHit);
}, isCustom, args.customHardLimit);
raw->setTextWithTags(ComposeEmojiList(reactions, args.selected));
using SelectorState = ReactionsSelectorState;
std::move(
args.stateValue
) | rpl::start_with_next([=](SelectorState value) {
switch (value) {
case SelectorState::Active:
state->overlay = nullptr;
state->focusLifetime.destroy();
if (raw->empty()) {
raw->setTextWithTags(
ComposeEmojiList(reactions, DefaultSelected()));
}
raw->setDisabled(false);
raw->setFocusFast();
break;
case SelectorState::Disabled:
state->overlay = std::make_unique<Ui::RpWidget>(parent);
state->overlay->show();
raw->geometryValue() | rpl::start_with_next([=](QRect rect) {
state->overlay->setGeometry(rect);
}, state->overlay->lifetime());
state->overlay->paintRequest() | rpl::start_with_next([=](QRect clip) {
auto color = st::boxBg->c;
color.setAlphaF(0.5);
QPainter(state->overlay.get()).fillRect(
clip,
color);
}, state->overlay->lifetime());
[[fallthrough]];
case SelectorState::Hidden:
if (Ui::InFocusChain(raw)) {
raw->parentWidget()->setFocus();
}
raw->setDisabled(true);
raw->focusedChanges(
) | rpl::start_with_next([=](bool focused) {
if (focused) {
raw->parentWidget()->setFocus();
}
}, state->focusLifetime);
break;
}
}, raw->lifetime());
const auto toggle = Ui::CreateChild<Ui::IconButton>(
parent.get(),
st::manageGroupReactions);
const auto panel = Ui::CreateChild<TabbedPanel>(
args.outer.get(),
args.controller,
object_ptr<TabbedSelector>(
nullptr,
args.controller->uiShow(),
Window::GifPauseReason::Layer,
(args.all
? TabbedSelector::Mode::FullReactions
: TabbedSelector::Mode::RecentReactions)));
panel->selector()->provideRecentEmoji(
state->unifiedFactoryOwner->unifiedIdsList());
panel->setDesiredHeightValues(
1.,
st::emojiPanMinHeight / 2,
st::emojiPanMinHeight);
panel->hide();
panel->selector()->customEmojiChosen(
) | rpl::start_with_next([=](ChatHelpers::FileChosen data) {
Data::InsertCustomEmoji(raw, data.document);
}, panel->lifetime());
const auto updateEmojiPanelGeometry = [=] {
const auto parent = panel->parentWidget();
const auto global = toggle->mapToGlobal({ 0, 0 });
const auto local = parent->mapFromGlobal(global);
panel->moveBottomRight(
local.y(),
local.x() + toggle->width() * 3);
};
const auto scheduleUpdateEmojiPanelGeometry = [=] {
// updateEmojiPanelGeometry uses not only container geometry, but
// also container children geometries that will be updated later.
crl::on_main(raw, updateEmojiPanelGeometry);
};
const auto filterCallback = [=](not_null<QEvent*> event) {
const auto type = event->type();
if (type == QEvent::Move || type == QEvent::Resize) {
scheduleUpdateEmojiPanelGeometry();
}
return base::EventFilterResult::Continue;
};
for (auto widget = (QWidget*)raw
; widget && widget != args.outer
; widget = widget->parentWidget()) {
base::install_event_filter(raw, widget, filterCallback);
}
base::install_event_filter(raw, args.outer, filterCallback);
scheduleUpdateEmojiPanelGeometry();
toggle->installEventFilter(panel);
toggle->addClickHandler([=] {
panel->toggleAnimated();
});
raw->geometryValue() | rpl::start_with_next([=](QRect geometry) {
toggle->move(
geometry.x() + geometry.width() - toggle->width(),
geometry.y() + geometry.height() - toggle->height());
updateEmojiPanelGeometry();
}, toggle->lifetime());
return result;
}
void AddReactionsText(
not_null<Ui::VerticalLayout*> container,
not_null<Window::SessionNavigation*> navigation,
int allowedCustomReactions,
rpl::producer<int> customCountValue,
Fn<void(int required)> askForBoosts) {
auto ownedInner = object_ptr<Ui::VerticalLayout>(container);
const auto inner = ownedInner.data();
const auto count = inner->lifetime().make_state<rpl::variable<int>>(
std::move(customCountValue));
container->add(
object_ptr<Ui::DividerLabel>(
container,
std::move(ownedInner),
st::defaultBoxDividerLabelPadding),
QMargins(0, st::manageGroupReactionsTextSkip, 0, 0));
const auto label = inner->add(
object_ptr<Ui::FlatLabel>(
inner,
tr::lng_manage_peer_reactions_own(
lt_link,
tr::lng_manage_peer_reactions_own_link(
) | Ui::Text::ToLink(),
Ui::Text::WithEntities),
st::boxDividerLabel));
const auto weak = base::make_weak(navigation);
label->setClickHandlerFilter([=](const auto &...) {
if (const auto strong = weak.get()) {
strong->showPeerByLink(Window::PeerByLinkInfo{
.usernameOrId = u"stickers"_q,
.resolveType = Window::ResolveType::Mention,
});
}
return false;
});
auto countString = count->value() | rpl::map([](int count) {
return TextWithEntities{ QString::number(count) };
});
auto needs = rpl::combine(
tr::lng_manage_peer_reactions_level(
lt_count,
count->value() | tr::to_count(),
lt_same_count,
std::move(countString),
Ui::Text::RichLangValue),
tr::lng_manage_peer_reactions_boost(
lt_link,
tr::lng_manage_peer_reactions_boost_link() | Ui::Text::ToLink(),
Ui::Text::RichLangValue)
) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) {
a.append(' ').append(std::move(b));
return std::move(a);
});
const auto wrap = inner->add(
object_ptr<Ui::SlideWrap<Ui::FlatLabel>>(
inner,
object_ptr<Ui::FlatLabel>(
inner,
std::move(needs),
st::boxDividerLabel),
QMargins{ 0, st::normalFont->height, 0, 0 }));
wrap->toggleOn(count->value() | rpl::map(
rpl::mappers::_1 > allowedCustomReactions
));
wrap->finishAnimating();
wrap->entity()->setClickHandlerFilter([=](const auto &...) {
askForBoosts(count->current());
return false;
});
}
} // namespace
void EditAllowedReactionsBox( void EditAllowedReactionsBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> navigation, EditAllowedReactionsArgs &&args) {
bool isGroup,
const std::vector<Data::Reaction> &list,
const Data::AllowedReactions &allowed,
Fn<void(const Data::AllowedReactions &)> callback) {
using namespace Data; using namespace Data;
using namespace rpl::mappers; using namespace rpl::mappers;
const auto iconHeight = st::editPeerReactionsPreview;
box->setTitle(tr::lng_manage_peer_reactions()); box->setTitle(tr::lng_manage_peer_reactions());
box->setWidth(st::boxWideWidth);
enum class Option { enum class Option {
All, All,
Some, Some,
None, None,
}; };
using SelectorState = ReactionsSelectorState;
struct State { struct State {
base::flat_map<ReactionId, not_null<Ui::SettingsButton*>> toggles;
rpl::variable<Option> option; // For groups. rpl::variable<Option> option; // For groups.
rpl::variable<bool> anyToggled; // For channels. rpl::variable<SelectorState> selectorState;
rpl::event_stream<bool> forceToggleAll; // For channels. std::vector<Data::ReactionId> selected;
rpl::variable<int> customCount;
}; };
const auto allowed = args.allowed;
const auto optionInitial = (allowed.type != AllowedReactionsType::Some) const auto optionInitial = (allowed.type != AllowedReactionsType::Some)
? Option::All ? Option::All
: allowed.some.empty() : allowed.some.empty()
@ -56,57 +607,24 @@ void EditAllowedReactionsBox(
: Option::Some; : Option::Some;
const auto state = box->lifetime().make_state<State>(State{ const auto state = box->lifetime().make_state<State>(State{
.option = optionInitial, .option = optionInitial,
.anyToggled = (optionInitial != Option::None),
}); });
const auto collect = [=] {
auto result = AllowedReactions();
if (!isGroup || state->option.current() == Option::Some) {
result.some.reserve(state->toggles.size());
for (const auto &[id, button] : state->toggles) {
if (button->toggled()) {
result.some.push_back(id);
}
}
}
result.type = isGroup
? (state->option.current() != Option::All
? AllowedReactionsType::Some
: AllowedReactionsType::All)
: (result.some.size() == state->toggles.size())
? AllowedReactionsType::Default
: AllowedReactionsType::Some;
return result;
};
const auto container = box->verticalLayout(); const auto container = box->verticalLayout();
const auto isGroup = args.isGroup;
const auto enabled = isGroup ? nullptr : Settings::AddButton( const auto enabled = isGroup
container, ? nullptr
tr::lng_manage_peer_reactions_enable(), : container->add(object_ptr<Ui::SettingsButton>(
st::manageGroupButton.button container.get(),
).get(); tr::lng_manage_peer_reactions_enable(),
if (enabled && !list.empty()) { st::manageGroupNoIconButton.button));
AddReactionAnimatedIcon(
enabled,
enabled->sizeValue(
) | rpl::map([=](const QSize &size) {
return QPoint(
st::manageGroupButton.iconPosition.x(),
(size.height() - iconHeight) / 2);
}),
iconHeight,
list.front(),
rpl::never<>(),
rpl::never<>(),
&enabled->lifetime());
}
if (enabled) { if (enabled) {
enabled->toggleOn(state->anyToggled.value()); enabled->toggleOn(rpl::single(optionInitial != Option::None));
enabled->toggledChanges( enabled->toggledValue(
) | rpl::filter([=](bool value) { ) | rpl::start_with_next([=](bool value) {
return (value != state->anyToggled.current()); state->selectorState = value
}) | rpl::start_to_stream(state->forceToggleAll, enabled->lifetime()); ? SelectorState::Active
: SelectorState::Disabled;
}, enabled->lifetime());
} }
const auto group = std::make_shared<Ui::RadioenumGroup<Option>>( const auto group = std::make_shared<Ui::RadioenumGroup<Option>>(
state->option.current()); state->option.current());
@ -138,8 +656,8 @@ void EditAllowedReactionsBox(
} }
Unexpected("Option value in EditAllowedReactionsBox."); Unexpected("Option value in EditAllowedReactionsBox.");
}; };
Settings::AddSkip(container); Ui::AddSkip(container);
Settings::AddDividerText( Ui::AddDividerText(
container, container,
(isGroup (isGroup
? (state->option.value() ? (state->option.value()
@ -152,102 +670,106 @@ void EditAllowedReactionsBox(
container, container,
object_ptr<Ui::VerticalLayout>(container))); object_ptr<Ui::VerticalLayout>(container)));
if (wrap) { if (wrap) {
wrap->toggleOn(state->option.value() | rpl::map(_1 == Option::Some)); wrap->toggleOn(state->option.value(
) | rpl::map(_1 == Option::Some) | rpl::before_next([=](bool some) {
if (!some) {
state->selectorState = SelectorState::Hidden;
}
}) | rpl::after_next([=](bool some) {
if (some) {
state->selectorState = SelectorState::Active;
}
}));
wrap->finishAnimating(); wrap->finishAnimating();
} }
const auto reactions = wrap ? wrap->entity() : container.get(); const auto reactions = wrap ? wrap->entity() : container.get();
Settings::AddSkip(reactions); Ui::AddSkip(reactions);
Settings::AddSubsectionTitle(
reactions,
(enabled
? tr::lng_manage_peer_reactions_available()
: tr::lng_manage_peer_reactions_some_title()));
const auto like = QString::fromUtf8("\xf0\x9f\x91\x8d"); const auto all = args.list;
const auto dislike = QString::fromUtf8("\xf0\x9f\x91\x8e"); auto selected = (allowed.type != AllowedReactionsType::Some)
const auto activeOnStart = [&](const ReactionId &id) { ? (all
const auto inSome = ranges::contains(allowed.some, id); | ranges::views::transform(&Data::Reaction::id)
if (!isGroup) { | ranges::to_vector)
return inSome || (allowed.type != AllowedReactionsType::Some); : allowed.some;
} const auto changed = [=](
const auto emoji = id.emoji(); std::vector<Data::ReactionId> chosen,
const auto isDefault = (emoji == like) || (emoji == dislike); bool hardLimitHit) {
return (allowed.type != AllowedReactionsType::Some) state->selected = std::move(chosen);
? isDefault state->customCount = ranges::count_if(
: (inSome || (isDefault && allowed.some.empty())); state->selected,
}; &Data::ReactionId::custom);
const auto add = [&](const Reaction &entry) { if (hardLimitHit) {
const auto button = Settings::AddButton( box->uiShow()->showToast(
reactions, tr::lng_manage_peer_reactions_limit(tr::now));
rpl::single(entry.title),
st::manageGroupButton.button);
AddReactionAnimatedIcon(
button,
button->sizeValue(
) | rpl::map([=](const QSize &size) {
return QPoint(
st::editPeerReactionsIconLeft,
(size.height() - iconHeight) / 2);
}),
iconHeight,
entry,
button->events(
) | rpl::filter([=](not_null<QEvent*> event) {
return event->type() == QEvent::Enter;
}) | rpl::to_empty,
rpl::never<>(),
&button->lifetime());
state->toggles.emplace(entry.id, button);
button->toggleOn(rpl::single(
activeOnStart(entry.id)
) | rpl::then(enabled
? (state->forceToggleAll.events() | rpl::type_erased())
: rpl::never<bool>()
));
if (enabled) {
button->toggledChanges(
) | rpl::start_with_next([=](bool toggled) {
if (toggled) {
state->anyToggled = true;
} else if (collect().some.empty()) {
state->anyToggled = false;
}
}, button->lifetime());
} }
}; };
for (const auto &entry : list) { changed(selected.empty() ? DefaultSelected() : std::move(selected), {});
add(entry); reactions->add(AddReactionsSelector(reactions, {
} .outer = box->getDelegate()->outerContainer(),
for (const auto &id : allowed.some) { .controller = args.navigation->parentController(),
if (const auto customId = id.custom()) { .title = (enabled
// Some possible forward compatibility. ? tr::lng_manage_peer_reactions_available()
const auto button = Settings::AddButton( : tr::lng_manage_peer_reactions_some_title()),
reactions, .list = all,
rpl::single(u"Custom reaction"_q), .selected = state->selected,
st::manageGroupButton.button); .callback = changed,
AddReactionCustomIcon( .stateValue = state->selectorState.value(),
button, .customAllowed = args.allowedCustomReactions,
button->sizeValue( .customHardLimit = args.customReactionsHardLimit,
) | rpl::map([=](const QSize &size) { .all = !args.isGroup,
return QPoint( }), st::boxRowPadding);
st::editPeerReactionsIconLeft,
(size.height() - iconHeight) / 2); box->setFocusCallback([=] {
}), if (!wrap || state->option.current() == Option::Some) {
iconHeight, state->selectorState.force_assign(SelectorState::Active);
navigation->parentController(),
customId,
rpl::never<>(),
&button->lifetime());
state->toggles.emplace(id, button);
button->toggleOn(rpl::single(true));
} }
});
if (!isGroup) {
AddReactionsText(
container,
args.navigation,
args.allowedCustomReactions,
state->customCount.value(),
args.askForBoosts);
} }
const auto collect = [=] {
auto result = AllowedReactions();
if (isGroup
? (state->option.current() == Option::Some)
: (enabled->toggled())) {
result.some = state->selected;
}
auto some = result.some;
auto simple = all | ranges::views::transform(
&Data::Reaction::id
) | ranges::to_vector;
ranges::sort(some);
ranges::sort(simple);
result.type = isGroup
? (state->option.current() != Option::All
? AllowedReactionsType::Some
: AllowedReactionsType::All)
: (some == simple)
? AllowedReactionsType::Default
: AllowedReactionsType::Some;
return result;
};
box->addButton(tr::lng_settings_save(), [=] { box->addButton(tr::lng_settings_save(), [=] {
const auto result = collect(); const auto result = collect();
if (!isGroup) {
const auto custom = ranges::count_if(
result.some,
&Data::ReactionId::custom);
if (custom > args.allowedCustomReactions) {
args.askForBoosts(custom);
return;
}
}
box->closeBox(); box->closeBox();
callback(result); args.save(result);
}); });
box->addButton(tr::lng_cancel(), [=] { box->addButton(tr::lng_cancel(), [=] {
box->closeBox(); box->closeBox();

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
class PeerData; #include "data/data_peer.h"
namespace Data { namespace Data {
struct Reaction; struct Reaction;
@ -22,13 +22,20 @@ namespace Window {
class SessionNavigation; class SessionNavigation;
} // namespace Window } // namespace Window
struct EditAllowedReactionsArgs {
not_null<Window::SessionNavigation*> navigation;
int allowedCustomReactions = 0;
int customReactionsHardLimit = 0;
bool isGroup = false;
std::vector<Data::Reaction> list;
Data::AllowedReactions allowed;
Fn<void(int required)> askForBoosts;
Fn<void(const Data::AllowedReactions &)> save;
};
void EditAllowedReactionsBox( void EditAllowedReactionsBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> navigation, EditAllowedReactionsArgs &&args);
bool isGroup,
const std::vector<Data::Reaction> &list,
const Data::AllowedReactions &allowed,
Fn<void(const Data::AllowedReactions &)> callback);
void SaveAllowedReactions( void SaveAllowedReactions(
not_null<PeerData*> peer, not_null<PeerData*> peer,

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h" #include "base/unixtime.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "ui/round_rect.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "mtproto/sender.h"
namespace Window { namespace Window {
class SessionNavigation; class SessionNavigation;

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/vertical_list.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
@ -44,7 +45,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_settings.h"
namespace { namespace {
@ -218,9 +218,9 @@ void Controller::createContent() {
object_ptr<Ui::VerticalLayout>(_wrap.get()))); object_ptr<Ui::VerticalLayout>(_wrap.get())));
const auto wrap = _controls.whoSendWrap->entity(); const auto wrap = _controls.whoSendWrap->entity();
AddSkip(wrap); Ui::AddSkip(wrap);
if (_dataSavedValue->hasLinkedChat) { if (_dataSavedValue->hasLinkedChat) {
AddSubsectionTitle(wrap, tr::lng_manage_peer_send_title()); Ui::AddSubsectionTitle(wrap, tr::lng_manage_peer_send_title());
_controls.joinToWrite = wrap->add(EditPeerInfoBox::CreateButton( _controls.joinToWrite = wrap->add(EditPeerInfoBox::CreateButton(
wrap, wrap,
@ -264,16 +264,16 @@ void Controller::createContent() {
_dataSavedValue->requestToJoin = toggled; _dataSavedValue->requestToJoin = toggled;
}, wrap->lifetime()); }, wrap->lifetime());
AddSkip(wrap); Ui::AddSkip(wrap);
AddDividerText( Ui::AddDividerText(
wrap, wrap,
rpl::conditional( rpl::conditional(
std::move(joinToWrite), std::move(joinToWrite),
tr::lng_manage_peer_send_approve_members_about(), tr::lng_manage_peer_send_approve_members_about(),
tr::lng_manage_peer_send_only_members_about())); tr::lng_manage_peer_send_only_members_about()));
} }
AddSkip(_wrap.get()); Ui::AddSkip(_wrap.get());
AddSubsectionTitle( Ui::AddSubsectionTitle(
_wrap.get(), _wrap.get(),
tr::lng_manage_peer_no_forwards_title()); tr::lng_manage_peer_no_forwards_title());
_controls.noForwards = _wrap->add(EditPeerInfoBox::CreateButton( _controls.noForwards = _wrap->add(EditPeerInfoBox::CreateButton(
@ -289,8 +289,8 @@ void Controller::createContent() {
) | rpl::start_with_next([=](bool toggled) { ) | rpl::start_with_next([=](bool toggled) {
_dataSavedValue->noForwards = toggled; _dataSavedValue->noForwards = toggled;
}, _wrap->lifetime()); }, _wrap->lifetime());
AddSkip(_wrap.get()); Ui::AddSkip(_wrap.get());
AddDividerText( Ui::AddDividerText(
_wrap.get(), _wrap.get(),
(_isGroup (_isGroup
? tr::lng_manage_peer_no_forwards_about ? tr::lng_manage_peer_no_forwards_about
@ -419,13 +419,13 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
const auto container = result->entity(); const auto container = result->entity();
using namespace Settings; using namespace Settings;
AddSkip(container); Ui::AddSkip(container);
container->add( container->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
container, container,
tr::lng_create_group_link(), tr::lng_create_group_link(),
st::settingsSubsectionTitle), st::defaultSubsectionTitle),
st::settingsSubsectionTitlePadding); st::defaultSubsectionTitlePadding);
const auto placeholder = container->add( const auto placeholder = container->add(
object_ptr<Ui::RpWidget>(container), object_ptr<Ui::RpWidget>(container),
@ -453,7 +453,7 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
AddUsernameCheckLabel(container, _usernameCheckInfo.events()); AddUsernameCheckLabel(container, _usernameCheckInfo.events());
AddDividerText( Ui::AddDividerText(
container, container,
tr::lng_create_channel_link_about()); tr::lng_create_channel_link_about());
@ -675,7 +675,7 @@ object_ptr<Ui::RpWidget> Controller::createInviteLinkBlock() {
using namespace Settings; using namespace Settings;
if (_dataSavedValue) { if (_dataSavedValue) {
AddSkip(container); Ui::AddSkip(container);
AddSubsectionTitle(container, tr::lng_create_permanent_link_title()); AddSubsectionTitle(container, tr::lng_create_permanent_link_title());
} }
@ -686,9 +686,9 @@ object_ptr<Ui::RpWidget> Controller::createInviteLinkBlock() {
_peer->session().user(), _peer->session().user(),
nullptr); nullptr);
AddSkip(container); Ui::AddSkip(container);
AddDividerText( Ui::AddDividerText(
container, container,
((_peer->isMegagroup() || _peer->asChat()) ((_peer->isMegagroup() || _peer->asChat())
? tr::lng_group_invite_about_permanent_group() ? tr::lng_group_invite_about_permanent_group()

View file

@ -14,10 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h" #include "data/data_user.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/layers/show.h" #include "ui/layers/show.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "ui/text/text_utilities.h" // Ui::Text::RichLangValue. #include "ui/text/text_utilities.h" // Ui::Text::RichLangValue.
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
@ -25,7 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout_reorder.h" #include "ui/wrap/vertical_layout_reorder.h"
#include "styles/style_boxes.h" // contactsStatusFont. #include "styles/style_boxes.h" // contactsStatusFont.
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_settings.h" #include "styles/style_layers.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
@ -231,15 +231,15 @@ void UsernamesList::rebuild(const Data::Usernames &usernames) {
_container = base::make_unique_q<Ui::VerticalLayout>(this); _container = base::make_unique_q<Ui::VerticalLayout>(this);
{ {
Settings::AddSkip(_container); Ui::AddSkip(_container);
_container->add( _container->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
_container, _container,
_peer->isSelf() _peer->isSelf()
? tr::lng_usernames_subtitle() ? tr::lng_usernames_subtitle()
: tr::lng_channel_usernames_subtitle(), : tr::lng_channel_usernames_subtitle(),
st::settingsSubsectionTitle), st::defaultSubsectionTitle),
st::settingsSubsectionTitlePadding); st::defaultSubsectionTitlePadding);
} }
const auto content = _container->add( const auto content = _container->add(
@ -364,8 +364,8 @@ void UsernamesList::rebuild(const Data::Usernames &usernames) {
}, content->lifetime()); }, content->lifetime());
{ {
Settings::AddSkip(_container); Ui::AddSkip(_container);
Settings::AddDividerText( Ui::AddDividerText(
_container, _container,
_peer->isSelf() _peer->isSelf()
? tr::lng_usernames_description() ? tr::lng_usernames_description()

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "ui/layers/box_content.h"
namespace style { namespace style {
struct ShortInfoCover; struct ShortInfoCover;

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_domain.h" #include "main/main_domain.h"
@ -27,8 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_premium_limits.h" #include "data/data_premium_limits.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "settings/settings_common.h" #include "settings/settings_premium.h" // ShowPremium.
#include "settings/settings_premium.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "styles/style_premium.h" #include "styles/style_premium.h"
@ -48,11 +48,11 @@ struct InfographicDescriptor {
bool complexRatio = false; bool complexRatio = false;
}; };
void AddSubsectionTitle( void AddSubtitle(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
rpl::producer<QString> text) { rpl::producer<QString> text) {
const auto &subtitlePadding = st::settingsButton.padding; const auto &subtitlePadding = st::settingsButton.padding;
Settings::AddSubsectionTitle( Ui::AddSubsectionTitle(
container, container,
std::move(text), std::move(text),
{ 0, subtitlePadding.top(), 0, -subtitlePadding.bottom() }); { 0, subtitlePadding.top(), 0, -subtitlePadding.bottom() });
@ -395,7 +395,7 @@ void SimpleLimitBox(
? box->setPinnedToTopContent(object_ptr<Ui::VerticalLayout>(box)) ? box->setPinnedToTopContent(object_ptr<Ui::VerticalLayout>(box))
: box->verticalLayout(); : box->verticalLayout();
Settings::AddSkip(top, st::premiumInfographicPadding.top()); Ui::AddSkip(top, st::premiumInfographicPadding.top());
Ui::Premium::AddBubbleRow( Ui::Premium::AddBubbleRow(
top, top,
st::defaultPremiumBubble, st::defaultPremiumBubble,
@ -406,7 +406,7 @@ void SimpleLimitBox(
premiumPossible, premiumPossible,
descriptor.phrase, descriptor.phrase,
descriptor.icon); descriptor.icon);
Settings::AddSkip(top, st::premiumLineTextSkip); Ui::AddSkip(top, st::premiumLineTextSkip);
if (premiumPossible) { if (premiumPossible) {
Ui::Premium::AddLimitRow( Ui::Premium::AddLimitRow(
top, top,
@ -417,7 +417,7 @@ void SimpleLimitBox(
(descriptor.complexRatio (descriptor.complexRatio
? (float64(descriptor.current) / descriptor.premiumLimit) ? (float64(descriptor.current) / descriptor.premiumLimit)
: Ui::Premium::kLimitRowRatio)); : Ui::Premium::kLimitRowRatio));
Settings::AddSkip(top, st::premiumInfographicPadding.bottom()); Ui::AddSkip(top, st::premiumInfographicPadding.bottom());
} }
box->setTitle(std::move(title)); box->setTitle(std::move(title));
@ -446,8 +446,8 @@ void SimpleLimitBox(
} }
if (fixed) { if (fixed) {
Settings::AddSkip(top, st::settingsButton.padding.bottom()); Ui::AddSkip(top, st::settingsButton.padding.bottom());
Settings::AddDivider(top); Ui::AddDivider(top);
} }
} }
@ -552,7 +552,7 @@ void ChannelsLimitBox(
{ defaultLimit, current, premiumLimit, &st::premiumIconGroups }, { defaultLimit, current, premiumLimit, &st::premiumIconGroups },
true); true);
AddSubsectionTitle(box->verticalLayout(), tr::lng_channels_leave_title()); AddSubtitle(box->verticalLayout(), tr::lng_channels_leave_title());
const auto delegate = box->lifetime().make_state<InactiveDelegate>(); const auto delegate = box->lifetime().make_state<InactiveDelegate>();
const auto controller = box->lifetime().make_state<InactiveController>( const auto controller = box->lifetime().make_state<InactiveController>(
@ -642,7 +642,7 @@ void PublicLinksLimitBox(
{ defaultLimit, current, premiumLimit, &st::premiumIconLinks }, { defaultLimit, current, premiumLimit, &st::premiumIconLinks },
true); true);
AddSubsectionTitle(box->verticalLayout(), tr::lng_links_revoke_title()); AddSubtitle(box->verticalLayout(), tr::lng_links_revoke_title());
const auto delegate = box->lifetime().make_state<InactiveDelegate>(); const auto delegate = box->lifetime().make_state<InactiveDelegate>();
const auto controller = box->lifetime().make_state<PublicsController>( const auto controller = box->lifetime().make_state<PublicsController>(
@ -1067,7 +1067,7 @@ void AccountsLimitBox(
const auto top = box->verticalLayout(); const auto top = box->verticalLayout();
const auto group = std::make_shared<Ui::RadiobuttonGroup>(0); const auto group = std::make_shared<Ui::RadiobuttonGroup>(0);
Settings::AddSkip(top, st::premiumInfographicPadding.top()); Ui::AddSkip(top, st::premiumInfographicPadding.top());
Ui::Premium::AddBubbleRow( Ui::Premium::AddBubbleRow(
top, top,
st::defaultPremiumBubble, st::defaultPremiumBubble,
@ -1082,7 +1082,7 @@ void AccountsLimitBox(
premiumPossible, premiumPossible,
std::nullopt, std::nullopt,
&st::premiumIconAccounts); &st::premiumIconAccounts);
Settings::AddSkip(top, st::premiumLineTextSkip); Ui::AddSkip(top, st::premiumLineTextSkip);
if (premiumPossible) { if (premiumPossible) {
Ui::Premium::AddLimitRow( Ui::Premium::AddLimitRow(
top, top,
@ -1090,7 +1090,7 @@ void AccountsLimitBox(
(QString::number(std::max(current, defaultLimit) + 1) (QString::number(std::max(current, defaultLimit) + 1)
+ ((current + 1 == premiumLimit) ? "" : "+")), + ((current + 1 == premiumLimit) ? "" : "+")),
QString::number(defaultLimit)); QString::number(defaultLimit));
Settings::AddSkip(top, st::premiumInfographicPadding.bottom()); Ui::AddSkip(top, st::premiumInfographicPadding.bottom());
} }
box->setTitle(tr::lng_accounts_limit_title()); box->setTitle(tr::lng_accounts_limit_title());

View file

@ -32,7 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "settings/settings_common.h" #include "ui/vertical_list.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "history/view/media/history_view_sticker.h" #include "history/view/media/history_view_sticker.h"
@ -93,6 +93,8 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[nodiscard]] rpl::producer<QString> SectionTitle(PremiumPreview section) { [[nodiscard]] rpl::producer<QString> SectionTitle(PremiumPreview section) {
switch (section) { switch (section) {
case PremiumPreview::Wallpapers:
return tr::lng_premium_summary_subtitle_wallpapers();
case PremiumPreview::Stories: case PremiumPreview::Stories:
return tr::lng_premium_summary_subtitle_stories(); return tr::lng_premium_summary_subtitle_stories();
case PremiumPreview::DoubleLimits: case PremiumPreview::DoubleLimits:
@ -127,6 +129,8 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[nodiscard]] rpl::producer<QString> SectionAbout(PremiumPreview section) { [[nodiscard]] rpl::producer<QString> SectionAbout(PremiumPreview section) {
switch (section) { switch (section) {
case PremiumPreview::Wallpapers:
return tr::lng_premium_summary_about_wallpapers();
case PremiumPreview::Stories: case PremiumPreview::Stories:
return tr::lng_premium_summary_about_stories(); return tr::lng_premium_summary_about_stories();
case PremiumPreview::DoubleLimits: case PremiumPreview::DoubleLimits:
@ -471,6 +475,7 @@ struct VideoPreviewDocument {
case PremiumPreview::ProfileBadge: return "profile_badge"; case PremiumPreview::ProfileBadge: return "profile_badge";
case PremiumPreview::AnimatedUserpics: return "animated_userpics"; case PremiumPreview::AnimatedUserpics: return "animated_userpics";
case PremiumPreview::RealTimeTranslation: return "translations"; case PremiumPreview::RealTimeTranslation: return "translations";
case PremiumPreview::Wallpapers: return "wallpapers";
} }
return ""; return "";
}(); }();
@ -1488,7 +1493,7 @@ void UpgradedStoriesPreviewBox(
st::defaultPremiumLimits, st::defaultPremiumLimits,
std::move(entries)); std::move(entries));
Settings::AddDividerText( Ui::AddDividerText(
box->verticalLayout(), box->verticalLayout(),
tr::lng_premium_stories_about_mobile()); tr::lng_premium_stories_about_mobile());
} }

View file

@ -60,6 +60,7 @@ enum class PremiumPreview {
ProfileBadge, ProfileBadge,
AnimatedUserpics, AnimatedUserpics,
RealTimeTranslation, RealTimeTranslation,
Wallpapers,
kCount, kCount,
}; };

View file

@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "boxes/premium_preview_box.h" #include "boxes/premium_preview_box.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
@ -33,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/animated_icon.h" #include "ui/animated_icon.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "window/section_widget.h" #include "window/section_widget.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -64,8 +64,8 @@ PeerId GenerateUser(not_null<History*> history, const QString &name) {
MTPEmojiStatus(), MTPEmojiStatus(),
MTPVector<MTPUsername>(), MTPVector<MTPUsername>(),
MTPint(), // stories_max_id MTPint(), // stories_max_id
MTP_int(0), // color MTPPeerColor(), // color
MTPlong())); // background_emoji_id MTPPeerColor())); // profile_color
return peerId; return peerId;
} }
@ -105,7 +105,7 @@ void AddMessage(
object_ptr<Ui::RpWidget>(container), object_ptr<Ui::RpWidget>(container),
style::margins( style::margins(
0, 0,
st::settingsSectionSkip, st::defaultVerticalListSkip,
0, 0,
st::settingsPrivacySkipTop)); st::settingsPrivacySkipTop));
@ -486,7 +486,7 @@ void ReactionsSettingsBox(
auto idValue = state->selectedId.value(); auto idValue = state->selectedId.value();
AddMessage(pinnedToTop, controller, std::move(idValue), box->width()); AddMessage(pinnedToTop, controller, std::move(idValue), box->width());
Settings::AddSubsectionTitle( Ui::AddSubsectionTitle(
pinnedToTop, pinnedToTop,
tr::lng_settings_chat_reactions_subtitle()); tr::lng_settings_chat_reactions_subtitle());
@ -515,10 +515,10 @@ void ReactionsSettingsBox(
} }
} }
for (const auto &r : list) { for (const auto &r : list) {
const auto button = Settings::AddButton( const auto button = container->add(object_ptr<Ui::SettingsButton>(
container, container,
rpl::single<QString>(base::duplicate(r.title)), rpl::single<QString>(base::duplicate(r.title)),
st::settingsButton); st::settingsButton));
const auto premium = r.premium; const auto premium = r.premium;
if (premium && !premiumPossible) { if (premium && !premiumPossible) {

View file

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_ringtones.h" #include "api/api_ringtones.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "base/base_file_utilities.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "base/event_filter.h" #include "base/event_filter.h"
#include "base/timer_rpl.h" #include "base/timer_rpl.h"
@ -27,16 +26,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include "platform/platform_notifications_manager.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/vertical_list.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -217,7 +215,7 @@ void RingtonesBox(
} }
}, box->lifetime()); }, box->lifetime());
Settings::AddSubsectionTitle( Ui::AddSubsectionTitle(
container, container,
tr::lng_ringtones_box_cloud_subtitle()); tr::lng_ringtones_box_cloud_subtitle());
@ -272,7 +270,7 @@ void RingtonesBox(
rebuild(); rebuild();
const auto upload = box->addRow( const auto upload = box->addRow(
Settings::CreateButton( Settings::CreateButtonWithIcon(
container, container,
tr::lng_ringtones_box_upload_button(), tr::lng_ringtones_box_upload_button(),
st::ringtonesBoxButton, st::ringtonesBoxButton,
@ -323,7 +321,7 @@ void RingtonesBox(
}); });
box->addSkip(st::ringtonesBoxSkip); box->addSkip(st::ringtonesBoxSkip);
Settings::AddDividerText(container, tr::lng_ringtones_box_about()); Ui::AddDividerText(container, tr::lng_ringtones_box_about());
box->addSkip(st::ringtonesBoxSkip); box->addSkip(st::ringtonesBoxSkip);

Some files were not shown because too many files have changed in this diff Show more