Compare commits

..

138 Commits

Author SHA1 Message Date
John Preston
232fceeee6 Beta version 4.4.2: Fix build with GCC. 2022-12-28 17:39:29 +04:00
John Preston
19c4130a1d Beta version 4.4.2.
- Send photos and video files hidden by a spoiler effect.
- Set a public photo for those who are restricted to see
your profile photo in the Privacy Settings.
- Bug fixes and other minor improvements.
2022-12-28 16:03:17 +04:00
Ilya Fedin
dc5abf8ddd Support ICCv4 with Little CMS on Linux 2022-12-28 16:02:35 +04:00
John Preston
b334a1f4fd Support spoilers in chats list media previews. 2022-12-28 14:07:38 +04:00
John Preston
17f40d6a1f Don't lose focus when showing image editor. 2022-12-28 13:05:23 +04:00
John Preston
77078f704c Fix a crash in topic deletion. 2022-12-28 12:44:01 +04:00
John Preston
df8176d671 Fix non-shown group thumb in media viewer. 2022-12-28 12:41:30 +04:00
John Preston
cad8a85497 Fix empty fallback photo appending. 2022-12-28 12:41:06 +04:00
Ilya Fedin
66093f0cb5 cTimeFormat/cDateFormat -> QLocale::ShortFormat
This allows to use platform-specific formatting functions
2022-12-28 10:28:12 +04:00
John Preston
9633f93690 Fix reactions panel expanding animation. 2022-12-28 10:11:38 +04:00
Ilya Fedin
1b8352f878 Fix image format mime type filter 2022-12-28 09:56:16 +04:00
23rd
27bcd35832 Added ability to translate transcribed voice messages. 2022-12-28 00:18:43 +03:00
23rd
b401f0bfea Added phrase to admin log when user joined via public request. 2022-12-28 00:18:43 +03:00
23rd
36391617d7 Fixed possible crash in optimized ministars animation. 2022-12-27 22:06:32 +03:00
23rd
5bf46c0e90 Adjusted button style in intro steps to style in settings steps. 2022-12-27 22:06:26 +03:00
Ilya Fedin
690e1013cf Find venv without configure.bat 2022-12-27 15:14:12 +04:00
John Preston
63c2db30f2 Fix folder updating when leaving a channel. 2022-12-27 14:05:22 +04:00
John Preston
bf388d8a37 Fix assertion violation in topic create box. 2022-12-27 13:55:34 +04:00
John Preston
b4571b80d6 Show spoilers in shared media overview. 2022-12-27 13:10:38 +04:00
Ilya Fedin
2cbd2725e5 Remove force-disabling of Qt's color space support for sent images
Qt had a bug with interpreting PNG gamma, but it seems it's fixed now.
2022-12-27 11:52:27 +04:00
John Preston
7f969e5102 Fix forwarding to General topic. 2022-12-27 11:49:03 +04:00
John Preston
e878ccccb4 Fix crash in sending media with spoilers. 2022-12-27 11:48:54 +04:00
John Preston
11bb4ec615 Closed alpha version 4.4.1.6. 2022-12-26 18:11:44 +04:00
John Preston
168cdaf350 Fix build with GCC. 2022-12-26 14:27:19 +04:00
John Preston
0ae819397a Fix protobuf timestamp generation. 2022-12-26 14:24:34 +04:00
John Preston
627eba1c5a Update API scheme on layer 151. 2022-12-26 14:24:08 +04:00
John Preston
673eb1090f Fix a crash and adjust some styles in snowflakes. 2022-12-26 14:24:08 +04:00
John Preston
43f0da683f Fix a crash in media spoilers. 2022-12-26 14:24:08 +04:00
John Preston
1bb6b07515 Fix build with GCC. 2022-12-26 14:24:08 +04:00
John Preston
aacb720664 Fix build with Xcode. 2022-12-26 14:24:08 +04:00
John Preston
12dd72bddf Closed alpha version 4.4.1.1. 2022-12-26 14:24:08 +04:00
John Preston
891559b3d9 Reverse message ranges for export. 2022-12-26 14:24:08 +04:00
23rd
b43f8fcff7 Slightly optimized drawing of ministars in premium settings. 2022-12-26 14:24:08 +04:00
John Preston
ce40ecc7f9 Show admins in participants_hidden group info. 2022-12-26 14:24:08 +04:00
John Preston
d6c188d642 Respect hidden_members_group_size_min in group edit. 2022-12-26 14:24:08 +04:00
John Preston
bd490421e8 No "Who Viewed" in case of hidden members. 2022-12-26 14:24:08 +04:00
John Preston
b9b6d4dba1 Show toast after photo suggestion is accepted. 2022-12-26 14:24:08 +04:00
John Preston
349fbeeb23 Add original userpic to "Reset to Original" menu item. 2022-12-26 14:24:08 +04:00
23rd
68b1b595a5 Fixed height of top bar with large subtext in premium settings. 2022-12-26 14:24:08 +04:00
23rd
cf4dfa55da Fixed order of premium feature previews. 2022-12-26 14:24:07 +04:00
23rd
8296d72923 Added first state to snowflakes effect in main menu. 2022-12-26 14:24:07 +04:00
John Preston
2364b0ad4e Show additional information in userpic suggest / accept. 2022-12-26 14:24:07 +04:00
John Preston
076f0e0800 Fix General topic message links. 2022-12-26 14:24:07 +04:00
John Preston
191ea6f0f4 Fix search in chat / jump to archive. 2022-12-26 14:24:07 +04:00
John Preston
7cf3babcbd Fix search by a hashtag from a topic. 2022-12-26 14:24:07 +04:00
John Preston
98af2d3006 Fix reactions layout for large emoji messages. 2022-12-26 14:24:07 +04:00
John Preston
b3858d5d97 Fix streamed media downloading.
Fixes #8500.
2022-12-26 14:24:07 +04:00
John Preston
1d7ad701b4 Implement blurred background for photo editor. 2022-12-26 14:24:07 +04:00
John Preston
9513aaa768 Allow accepting video userpic suggestions. 2022-12-26 14:24:07 +04:00
John Preston
446f0f1653 Fix channels limit info when trying an invite link. 2022-12-26 14:24:07 +04:00
John Preston
7d9b999cb0 Support request_write_access flag in attach bots. 2022-12-26 14:24:07 +04:00
John Preston
c647afec02 Support clipboard reading for attach menu bots. 2022-12-26 14:24:07 +04:00
23rd
4c181b6d08 Added initial implementation of fallback photo management in settings. 2022-12-26 14:24:07 +04:00
23rd
a4d3c694bc Added ability to use short info user for fallback photo. 2022-12-26 14:24:07 +04:00
23rd
721b2ebe8a Added initial support of api for fallback photo. 2022-12-26 14:24:07 +04:00
23rd
b135a09e00 Added initial support of fallback user photo to storage module. 2022-12-26 14:24:07 +04:00
23rd
6327d5ea38 Fixed conflict between peer update flags. 2022-12-26 14:24:07 +04:00
23rd
2a99046bbd Added snowflakes effect. 2022-12-26 14:24:07 +04:00
23rd
a3a48a38c8 Replaced callback for box showing with dedicated class in photo editor. 2022-12-26 14:24:07 +04:00
John Preston
4518067f9c Support persistent flag for bot keyboard. 2022-12-26 14:24:07 +04:00
John Preston
54a12aa74f Update API scheme on layer 151. 2022-12-26 14:24:06 +04:00
John Preston
1dd83f3d34 Support personal photo edit in EditContactBox. 2022-12-26 14:24:06 +04:00
John Preston
c7c652a277 Improve icons and phrases. 2022-12-26 14:24:06 +04:00
John Preston
faf6c48f25 Remove ui/special_buttons module. 2022-12-26 14:24:06 +04:00
John Preston
14f113266f Improve suggested photo service message. 2022-12-26 14:24:06 +04:00
John Preston
5ebea97ded Fix deleting a search result in chats list. 2022-12-26 14:24:06 +04:00
John Preston
af350e2daa Allow hiding members list in groups. 2022-12-26 14:24:06 +04:00
John Preston
b0a24238e8 Add icons to the photo set/suggest menu. 2022-12-26 14:24:06 +04:00
John Preston
2ce8094932 Add spoiler toggle to three dot menu in SendFilesBox. 2022-12-26 14:24:06 +04:00
John Preston
ca0b34dcf0 Update API scheme on layer 151. 2022-12-26 14:24:06 +04:00
John Preston
833a259234 Colorize emoji in text color correctly. 2022-12-26 14:24:06 +04:00
23rd
1ab8830ba8 Fixed outdated album info in reply on deleting dependency message. 2022-12-26 14:24:06 +04:00
23rd
40443b7547 Fixed mirrored display of shared screen in video calls. 2022-12-26 14:24:06 +04:00
John Preston
ca1c826c5c Simplify some code. 2022-12-26 14:24:06 +04:00
John Preston
bd1d7f4d96 Allow apply spoiler when editing to another media. 2022-12-26 14:24:05 +04:00
John Preston
5bee6310c0 Allow sending media with spoilers. 2022-12-26 14:24:05 +04:00
John Preston
3a38497c4c Support displaying of video spoilers. 2022-12-26 14:24:05 +04:00
John Preston
ae3659d15b Remove languages not supported in Qt 5. 2022-12-26 14:24:05 +04:00
John Preston
25746d195c Support displaying of photo spoilers. 2022-12-26 14:24:05 +04:00
John Preston
ae819eb1a6 Open settings when done changing photo. 2022-12-26 14:24:05 +04:00
John Preston
48cf0a4382 Implement suggested profile photo message. 2022-12-26 14:24:05 +04:00
John Preston
5fe9c93cb6 Set / suggest / reset a contact personal photo. 2022-12-26 14:24:05 +04:00
John Preston
cb99d611f3 Update API scheme to layer 151. 2022-12-26 14:24:05 +04:00
23rd
0e93693856 Moved current interface language to top of list in translate box. 2022-12-26 14:24:05 +04:00
23rd
9e93ecc154 Added more languages to translate box. 2022-12-26 14:24:05 +04:00
23rd
2cf579426b Added interface support of skipping translation for multiple languages. 2022-12-26 14:24:05 +04:00
23rd
6118ced862 Fixed possible crash on local clearing of filters. 2022-12-26 14:24:05 +04:00
23rd
8db8bc466e Added ability to remember last choice in send files box. 2022-12-26 14:24:05 +04:00
23rd
994d789c60 Added ability to remember last choice in delete messages box. 2022-12-26 14:24:05 +04:00
23rd
a043e22622 Added internal support of skipping translation for multiple languages. 2022-12-26 14:24:05 +04:00
John Preston
ccb3bbea15 Apply initial forwards count from the message. 2022-12-26 14:24:05 +04:00
John Preston
1b73b34810 Make HistoryItem a final class. 2022-12-26 14:24:04 +04:00
Ilya Fedin
36de2e98d4 Get supported image extensions from QImageReader 2022-12-26 14:23:23 +04:00
Ilya Fedin
9fba9048af Use the same check for drag'n'drop image type as for file dialog
The code path when choosing an image in file dialog tries to read a QImage with Images::Read and then only checks that mime type starts with image/ in ValidPhotoForAlbum

Core::FileIsImage and QImageReader::canRead checks should provide the same behavior
2022-12-26 14:23:23 +04:00
Ilya Fedin
95b29f5f35 Enable ffmpeg dav1d support 2022-12-25 08:40:16 +04:00
Ilya Fedin
13eeddf479 Don't wait for input when there are fullscreen applications 2022-12-23 14:04:17 +04:00
Ilya Fedin
3991be752c Replace various QDesktopService::openUrl with File::OpenUrl for correct operation on Linux
This also reverts commit bb94507af1.
2022-12-23 14:02:25 +04:00
Lesiuk
0f3ec7893d Removed downscaling of 2560px images before displaying them
Fixes #2206
2022-12-23 11:00:07 +04:00
Daniel Novomeský
351a2eee08 Update cmake_helpers submodule 2022-12-23 10:58:22 +04:00
Daniel Novomeský
6ff2c08764 Added dependencies for Windows build
They will be used for plugins in kimageformats:
dav1d, libavif are needed for AVIF plugin
libde265, libheif are needed for HEIF plugin
libjxl is needed for JXL plugin
dav1d could be used by ffmpeg to provide AV1 decoding
meson is required to build dav1d
2022-12-23 10:58:22 +04:00
Daniel Novomeský
d163135117 Update kimageformats submodule
It is necessary to use new heif.cpp to enable static linkage on Windows
There are important fixes for AVIF and JPEG XL plugins too.
2022-12-23 10:58:22 +04:00
Ilya Fedin
ecd217a79f Implement autostart in snap 2022-12-20 18:55:29 +04:00
Ilya Fedin
4aa9c1fea3 Get saving desktop file out of group loop 2022-12-20 18:55:29 +04:00
Ilya Fedin
2e60b28612 Install Python and cmake to default paths
There's no real need to install to custom paths
2022-12-20 17:22:19 +04:00
Ilya Fedin
2bbe511a6f Revert some mistakenly replaced '/' symbols earlier 2022-12-20 17:22:19 +04:00
Ilya Fedin
5cbdc2f739 Install gyp python dependencies in prepare.py 2022-12-20 17:22:19 +04:00
Ilya Fedin
6f88e46938 Update kcoreaddons
This finally fixes portal paste on X11
2022-12-16 11:14:28 +04:00
Ilya Fedin
8209602cbd Fix Linux action 2022-12-16 11:03:37 +04:00
Ilya Fedin
b3e547f4dd Fix a warning in snap build 2022-12-16 11:03:37 +04:00
Ilya Fedin
5289810b81 Fix snap action lxd firewall integration 2022-12-16 11:03:37 +04:00
Ilya Fedin
3cb333d323 Fix counter paint when DPR != 1 in Linux tray 2022-12-09 16:04:07 +04:00
Ilya Fedin
2565b948d9 Cache system icon in Linux tray 2022-12-09 16:04:07 +04:00
23rd
5101ea2a96 Updated Qt to 5.15.7 on Windows. 2022-12-09 11:54:37 +03:00
23rd
23150d4e2a Added special branch for Windows Github CI. 2022-12-09 11:54:37 +03:00
23rd
66926ba25e Fixed scrolling to end when media is replaced. 2022-12-09 11:54:37 +03:00
23rd
b4a7d98fa0 Added support of custom emoji to translate box. 2022-12-09 11:54:37 +03:00
Klemens Nanni
620f6657ae Update to minizip 1.2.13
https://github.com/madler/zlib/releases/tag/v1.2.13

Tested with tdesktop 4.4.1 on OpenBSD/amd64, where a manual fix is still
required to build tdesktop's old zlib version:
https://github.com/openbsd/ports/blob/master/net/tdesktop/Makefile#L105-L108

I upstreamed this fix with https://github.com/madler/zlib/pull/678,
although it got fixed differently in
40c5a9bc06
2022-12-09 09:58:16 +04:00
Ilya Fedin
577f4b6271 Don't check com.canonical.Unity for the counter
It seems there's a race condition when Telegram is auto-started on Plasma and it doesn't hurt to issue the signal always, so just remove the check
2022-12-09 09:19:00 +04:00
Klemens Nanni
9c27271571 Use std::invoke_result_T not ::result_of to fix C++20 tdesktop 4.3.4
tdesktop defaults to (probably requires) C++20, but `std::result_of`[0]
was deprecated in C++17 and removed in C++20.

0: https://en.cppreference.com/w/cpp/types/result_of
2022-12-09 09:12:34 +04:00
John Preston
cad87f6818 Update to WebRTC M108. 2022-12-08 14:22:04 +04:00
Ilya Fedin
a9a69c7d14 Update submodules 2022-12-08 10:15:59 +04:00
Ilya Fedin
5990b0fabf Fix build with Qt 5 2022-12-08 10:15:59 +04:00
John Preston
6986430f37 Version 4.4.1.
- Bug fixes and other minor improvements.
2022-12-07 13:41:04 +04:00
John Preston
04eff72ce8 Update lib_spellcheck submodule. 2022-12-07 13:39:09 +04:00
John Preston
985f557adf Forbid deleting General topic. 2022-12-07 13:36:42 +04:00
John Preston
77b2572854 Add some General topic phrases. 2022-12-07 13:35:24 +04:00
23rd
993b501996 Filtered out only channels in list of applying TTL for multiple chats. 2022-12-07 13:09:46 +04:00
23rd
bba45293da Added gradient colors to sessions section. 2022-12-07 13:09:45 +04:00
John Preston
58fe2d7ecc Fix last topic opening on some systems. 2022-12-07 13:08:41 +04:00
John Preston
cfddca8f58 Fix possible crashes in toastParent expiring. 2022-12-07 13:07:36 +04:00
Ilya Fedin
6f50906952 Don't use unneeded QEventLoop::ApplicationExec 2022-12-07 11:27:49 +04:00
John Preston
1f39d16a35 Fix warning in building with LTCG libs. 2022-12-07 11:27:07 +04:00
John Preston
54f697eba1 Selectively request LTCG on Windows 32 bit build. 2022-12-07 11:01:05 +04:00
John Preston
02e2fb1258 Fix crash in pinned topic deletion. 2022-12-07 11:01:05 +04:00
mid-kid
d01969ff1e Fix building without spellcheck
Port from gentoo: f62d7c6599/net-im/telegram-desktop/files/tdesktop-4.3.4-fix-disabling-spellcheck.patch

/var/tmp/portage/net-im/telegram-desktop-4.3.4/work/tdesktop-4.3.4-full/Telegram/SourceFiles/boxes/translate_box.cpp:18:10: fatal error: spellcheck/platform/platform_language.h: No such file or directory
   18 | #include "spellcheck/platform/platform_language.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
2022-12-07 09:44:14 +04:00
Robin van der Vliet
e4d8a06cf9 Add Esperanto to language list of translate box 2022-12-07 09:35:53 +04:00
John Preston
8ec64f4167 Fix crash in Replies go-to-original button ripple. 2022-12-07 09:30:36 +04:00
John Preston
06ea927095 Fix build of not used lib_base subproject. 2022-12-07 08:49:56 +04:00
392 changed files with 12272 additions and 8108 deletions

View File

@@ -54,6 +54,7 @@ jobs:
- name: First set up.
run: |
sudo iptables -P FORWARD ACCEPT
sudo snap install --classic snapcraft
sudo usermod -aG lxd $USER
sudo snap run lxd init --auto

View File

@@ -82,9 +82,6 @@ jobs:
submodules: recursive
path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}
- name: Python installs.
run: pip3 install --upgrade pywin32 six
- name: Set up environment paths.
shell: bash
run: |
@@ -119,13 +116,20 @@ jobs:
DEFINE=""
if [ -n "${{ matrix.defines }}" ]; then
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
else
echo "ARTIFACT_NAME=Telegram_${{ matrix.arch }}" >> $GITHUB_ENV
fi
echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV
API="-D TDESKTOP_API_TEST=ON"
if [ ${{ github.ref == 'refs/heads/nightly' }} ]; then
echo "Use the open credentials."
API="-D TDESKTOP_API_ID=611335 -D TDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c"
fi
echo "TDESKTOP_BUILD_API=$API" >> $GITHUB_ENV
- name: Free up some disk space.
run: |
del /S Libraries\*.pdb
@@ -139,7 +143,7 @@ jobs:
call configure.bat ^
${{ matrix.arch }} ^
-D TDESKTOP_API_TEST=ON ^
%TDESKTOP_BUILD_API% ^
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^
-D DESKTOP_APP_NO_PDB=ON ^
%TDESKTOP_BUILD_DEFINE% ^
@@ -149,13 +153,13 @@ jobs:
msbuild -m Telegram.sln /p:Configuration=Debug,Platform=${{ matrix.arch }},DebugSymbols=false,DebugType=none
- name: Move artifact.
if: env.UPLOAD_ARTIFACT == 'true'
if: (env.UPLOAD_ARTIFACT == 'true') || ${{ github.ref == 'refs/heads/nightly' }}
run: |
mkdir artifact
move %TBUILD%\%REPO_NAME%\out\Debug\Telegram.exe artifact/
- uses: actions/upload-artifact@master
name: Upload artifact.
if: env.UPLOAD_ARTIFACT == 'true'
if: (env.UPLOAD_ARTIFACT == 'true') || ${{ github.ref == 'refs/heads/nightly' }}
with:
name: ${{ env.ARTIFACT_NAME }}
path: artifact\

View File

@@ -36,6 +36,10 @@ get_filename_component(third_party_loc "Telegram/ThirdParty" REALPATH)
get_filename_component(submodules_loc "Telegram" REALPATH)
get_filename_component(cmake_helpers_loc "cmake" REALPATH)
if (NOT DESKTOP_APP_USE_PACKAGED AND WIN32)
set(Python_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/python/Scripts/python)
endif()
include(cmake/variables.cmake)
include(cmake/nice_target_sources.cmake)
include(cmake/target_compile_options_if_exists.cmake)
@@ -52,7 +56,7 @@ include(cmake/options.cmake)
if (NOT DESKTOP_APP_USE_PACKAGED)
if (WIN32)
set(qt_version 5.15.4)
set(qt_version 5.15.7)
elseif (APPLE)
set(qt_version 6.3.2)
else()

View File

@@ -5,7 +5,7 @@
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
add_executable(Telegram WIN32 MACOSX_BUNDLE)
init_non_host_target(Telegram)
init_non_host_target(Telegram ltcg)
add_subdirectory(lib_rpl)
add_subdirectory(lib_crl)
@@ -184,6 +184,8 @@ PRIVATE
boxes/peers/edit_forum_topic_box.h
boxes/peers/edit_linked_chat_box.cpp
boxes/peers/edit_linked_chat_box.h
boxes/peers/edit_members_visible.cpp
boxes/peers/edit_members_visible.h
boxes/peers/edit_participant_box.cpp
boxes/peers/edit_participant_box.h
boxes/peers/edit_participants_box.cpp
@@ -667,14 +669,18 @@ PRIVATE
history/view/media/history_view_media_common.h
history/view/media/history_view_media_grouped.cpp
history/view/media/history_view_media_grouped.h
history/view/media/history_view_media_spoiler.cpp
history/view/media/history_view_media_spoiler.h
history/view/media/history_view_media_unwrapped.cpp
history/view/media/history_view_media_unwrapped.h
history/view/media/history_view_photo.cpp
history/view/media/history_view_photo.h
history/view/media/history_view_poll.cpp
history/view/media/history_view_poll.h
history/view/media/history_view_service_media_gift.cpp
history/view/media/history_view_service_media_gift.h
history/view/media/history_view_premium_gift.cpp
history/view/media/history_view_premium_gift.h
history/view/media/history_view_service_box.cpp
history/view/media/history_view_service_box.h
history/view/media/history_view_slot_machine.cpp
history/view/media/history_view_slot_machine.h
history/view/media/history_view_sticker.cpp
@@ -684,6 +690,8 @@ PRIVATE
history/view/media/history_view_sticker_player_abstract.h
history/view/media/history_view_theme_document.cpp
history/view/media/history_view_theme_document.h
history/view/media/history_view_userpic_suggestion.cpp
history/view/media/history_view_userpic_suggestion.h
history/view/media/history_view_web_page.cpp
history/view/media/history_view_web_page.h
history/view/reactions/history_view_reactions.cpp
@@ -764,6 +772,8 @@ PRIVATE
history/history_item_components.h
history/history_item_edition.cpp
history/history_item_edition.h
history/history_item_helpers.cpp
history/history_item_helpers.h
history/history_item_reply_markup.cpp
history/history_item_reply_markup.h
history/history_item_text.cpp
@@ -772,10 +782,6 @@ PRIVATE
history/history_inner_widget.h
history/history_location_manager.cpp
history/history_location_manager.h
history/history_message.cpp
history/history_message.h
history/history_service.cpp
history/history_service.h
history/history_unread_things.cpp
history/history_unread_things.h
history/history_view_highlight_manager.cpp
@@ -1254,6 +1260,10 @@ PRIVATE
ui/chat/choose_send_as.h
ui/chat/choose_theme_controller.cpp
ui/chat/choose_theme_controller.h
ui/controls/silent_toggle.cpp
ui/controls/silent_toggle.h
ui/controls/userpic_button.cpp
ui/controls/userpic_button.h
ui/effects/emoji_fly_animation.cpp
ui/effects/emoji_fly_animation.h
ui/effects/message_sending_animation_common.h
@@ -1282,8 +1292,6 @@ PRIVATE
ui/resize_area.h
ui/search_field_controller.cpp
ui/search_field_controller.h
ui/special_buttons.cpp
ui/special_buttons.h
ui/text/format_song_document_name.cpp
ui/text/format_song_document_name.h
ui/unread_badge.cpp
@@ -1601,17 +1609,6 @@ if (WIN32)
/DELAYLOAD:wtsapi32.dll
/DELAYLOAD:propsys.dll
)
if (NOT build_win64 AND DESKTOP_APP_SPECIAL_TARGET)
target_compile_options(Telegram
PRIVATE
$<IF:$<CONFIG:Debug>,,/GL>
)
target_link_options(Telegram
PRIVATE
$<IF:$<CONFIG:Debug>,,/LTCG>
)
endif()
endif()
target_prepare_qrc(Telegram)

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 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: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -166,6 +166,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_scam_badge" = "SCAM";
"lng_fake_badge" = "FAKE";
"lng_remember" = "Remember this choice";
"lng_channels_limit_title" = "Too Many Communities";
"lng_channels_limit1#one" = "You are a member of **{count}** groups and channels.";
"lng_channels_limit1#other" = "You are a member of **{count}** groups and channels.";
@@ -306,18 +308,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_caption_voice" = "Sorry, you can't edit your message while you're having an unsent voice message.";
"lng_intro_about" = "Welcome to the official Telegram Desktop app.\nIt's fast and secure.";
"lng_start_msgs" = "START MESSAGING";
"lng_start_msgs" = "Start messaging";
"lng_intro_next" = "NEXT";
"lng_intro_finish" = "SIGN UP";
"lng_intro_submit" = "SUBMIT";
"lng_intro_next" = "Next";
"lng_intro_finish" = "Sign up";
"lng_intro_submit" = "Submit";
"lng_photo_caption" = "Caption";
"lng_photos_comment" = "Comment";
"lng_intro_qr_title" = "Scan From Mobile Telegram";
"lng_intro_qr_step1" = "Open Telegram on your phone";
"lng_intro_qr_step2" = "Go to Settings > Devices > Scan QR Code";
"lng_intro_qr_step2" = "Go to Settings > Devices > Link Desktop";
"lng_intro_qr_step3" = "Scan this image to Log In";
"lng_intro_qr_skip" = "Or log in using your phone number";
@@ -391,8 +393,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_save" = "Save";
"lng_settings_upload" = "Set Profile Photo";
"lng_settings_crop_profile" = "Select an area for your profile photo";
"lng_settings_uploading_photo" = "Uploading photo...";
"lng_settings_edit" = "Edit";
"lng_settings_drop_area_subtitle" = "to set it as your photo";
@@ -493,6 +493,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_change_lang" = "Change language";
"lng_languages" = "Languages";
"lng_languages_none" = "No languages found.";
"lng_languages_count#one" = "{count} language";
"lng_languages_count#other" = "{count} languages";
"lng_sure_save_language" = "Telegram will restart in order to change language";
"lng_settings_update_automatically" = "Update automatically";
"lng_settings_install_beta" = "Install beta versions";
@@ -691,6 +693,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_ttl_select_chats_title" = "Select Chats";
"lng_settings_ttl_select_chats_subtitle" = "to apply the self-destruct timer";
"lng_settings_ttl_select_chats_subtitle_chosen" = "will have the self-destruct timer";
"lng_settings_ttl_select_chats_sorry" = "Sorry, you can't set self-destruct timer for this chat.";
"lng_settings_ttl_select_chats_status" = "auto-delete after {after_duration}";
"lng_settings_ttl_select_chats_status_disabled" = "auto-deletion disabled";
"lng_settings_ttl_select_chats_toast#one" = "Self-destruct timer for {duration} has been enabled in {count} selected chat.";
@@ -1036,6 +1039,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_forwards_always_empty" = "Always allow";
"lng_edit_privacy_forwards_never_empty" = "Never allow";
"lng_edit_privacy_forwards_exceptions" = "These settings will override the values above.";
"lng_edit_privacy_forwards_exceptions_everyone" = "You can add users or entire groups which will not see your profile photo.";
"lng_edit_privacy_forwards_exceptions_nobody" = "Add users or entire groups which will still see your profile photo.";
"lng_edit_privacy_forwards_always_title" = "Always allow";
"lng_edit_privacy_forwards_never_title" = "Never allow";
"lng_edit_privacy_forwards_sample_message" = "Reinhardt, we need to find you some new tunes 🎶";
@@ -1050,6 +1055,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_profile_photo_exceptions" = "These settings will override the values above.";
"lng_edit_privacy_profile_photo_always_title" = "Always allow";
"lng_edit_privacy_profile_photo_never_title" = "Never allow";
"lng_edit_privacy_profile_photo_public_set" = "Set Public Photo";
"lng_edit_privacy_profile_photo_public_update" = "Update Public Photo";
"lng_edit_privacy_profile_photo_public_remove" = "Remove Public Photo";
"lng_edit_privacy_profile_photo_public_about" = "You can upload a public photo for those who are restricted from viewing your real profile photo.";
"lng_edit_privacy_profile_photo_public_toast" = "This photo is now set for those who are restricted from viewing your main photo.";
"lng_edit_privacy_voices_title" = "Voice messages settings";
"lng_edit_privacy_voices_header" = "Who can send me voice messages";
@@ -1136,6 +1146,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_set_group_photo" = "Set Photo";
"lng_profile_add_participant" = "Add Members";
"lng_profile_add_via_link" = "Invite via Link";
"lng_profile_hide_participants" = "Hide Members";
"lng_profile_hide_participants_about" = "Switch this on to hide the list of members in this group. Admins will remain visible.";
"lng_profile_view_channel" = "View Channel";
"lng_profile_view_discussion" = "View discussion";
"lng_profile_join_channel" = "Join Channel";
@@ -1178,6 +1190,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_info_section" = "Info";
"lng_info_tab_media" = "Media";
"lng_info_public_photo" = "public photo";
"lng_info_mobile_label" = "Mobile";
"lng_info_mobile_hidden" = "Hidden";
"lng_info_username_label" = "Username";
@@ -1195,6 +1208,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_send_message" = "Send Message";
"lng_info_add_as_contact" = "Add to contacts";
"lng_profile_shared_media" = "Shared media";
"lng_profile_suggest_photo" = "Suggest Profile Photo";
"lng_profile_set_photo_for" = "Set Profile Photo";
"lng_profile_photo_reset" = "Reset to Original";
"lng_profile_set_for_done" = "You will now always see this photo for {user}'s account.";
"lng_profile_suggest_sure" = "You can suggest {user} to set this photo for their page.";
"lng_profile_suggest_button" = "Suggest";
"lng_profile_set_personal_sure" = "Only you will see this photo and it will replace any photo {user} sets for themselves.";
"lng_profile_accept_photo_sure" = "{user} suggests you to use this profile photo for your Telegram account.";
"lng_profile_set_photo_button" = "Set Photo";
"lng_profile_accept_video_sure" = "{user} suggests you to use this profile video for your Telegram account.";
"lng_profile_set_video_button" = "Set Video";
"lng_profile_changed_photo_title" = "Photo updated";
"lng_profile_changed_photo_about" = "You can change it in {link}.";
"lng_profile_changed_photo_link" = "Settings";
"lng_media_type_photos" = "Photos";
"lng_media_type_gifs" = "GIFs";
"lng_media_type_videos" = "Videos";
@@ -1428,9 +1455,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_create_channel_link_pending" = "Checking name...";
"lng_create_channel_link_copied" = "Link copied to clipboard";
"lng_create_group_crop" = "Select an area for group photo";
"lng_create_channel_crop" = "Select an area for channel photo";
"lng_failed_add_participant" = "Could not add user. Please try again later.";
"lng_failed_add_not_mutual" = "Sorry, if a person leaves a group, only a mutual contact can bring them back (they need to have your phone number, and you need theirs).";
"lng_failed_add_not_mutual_channel" = "Sorry, if a person leaves a channel, only a mutual contact can bring them back (they need to have your phone number, and you need theirs).";
@@ -1553,12 +1577,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_webview_data_done" = "You have just successfully transferred data from the «{text}» button to the bot.";
"lng_action_gift_received" = "{user} sent you a gift for {cost}";
"lng_action_gift_received_me" = "You sent to {user} a gift for {cost}";
"lng_action_suggested_photo_me" = "You suggested {user} to use this profile photo.";
"lng_action_suggested_photo" = "{user} suggests you to use this profile photo.";
"lng_action_suggested_photo_button" = "View Photo";
"lng_action_suggested_video_me" = "You suggested {user} to use this profile video.";
"lng_action_suggested_video" = "{user} suggests you to use this profile video.";
"lng_action_suggested_video_button" = "View Video";
"lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu.";
"lng_action_topic_created_inside" = "Topic created";
"lng_action_topic_closed_inside" = "Topic closed";
"lng_action_topic_reopened_inside" = "Topic reopened";
"lng_action_topic_hidden_inside" = "Topic hidden";
"lng_action_topic_unhidden_inside" = "Topic unhidden";
"lng_action_topic_created" = "«{topic}» was created";
"lng_action_topic_closed" = "«{topic}» was closed";
"lng_action_topic_reopened" = "«{topic}» was reopened";
"lng_action_topic_hidden" = "«{topic}» was hidden";
"lng_action_topic_unhidden" = "«{topic}» was unhidden";
"lng_action_topic_placeholder" = "topic";
"lng_action_topic_renamed" = "{from} renamed the {link} to «{title}»";
"lng_action_topic_icon_changed" = "{from} changed the {link} icon to {emoji}";
@@ -2312,6 +2347,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_animated_reactions_many#one" = "Reactions contain emoji from **{count} pack**.";
"lng_context_animated_reactions_many#other" = "Reactions contain emoji from **{count} packs**.";
"lng_context_spoiler_effect" = "Hide with Spoiler";
"lng_context_disable_spoiler" = "Remove Spoiler";
"lng_downloads_section" = "Downloads";
"lng_downloads_view_in_chat" = "View in chat";
"lng_downloads_view_in_section" = "View in downloads";
@@ -2325,17 +2363,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_send_image_empty" = "Could not send an empty file: {name}";
"lng_send_images_selected#one" = "{count} image selected";
"lng_send_images_selected#other" = "{count} images selected";
"lng_send_photos#one" = "Send {count} photo";
"lng_send_photos#other" = "Send {count} photos";
"lng_send_separate_photos" = "Send as separate photos";
"lng_send_separate_photos_videos" = "Send as separate media";
"lng_send_files_selected#one" = "{count} file selected";
"lng_send_files_selected#other" = "{count} files selected";
"lng_send_files#one" = "Send {count} file";
"lng_send_files#other" = "Send {count} files";
"lng_send_grouped" = "Group items";
"lng_send_compressed_one" = "Compress the image";
"lng_send_compressed" = "Compress images";
"lng_send_media_invalid_files" = "Sorry, no valid files found.";
"lng_send_image" = "Send an image";
"lng_send_file" = "Send a file";
"lng_send_video" = "Send a video file";
"lng_forward_choose" = "Choose recipient...";
"lng_forward_cant" = "Sorry, no way to forward here :(";
@@ -2454,6 +2490,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_mediaview_group_photo" = "Group Photo";
"lng_mediaview_channel_photo" = "Channel Photo";
"lng_mediaview_profile_photo" = "Profile Photo";
"lng_mediaview_profile_public_photo" = "Public Photo";
"lng_mediaview_file_n_of_amount" = "{file} {n} of {amount}";
"lng_mediaview_n_of_amount" = "Photo {n} of {amount}";
"lng_mediaview_doc_image" = "File";
@@ -3102,6 +3139,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_participant_joined_by_link_channel" = "{from} joined the channel via {link}";
"lng_admin_log_participant_approved_by_link" = "{from} was approved to join the group via {link} by {user}";
"lng_admin_log_participant_approved_by_link_channel" = "{from} was approved to join the channel via {link} by {user}";
"lng_admin_log_participant_approved_by_request" = "{from} joined to the group via public request, approved by {user}";
"lng_admin_log_participant_approved_by_request_channel" = "{from} joined to the channel via public request, approved by {user}";
"lng_admin_log_revoke_invite_link" = "{from} revoked invite link {link}";
"lng_admin_log_delete_invite_link" = "{from} deleted invite link {link}";
"lng_admin_log_participant_left" = "{from} left the group";
@@ -3161,6 +3200,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_topics_changed" = "{from} changed topic {topic} to {new_topic}";
"lng_admin_log_topics_closed" = "{from} closed topic {topic}";
"lng_admin_log_topics_reopened" = "{from} reopened topic {topic}";
"lng_admin_log_topics_hidden" = "{from} hid topic {topic}";
"lng_admin_log_topics_unhidden" = "{from} unhid topic {topic}";
"lng_admin_log_topics_deleted" = "{from} deleted topic {topic}";
"lng_admin_log_topics_pinned" = "{from} pinned topic {topic}";
"lng_admin_log_topics_unpinned" = "{from} unpinned topic {topic}";

View File

@@ -58,15 +58,15 @@ inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile
inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;
inputMediaEmpty#9664f57f = InputMedia;
inputMediaUploadedPhoto#1e287d04 flags:# file:InputFile stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaPhoto#b3ba0635 flags:# id:InputPhoto ttl_seconds:flags.0?int = InputMedia;
inputMediaUploadedPhoto#1e287d04 flags:# spoiler:flags.2?true file:InputFile stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaPhoto#b3ba0635 flags:# spoiler:flags.1?true id:InputPhoto ttl_seconds:flags.0?int = InputMedia;
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#33473058 flags:# id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#33473058 flags:# spoiler:flags.2?true id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaPhotoExternal#e5bbfe1a flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#fb52dc99 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
inputMediaInvoice#8eb5a6d5 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:flags.1?string extended_media:flags.2?InputMedia = InputMedia;
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
@@ -113,7 +113,7 @@ userEmpty#d3bc4b7a id:long = User;
user#8f97c628 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
userStatusEmpty#9d05049 = UserStatus;
userStatusOnline#edb93949 expires:int = UserStatus;
@@ -129,7 +129,7 @@ channel#83259464 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull;
channelFull#f2355507 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull;
channelFull#f2355507 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@@ -146,11 +146,11 @@ message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:fl
messageService#2b085862 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction ttl_period:flags.25?int = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
messageMediaPhoto#695150d7 flags:# spoiler:flags.3?true photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia;
messageMediaUnsupported#9f84f49e = MessageMedia;
messageMediaDocument#9cb070d7 flags:# nopremium:flags.3?true document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia;
messageMediaDocument#9cb070d7 flags:# nopremium:flags.3?true spoiler:flags.4?true document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia;
messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
messageMediaGame#fdb19008 game:Game = MessageMedia;
@@ -194,6 +194,8 @@ messageActionWebViewDataSent#b4c38cb5 text:string = MessageAction;
messageActionGiftPremium#aba0f5c6 currency:string amount:long months:int = MessageAction;
messageActionTopicCreate#d999256 flags:# title:string icon_color:int icon_emoji_id:flags.0?long = MessageAction;
messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags.1?long closed:flags.2?Bool hidden:flags.3?Bool = MessageAction;
messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction;
messageActionAttachMenuBotAllowed#e7e75f97 = MessageAction;
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
@@ -244,7 +246,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#c4b1fc3f flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true id:long about:flags.1?string settings:PeerSettings profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> = UserFull;
userFull#f8d32aed flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact;
@@ -302,7 +304,6 @@ updateChatUserTyping#83487af0 chat_id:long from_id:Peer action:SendMessageAction
updateChatParticipants#7761198 participants:ChatParticipants = Update;
updateUserStatus#e5bdf8de user_id:long status:UserStatus = Update;
updateUserName#a7848924 user_id:long first_name:string last_name:string usernames:Vector<Username> = Update;
updateUserPhoto#f227868c user_id:long date:int photo:UserProfilePhoto previous:Bool = Update;
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
@@ -403,6 +404,7 @@ updateMoveStickerSetToTop#86fccf85 flags:# masks:flags.0?true emojis:flags.1?tru
updateMessageExtendedMedia#5a73a98c peer:Peer msg_id:int extended_media:MessageExtendedMedia = Update;
updateChannelPinnedTopic#192efbe3 flags:# pinned:flags.0?true channel_id:long topic_id:int = Update;
updateChannelPinnedTopics#fe198602 flags:# channel_id:long order:flags.0?Vector<int> = Update;
updateUser#20529438 user_id:long = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@@ -547,7 +549,7 @@ documentAttributeVideo#ef02ce6 flags:# round_message:flags.0?true supports_strea
documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute;
documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
documentAttributeHasStickers#9801d2f7 = DocumentAttribute;
documentAttributeCustomEmoji#fd149899 flags:# free:flags.0?true alt:string stickerset:InputStickerSet = DocumentAttribute;
documentAttributeCustomEmoji#fd149899 flags:# free:flags.0?true text_color:flags.1?true alt:string stickerset:InputStickerSet = DocumentAttribute;
messages.stickersNotModified#f1749a22 = messages.Stickers;
messages.stickers#30a6ec7e hash:long stickers:Vector<Document> = messages.Stickers;
@@ -625,7 +627,7 @@ keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup;
replyKeyboardForceReply#86b40b08 flags:# single_use:flags.1?true selective:flags.2?true placeholder:flags.3?string = ReplyMarkup;
replyKeyboardMarkup#85dd99d1 flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector<KeyboardButtonRow> placeholder:flags.3?string = ReplyMarkup;
replyKeyboardMarkup#85dd99d1 flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true persistent:flags.4?true rows:Vector<KeyboardButtonRow> placeholder:flags.3?string = ReplyMarkup;
replyInlineMarkup#48a30254 rows:Vector<KeyboardButtonRow> = ReplyMarkup;
messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity;
@@ -780,6 +782,7 @@ messages.stickerSetInstallResultArchive#35e410a8 sets:Vector<StickerSetCovered>
stickerSetCovered#6410a5d2 set:StickerSet cover:Document = StickerSetCovered;
stickerSetMultiCovered#3407e51b set:StickerSet covers:Vector<Document> = StickerSetCovered;
stickerSetFullCovered#40d13c0e set:StickerSet packs:Vector<StickerPack> keywords:Vector<StickerKeyword> documents:Vector<Document> = StickerSetCovered;
stickerSetNoCovered#77b15d1c set:StickerSet = StickerSetCovered;
maskCoords#aed6dbb2 n:int x:double y:double zoom:double = MaskCoords;
@@ -1379,7 +1382,7 @@ attachMenuBotIconColor#4576f3f0 name:string color:int = AttachMenuBotIconColor;
attachMenuBotIcon#b2a7386b flags:# name:string icon:Document colors:flags.0?Vector<AttachMenuBotIconColor> = AttachMenuBotIcon;
attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true bot_id:long short_name:string peer_types:Vector<AttachMenuPeerType> icons:Vector<AttachMenuBotIcon> = AttachMenuBot;
attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true bot_id:long short_name:string peer_types:Vector<AttachMenuPeerType> icons:Vector<AttachMenuBotIcon> = AttachMenuBot;
attachMenuBotsNotModified#f1d88a5c = AttachMenuBots;
attachMenuBots#3c4301c0 hash:long bots:Vector<AttachMenuBot> users:Vector<User> = AttachMenuBots;
@@ -1781,7 +1784,7 @@ messages.readReactions#54aa7f8e flags:# peer:InputPeer top_msg_id:flags.0?int =
messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = messages.Messages;
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
messages.toggleBotInAttachMenu#1aee33af bot:InputUser enabled:Bool = Bool;
messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool;
messages.requestWebView#178b480b flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to_msg_id:flags.0?int top_msg_id:flags.9?int send_as:flags.13?InputPeer = WebViewResult;
messages.prolongWebView#7ff34309 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to_msg_id:flags.0?int top_msg_id:flags.9?int send_as:flags.13?InputPeer = Bool;
messages.requestSimpleWebView#299bec8e flags:# bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult;
@@ -1804,10 +1807,11 @@ updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
updates.getChannelDifference#3173d78 flags:# force:flags.0?true channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference;
photos.updateProfilePhoto#72d4742c id:InputPhoto = photos.Photo;
photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
photos.updateProfilePhoto#1c3d5956 flags:# fallback:flags.0?true id:InputPhoto = photos.Photo;
photos.uploadProfilePhoto#89f30f69 flags:# fallback:flags.3?true file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
photos.deletePhotos#87cf7f2f id:Vector<InputPhoto> = Vector<long>;
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
photos.uploadContactProfilePhoto#b91a83bf flags:# suggest:flags.3?true save:flags.4?true user_id:InputUser file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
upload.getFile#be5335be flags:# precise:flags.0?true cdn_supported:flags.1?true location:InputFileLocation offset:long limit:int = upload.File;
@@ -1896,6 +1900,7 @@ channels.deleteTopicHistory#34435f2d channel:InputChannel top_msg_id:int = messa
channels.reorderPinnedForumTopics#2950a18f flags:# force:flags.0?true channel:InputChannel order:Vector<int> = Updates;
channels.toggleAntiSpam#68f3e4eb channel:InputChannel enabled:Bool = Updates;
channels.reportAntiSpamFalsePositive#a850a693 channel:InputChannel msg_id:int = Bool;
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
@@ -1974,4 +1979,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
// LAYER 150
// LAYER 151

View File

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

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,4,0,0
PRODUCTVERSION 4,4,0,0
FILEVERSION 4,4,2,0
PRODUCTVERSION 4,4,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "4.4.0.0"
VALUE "FileVersion", "4.4.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.4.0.0"
VALUE "ProductVersion", "4.4.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,4,0,0
PRODUCTVERSION 4,4,0,0
FILEVERSION 4,4,2,0
PRODUCTVERSION 4,4,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "4.4.0.0"
VALUE "FileVersion", "4.4.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.4.0.0"
VALUE "ProductVersion", "4.4.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -79,12 +79,16 @@ Authorizations::Entry ParseEntry(const MTPDauthorization &data) {
const auto nowDate = now.date();
const auto lastDate = lastTime.date();
if (lastDate == nowDate) {
result.active = QLocale().toString(lastTime, cTimeFormat());
result.active = QLocale().toString(
lastTime.time(),
QLocale::ShortFormat);
} else if (lastDate.year() == nowDate.year()
&& lastDate.weekNumber() == nowDate.weekNumber()) {
result.active = langDayOfWeek(lastDate);
} else {
result.active = QLocale().toString(lastDate, cDateFormat());
result.active = QLocale().toString(
lastDate,
QLocale::ShortFormat);
}
}
result.location = country;

View File

@@ -110,7 +110,9 @@ void SendBotCallbackData(
const auto showAlert = data.is_alert();
if (!message.isEmpty()) {
if (showAlert) {
if (!show->valid()) {
return;
} else if (showAlert) {
show->showBox(Ui::MakeInformBox(message));
} else {
if (withPassword) {

View File

@@ -81,6 +81,7 @@ void SubmitChatInvite(
} else if (type == u"CHANNELS_TOO_MUCH"_q) {
strongController->show(
Box(ChannelsLimitBox, &strongController->session()));
return;
}
strongController->hideLayer();

View File

@@ -365,6 +365,7 @@ void ChatParticipants::requestForAdd(
void ChatParticipants::requestLast(not_null<ChannelData*> channel) {
if (!channel->isMegagroup()
|| !channel->canViewMembers()
|| _participantsRequests.contains(channel)) {
return;
}
@@ -532,6 +533,7 @@ ChatParticipants::Parsed ChatParticipants::ParseRecent(
const TLMembers &data) {
const auto result = Parse(channel, data);
const auto applyLast = channel->isMegagroup()
&& channel->canViewMembers()
&& (channel->mgInfo->lastParticipants.size() <= result.list.size());
if (applyLast) {
ApplyLastList(channel, result.availableCount, result.list);

View File

@@ -206,7 +206,7 @@ void EditMessageWithUploadedPhoto(
EditMessageWithUploadedMedia(
item,
options,
PrepareUploadedPhoto(std::move(info)));
PrepareUploadedPhoto(item, std::move(info)));
}
mtpRequestId EditCaption(

View File

@@ -75,10 +75,14 @@ MTPVector<MTPDocumentAttribute> ComposeSendingDocumentAttributes(
} // namespace
MTPInputMedia PrepareUploadedPhoto(RemoteFileInfo info) {
const auto flags = info.attachedStickers.empty()
? MTPDinputMediaUploadedPhoto::Flags(0)
: MTPDinputMediaUploadedPhoto::Flag::f_stickers;
MTPInputMedia PrepareUploadedPhoto(
not_null<HistoryItem*> item,
RemoteFileInfo info) {
using Flag = MTPDinputMediaUploadedPhoto::Flag;
const auto spoiler = item->media()
&& item->media()->hasSpoiler();
const auto flags = (spoiler ? Flag::f_spoiler : Flag())
| (info.attachedStickers.empty() ? Flag() : Flag::f_stickers);
return MTP_inputMediaUploadedPhoto(
MTP_flags(flags),
info.file,
@@ -93,12 +97,13 @@ MTPInputMedia PrepareUploadedDocument(
if (!item || !item->media() || !item->media()->document()) {
return MTP_inputMediaEmpty();
}
const auto emptyFlag = MTPDinputMediaUploadedDocument::Flags(0);
using DocFlags = MTPDinputMediaUploadedDocument::Flag;
const auto flags = emptyFlag
| (info.thumb ? DocFlags::f_thumb : emptyFlag)
| (item->groupId() ? DocFlags::f_nosound_video : emptyFlag)
| (info.attachedStickers.empty() ? DocFlags::f_stickers : emptyFlag);
using Flag = MTPDinputMediaUploadedDocument::Flag;
const auto spoiler = item->media()
&& item->media()->hasSpoiler();
const auto flags = (spoiler ? Flag::f_spoiler : Flag())
| (info.thumb ? Flag::f_thumb : Flag())
| (item->groupId() ? Flag::f_nosound_video : Flag())
| (info.attachedStickers.empty() ? Flag::f_stickers : Flag());
const auto document = item->media()->document();
return MTP_inputMediaUploadedDocument(
MTP_flags(flags),

View File

@@ -13,7 +13,9 @@ namespace Api {
struct RemoteFileInfo;
MTPInputMedia PrepareUploadedPhoto(RemoteFileInfo info);
MTPInputMedia PrepareUploadedPhoto(
not_null<HistoryItem*> item,
RemoteFileInfo info);
MTPInputMedia PrepareUploadedDocument(
not_null<HistoryItem*> item,

View File

@@ -13,10 +13,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_file_origin.h"
#include "data/data_peer.h"
#include "data/data_photo.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/data_user_photos.h"
#include "history/history.h"
#include "main/main_session.h"
#include "storage/file_upload.h"
@@ -112,7 +114,54 @@ PeerPhoto::PeerPhoto(not_null<ApiWrap*> api)
});
}
void PeerPhoto::upload(not_null<PeerData*> peer, QImage &&image) {
void PeerPhoto::upload(
not_null<PeerData*> peer,
QImage &&image,
Fn<void()> done) {
upload(peer, std::move(image), UploadType::Default, std::move(done));
}
void PeerPhoto::uploadFallback(not_null<PeerData*> peer, QImage &&image) {
upload(peer, std::move(image), UploadType::Fallback, nullptr);
}
void PeerPhoto::updateSelf(
not_null<PhotoData*> photo,
Data::FileOrigin origin,
Fn<void()> done) {
const auto send = [=](auto resend) -> void {
const auto usedFileReference = photo->fileReference();
_api.request(MTPphotos_UpdateProfilePhoto(
MTP_flags(0),
photo->mtpInput()
)).done([=](const MTPphotos_Photo &result) {
result.match([&](const MTPDphotos_photo &data) {
_session->data().processPhoto(data.vphoto());
_session->data().processUsers(data.vusers());
});
if (done) {
done();
}
}).fail([=](const MTP::Error &error) {
if (error.code() == 400
&& error.type().startsWith(u"FILE_REFERENCE_"_q)) {
photo->session().api().refreshFileReference(origin, [=](
const auto &) {
if (photo->fileReference() != usedFileReference) {
resend(resend);
}
});
}
}).send();
};
send(send);
}
void PeerPhoto::upload(
not_null<PeerData*> peer,
QImage &&image,
UploadType type,
Fn<void()> done) {
peer = peer->migrateToOrMe();
const auto ready = PreparePeerPhoto(
_api.instance().mainDcId(),
@@ -125,19 +174,26 @@ void PeerPhoto::upload(not_null<PeerData*> peer, QImage &&image) {
const auto already = ranges::find(
_uploads,
peer,
[](const auto &pair) { return pair.second; });
[](const auto &pair) { return pair.second.peer; });
if (already != end(_uploads)) {
_session->uploader().cancel(already->first);
_uploads.erase(already);
}
_uploads.emplace(fakeId, peer);
_uploads.emplace(
fakeId,
UploadValue{ peer, type, std::move(done) });
_session->uploader().uploadMedia(fakeId, ready);
}
void PeerPhoto::suggest(not_null<PeerData*> peer, QImage &&image) {
upload(peer, std::move(image), UploadType::Suggestion, nullptr);
}
void PeerPhoto::clear(not_null<PhotoData*> photo) {
const auto self = _session->user();
if (self->userpicPhotoId() == photo->id) {
_api.request(MTPphotos_UpdateProfilePhoto(
MTP_flags(0),
MTP_inputPhotoEmpty()
)).done([=](const MTPphotos_Photo &result) {
self->setPhoto(MTP_userProfilePhotoEmpty());
@@ -158,12 +214,44 @@ void PeerPhoto::clear(not_null<PhotoData*> photo) {
)).done(applier).send();
}
} else {
_api.request(MTPphotos_DeletePhotos(
MTP_vector<MTPInputPhoto>(1, photo->mtpInput())
)).send();
const auto fallbackPhotoId = SyncUserFallbackPhotoViewer(self);
if (fallbackPhotoId && (*fallbackPhotoId) == photo->id) {
_api.request(MTPphotos_UpdateProfilePhoto(
MTP_flags(MTPphotos_UpdateProfilePhoto::Flag::f_fallback),
MTP_inputPhotoEmpty()
)).send();
_session->storage().add(Storage::UserPhotosSetBack(
peerToUser(self->id),
PhotoId()));
} else {
_api.request(MTPphotos_DeletePhotos(
MTP_vector<MTPInputPhoto>(1, photo->mtpInput())
)).send();
_session->storage().remove(Storage::UserPhotosRemoveOne(
peerToUser(self->id),
photo->id));
}
}
}
void PeerPhoto::clearPersonal(not_null<UserData*> user) {
_api.request(MTPphotos_UploadContactProfilePhoto(
MTP_flags(MTPphotos_UploadContactProfilePhoto::Flag::f_save),
user->inputUser,
MTPInputFile(),
MTPInputFile(), // video
MTPdouble() // video_start_ts
)).done([=](const MTPphotos_Photo &result) {
result.match([&](const MTPDphotos_photo &data) {
_session->data().processPhoto(data.vphoto());
_session->data().processUsers(data.vusers());
});
}).send();
if (!user->userpicPhotoUnknown() && user->hasPersonalPhoto()) {
_session->storage().remove(Storage::UserPhotosRemoveOne(
peerToUser(self->id),
photo->id));
peerToUser(user->id),
user->userpicPhotoId()));
}
}
@@ -173,6 +261,7 @@ void PeerPhoto::set(not_null<PeerData*> peer, not_null<PhotoData*> photo) {
}
if (peer == _session->user()) {
_api.request(MTPphotos_UpdateProfilePhoto(
MTP_flags(0),
photo->mtpInput()
)).done([=](const MTPphotos_Photo &result) {
result.match([&](const MTPDphotos_photo &data) {
@@ -199,25 +288,40 @@ void PeerPhoto::set(not_null<PeerData*> peer, not_null<PhotoData*> photo) {
}
void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
const auto maybePeer = _uploads.take(msgId);
if (!maybePeer) {
const auto maybeUploadValue = _uploads.take(msgId);
if (!maybeUploadValue) {
return;
}
const auto peer = *maybePeer;
const auto peer = maybeUploadValue->peer;
const auto type = maybeUploadValue->type;
const auto done = maybeUploadValue->done;
const auto applier = [=](const MTPUpdates &result) {
_session->updates().applyUpdates(result);
if (done) {
done();
}
};
if (peer->isSelf()) {
_api.request(MTPphotos_UploadProfilePhoto(
MTP_flags(MTPphotos_UploadProfilePhoto::Flag::f_file),
MTP_flags(MTPphotos_UploadProfilePhoto::Flag::f_file
| ((type == UploadType::Fallback)
? MTPphotos_UploadProfilePhoto::Flag::f_fallback
: MTPphotos_UploadProfilePhoto::Flags(0))),
file,
MTPInputFile(), // video
MTPdouble() // video_start_ts
)).done([=](const MTPphotos_Photo &result) {
result.match([&](const MTPDphotos_photo &data) {
_session->data().processPhoto(data.vphoto());
_session->data().processUsers(data.vusers());
});
const auto photoId = _session->data().processPhoto(
result.data().vphoto())->id;
_session->data().processUsers(result.data().vusers());
if (type == UploadType::Fallback) {
_session->storage().add(Storage::UserPhotosSetBack(
peerToUser(peer->id),
photoId));
}
if (done) {
done();
}
}).send();
} else if (const auto chat = peer->asChat()) {
const auto history = _session->data().history(chat);
@@ -239,6 +343,29 @@ void PeerPhoto::ready(const FullMsgId &msgId, const MTPInputFile &file) {
MTPInputFile(), // video
MTPdouble()) // video_start_ts
)).done(applier).afterRequest(history->sendRequestId).send();
} else if (const auto user = peer->asUser()) {
using Flag = MTPphotos_UploadContactProfilePhoto::Flag;
_api.request(MTPphotos_UploadContactProfilePhoto(
MTP_flags(Flag::f_file
| ((type == UploadType::Suggestion)
? Flag::f_suggest
: Flag::f_save)),
user->inputUser,
file,
MTPInputFile(), // video
MTPdouble() // video_start_ts
)).done([=](const MTPphotos_Photo &result) {
result.match([&](const MTPDphotos_photo &data) {
_session->data().processPhoto(data.vphoto());
_session->data().processUsers(data.vusers());
});
if (type != UploadType::Suggestion) {
user->updateFullForced();
}
if (done) {
done();
}
}).send();
}
}
@@ -257,26 +384,34 @@ void PeerPhoto::requestUserPhotos(
)).done([this, user](const MTPphotos_Photos &result) {
_userPhotosRequests.remove(user);
const auto fullCount = result.match([](const MTPDphotos_photos &d) {
auto fullCount = result.match([](const MTPDphotos_photos &d) {
return int(d.vphotos().v.size());
}, [](const MTPDphotos_photosSlice &d) {
return d.vcount().v;
});
auto &owner = _session->data();
auto photoIds = result.match([&](const auto &data) {
auto &owner = _session->data();
owner.processUsers(data.vusers());
auto photoIds = std::vector<PhotoId>();
photoIds.reserve(data.vphotos().v.size());
for (const auto &photo : data.vphotos().v) {
if (const auto photoData = owner.processPhoto(photo)) {
photoIds.push_back(photoData->id);
for (const auto &single : data.vphotos().v) {
const auto photo = owner.processPhoto(single);
if (!photo->isNull()) {
photoIds.push_back(photo->id);
}
}
return photoIds;
});
if (!user->userpicPhotoUnknown() && user->hasPersonalPhoto()) {
const auto photo = owner.photo(user->userpicPhotoId());
if (!photo->isNull()) {
++fullCount;
photoIds.insert(begin(photoIds), photo->id);
}
}
_session->storage().add(Storage::UserPhotosAddSlice(
peerToUser(user->id),
@@ -289,4 +424,21 @@ void PeerPhoto::requestUserPhotos(
_userPhotosRequests.emplace(user, requestId);
}
// Non-personal photo in case a personal photo is set.
void PeerPhoto::registerNonPersonalPhoto(
not_null<UserData*> user,
not_null<PhotoData*> photo) {
_nonPersonalPhotos.emplace_or_assign(user, photo);
}
void PeerPhoto::unregisterNonPersonalPhoto(not_null<UserData*> user) {
_nonPersonalPhotos.erase(user);
}
PhotoData *PeerPhoto::nonPersonalPhoto(
not_null<UserData*> user) const {
const auto i = _nonPersonalPhotos.find(user);
return (i != end(_nonPersonalPhotos)) ? i->second.get() : nullptr;
}
} // namespace Api

View File

@@ -13,6 +13,10 @@ class ApiWrap;
class PeerData;
class UserData;
namespace Data {
struct FileOrigin;
} // namespace Data
namespace Main {
class Session;
} // namespace Main
@@ -24,22 +28,61 @@ public:
using UserPhotoId = PhotoId;
explicit PeerPhoto(not_null<ApiWrap*> api);
void upload(not_null<PeerData*> peer, QImage &&image);
void upload(
not_null<PeerData*> peer,
QImage &&image,
Fn<void()> done = nullptr);
void uploadFallback(not_null<PeerData*> peer, QImage &&image);
void updateSelf(
not_null<PhotoData*> photo,
Data::FileOrigin origin,
Fn<void()> done = nullptr);
void suggest(not_null<PeerData*> peer, QImage &&image);
void clear(not_null<PhotoData*> photo);
void clearPersonal(not_null<UserData*> user);
void set(not_null<PeerData*> peer, not_null<PhotoData*> photo);
void requestUserPhotos(not_null<UserData*> user, UserPhotoId afterId);
// Non-personal photo in case a personal photo is set.
void registerNonPersonalPhoto(
not_null<UserData*> user,
not_null<PhotoData*> photo);
void unregisterNonPersonalPhoto(not_null<UserData*> user);
[[nodiscard]] PhotoData *nonPersonalPhoto(
not_null<UserData*> user) const;
private:
enum class UploadType {
Default,
Suggestion,
Fallback,
};
void ready(const FullMsgId &msgId, const MTPInputFile &file);
void upload(
not_null<PeerData*> peer,
QImage &&image,
UploadType type,
Fn<void()> done);
const not_null<Main::Session*> _session;
MTP::Sender _api;
base::flat_map<FullMsgId, not_null<PeerData*>> _uploads;
struct UploadValue {
not_null<PeerData*> peer;
UploadType type = UploadType::Default;
Fn<void()> done;
};
base::flat_map<FullMsgId, UploadValue> _uploads;
base::flat_map<not_null<UserData*>, mtpRequestId> _userPhotosRequests;
base::flat_map<
not_null<UserData*>,
not_null<PhotoData*>> _nonPersonalPhotos;
};
} // namespace Api

View File

@@ -16,7 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_poll.h"
#include "data/data_session.h"
#include "history/history.h"
#include "history/history_message.h" // ShouldSendSilent
#include "history/history_item.h"
#include "history/history_item_helpers.h" // ShouldSendSilent
#include "main/main_session.h"
namespace Api {

View File

@@ -44,9 +44,10 @@ void SendReport(
Ui::ReportReason reason,
const QString &comment,
std::variant<v::null_t, MessageIdsList, not_null<PhotoData*>> data) {
auto done = [=] {
auto weak = Ui::MakeWeak(toastParent.get());
auto done = crl::guard(toastParent, [=] {
Ui::Toast::Show(toastParent, tr::lng_report_thanks(tr::now));
};
});
v::match(data, [&](v::null_t) {
peer->session().api().request(MTPaccount_ReportPeer(
peer->input,

View File

@@ -20,7 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h"
#include "data/stickers/data_stickers.h"
#include "history/history.h"
#include "history/history_message.h" // NewMessageFlags.
#include "history/history_item.h"
#include "history/history_item_helpers.h" // NewMessageFlags.
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
#include "chat_helpers/stickers_dice_pack.h" // DicePacks::kDiceString.
#include "ui/text/text_entity.h" // TextWithEntities.
@@ -392,6 +393,7 @@ void SendConfirmedFile(
action.replyTo = file->to.replyTo;
action.topicRootId = file->to.topicRootId;
action.generateLocal = true;
action.replaceMediaOf = file->to.replaceMediaOf;
session->api().sendAction(action);
auto caption = TextWithEntities{
@@ -439,13 +441,17 @@ void SendConfirmedFile(
const auto media = MTPMessageMedia([&] {
if (file->type == SendMediaType::Photo) {
using Flag = MTPDmessageMediaPhoto::Flag;
return MTP_messageMediaPhoto(
MTP_flags(MTPDmessageMediaPhoto::Flag::f_photo),
MTP_flags(Flag::f_photo
| (file->spoiler ? Flag::f_spoiler : Flag())),
file->photo,
MTPint());
} else if (file->type == SendMediaType::File) {
using Flag = MTPDmessageMediaDocument::Flag;
return MTP_messageMediaDocument(
MTP_flags(MTPDmessageMediaDocument::Flag::f_document),
MTP_flags(Flag::f_document
| (file->spoiler ? Flag::f_spoiler : Flag())),
file->document,
MTPint());
} else if (file->type == SendMediaType::Audio) {

View File

@@ -1513,7 +1513,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
// Request last active supergroup participants if the 'from' user was not loaded yet.
// This will optimize similar getDifference() calls for almost all next messages.
if (isDataLoaded == DataIsLoadedResult::FromNotLoaded && channel && channel->isMegagroup()) {
if (channel->mgInfo->lastParticipants.size() < _session->serverConfig().chatSizeMax
if (channel->canViewMembers()
&& channel->mgInfo->lastParticipants.size() < _session->serverConfig().chatSizeMax
&& (channel->mgInfo->lastParticipants.empty()
|| channel->mgInfo->lastParticipants.size() < channel->membersCount())) {
session().api().chatParticipants().requestLast(channel);
@@ -1895,26 +1896,12 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
} break;
case mtpc_updateUserPhoto: {
auto &d = update.c_updateUserPhoto();
if (auto user = session().data().userLoaded(d.vuser_id())) {
user->setPhoto(d.vphoto());
user->loadUserpic();
// After that update we don't have enough information to
// create a 'photo' with all necessary fields. So if
// we receive second such update we end up with a 'photo_id'
// in user_photos list without a loaded 'photo'.
// It fails to show in media overview if you try to open it.
//
//if (mtpIsTrue(d.vprevious()) || !user->userpicPhotoId()) {
session().storage().remove(Storage::UserPhotosRemoveAfter(
peerToUser(user->id),
user->userpicPhotoId()));
//} else {
// session().storage().add(Storage::UserPhotosAddNew(
// peerToUser(user->id),
// user->userpicPhotoId()));
//}
case mtpc_updateUser: {
auto &d = update.c_updateUser();
if (const auto user = session().data().userLoaded(d.vuser_id())) {
if (user->wasFullUpdated()) {
user->updateFullForced();
}
}
} break;

View File

@@ -571,7 +571,10 @@ bool WhoReadExists(not_null<HistoryItem*> item) {
const auto peer = history->peer;
const auto chat = peer->asChat();
const auto megagroup = peer->asMegagroup();
if ((!chat && !megagroup) || peer->isForum()) {
if ((!chat && !megagroup)
|| peer->isForum()
|| (megagroup
&& (megagroup->flags() & ChannelDataFlag::ParticipantsHidden))) {
return false;
}
const auto &appConfig = peer->session().account().appConfig();

View File

@@ -67,8 +67,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/add_contact_box.h"
#include "mtproto/mtproto_config.h"
#include "history/history.h"
#include "history/history_message.h"
#include "history/history_item.h"
#include "history/history_item_components.h"
#include "history/history_item_helpers.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "main/main_account.h"
@@ -690,7 +691,11 @@ QString ApiWrap::exportDirectMessageLink(
auto linkThreadId = MsgId();
auto linkThreadIsTopic = false;
if (inRepliesContext) {
if (const auto rootId = item->replyToTop()) {
linkThreadIsTopic = item->history()->isForum();
const auto rootId = linkThreadIsTopic
? item->topicRootId()
: item->replyToTop();
if (rootId) {
const auto root = item->history()->owner().message(
channel->id,
rootId);
@@ -710,7 +715,6 @@ QString ApiWrap::exportDirectMessageLink(
} else {
// Reply in a thread, maybe comment in a private channel.
linkThreadId = rootId;
linkThreadIsTopic = (item->topicRootId() == rootId);
}
}
}
@@ -2415,6 +2419,12 @@ void ApiWrap::refreshFileReference(
} else {
fail();
}
}, [&](Data::FileOriginFullUser data) {
if (const auto user = _session->data().user(data.userId)) {
request(MTPusers_GetFullUser(user->inputUser));
} else {
fail();
}
}, [&](Data::FileOriginPeerPhoto data) {
fail();
}, [&](Data::FileOriginStickerSet data) {
@@ -3055,7 +3065,7 @@ void ApiWrap::sharedMediaDone(
}
void ApiWrap::sendAction(const SendAction &action) {
if (!action.options.scheduled) {
if (!action.options.scheduled && !action.replaceMediaOf) {
const auto topic = action.topicRootId
? action.history->peer->forumTopicFor(action.topicRootId)
: nullptr;
@@ -3147,7 +3157,11 @@ void ApiWrap::forwardMessages(
if (sendAs) {
sendFlags |= MTPmessages_ForwardMessages::Flag::f_send_as;
}
if (action.topicRootId) {
const auto kGeneralId = Data::ForumTopic::kGeneralId;
const auto topMsgId = (action.topicRootId == kGeneralId)
? MsgId(0)
: action.topicRootId;
if (topMsgId) {
sendFlags |= MTPmessages_ForwardMessages::Flag::f_top_msg_id;
}
@@ -3169,7 +3183,7 @@ void ApiWrap::forwardMessages(
MTP_vector<MTPint>(ids),
MTP_vector<MTPlong>(randomIds),
peer->input,
MTP_int(action.topicRootId),
MTP_int(topMsgId),
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
)).done([=](const MTPUpdates &result) {
@@ -3222,7 +3236,7 @@ void ApiWrap::forwardMessages(
messageFromId,
messagePostAuthor,
item,
action.topicRootId);
topMsgId);
_session->data().registerMessageRandomId(randomId, newId);
if (!localIds) {
localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();
@@ -3364,7 +3378,8 @@ void ApiWrap::editMedia(
std::move(file.information),
type,
to,
caption));
caption,
file.spoiler));
}
void ApiWrap::sendFiles(
@@ -3405,6 +3420,7 @@ void ApiWrap::sendFiles(
uploadWithType,
to,
caption,
file.spoiler,
album));
caption = TextWithTags();
}
@@ -3424,14 +3440,17 @@ void ApiWrap::sendFile(
const SendAction &action) {
const auto to = fileLoadTaskOptions(action);
auto caption = TextWithTags();
const auto spoiler = false;
const auto information = nullptr;
_fileLoader->addTask(std::make_unique<FileLoadTask>(
&session(),
QString(),
fileContent,
nullptr,
information,
type,
to,
caption));
caption,
spoiler));
}
void ApiWrap::sendUploadedPhoto(
@@ -3439,7 +3458,7 @@ void ApiWrap::sendUploadedPhoto(
Api::RemoteFileInfo info,
Api::SendOptions options) {
if (const auto item = _session->data().message(localId)) {
const auto media = Api::PrepareUploadedPhoto(std::move(info));
const auto media = Api::PrepareUploadedPhoto(item, std::move(info));
if (const auto groupId = item->groupId()) {
uploadAlbumMedia(item, groupId, media);
} else {
@@ -3790,7 +3809,9 @@ void ApiWrap::uploadAlbumMedia(
failed();
return;
}
auto spoiler = false;
if (const auto media = item->media()) {
spoiler = media->hasSpoiler();
if (const auto photo = media->photo()) {
photo->setWaitingForAlbum();
} else if (const auto document = media->document()) {
@@ -3807,10 +3828,10 @@ void ApiWrap::uploadAlbumMedia(
return;
}
const auto &fields = photo->c_photo();
const auto flags = MTPDinputMediaPhoto::Flags(0)
| (data.vttl_seconds()
? MTPDinputMediaPhoto::Flag::f_ttl_seconds
: MTPDinputMediaPhoto::Flag(0));
using Flag = MTPDinputMediaPhoto::Flag;
const auto flags = Flag()
| (data.vttl_seconds() ? Flag::f_ttl_seconds : Flag())
| (spoiler ? Flag::f_spoiler : Flag());
const auto media = MTP_inputMediaPhoto(
MTP_flags(flags),
MTP_inputPhoto(
@@ -3829,10 +3850,10 @@ void ApiWrap::uploadAlbumMedia(
return;
}
const auto &fields = document->c_document();
const auto flags = MTPDinputMediaDocument::Flags(0)
| (data.vttl_seconds()
? MTPDinputMediaDocument::Flag::f_ttl_seconds
: MTPDinputMediaDocument::Flag(0));
using Flag = MTPDinputMediaDocument::Flag;
const auto flags = Flag()
| (data.vttl_seconds() ? Flag::f_ttl_seconds : Flag())
| (spoiler ? Flag::f_spoiler : Flag());
const auto media = MTP_inputMediaDocument(
MTP_flags(flags),
MTP_inputDocument(

View File

@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/labels.h"
#include "ui/text/text_utilities.h"
#include "base/platform/base_platform_info.h"
#include "core/file_utilities.h"
#include "core/click_handler_types.h"
#include "core/update_checker.h"
#include "core/application.h"
@@ -116,7 +117,7 @@ void AboutBox::showVersionHistory() {
"version of Telegram Desktop was copied to the clipboard."),
Ui::LayerOption::CloseOther);
} else {
UrlClickHandler::Open(Core::App().changelogLink());
File::OpenUrl(Core::App().changelogLink());
}
}

View File

@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/about_sponsored_box.h"
#include "core/file_utilities.h"
#include "lang/lang_keys.h"
#include "ui/layers/generic_box.h"
#include "ui/widgets/buttons.h"
@@ -14,8 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include <QtGui/QDesktopServices>
namespace Ui {
namespace {
@@ -50,7 +49,7 @@ void AboutSponsoredBox(not_null<Ui::GenericBox*> box) {
(rowSize.height() - buttonSize.height()) / 2);
}, row->lifetime());
button->addClickHandler([=] {
QDesktopServices::openUrl({ kUrl.utf8() });
File::OpenUrl(kUrl.utf8());
});
};

View File

@@ -22,11 +22,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "countries/countries_instance.h" // Countries::ExtractPhoneCode.
#include "window/window_session_controller.h"
#include "menu/menu_ttl.h"
#include "ui/controls/userpic_button.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/toast/toast.h"
#include "ui/special_buttons.h"
#include "ui/widgets/fields/special_fields.h"
#include "ui/widgets/popup_menu.h"
#include "ui/text/format_values.h"
@@ -465,10 +465,7 @@ void GroupInfoBox::prepare() {
_photo.create(
this,
&_navigation->parentController()->window(),
((_type == Type::Channel)
? tr::lng_create_channel_crop
: tr::lng_create_group_crop)(tr::now),
Ui::UserpicButton::Role::ChangePhoto,
Ui::UserpicButton::Role::ChoosePhoto,
st::defaultUserpicButton);
_title.create(
this,

View File

@@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/painter.h"
#include "ui/ui_utility.h"
#include "history/history.h"
#include "history/history_message.h"
#include "history/history_item.h"
#include "history/view/history_view_message.h"
#include "main/main_session.h"
#include "apiwrap.h"

View File

@@ -62,6 +62,18 @@ defaultUserpicButton: UserpicButton {
uploadIcon: defaultUploadUserpicIcon;
uploadIconPosition: point(-1px, 1px);
}
uploadUserpicSize: 32px;
uploadUserpicButton: UserpicButton(defaultUserpicButton) {
size: size(uploadUserpicSize, uploadUserpicSize);
photoSize: uploadUserpicSize;
changeIcon: icon {{ "settings/photo", activeButtonFg }};
changeIconPosition: point(4px, 4px);
}
uploadUserpicButtonBorder: 2px;
restoreUserpicIcon: UserpicButton(defaultUserpicButton) {
size: size(22px, 22px);
photoSize: 22px;
}
confirmInviteTitle: FlatLabel(defaultFlatLabel) {
align: align(center);
@@ -565,9 +577,6 @@ colorResultInput: InputField(colorValueInput) {
changePhoneButton: RoundButton(defaultActiveButton) {
width: 256px;
height: 42px;
textTop: 11px;
font: boxButtonFont;
}
changePhoneButtonPadding: margins(0px, 32px, 0px, 44px);
changePhoneTitle: FlatLabel(boxTitle) {

View File

@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_messages_search.h"
#include "base/unixtime.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_histories.h"
@@ -27,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "ui/wrap/slide_wrap.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@@ -229,11 +231,32 @@ void DeleteMessagesBox::prepare() {
auto count = int(_ids.size());
if (hasScheduledMessages()) {
} else if (auto revoke = revokeText(peer)) {
const auto &settings = Core::App().settings();
const auto revokeByDefault =
!settings.rememberedDeleteMessageOnlyForYou();
_revoke.create(
this,
revoke->checkbox,
true,
revokeByDefault,
st::defaultBoxCheckbox);
_revokeRemember.create(
this,
object_ptr<Ui::Checkbox>(
this,
tr::lng_remember(),
false,
st::defaultBoxCheckbox));
_revokeRemember->hide(anim::type::instant);
_revoke->checkedValue(
) | rpl::start_with_next([=](bool checked) {
_revokeRemember->toggle(
checked != revokeByDefault,
anim::type::normal);
}, _revokeRemember->lifetime());
_revokeRemember->heightValue(
) | rpl::start_with_next([=](int h) {
setDimensions(st::boxWidth, _fullHeight + h);
}, lifetime());
appendDetails(std::move(revoke->description));
} else if (peer->isChannel()) {
if (peer->isMegagroup()) {
@@ -309,6 +332,7 @@ void DeleteMessagesBox::prepare() {
+ st::boxLittleSkip;
}
setDimensions(st::boxWidth, fullHeight);
_fullHeight = fullHeight;
}
bool DeleteMessagesBox::hasScheduledMessages() const {
@@ -450,6 +474,11 @@ void DeleteMessagesBox::resizeEvent(QResizeEvent *e) {
_revoke->resizeToNaturalWidth(availableWidth);
_revoke->moveToLeft(padding.left(), top);
top += _revoke->heightNoMargins() + st::boxLittleSkip;
if (_revokeRemember) {
_revokeRemember->resizeToNaturalWidth(availableWidth);
_revokeRemember->moveToLeft(padding.left(),top);
top += _revokeRemember->heightNoMargins();
}
}
if (_autoDeleteSettings) {
top += st::boxMediumSkip - st::boxLittleSkip;
@@ -469,6 +498,14 @@ void DeleteMessagesBox::keyPressEvent(QKeyEvent *e) {
}
void DeleteMessagesBox::deleteAndClear() {
if (_revoke
&& _revokeRemember
&& _revokeRemember->toggled()
&& _revokeRemember->entity()->checked()) {
Core::App().settings().setRememberedDeleteMessageOnlyForYou(
!_revoke->checked());
Core::App().saveSettingsDelayed();
}
const auto revoke = _revoke ? _revoke->checked() : _revokeForBot;
const auto session = _session;
const auto invokeCallbackAndClose = [&] {

View File

@@ -17,6 +17,8 @@ namespace Ui {
class Checkbox;
class FlatLabel;
class LinkButton;
template <typename Widget>
class SlideWrap;
} // namespace Ui
class DeleteMessagesBox final : public Ui::BoxContent {
@@ -73,11 +75,14 @@ private:
object_ptr<Ui::FlatLabel> _text = { nullptr };
object_ptr<Ui::Checkbox> _revoke = { nullptr };
object_ptr<Ui::SlideWrap<Ui::Checkbox>> _revokeRemember = { nullptr };
object_ptr<Ui::Checkbox> _banUser = { nullptr };
object_ptr<Ui::Checkbox> _reportSpam = { nullptr };
object_ptr<Ui::Checkbox> _deleteAll = { nullptr };
object_ptr<Ui::LinkButton> _autoDeleteSettings = { nullptr };
int _fullHeight = 0;
Fn<void()> _deleteConfirmedCallback;
};

View File

@@ -28,6 +28,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_premium_limits.h"
#include "data/stickers/data_stickers.h"
#include "data/stickers/data_custom_emoji.h"
#include "editor/editor_layer_widget.h"
#include "editor/photo_editor.h"
#include "editor/photo_editor_layer_widget.h"
#include "history/history_drag_area.h"
#include "history/history_item.h"
@@ -175,12 +177,15 @@ void EditCaptionBox::rebuildPreview() {
Window::GifPauseReason::Layer);
};
applyChanges();
_previewHasSpoiler = nullptr;
if (_preparedList.files.empty()) {
const auto media = _historyItem->media();
const auto photo = media->photo();
const auto document = media->document();
_isPhoto = (photo != nullptr);
if (photo || document->isVideoFile() || document->isAnimation()) {
_isPhoto = (photo != nullptr);
const auto media = Ui::CreateChild<Ui::ItemSingleMediaPreview>(
this,
gifPaused,
@@ -189,7 +194,6 @@ void EditCaptionBox::rebuildPreview() {
_photoMedia = media->sharedPhotoMedia();
_content.reset(media);
} else {
_isPhoto = false;
_content.reset(Ui::CreateChild<Ui::ItemSingleFilePreview>(
this,
_historyItem,
@@ -203,11 +207,12 @@ void EditCaptionBox::rebuildPreview() {
gifPaused,
file,
Ui::AttachControls::Type::EditOnly);
if (media) {
_isPhoto = media->isPhoto();
_isPhoto = (media && media->isPhoto());
const auto withCheckbox = _isPhoto && CanBeCompressed(_albumType);
if (media && (!withCheckbox || !_asFile)) {
_previewHasSpoiler = [media] { return media->hasSpoiler(); };
_content.reset(media);
} else {
_isPhoto = false;
_content.reset(Ui::CreateChild<Ui::SingleFilePreview>(
this,
file,
@@ -299,7 +304,7 @@ void EditCaptionBox::setupControls() {
{}
) | rpl::map([=] {
return _controller->session().settings().photoEditorHintShown()
? _isPhoto
? (_isPhoto && !_asFile)
: false;
});
@@ -316,7 +321,7 @@ void EditCaptionBox::setupControls() {
this,
object_ptr<Ui::Checkbox>(
this,
tr::lng_send_compressed(tr::now),
tr::lng_send_compressed_one(tr::now),
true,
st::defaultBoxCheckbox),
st::editMediaCheckboxMargins)
@@ -329,7 +334,9 @@ void EditCaptionBox::setupControls() {
anim::type::instant
)->entity()->checkedChanges(
) | rpl::start_with_next([&](bool checked) {
applyChanges();
_asFile = !checked;
rebuildPreview();
}, _controls->lifetime());
_controls->resizeToWidth(st::sendMediaPreviewSize);
@@ -430,6 +437,8 @@ void EditCaptionBox::setupPhotoEditorEventHandler() {
return;
}
auto copy = large->original();
const auto wasSpoiler = hasSpoiler();
_preparedList = Storage::PrepareMediaFromImage(
std::move(copy),
QByteArray(),
@@ -437,6 +446,7 @@ void EditCaptionBox::setupPhotoEditorEventHandler() {
using ImageInfo = Ui::PreparedFileInformation::Image;
auto &file = _preparedList.files.front();
file.spoiler = wasSpoiler;
const auto image = std::get_if<ImageInfo>(
&file.information->media);
@@ -445,13 +455,18 @@ void EditCaptionBox::setupPhotoEditorEventHandler() {
rebuildPreview();
};
const auto fileImage = std::make_shared<Image>(*large);
auto editor = base::make_unique_q<Editor::PhotoEditor>(
this,
&controller->window(),
fileImage,
Editor::PhotoModifications());
const auto raw = editor.get();
auto layer = std::make_unique<Editor::LayerWidget>(
this,
std::move(editor));
Editor::InitEditorLayer(layer.get(), raw, std::move(callback));
controller->showLayer(
std::make_unique<Editor::LayerWidget>(
this,
&controller->window(),
fileImage,
Editor::PhotoModifications(),
std::move(callback)),
std::move(layer),
Ui::LayerOption::KeepOther);
}
}, lifetime());
@@ -581,11 +596,20 @@ bool EditCaptionBox::setPreparedList(Ui::PreparedList &&list) {
tr::lng_edit_media_album_error(tr::now));
return false;
}
const auto wasSpoiler = hasSpoiler();
_preparedList = std::move(list);
_preparedList.files.front().spoiler = wasSpoiler;
rebuildPreview();
return true;
}
bool EditCaptionBox::hasSpoiler() const {
return _preparedList.files.empty()
? (_historyItem->media()
&& _historyItem->media()->hasSpoiler())
: _preparedList.files.front().spoiler;
}
void EditCaptionBox::captionResized() {
updateBoxSize();
resizeEvent(0);
@@ -690,6 +714,12 @@ bool EditCaptionBox::validateLength(const QString &text) const {
return false;
}
void EditCaptionBox::applyChanges() {
if (!_preparedList.files.empty() && _previewHasSpoiler) {
_preparedList.files.front().spoiler = _previewHasSpoiler();
}
}
void EditCaptionBox::save() {
if (_saveRequestId) {
return;
@@ -727,10 +757,14 @@ void EditCaptionBox::save() {
action.replaceMediaOf = item->fullId().msg;
Storage::ApplyModifications(_preparedList);
if (!_preparedList.files.empty()) {
_preparedList.files.front().spoiler = false;
applyChanges();
}
_controller->session().api().editMedia(
std::move(_preparedList),
(!_asFile && _isPhoto && CanBeCompressed(_albumType))
(_isPhoto && !_asFile && CanBeCompressed(_albumType))
? SendMediaType::Photo
: SendMediaType::File,
_field->getTextWithAppliedMarkdown(),

View File

@@ -64,11 +64,13 @@ private:
void setupDragArea();
bool validateLength(const QString &text) const;
void applyChanges();
void save();
bool fileFromClipboard(not_null<const QMimeData*> data);
int errorTopSkip() const;
[[nodiscard]] int errorTopSkip() const;
[[nodiscard]] bool hasSpoiler() const;
bool setPreparedList(Ui::PreparedList &&list);
@@ -83,6 +85,7 @@ private:
const base::unique_qptr<Ui::EmojiButton> _emojiToggle;
base::unique_qptr<Ui::AbstractSinglePreview> _content;
Fn<bool()> _previewHasSpoiler;
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
base::unique_qptr<QObject> _emojiFilter;

View File

@@ -276,6 +276,11 @@ void EditPrivacyBox::setupContent() {
? tr::lng_edit_privacy_exceptions_count(tr::now, lt_count, count)
: tr::lng_edit_privacy_exceptions_add(tr::now);
});
_controller->handleExceptionsChange(
exception,
update->events_starting_with({}) | rpl::map([=] {
return Settings::ExceptionUsersCount(exceptions(exception));
}));
auto text = _controller->exceptionButtonTextKey(exception);
const auto always = (exception == Exception::Always);
const auto button = content->add(

View File

@@ -57,6 +57,10 @@ public:
Exception exception) const = 0;
[[nodiscard]] virtual auto exceptionsDescription()
const -> rpl::producer<QString> = 0;
virtual void handleExceptionsChange(
Exception exception,
rpl::producer<int> value) {
}
[[nodiscard]] virtual object_ptr<Ui::RpWidget> setupAboveWidget(
not_null<QWidget*> parent,
@@ -72,7 +76,7 @@ public:
}
[[nodiscard]] virtual object_ptr<Ui::RpWidget> setupBelowWidget(
not_null<Window::SessionController*> controller,
not_null<QWidget*> parent) const {
not_null<QWidget*> parent) {
return { nullptr };
}

View File

@@ -19,10 +19,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "settings/settings_premium.h"
#include "ui/basic_click_handlers.h" // UrlClickHandler::Open.
#include "ui/controls/userpic_button.h"
#include "ui/effects/premium_graphics.h"
#include "ui/effects/premium_stars_colored.h"
#include "ui/layers/generic_box.h"
#include "ui/special_buttons.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/checkbox.h"
@@ -86,7 +86,6 @@ void GiftBox(
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
top,
user,
Ui::UserpicButton::Role::Custom,
st::defaultUserpicButton);
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
top->widthValue(

View File

@@ -1117,7 +1117,8 @@ void LanguageBox::prepare() {
Core::App().saveSettingsDelayed();
}, translateEnabled->lifetime());
const auto label = lifetime().make_state<rpl::event_stream<QLocale>>();
using Locales = std::vector<QLocale>;
const auto label = lifetime().make_state<rpl::event_stream<Locales>>();
const auto translateSkipWrap = topContainer->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
topContainer,
@@ -1129,30 +1130,27 @@ void LanguageBox::prepare() {
const auto translateSkip = Settings::AddButtonWithLabel(
translateSkipWrap->entity(),
tr::lng_translate_settings_choose(),
label->events() | rpl::map(Ui::LanguageName),
label->events(
) | rpl::map([](const Locales &locales) {
return (locales.size() > 1)
? tr::lng_languages_count(tr::now, lt_count, locales.size())
: Ui::LanguageName(locales.front());
}),
st::settingsButtonNoIcon);
{
const auto settingsLang =
Core::App().settings().skipTranslationForLanguage();
const auto locale = (settingsLang == QLocale::English)
? QLocale(Lang::LanguageIdOrDefault(Lang::Id()))
: (settingsLang == QLocale::C)
? QLocale(QLocale::English)
: QLocale(settingsLang);
label->fire_copy(locale);
}
label->fire(Ui::Translate::LocalesFromSettings());
translateSkip->setClickedCallback([=] {
Ui::BoxShow(this).showBox(
Box(Ui::ChooseLanguageBox, [=](QLocale locale) {
label->fire_copy(locale);
const auto result = (locale.language() == QLocale::English)
? QLocale::c()
: locale;
Core::App().settings().setSkipTranslationForLanguage(
result.language());
Box(Ui::ChooseLanguageBox, [=](std::vector<QLocale> locales) {
label->fire_copy(locales);
const auto result = ranges::views::all(
locales
) | ranges::views::transform([](const QLocale &l) {
return int(l.language());
}) | ranges::to_vector;
Core::App().settings().setSkipTranslationForLanguages(result);
Core::App().saveSettingsDelayed();
}),
}, Ui::Translate::LocalesFromSettings()),
Ui::LayerOption::KeepOther);
});
Settings::AddSkip(topContainer);

View File

@@ -363,10 +363,6 @@ void PeerListController::peerListSearchRefreshRows() {
delegate()->peerListRefreshRows();
}
rpl::producer<int> PeerListController::onlineCountValue() const {
return rpl::single(0);
}
void PeerListController::setDescriptionText(const QString &text) {
if (text.isEmpty()) {
setDescription(nullptr);
@@ -735,7 +731,6 @@ int PeerListRow::paintNameIconGetWidth(
.premiumFg = &(selected
? st::dialogsVerifiedIconBgOver
: st::dialogsVerifiedIconBg),
.preview = st::windowBgOver->c,
.customEmojiRepaint = repaint,
.now = now,
.paused = false,

View File

@@ -529,8 +529,6 @@ public:
Unexpected("PeerListController::customRowRippleMaskGenerator.");
}
[[nodiscard]] virtual rpl::producer<int> onlineCountValue() const;
[[nodiscard]] rpl::lifetime &lifetime() {
return _lifetime;
}

View File

@@ -46,7 +46,7 @@ base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
if (const auto chat = peer->asChat()) {
return chat->participants;
} else if (const auto channel = peer->asChannel()) {
if (channel->isMegagroup()) {
if (channel->isMegagroup() && channel->canViewMembers()) {
const auto &participants = channel->mgInfo->lastParticipants;
return { participants.cbegin(), participants.cend() };
}
@@ -140,6 +140,7 @@ bool AddParticipantsBoxController::isAlreadyIn(
} else if (const auto channel = _peer->asChannel()) {
return _alreadyIn.contains(user)
|| (channel->isMegagroup()
&& channel->canViewMembers()
&& base::contains(channel->mgInfo->lastParticipants, user));
}
Unexpected("User in AddParticipantsBoxController::isAlreadyIn");

View File

@@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "api/api_peer_photo.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_info.h"
@@ -41,7 +42,8 @@ void SendRequest(
bool sharePhone,
const QString &first,
const QString &last,
const QString &phone) {
const QString &phone,
Fn<void()> done) {
const auto wasContact = user->isContact();
using Flag = MTPcontacts_AddContact::Flag;
user->session().api().request(MTPcontacts_AddContact(
@@ -73,6 +75,7 @@ void SendRequest(
}
box->closeBox();
}
done();
}).send();
}
@@ -103,6 +106,7 @@ private:
QString _phone;
Fn<void()> _focus;
Fn<void()> _save;
Fn<std::optional<QImage>()> _updatedPersonalPhoto;
};
@@ -136,15 +140,17 @@ void Controller::setupContent() {
}
void Controller::setupCover() {
_box->addRow(
const auto cover = _box->addRow(
object_ptr<Info::Profile::Cover>(
_box,
_user,
_window,
_user,
Info::Profile::Cover::Role::EditContact,
(_phone.isEmpty()
? tr::lng_contact_mobile_hidden()
: rpl::single(Ui::FormatPhone(_phone)))),
style::margins())->setAttribute(Qt::WA_TransparentForMouseEvents);
style::margins());
_updatedPersonalPhoto = [=] { return cover->updatedPersonalPhoto(); };
}
void Controller::setupNameFields() {
@@ -198,13 +204,29 @@ void Controller::initNameFields(
(inverted ? last : first)->showError();
return;
}
const auto user = _user;
const auto personal = _updatedPersonalPhoto
? _updatedPersonalPhoto()
: std::nullopt;
const auto done = [=] {
if (personal) {
if (personal->isNull()) {
user->session().api().peerPhoto().clearPersonal(user);
} else {
user->session().api().peerPhoto().upload(
user,
base::duplicate(*personal));
}
}
};
SendRequest(
Ui::MakeWeak(_box),
_user,
user,
_sharePhone && _sharePhone->checked(),
firstValue,
lastValue,
_phone);
_phone,
done);
};
const auto submit = [=] {
const auto firstValue = first->getLastText().trimmed();

View File

@@ -177,7 +177,7 @@ bool DefaultIconEmoji::readyInDefaultState() {
return !paintIconFrame(result);
}) | rpl::start_with_next([=](QRect clip) {
auto args = Ui::Text::CustomEmoji::Context{
.preview = st::windowBgOver->c,
.textColor = st::windowFg->c,
.now = crl::now(),
.paused = controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer),

View File

@@ -0,0 +1,78 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peers/edit_members_visible.h"
#include "boxes/peers/edit_peer_info_box.h"
#include "data/data_channel.h"
#include "ui/rp_widget.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/buttons.h"
#include "settings/settings_common.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "lang/lang_keys.h"
#include "styles/style_info.h"
namespace {
[[nodiscard]] int EnableHideMembersMin(not_null<ChannelData*> channel) {
return channel->session().account().appConfig().get<int>(
u"hidden_members_group_size_min"_q,
100);
}
} // namespace
[[nodiscard]] object_ptr<Ui::RpWidget> CreateMembersVisibleButton(
not_null<ChannelData*> megagroup) {
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
const auto container = result.data();
const auto min = EnableHideMembersMin(megagroup);
if (!megagroup->canBanMembers() || megagroup->membersCount() < min) {
return { nullptr };
}
struct State {
rpl::event_stream<bool> toggled;
};
Settings::AddSkip(container);
const auto state = container->lifetime().make_state<State>();
const auto button = container->add(
EditPeerInfoBox::CreateButton(
container,
tr::lng_profile_hide_participants(),
rpl::single(QString()),
[] {},
st::manageGroupTopicsButton,
{ &st::infoRoundedIconHideMembers, Settings::kIconDarkBlue }
))->toggleOn(rpl::single(
(megagroup->flags() & ChannelDataFlag::ParticipantsHidden) != 0
) | rpl::then(state->toggled.events()));
Settings::AddSkip(container);
Settings::AddDividerText(
container,
tr::lng_profile_hide_participants_about());
button->toggledValue(
) | rpl::start_with_next([=](bool toggled) {
megagroup->session().api().request(
MTPchannels_ToggleParticipantsHidden(
megagroup->inputChannel,
MTP_bool(toggled)
)
).done([=](const MTPUpdates &result) {
megagroup->session().api().applyUpdates(result);
}).send();
}, button->lifetime());
return result;
}

View File

@@ -0,0 +1,19 @@
/*
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/object_ptr.h"
class ChannelData;
namespace Ui {
class RpWidget;
} // namespace Ui
[[nodiscard]] object_ptr<Ui::RpWidget> CreateMembersVisibleButton(
not_null<ChannelData*> megagroup);

View File

@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_participant_box.h"
#include "lang/lang_keys.h"
#include "ui/controls/userpic_button.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
@@ -20,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/text/text_utilities.h"
#include "ui/text/text_options.h"
#include "ui/special_buttons.h"
#include "ui/painter.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "settings/settings_privacy_security.h"
@@ -85,11 +85,7 @@ EditParticipantBox::Inner::Inner(
: RpWidget(parent)
, _peer(peer)
, _user(user)
, _userPhoto(
this,
_user,
Ui::UserpicButton::Role::Custom,
st::rightsPhotoButton)
, _userPhoto(this, _user, st::rightsPhotoButton)
, _hasAdminRights(hasAdminRights)
, _rows(this) {
_rows->heightValue(
@@ -97,7 +93,7 @@ EditParticipantBox::Inner::Inner(
resizeToWidth(width());
}, lifetime());
_userPhoto->setPointerCursor(false);
_userPhoto->setAttribute(Qt::WA_TransparentForMouseEvents);
_userName.setText(
st::rightsNameStyle,
_user->name(),
@@ -622,21 +618,21 @@ void EditAdminBox::sendTransferRequestFrom(
channel->inputChannel,
user->inputUser,
result.result
)).done([=, toastParent = _show.toastParent()](const MTPUpdates &result) {
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result);
if (!box && !weak) {
return;
}
Ui::Toast::Show(
toastParent,
(box ? Ui::BoxShow(box) : weak->_show).toastParent(),
(channel->isBroadcast()
? tr::lng_rights_transfer_done_channel
: tr::lng_rights_transfer_done_group)(
tr::now,
lt_user,
user->shortName()));
if (box) {
Ui::BoxShow(box).hideLayer();
} else if (weak) {
weak->_show.hideLayer();
}
(box ? Ui::BoxShow(box) : weak->_show).hideLayer();
}).fail(crl::guard(this, [=](const MTP::Error &error) {
if (weak) {
_transferRequestId = 0;

View File

@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_participant_box.h"
#include "boxes/peers/add_participants_box.h"
#include "boxes/peers/prepare_short_info_box.h" // PrepareShortInfoBox
#include "boxes/peers/edit_members_visible.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/max_invite_box.h"
#include "boxes/add_contact_box.h"
@@ -500,7 +501,7 @@ void ParticipantsAdditionalData::fillFromChat(not_null<ChatData*> chat) {
void ParticipantsAdditionalData::fillFromChannel(
not_null<ChannelData*> channel) {
const auto information = channel->mgInfo.get();
if (!information) {
if (!information || !channel->canViewMembers()) {
return;
}
if (information->creator) {
@@ -900,7 +901,7 @@ void ParticipantsBoxController::setupListChangeViewers() {
});
} else if (auto row = createRow(user)) {
delegate()->peerListPrependRow(std::move(row));
delegate()->peerListRefreshRows();
refreshRows();
if (_onlineSorter) {
_onlineSorter->sort();
}
@@ -913,7 +914,7 @@ void ParticipantsBoxController::setupListChangeViewers() {
if (const auto row = delegate()->peerListFindRow(user->id.value)) {
delegate()->peerListRemoveRow(row);
}
delegate()->peerListRefreshRows();
refreshRows();
}, lifetime());
}
@@ -1169,9 +1170,11 @@ void ParticipantsBoxController::restoreState(
}
rpl::producer<int> ParticipantsBoxController::onlineCountValue() const {
return _onlineSorter
? _onlineSorter->onlineCountValue()
: rpl::single(0);
return _onlineCountValue.value();
}
rpl::producer<int> ParticipantsBoxController::fullCountValue() const {
return _fullCountValue.value();
}
void ParticipantsBoxController::prepare() {
@@ -1188,11 +1191,14 @@ void ParticipantsBoxController::prepare() {
Unexpected("Role in ParticipantsBoxController::prepare()");
}();
if (const auto megagroup = _peer->asMegagroup()) {
if ((_role == Role::Admins)
if (_role == Role::Members) {
delegate()->peerListSetAboveWidget(CreateMembersVisibleButton(
megagroup));
} else if ((_role == Role::Admins)
&& (megagroup->amCreator() || megagroup->hasAdminRights())) {
const auto validator = AntiSpamMenu::AntiSpamValidator(
_navigation->parentController(),
_peer->asChannel());
megagroup);
delegate()->peerListSetAboveWidget(validator.createButton());
}
}
@@ -1201,17 +1207,48 @@ void ParticipantsBoxController::prepare() {
setDescriptionText(tr::lng_contacts_loading(tr::now));
setSearchNoResultsText(tr::lng_blocked_list_not_found(tr::now));
if (_role == Role::Profile) {
auto visible = _peer->isMegagroup()
? Info::Profile::CanViewParticipantsValue(_peer->asMegagroup())
: rpl::single(true);
std::move(visible) | rpl::start_with_next([=](bool visible) {
if (!visible) {
_onlineCountValue = 0;
_onlineSorter = nullptr;
} else if (!_onlineSorter) {
_onlineSorter = std::make_unique<ParticipantsOnlineSorter>(
_peer,
delegate());
_onlineCountValue = _onlineSorter->onlineCountValue();
}
unload();
rebuild();
}, lifetime());
} else {
rebuild();
}
}
void ParticipantsBoxController::unload() {
while (delegate()->peerListFullRowsCount() > 0) {
delegate()->peerListRemoveRow(
delegate()->peerListRowAt(
delegate()->peerListFullRowsCount() - 1));
}
if (const auto requestId = base::take(_loadRequestId)) {
_api.request(requestId).cancel();
}
_allLoaded = false;
_offset = 0;
}
void ParticipantsBoxController::rebuild() {
if (const auto chat = _peer->asChat()) {
prepareChatRows(chat);
} else {
loadMoreRows();
}
if (_role == Role::Profile && !_onlineSorter) {
_onlineSorter = std::make_unique<ParticipantsOnlineSorter>(
_peer,
delegate());
}
delegate()->peerListRefreshRows();
refreshRows();
}
QPointer<Ui::BoxContent> ParticipantsBoxController::showBox(
@@ -1287,7 +1324,7 @@ void ParticipantsBoxController::rebuildChatParticipants(
}
_onlineSorter->sort();
delegate()->peerListRefreshRows();
refreshRows();
chatListReady();
}
@@ -1340,7 +1377,7 @@ void ParticipantsBoxController::rebuildChatAdmins(
}
}
delegate()->peerListRefreshRows();
refreshRows();
chatListReady();
}
@@ -1362,7 +1399,7 @@ void ParticipantsBoxController::rebuildRowTypes() {
delegate()->peerListRowAt(i).get());
row->setType(computeType(row->user()));
}
delegate()->peerListRefreshRows();
refreshRows();
}
void ParticipantsBoxController::loadMoreRows() {
@@ -1401,11 +1438,13 @@ void ParticipantsBoxController::loadMoreRows() {
MTP_int(perPage),
MTP_long(participantsHash)
)).done([=](const MTPchannels_ChannelParticipants &result) {
auto added = false;
const auto firstLoad = !_offset;
_loadRequestId = 0;
auto wasRecentRequest = firstLoad
&& (_role == Role::Members || _role == Role::Profile);
&& (_role == Role::Members || _role == Role::Profile)
&& channel->canViewMembers();
result.match([&](const MTPDchannels_channelParticipants &data) {
const auto &[availableCount, list] = wasRecentRequest
@@ -1414,7 +1453,9 @@ void ParticipantsBoxController::loadMoreRows() {
for (const auto &data : list) {
if (const auto participant = _additional.applyParticipant(
data)) {
appendRow(participant);
if (appendRow(participant)) {
added = true;
}
}
}
if (const auto size = list.size()) {
@@ -1427,7 +1468,9 @@ void ParticipantsBoxController::loadMoreRows() {
LOG(("API Error: "
"channels.channelParticipantsNotModified received!"));
});
if (!firstLoad && !added) {
_allLoaded = true;
}
if (_allLoaded
|| (firstLoad && delegate()->peerListFullRowsCount() > 0)) {
refreshDescription();
@@ -1435,7 +1478,7 @@ void ParticipantsBoxController::loadMoreRows() {
if (_onlineSorter) {
_onlineSorter->sort();
}
delegate()->peerListRefreshRows();
refreshRows();
}).fail([this] {
_loadRequestId = 0;
}).send();
@@ -1457,7 +1500,7 @@ bool ParticipantsBoxController::feedMegagroupLastParticipants() {
return false;
}
const auto megagroup = _peer->asMegagroup();
if (!megagroup) {
if (!megagroup || !megagroup->canViewMembers()) {
return false;
}
const auto info = megagroup->mgInfo.get();
@@ -1659,7 +1702,7 @@ void ParticipantsBoxController::editAdminDone(
}
}
recomputeTypeFor(user);
delegate()->peerListRefreshRows();
refreshRows();
}
void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
@@ -1723,7 +1766,7 @@ void ParticipantsBoxController::editRestrictedDone(
}
}
recomputeTypeFor(participant);
delegate()->peerListRefreshRows();
refreshRows();
}
void ParticipantsBoxController::kickParticipant(not_null<PeerData*> participant) {
@@ -1748,7 +1791,7 @@ void ParticipantsBoxController::unkickParticipant(not_null<UserData*> user) {
_editBox = nullptr;
if (const auto row = delegate()->peerListFindRow(user->id.value)) {
delegate()->peerListRemoveRow(row);
delegate()->peerListRefreshRows();
refreshRows();
}
_peer->session().api().chatParticipants().add(_peer, { 1, user });
}
@@ -1764,7 +1807,7 @@ void ParticipantsBoxController::kickParticipantSure(
if (const auto row = delegate()->peerListFindRow(participant->id.value)) {
delegate()->peerListRemoveRow(row);
delegate()->peerListRefreshRows();
refreshRows();
}
auto &session = _peer->session();
if (const auto chat = _peer->asChat()) {
@@ -1838,7 +1881,7 @@ void ParticipantsBoxController::removeKicked(
&& !delegate()->peerListFullRowsCount()) {
setDescriptionText(tr::lng_blocked_list_not_found(tr::now));
}
delegate()->peerListRefreshRows();
refreshRows();
removeKicked(participant);
}
@@ -2055,6 +2098,11 @@ void ParticipantsBoxController::fullListRefresh() {
delegate()->peerListRowAt(count - 1));
}
loadMoreRows();
refreshRows();
}
void ParticipantsBoxController::refreshRows() {
_fullCountValue = delegate()->peerListFullRowsCount();
delegate()->peerListRefreshRows();
}

View File

@@ -184,7 +184,8 @@ public:
std::unique_ptr<PeerListState> saveState() const override;
void restoreState(std::unique_ptr<PeerListState> state) override;
rpl::producer<int> onlineCountValue() const override;
[[nodiscard]] rpl::producer<int> onlineCountValue() const;
[[nodiscard]] rpl::producer<int> fullCountValue() const;
protected:
// Allow child controllers not providing navigation.
@@ -229,6 +230,8 @@ private:
void rebuildChatAdmins(not_null<ChatData*> chat);
void chatListReady();
void rebuildRowTypes();
void rebuild();
void unload();
void addNewItem();
void addNewParticipants();
@@ -266,6 +269,7 @@ private:
void migrate(not_null<ChatData*> chat, not_null<ChannelData*> channel);
void subscribeToCreatorChange(not_null<ChannelData*> channel);
void fullListRefresh();
void refreshRows();
// It may be nullptr in subclasses of this controller.
Window::SessionNavigation *_navigation = nullptr;
@@ -278,6 +282,8 @@ private:
bool _allLoaded = false;
ParticipantsAdditionalData _additional;
std::unique_ptr<ParticipantsOnlineSorter> _onlineSorter;
rpl::variable<int> _onlineCountValue;
rpl::variable<int> _fullCountValue;
Ui::BoxPointer _editBox;
Ui::BoxPointer _addBox;
QPointer<Ui::BoxContent> _editParticipantBox;

View File

@@ -43,8 +43,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "settings/settings_common.h"
#include "ui/controls/userpic_button.h"
#include "ui/rp_widget.h"
#include "ui/special_buttons.h"
#include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h"
#include "ui/text/text_utilities.h"
@@ -470,9 +470,10 @@ object_ptr<Ui::RpWidget> Controller::createPhotoEdit() {
_wrap,
object_ptr<Ui::UserpicButton>(
_wrap,
&_navigation->parentController()->window(),
_navigation->parentController(),
_peer,
Ui::UserpicButton::Role::ChangePhoto,
Ui::UserpicButton::Source::PeerPhoto,
st::defaultUserpicButton),
st::editPeerPhotoMargins);
_controls.photo = photoWrap->entity();

View File

@@ -32,7 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/painter.h"
#include "boxes/share_box.h"
#include "history/view/history_view_group_call_bar.h" // GenerateUserpics...
#include "history/history_message.h" // GetErrorTextForSending.
#include "history/history_item_helpers.h" // GetErrorTextForSending.
#include "history/history.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/peer_list_box.h"
@@ -1374,7 +1374,7 @@ QString PrepareRequestedRowStatus(TimeId date) {
const auto now = QDateTime::currentDateTime();
const auto parsed = base::unixtime::parse(date);
const auto parsedDate = parsed.date();
const auto time = QLocale().toString(parsed.time(), cTimeFormat());
const auto time = QLocale().toString(parsed.time(), QLocale::ShortFormat);
const auto generic = [&] {
return tr::lng_group_requests_status_date_time(
tr::now,

View File

@@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "mtproto/sender.h"
#include "ui/rp_widget.h"
#include "ui/special_buttons.h"
#include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/input_fields.h"

View File

@@ -354,7 +354,9 @@ bool ProcessCurrent(
[[nodiscard]] PreparedShortInfoUserpic UserpicValue(
not_null<PeerData*> peer,
const style::ShortInfoCover &st) {
const style::ShortInfoCover &st,
rpl::producer<UserPhotosSlice> slices,
Fn<bool(not_null<UserpicState*>)> customProcess) {
const auto moveRequests = std::make_shared<rpl::event_stream<int>>();
auto move = [=](int shift) {
moveRequests->fire_copy(shift);
@@ -367,7 +369,7 @@ bool ProcessCurrent(
state->size = size;
state->roundMask = Images::CornersMask(radius);
const auto push = [=](bool force = false) {
if (ProcessCurrent(peer, state) || force) {
if (customProcess(state) || force) {
consumer.put_next_copy(state->current);
}
};
@@ -381,17 +383,12 @@ bool ProcessCurrent(
push();
}, lifetime);
if (const auto user = peer->asUser()) {
UserPhotosReversedViewer(
&peer->session(),
UserPhotosSlice::Key(peerToUser(user->id), PhotoId()),
kOverviewLimit,
kOverviewLimit
) | rpl::start_with_next([=](UserPhotosSlice &&slice) {
state->userSlice = std::move(slice);
push();
}, lifetime);
}
rpl::duplicate(
slices
) | rpl::start_with_next([=](UserPhotosSlice &&slice) {
state->userSlice = std::move(slice);
push();
}, lifetime);
moveRequests->events(
) | rpl::filter([=] {
@@ -429,7 +426,7 @@ object_ptr<Ui::BoxContent> PrepareShortInfoBox(
: peer->isBroadcast()
? PeerShortInfoType::Channel
: PeerShortInfoType::Group;
auto userpic = UserpicValue(peer, st::shortInfoCover);
auto userpic = PrepareShortInfoUserpic(peer, st::shortInfoCover);
auto result = Box<PeerShortInfoBox>(
type,
FieldsValue(peer),
@@ -467,5 +464,39 @@ rpl::producer<QString> PrepareShortInfoStatus(not_null<PeerData*> peer) {
PreparedShortInfoUserpic PrepareShortInfoUserpic(
not_null<PeerData*> peer,
const style::ShortInfoCover &st) {
return UserpicValue(peer, st);
auto slices = peer->isUser()
? UserPhotosReversedViewer(
&peer->session(),
UserPhotosSlice::Key(peerToUser(peer->asUser()->id), PhotoId()),
kOverviewLimit,
kOverviewLimit)
: rpl::never<UserPhotosSlice>();
auto process = [=](not_null<UserpicState*> state) {
return ProcessCurrent(peer, state);
};
return UserpicValue(peer, st, std::move(slices), std::move(process));
}
PreparedShortInfoUserpic PrepareShortInfoFallbackUserpic(
not_null<PeerData*> peer,
const style::ShortInfoCover &st) {
Expects(peer->isUser());
const auto photoId = SyncUserFallbackPhotoViewer(peer->asUser());
auto slices = photoId
? rpl::single<UserPhotosSlice>(UserPhotosSlice(
Storage::UserPhotosKey(peerToUser(peer->id), *photoId),
std::deque<PhotoId>({ *photoId }),
1,
1,
1))
: (rpl::never<UserPhotosSlice>() | rpl::type_erased());
auto process = [=](not_null<UserpicState*> state) {
if (photoId) {
ProcessFullPhoto(peer, state, peer->owner().photo(*photoId));
return true;
}
return false;
};
return UserpicValue(peer, st, std::move(slices), std::move(process));
}

View File

@@ -45,3 +45,7 @@ struct PreparedShortInfoUserpic {
[[nodiscard]] PreparedShortInfoUserpic PrepareShortInfoUserpic(
not_null<PeerData*> peer,
const style::ShortInfoCover &st);
[[nodiscard]] PreparedShortInfoUserpic PrepareShortInfoFallbackUserpic(
not_null<PeerData*> peer,
const style::ShortInfoCover &st);

View File

@@ -52,7 +52,6 @@ namespace {
constexpr auto kPremiumShift = 21. / 240;
constexpr auto kReactionsPerRow = 5;
constexpr auto kDisabledOpacity = 0.5;
constexpr auto kPreviewsCount = int(PremiumPreview::kCount);
constexpr auto kToggleStickerTimeout = 2 * crl::time(1000);
constexpr auto kStarOpacityOff = 0.1;
constexpr auto kStarOpacityOn = 1.;
@@ -744,19 +743,21 @@ struct VideoPreviewDocument {
[[nodiscard]] object_ptr<Ui::RpWidget> CreateSwitch(
not_null<Ui::RpWidget*> parent,
not_null<rpl::variable<PremiumPreview>*> selected) {
not_null<rpl::variable<PremiumPreview>*> selected,
std::vector<PremiumPreview> order) {
const auto padding = st::premiumDotPadding;
const auto width = padding.left() + st::premiumDot + padding.right();
const auto height = padding.top() + st::premiumDot + padding.bottom();
const auto stops = Ui::Premium::ButtonGradientStops();
auto result = object_ptr<Ui::FixedHeightWidget>(parent.get(), height);
const auto raw = result.data();
for (auto i = 0; i != kPreviewsCount; ++i) {
const auto section = PremiumPreview(i);
const auto count = order.size();
for (auto i = 0; i != count; ++i) {
const auto section = order[i];
const auto button = Ui::CreateChild<Ui::AbstractButton>(raw);
parent->widthValue(
) | rpl::start_with_next([=](int outer) {
const auto full = width * kPreviewsCount;
const auto full = width * count;
const auto left = (outer - full) / 2 + (i * width);
button->setGeometry(left, 0, width, height);
}, button->lifetime());
@@ -770,7 +771,7 @@ struct VideoPreviewDocument {
p.setBrush((selected->current() == section)
? anim::gradient_color_at(
stops,
float64(i) / (kPreviewsCount - 1))
float64(i) / (count - 1))
: st::windowBgRipple->c);
p.setPen(Qt::NoPen);
p.drawEllipse(
@@ -815,15 +816,23 @@ void PreviewBox(
Fn<void()> preload;
std::vector<Hiding> hiding;
rpl::variable<PremiumPreview> selected;
std::vector<PremiumPreview> order;
};
const auto state = outer->lifetime().make_state<State>();
state->selected = descriptor.section;
state->order = Settings::PremiumPreviewOrder(&controller->session());
const auto index = [=](PremiumPreview section) {
const auto it = ranges::find(state->order, section);
return (it == end(state->order))
? 0
: std::distance(begin(state->order), it);
};
const auto move = [=](int delta) {
using Type = PremiumPreview;
const auto count = int(Type::kCount);
const auto count = int(state->order.size());
const auto now = state->selected.current();
state->selected = Type((int(now) + count + delta) % count);
state->selected = state->order[(index(now) + count + delta) % count];
};
const auto buttonsParent = box->verticalLayout().get();
@@ -912,7 +921,7 @@ void PreviewBox(
}
};
animationCallback();
const auto toLeft = int(now) > int(was);
const auto toLeft = index(now) > index(was);
auto start = state->content->x() + (toLeft ? single : -single);
for (const auto &hiding : state->hiding) {
const auto left = hiding.widget->x();
@@ -955,14 +964,10 @@ void PreviewBox(
}, outer->lifetime());
auto title = state->selected.value(
) | rpl::map([=](PremiumPreview section) {
return SectionTitle(section);
}) | rpl::flatten_latest();
) | rpl::map(SectionTitle) | rpl::flatten_latest();
auto text = state->selected.value(
) | rpl::map([=](PremiumPreview section) {
return SectionAbout(section);
}) | rpl::flatten_latest();
) | rpl::map(SectionAbout) | rpl::flatten_latest();
const auto padding = st::premiumPreviewAboutPadding;
const auto available = size.width() - padding.left() - padding.right();
@@ -985,7 +990,7 @@ void PreviewBox(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(box, std::move(textLabel)),
padding);
box->addRow(
CreateSwitch(box->verticalLayout(), &state->selected),
CreateSwitch(box->verticalLayout(), &state->selected, state->order),
st::premiumDotsMargin);
const auto showFinished = [=] {
state->showFinished = true;

View File

@@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "history/admin_log/history_admin_log_item.h"
#include "history/history.h"
#include "history/history_message.h"
#include "history/history_item.h"
#include "history/view/history_view_element.h"
#include "history/view/reactions/history_view_reactions_strip.h"
#include "lang/lang_keys.h"
@@ -447,7 +447,7 @@ void AddReactionCustomIcon(
const auto ratio = style::DevicePixelRatio();
const auto size = Data::FrameSizeFromTag(tag) / ratio;
state->custom->paint(p, {
.preview = st::windowBgRipple->c,
.textColor = st::windowFg->c,
.now = crl::now(),
.position = QPoint(
(widget->width() - size) / 2,

View File

@@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/popup_menu.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/chat/attach/attach_send_files_way.h"
@@ -62,6 +63,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_info.h"
#include "styles/style_menu_icons.h"
#include <QtCore/QMimeData>
@@ -215,19 +218,50 @@ rpl::producer<int> SendFilesBox::Block::itemModifyRequest() const {
void SendFilesBox::Block::setSendWay(Ui::SendFilesWay way) {
if (!_isAlbum) {
if (_isSingleMedia) {
const auto media = static_cast<Ui::SingleMediaPreview*>(
_preview.get());
media->setSendWay(way);
}
return;
}
applyAlbumOrder();
applyChanges();
const auto album = static_cast<Ui::AlbumPreview*>(_preview.get());
album->setSendWay(way);
}
void SendFilesBox::Block::applyAlbumOrder() {
void SendFilesBox::Block::toggleSpoilers(bool enabled) {
if (_isAlbum) {
const auto album = static_cast<Ui::AlbumPreview*>(_preview.get());
album->toggleSpoilers(enabled);
} else if (_isSingleMedia) {
const auto media = static_cast<Ui::SingleMediaPreview*>(
_preview.get());
media->setSpoiler(enabled);
}
}
void SendFilesBox::Block::applyChanges() {
if (!_isAlbum) {
if (_isSingleMedia) {
const auto media = static_cast<Ui::SingleMediaPreview*>(
_preview.get());
if (media->canHaveSpoiler()) {
(*_items)[_from].spoiler = media->hasSpoiler();
}
}
return;
}
const auto album = static_cast<Ui::AlbumPreview*>(_preview.get());
const auto order = album->takeOrder();
const auto guard = gsl::finally([&] {
const auto spoilered = album->collectSpoileredIndices();
for (auto i = 0, count = int(order.size()); i != count; ++i) {
if (album->canHaveSpoiler(i)) {
(*_items)[_from + i].spoiler = spoilered.contains(i);
}
}
});
const auto isIdentity = [&] {
for (auto i = 0, count = int(order.size()); i != count; ++i) {
if (order[i] != i) {
@@ -277,7 +311,7 @@ SendFilesBox::SendFilesBox(
void SendFilesBox::initPreview() {
using namespace rpl::mappers;
refreshControls();
refreshControls(true);
updateBoxSize();
@@ -325,19 +359,6 @@ void SendFilesBox::enqueueNextPrepare() {
}
void SendFilesBox::prepare() {
_send = addButton(
(_sendType == Api::SendType::Normal
? tr::lng_send_button()
: tr::lng_create_group_next()),
[=] { send({}); });
if (_sendType == Api::SendType::Normal) {
SendMenu::SetupMenuAndShortcuts(
_send,
[=] { return _sendMenuType; },
[=] { sendSilent(); },
[=] { sendScheduled(); });
}
addButton(tr::lng_cancel(), [=] { closeBox(); });
initSendWay();
setupCaption();
setupSendWayControls();
@@ -351,11 +372,6 @@ void SendFilesBox::prepare() {
}
}, lifetime());
_addFile = addLeftButton(
tr::lng_stickers_featured_add(),
base::fn_delayed(st::historyAttach.ripple.hideDuration, this, [=] {
openDialogToAddFileToAlbum();
}));
setupDragArea();
}
@@ -385,19 +401,25 @@ void SendFilesBox::setupDragArea() {
areas.photo->setDroppedCallback(droppedCallback(true));
}
void SendFilesBox::refreshAllAfterChanges(int fromItem) {
void SendFilesBox::refreshAllAfterChanges(int fromItem, Fn<void()> perform) {
auto fromBlock = 0;
for (auto count = int(_blocks.size()); fromBlock != count; ++fromBlock) {
if (_blocks[fromBlock].tillIndex() >= fromItem) {
break;
}
}
for (auto index = fromBlock; index < _blocks.size(); ++index) {
_blocks[index].applyChanges();
}
if (perform) {
perform();
}
generatePreviewFrom(fromBlock);
{
auto sendWay = _sendWay.current();
sendWay.setHasCompressedStickers(_list.hasSticker());
_sendWay = sendWay;
}
generatePreviewFrom(fromBlock);
_inner->resizeToWidth(st::boxWideWidth);
refreshControls();
captionResized();
@@ -431,6 +453,103 @@ void SendFilesBox::openDialogToAddFileToAlbum() {
crl::guard(this, callback));
}
void SendFilesBox::refreshButtons() {
clearButtons();
_send = addButton(
(_sendType == Api::SendType::Normal
? tr::lng_send_button()
: tr::lng_create_group_next()),
[=] { send({}); });
if (_sendType == Api::SendType::Normal) {
SendMenu::SetupMenuAndShortcuts(
_send,
[=] { return _sendMenuType; },
[=] { sendSilent(); },
[=] { sendScheduled(); });
}
addButton(tr::lng_cancel(), [=] { closeBox(); });
_addFile = addLeftButton(
tr::lng_stickers_featured_add(),
base::fn_delayed(st::historyAttach.ripple.hideDuration, this, [=] {
openDialogToAddFileToAlbum();
}));
addMenuButton();
}
bool SendFilesBox::hasSendMenu() const {
return (_sendMenuType != SendMenu::Type::Disabled);
}
bool SendFilesBox::hasSpoilerMenu() const {
const auto allAreVideo = !ranges::any_of(_list.files, [](const auto &f) {
using Type = Ui::PreparedFile::Type;
return (f.type != Type::Video);
});
const auto allAreMedia = !ranges::any_of(_list.files, [](const auto &f) {
using Type = Ui::PreparedFile::Type;
return (f.type != Type::Photo) && (f.type != Type::Video);
});
return allAreVideo
|| (allAreMedia && _sendWay.current().sendImagesAsPhotos());
}
void SendFilesBox::applyBlockChanges() {
for (auto &block : _blocks) {
block.applyChanges();
}
}
bool SendFilesBox::allWithSpoilers() {
applyBlockChanges();
return ranges::all_of(_list.files, &Ui::PreparedFile::spoiler);
}
void SendFilesBox::toggleSpoilers(bool enabled) {
for (auto &file : _list.files) {
file.spoiler = enabled;
}
for (auto &block : _blocks) {
block.toggleSpoilers(enabled);
}
}
void SendFilesBox::addMenuButton() {
if (!hasSendMenu() && !hasSpoilerMenu()) {
return;
}
const auto top = addTopButton(st::infoTopBarMenu);
top->setClickedCallback([=] {
_menu = base::make_unique_q<Ui::PopupMenu>(
top,
st::popupMenuExpandedSeparator);
if (hasSpoilerMenu()) {
const auto spoilered = allWithSpoilers();
_menu->addAction(
(spoilered
? tr::lng_context_disable_spoiler(tr::now)
: tr::lng_context_spoiler_effect(tr::now)),
[=] { toggleSpoilers(!spoilered); },
spoilered ? &st::menuIconSpoilerOff : &st::menuIconSpoiler);
if (hasSendMenu()) {
_menu->addSeparator();
}
}
if (hasSendMenu()) {
SendMenu::FillSendMenu(
_menu.get(),
_sendMenuType,
[=] { sendSilent(); },
[=] { sendScheduled(); });
}
_menu->popup(QCursor::pos());
return true;
});
}
void SendFilesBox::initSendWay() {
_sendWay = [&] {
auto result = Core::App().settings().sendFilesWay();
@@ -454,6 +573,9 @@ void SendFilesBox::initSendWay() {
for (auto &block : _blocks) {
block.setSendWay(value);
}
if (!hasSendMenu()) {
refreshButtons();
}
setInnerFocus();
}, lifetime());
}
@@ -489,11 +611,7 @@ void SendFilesBox::generatePreviewFrom(int fromBlock) {
using Type = Ui::PreparedFile::Type;
const auto eraseFrom = _blocks.begin() + fromBlock;
for (auto i = eraseFrom; i != _blocks.end(); ++i) {
i->applyAlbumOrder();
}
_blocks.erase(eraseFrom, _blocks.end());
_blocks.erase(_blocks.begin() + fromBlock, _blocks.end());
const auto fromItem = _blocks.empty() ? 0 : _blocks.back().tillIndex();
Assert(fromItem <= _list.files.size());
@@ -559,8 +677,9 @@ void SendFilesBox::pushBlock(int from, int till) {
closeBox();
return;
}
_list.files.erase(_list.files.begin() + index);
refreshAllAfterChanges(from);
refreshAllAfterChanges(index, [&] {
_list.files.erase(_list.files.begin() + index);
});
});
}, widget->lifetime());
@@ -571,8 +690,9 @@ void SendFilesBox::pushBlock(int from, int till) {
if (list.files.empty()) {
return;
}
_list.files[index] = std::move(list.files.front());
refreshAllAfterChanges(from);
refreshAllAfterChanges(from, [&] {
_list.files[index] = std::move(list.files.front());
});
};
const auto checkResult = [=](const Ui::PreparedList &list) {
if (_sendLimit != SendLimit::One) {
@@ -626,22 +746,27 @@ void SendFilesBox::pushBlock(int from, int till) {
}, widget->lifetime());
}
void SendFilesBox::refreshControls() {
void SendFilesBox::refreshControls(bool initial) {
if (initial || !hasSendMenu()) {
refreshButtons();
}
refreshTitleText();
updateSendWayControlsVisibility();
updateSendWayControls();
updateCaptionPlaceholder();
}
void SendFilesBox::setupSendWayControls() {
const auto groupFilesFirst = _sendWay.current().groupFiles();
const auto asPhotosFirst = _sendWay.current().sendImagesAsPhotos();
_groupFiles.create(
this,
tr::lng_send_grouped(tr::now),
_sendWay.current().groupFiles(),
groupFilesFirst,
st::defaultBoxCheckbox);
_sendImagesAsPhotos.create(
this,
tr::lng_send_compressed(tr::now),
_sendWay.current().sendImagesAsPhotos(),
asPhotosFirst,
st::defaultBoxCheckbox);
_sendWay.changes(
@@ -664,17 +789,35 @@ void SendFilesBox::setupSendWayControls() {
_sendWay = sendWay;
}, lifetime());
_wayRemember.create(
this,
tr::lng_remember(tr::now),
false,
st::defaultBoxCheckbox);
_wayRemember->hide();
rpl::combine(
_groupFiles->checkedValue(),
_sendImagesAsPhotos->checkedValue()
) | rpl::start_with_next([=](bool groupFiles, bool asPhoto) {
_wayRemember->setVisible(
(groupFiles != groupFilesFirst) || (asPhoto != asPhotosFirst));
captionResized();
}, lifetime());
_hintLabel.create(
this,
tr::lng_edit_photo_editor_hint(tr::now),
st::editMediaHintLabel);
}
void SendFilesBox::updateSendWayControlsVisibility() {
void SendFilesBox::updateSendWayControls() {
const auto onlyOne = (_sendLimit == SendLimit::One);
_groupFiles->setVisible(_list.hasGroupOption(onlyOne));
_sendImagesAsPhotos->setVisible(
_list.hasSendImagesAsPhotosOption(onlyOne));
_sendImagesAsPhotos->setText((_list.files.size() > 1)
? tr::lng_send_compressed(tr::now)
: tr::lng_send_compressed_one(tr::now));
_hintLabel->setVisible(
_controller->session().settings().photoEditorHintShown()
@@ -892,20 +1035,27 @@ void SendFilesBox::addFile(Ui::PreparedFile &&file) {
}
void SendFilesBox::refreshTitleText() {
using Type = Ui::PreparedFile::Type;
const auto count = int(_list.files.size());
if (count > 1) {
const auto imagesCount = ranges::count(
_list.files,
Ui::PreparedFile::Type::Photo,
Type::Photo,
&Ui::PreparedFile::type);
_titleText = (imagesCount == count)
? tr::lng_send_images_selected(tr::now, lt_count, count)
: tr::lng_send_files_selected(tr::now, lt_count, count);
_titleHeight = st::boxTitleHeight;
} else {
_titleText = QString();
_titleHeight = count ? st::boxPhotoPadding.top() : 0;
const auto type = _list.files.empty()
? Type::None
: _list.files.front().type;
_titleText = (type == Type::Photo)
? tr::lng_send_image(tr::now)
: (type == Type::Video)
? tr::lng_send_video(tr::now)
: tr::lng_send_file(tr::now);
}
_titleHeight = st::boxTitleHeight;
}
void SendFilesBox::updateBoxSize() {
@@ -913,9 +1063,10 @@ void SendFilesBox::updateBoxSize() {
if (_caption) {
footerHeight += st::boxPhotoCaptionSkip + _caption->height();
}
const auto pairs = std::array<std::pair<RpWidget*, int>, 3>{ {
const auto pairs = std::array<std::pair<RpWidget*, int>, 4>{ {
{ _groupFiles.data(), st::boxPhotoCompressedSkip },
{ _sendImagesAsPhotos.data(), st::boxPhotoCompressedSkip },
{ _wayRemember.data(), st::boxPhotoCompressedSkip },
{ _hintLabel.data(), st::editMediaLabelMargins.top() },
} };
for (const auto &pair : pairs) {
@@ -980,10 +1131,11 @@ void SendFilesBox::updateControlsGeometry() {
_emojiToggle->update();
}
}
const auto pairs = std::array<std::pair<RpWidget*, int>, 3>{ {
const auto pairs = std::array<std::pair<RpWidget*, int>, 4>{ {
{ _hintLabel.data(), st::editMediaLabelMargins.top() },
{ _groupFiles.data(), st::boxPhotoCompressedSkip },
{ _sendImagesAsPhotos.data(), st::boxPhotoCompressedSkip },
{ _wayRemember.data(), st::boxPhotoCompressedSkip },
} };
for (const auto &pair : ranges::views::reverse(pairs)) {
const auto pointer = pair.first;
@@ -1052,12 +1204,15 @@ void SendFilesBox::send(
return;
}
saveSendWaySettings();
for (auto &block : _blocks) {
block.applyAlbumOrder();
if (_wayRemember && _wayRemember->checked()) {
saveSendWaySettings();
}
for (auto &item : _list.files) {
item.spoiler = false;
}
applyBlockChanges();
Storage::ApplyModifications(_list);
_confirmed = true;

View File

@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/chat/attach/attach_send_files_way.h"
#include "ui/widgets/popup_menu.h"
#include "storage/localimageloader.h"
#include "storage/storage_media_prepare.h"
@@ -36,6 +37,7 @@ class EmojiButton;
class AlbumPreview;
class VerticalLayout;
class FlatLabel;
class PopupMenu;
} // namespace Ui
namespace Window {
@@ -106,7 +108,8 @@ private:
[[nodiscard]] rpl::producer<int> itemModifyRequest() const;
void setSendWay(Ui::SendFilesWay way);
void applyAlbumOrder();
void toggleSpoilers(bool enabled);
void applyChanges();
private:
base::unique_qptr<Ui::RpWidget> _preview;
@@ -117,16 +120,24 @@ private:
bool _isSingleMedia = false;
};
void initSendWay();
void initPreview();
[[nodiscard]] bool hasSendMenu() const;
[[nodiscard]] bool hasSpoilerMenu() const;
[[nodiscard]] bool allWithSpoilers();
void addMenuButton();
void applyBlockChanges();
void toggleSpoilers(bool enabled);
bool validateLength(const QString &text) const;
void refreshControls();
void refreshButtons();
void refreshControls(bool initial = false);
void setupSendWayControls();
void setupCaption();
void setupEmojiPanel();
void updateSendWayControlsVisibility();
void updateSendWayControls();
void updateEmojiPanelGeometry();
void emojiFilterForGeometry(not_null<QEvent*> event);
@@ -152,7 +163,7 @@ private:
void pushBlock(int from, int till);
void openDialogToAddFileToAlbum();
void refreshAllAfterChanges(int fromItem);
void refreshAllAfterChanges(int fromItem, Fn<void()> perform = nullptr);
void enqueueNextPrepare();
void addPreparedAsyncFile(Ui::PreparedFile &&file);
@@ -187,6 +198,7 @@ private:
object_ptr<Ui::Checkbox> _groupFiles = { nullptr };
object_ptr<Ui::Checkbox> _sendImagesAsPhotos = { nullptr };
object_ptr<Ui::Checkbox> _wayRemember = { nullptr };
object_ptr<Ui::FlatLabel> _hintLabel = { nullptr };
rpl::variable<Ui::SendFilesWay> _sendWay = Ui::SendFilesWay();
@@ -199,6 +211,8 @@ private:
Fn<void()> _whenReadySend;
bool _preparing = false;
base::unique_qptr<Ui::PopupMenu> _menu;
QPointer<Ui::RoundButton> _send;
QPointer<Ui::RoundButton> _addFile;

View File

@@ -218,29 +218,43 @@ void RenameBox(not_null<Ui::GenericBox*> box) {
return Type::Other;
}
[[nodiscard]] style::color ColorForType(Type type) {
switch (type) {
case Type::Windows:
case Type::Mac:
case Type::Other:
return st::historyPeer4UserpicBg; // blue
case Type::Ubuntu:
return st::historyPeer8UserpicBg; // orange
case Type::Linux:
return st::historyPeer5UserpicBg; // purple
case Type::iPhone:
case Type::iPad:
return st::historyPeer7UserpicBg; // sea
case Type::Android:
return st::historyPeer2UserpicBg; // green
case Type::Web:
case Type::Chrome:
case Type::Edge:
case Type::Firefox:
case Type::Safari:
return st::historyPeer6UserpicBg; // pink
}
Unexpected("Type in ColorForType.");
[[nodiscard]] QBrush GradientForType(Type type, int size) {
const auto colors = [&]() -> std::pair<style::color, style::color> {
switch (type) {
case Type::Windows:
case Type::Mac:
case Type::Other:
// Blue.
return { st::historyPeer4UserpicBg, st::historyPeer4UserpicBg2 };
case Type::Ubuntu:
// Orange.
return { st::historyPeer8UserpicBg, st::historyPeer8UserpicBg2 };
case Type::Linux:
// Purple.
return { st::historyPeer5UserpicBg, st::historyPeer5UserpicBg2 };
case Type::iPhone:
case Type::iPad:
// Sea.
return { st::historyPeer7UserpicBg, st::historyPeer7UserpicBg2 };
case Type::Android:
// Green.
return { st::historyPeer2UserpicBg, st::historyPeer2UserpicBg2 };
case Type::Web:
case Type::Chrome:
case Type::Edge:
case Type::Firefox:
case Type::Safari:
// Pink.
return { st::historyPeer6UserpicBg, st::historyPeer6UserpicBg2 };
}
Unexpected("Type in GradientForType.");
}();
auto gradient = QLinearGradient(0, 0, 0, size);
gradient.setStops({
{ 0.0, colors.first->c },
{ 1.0, colors.second->c },
});
return QBrush(std::move(gradient));
}
[[nodiscard]] const style::icon &IconForType(Type type) {
@@ -308,7 +322,7 @@ void RenameBox(not_null<Ui::GenericBox*> box) {
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
p.setBrush(ColorForType(type));
p.setBrush(GradientForType(type, size));
p.setPen(Qt::NoPen);
p.drawEllipse(rect);
IconForType(type).paintInCenter(p, rect);
@@ -344,7 +358,7 @@ void RenameBox(not_null<Ui::GenericBox*> box) {
auto p = QPainter(&state->background);
auto hq = PainterHighQualityEnabler(p);
p.setBrush(ColorForType(type));
p.setBrush(GradientForType(type, size));
p.setPen(Qt::NoPen);
p.drawEllipse(rect);
if (const auto icon = IconBigForType(type)) {

View File

@@ -30,7 +30,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "menu/menu_check_item.h"
#include "menu/menu_send.h"
#include "history/history.h"
#include "history/history_message.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "history/view/history_view_element.h" // HistoryView::Context.
#include "history/view/history_view_context_menu.h" // CopyPostLink.
#include "history/view/history_view_schedule_box.h"
@@ -1402,11 +1403,16 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
api.sendMessage(std::move(message));
}
const auto topicRootId = thread->topicRootId();
const auto kGeneralId = Data::ForumTopic::kGeneralId;
const auto topMsgId = (topicRootId == kGeneralId)
? MsgId(0)
: topicRootId;
const auto peer = thread->peer();
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
histories.sendRequest(history, requestType, [=](
Fn<void()> finish) {
auto &api = history->session().api();
const auto sendFlags = commonSendFlags
| (topicRootId ? Flag::f_top_msg_id : Flag(0))
| (topMsgId ? Flag::f_top_msg_id : Flag(0))
| (ShouldSendSilent(peer, options)
? Flag::f_silent
: Flag(0));
@@ -1417,7 +1423,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
MTP_vector<MTPint>(mtpMsgIds),
MTP_vector<MTPlong>(generateRandom()),
peer->input,
MTP_int(topicRootId),
MTP_int(topMsgId),
MTP_int(options.scheduled),
MTP_inputPeerEmpty() // send_as
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {

View File

@@ -331,7 +331,6 @@ private:
std::vector<Element> _elements;
std::unique_ptr<Lottie::MultiPlayer> _lottiePlayer;
mutable Ui::Text::CustomEmojiColored _colored;
base::flat_map<
not_null<DocumentData*>,
std::unique_ptr<Ui::Text::CustomEmoji>> _customEmoji;
@@ -1335,10 +1334,8 @@ void StickerSetBox::Inner::paintSticker(
(_singleSize.height() - size.height()) / 2);
auto lottieFrame = QImage();
if (element.emoji) {
_colored.color = st::profileVerifiedCheckBg->c;
element.emoji->paint(p, {
.preview = st::windowBgOver->c,
.colored = &_colored,
.textColor = st::windowFg->c,
.now = now,
.position = ppos,
.paused = paused,
@@ -1438,6 +1435,7 @@ void StickerSetBox::Inner::install() {
}
void StickerSetBox::Inner::archiveStickers() {
const auto toastParent = Window::Show(_controller).toastParent();
_api.request(MTPmessages_InstallStickerSet(
Data::InputStickerSet(_input),
MTP_boolTrue()
@@ -1445,9 +1443,9 @@ void StickerSetBox::Inner::archiveStickers() {
if (result.type() == mtpc_messages_stickerSetInstallResultSuccess) {
_setArchived.fire_copy(_setId);
}
}).fail([toastParent = Window::Show(_controller).toastParent()] {
}).fail(crl::guard(toastParent, [=] {
Ui::Toast::Show(toastParent, Lang::Hard::ServerError());
}).send();
})).send();
}
void StickerSetBox::Inner::updateItems() {

View File

@@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/sticker_set_box.h"
#include "apiwrap.h"
#include "storage/storage_account.h"
#include "dialogs/ui/dialogs_layout.h"
#include "lottie/lottie_single_player.h"
#include "chat_helpers/stickers_lottie.h"
#include "ui/widgets/buttons.h"
@@ -35,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/cached_round_corners.h"
#include "ui/painter.h"
#include "ui/unread_badge_paint.h"
#include "window/window_session_controller.h"
#include "media/clip/media_clip_reader.h"
#include "main/main_session.h"
@@ -66,7 +66,7 @@ private:
void setCounter(int counter);
QString _text;
Dialogs::Ui::UnreadBadgeStyle _st;
Ui::UnreadBadgeStyle _st;
};
@@ -335,7 +335,7 @@ void StickersBox::CounterWidget::setCounter(int counter) {
auto dummy = QImage(1, 1, QImage::Format_ARGB32_Premultiplied);
auto p = QPainter(&dummy);
const auto badge = Dialogs::Ui::PaintUnreadBadge(p, _text, 0, 0, _st);
const auto badge = Ui::PaintUnreadBadge(p, _text, 0, 0, _st);
resize(badge.width(), st::stickersFeaturedBadgeSize);
}
@@ -346,7 +346,7 @@ void StickersBox::CounterWidget::paintEvent(QPaintEvent *e) {
if (!_text.isEmpty()) {
const auto unreadRight = rtl() ? 0 : width();
const auto unreadTop = 0;
Dialogs::Ui::PaintUnreadBadge(p, _text, unreadRight, unreadTop, _st);
Ui::PaintUnreadBadge(p, _text, unreadRight, unreadTop, _st);
}
}

View File

@@ -9,21 +9,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/core_settings.h"
#include "core/ui_integration.h"
#include "data/data_peer.h"
#include "lang/lang_instance.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "mtproto/sender.h"
#include "settings/settings_common.h"
#ifndef TDESKTOP_DISABLE_SPELLCHECK
#include "spellcheck/platform/platform_language.h"
#endif
#include "ui/effects/loading_element.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/multi_select.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_info.h" // inviteLinkListItem.
#include "styles/style_layers.h"
#include "styles/style_settings.h" // settingsSubsectionTitlePadding.
@@ -35,48 +41,169 @@ namespace {
[[nodiscard]] std::vector<QLocale::Language> Languages() {
return std::vector<QLocale::Language>{
QLocale::English,
QLocale::Afrikaans,
QLocale::Albanian,
QLocale::Amharic,
QLocale::Arabic,
QLocale::Armenian,
QLocale::Azerbaijani,
QLocale::Basque,
QLocale::Belarusian,
QLocale::Bosnian,
QLocale::Bulgarian,
QLocale::Burmese,
QLocale::Catalan,
QLocale::Chinese,
QLocale::Croatian,
QLocale::Czech,
QLocale::Danish,
QLocale::Dutch,
QLocale::Esperanto,
QLocale::Estonian,
QLocale::Finnish,
QLocale::French,
QLocale::Gaelic,
QLocale::Galician,
QLocale::Georgian,
QLocale::German,
QLocale::Greek,
QLocale::Gusii,
QLocale::Hausa,
QLocale::Hebrew,
QLocale::Hindi,
QLocale::Hungarian,
QLocale::Icelandic,
QLocale::Igbo,
QLocale::Indonesian,
QLocale::Irish,
QLocale::Italian,
QLocale::Japanese,
QLocale::Kazakh,
QLocale::Kinyarwanda,
QLocale::Korean,
QLocale::Kurdish,
QLocale::Lao,
QLocale::Latvian,
QLocale::Lithuanian,
QLocale::Luxembourgish,
QLocale::Macedonian,
QLocale::Malagasy,
QLocale::Malay,
QLocale::Maltese,
QLocale::Maori,
QLocale::Mongolian,
QLocale::Nepali,
QLocale::Pashto,
QLocale::Persian,
QLocale::Polish,
QLocale::Portuguese,
QLocale::Romanian,
QLocale::Russian,
QLocale::Serbian,
QLocale::Shona,
QLocale::Sindhi,
QLocale::Sinhala,
QLocale::Slovak,
QLocale::Slovenian,
QLocale::Somali,
QLocale::Spanish,
QLocale::Sundanese,
QLocale::Swahili,
QLocale::Swedish,
QLocale::Tajik,
QLocale::Tamil,
QLocale::Tatar,
QLocale::Teso,
QLocale::Thai,
QLocale::Turkish,
QLocale::Turkmen,
QLocale::Ukrainian,
QLocale::Urdu,
QLocale::Uzbek,
QLocale::Vietnamese,
QLocale::Welsh,
QLocale::WesternFrisian,
QLocale::Xhosa,
QLocale::Yiddish,
};
}
class ShowButton : public RpWidget {
class Row final : public Ui::SettingsButton {
public:
Row(not_null<Ui::RpWidget*> parent, const QLocale &locale);
[[nodiscard]] bool filtered(const QString &query) const;
[[nodiscard]] QLocale locale() const;
int resizeGetHeight(int newWidth) override;
protected:
void paintEvent(QPaintEvent *e) override;
private:
const style::PeerListItem &_st;
const QLocale _locale;
const QString _status;
const QString _titleText;
Ui::Text::String _title;
};
Row::Row(not_null<Ui::RpWidget*> parent, const QLocale &locale)
: SettingsButton(parent, rpl::never<QString>())
, _st(st::inviteLinkListItem)
, _locale(locale)
, _status(QLocale::languageToString(locale.language()))
, _titleText(LanguageName(locale))
, _title(_st.nameStyle, _titleText) {
}
QLocale Row::locale() const {
return _locale;
}
bool Row::filtered(const QString &query) const {
return _status.startsWith(query, Qt::CaseInsensitive)
|| _titleText.startsWith(query, Qt::CaseInsensitive);
}
int Row::resizeGetHeight(int newWidth) {
return _st.height;
}
void Row::paintEvent(QPaintEvent *e) {
auto p = Painter(this);
const auto paintOver = (isOver() || isDown()) && !isDisabled();
Ui::SettingsButton::paintBg(p, e->rect(), paintOver);
Ui::SettingsButton::paintRipple(p, 0, 0);
Ui::SettingsButton::paintToggle(p, width());
const auto &color = st::windowSubTextFg;
p.setPen(Qt::NoPen);
p.setBrush(color);
const auto left = st::settingsSubsectionTitlePadding.left();
const auto toggleRect = Ui::SettingsButton::maybeToggleRect();
const auto right = left
+ (toggleRect.isEmpty() ? 0 : (width() - toggleRect.x()));
p.setPen(_st.nameFg);
_title.drawLeft(
p,
left,
_st.namePosition.y(),
width() - left - right,
width() - left - right);
p.setPen(paintOver ? _st.statusFgOver : _st.statusFg);
p.setFont(st::contactsStatusFont);
p.drawTextLeft(
left,
_st.statusPosition.y(),
width() - left - right,
_status);
}
class ShowButton final : public RpWidget {
public:
ShowButton(not_null<Ui::RpWidget*> parent);
@@ -125,11 +252,36 @@ rpl::producer<Qt::MouseButton> ShowButton::clicks() const {
} // namespace
namespace Translate {
std::vector<QLocale> LocalesFromSettings() {
const auto langs = Core::App().settings().skipTranslationForLanguages();
if (langs.empty()) {
return { QLocale(QLocale::English) };
}
return ranges::views::all(
langs
) | ranges::view::transform([](int langId) {
const auto lang = QLocale::Language(langId);
return (lang == QLocale::English)
? QLocale(Lang::LanguageIdOrDefault(Lang::Id()))
: (lang == QLocale::C)
? QLocale(QLocale::English)
: QLocale(lang);
}) | ranges::to_vector;
}
} // namespace Translate
using namespace Translate;
QString LanguageName(const QLocale &locale) {
if (locale.language() == QLocale::English
&& (locale.country() == QLocale::UnitedStates
|| locale.country() == QLocale::AnyCountry)) {
return u"English"_q;
} else if (locale.language() == QLocale::Spanish) {
return QString::fromUtf8("\x45\x73\x70\x61\xc3\xb1\x6f\x6c");
} else {
const auto name = locale.nativeLanguageName();
return name.left(1).toUpper() + name.mid(1);
@@ -145,13 +297,7 @@ void TranslateBox(
box->setWidth(st::boxWideWidth);
box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); });
const auto container = box->verticalLayout();
const auto settingsLang =
Core::App().settings().skipTranslationForLanguage();
const auto defaultId = (settingsLang == QLocale::English)
? Lang::LanguageIdOrDefault(Lang::Id())
: (settingsLang == QLocale::C)
? u"en"_q
: QLocale(settingsLang).name().mid(0, 2);
const auto defaultId = LocalesFromSettings().front().name().mid(0, 2);
const auto api = box->lifetime().make_state<MTP::Sender>(
&peer->session().mtp());
@@ -193,7 +339,12 @@ void TranslateBox(
original->entity()->setContextMenuHook([](auto&&) {
});
}
original->entity()->setMarkedText(text);
original->entity()->setMarkedText(
text,
Core::MarkedTextContext{
.session = &peer->session(),
.customEmojiRepaint = [=] { original->entity()->update(); },
});
original->setMinimalHeight(lineHeight);
original->hide(anim::type::instant);
@@ -292,28 +443,104 @@ void TranslateBox(
if (loading->toggled()) {
return;
}
Ui::BoxShow(box).showBox(Box(ChooseLanguageBox, [=](QLocale locale) {
Ui::BoxShow(box).showBox(Box(ChooseLanguageBox, [=](
std::vector<QLocale> locales) {
const auto &locale = locales.front();
state->locale.fire_copy(locale);
loading->show(anim::type::instant);
translated->hide(anim::type::instant);
send(locale.name().mid(0, 2));
}));
}, std::vector<QLocale>()));
});
}
void ChooseLanguageBox(
not_null<Ui::GenericBox*> box,
Fn<void(QLocale)> callback) {
Fn<void(std::vector<QLocale>)> callback,
std::vector<QLocale> toggled) {
box->setMinHeight(st::boxWidth);
box->setMaxHeight(st::boxWidth);
box->setTitle(tr::lng_languages());
for (const auto &lang : Languages()) {
const auto hasToggled = !toggled.empty();
const auto multiSelect = box->setPinnedToTopContent(
object_ptr<Ui::MultiSelect>(
box,
st::defaultMultiSelect,
tr::lng_participant_filter()));
box->setFocusCallback([=] { multiSelect->setInnerFocus(); });
const auto container = box->verticalLayout();
const auto langs = [&] {
auto langs = Languages();
const auto current = QLocale(
Lang::LanguageIdOrDefault(Lang::Id())).language();
if (const auto it = ranges::find(langs, current); it != end(langs)) {
base::reorder(langs, std::distance(begin(langs), it), 0);
}
return langs;
}();
auto rows = std::vector<not_null<Ui::SlideWrap<Row>*>>();
rows.reserve(langs.size());
for (const auto &lang : langs) {
const auto locale = QLocale(lang);
const auto button = Settings::AddButton(
box->verticalLayout(),
rpl::single(LanguageName(locale)),
st::defaultSettingsButton);
button->setClickedCallback([=] {
callback(locale);
const auto button = container->add(
object_ptr<Ui::SlideWrap<Row>>(
container,
object_ptr<Row>(container, locale)));
if (hasToggled) {
button->entity()->toggleOn(
rpl::single(ranges::contains(toggled, locale)),
false);
} else {
button->entity()->setClickedCallback([=] {
callback({ locale });
box->closeBox();
});
}
rows.push_back(button);
}
multiSelect->setQueryChangedCallback([=](const QString &query) {
for (const auto &row : rows) {
const auto toggled = row->entity()->filtered(query);
if (toggled != row->toggled()) {
row->toggle(toggled, anim::type::instant);
}
}
});
{
const auto label = Ui::CreateChild<Ui::FlatLabel>(
box.get(),
tr::lng_languages_none(),
st::membersAbout);
box->verticalLayout()->geometryValue(
) | rpl::start_with_next([=](const QRect &geometry) {
const auto shown = (geometry.height() <= 0);
label->setVisible(shown);
if (shown) {
label->moveToLeft(
(geometry.width() - label->width()) / 2,
geometry.y() + st::membersAbout.style.font->height * 4);
label->stackUnder(box->verticalLayout());
}
}, label->lifetime());
}
if (hasToggled) {
box->addButton(tr::lng_settings_save(), [=] {
auto result = ranges::views::all(
rows
) | ranges::views::filter([](const auto &row) {
return row->entity()->toggled();
}) | ranges::views::transform([](const auto &row) {
return row->entity()->locale();
}) | ranges::to_vector;
if (!result.empty()) {
callback(std::move(result));
}
box->closeBox();
});
}
@@ -342,18 +569,17 @@ bool SkipTranslate(TextWithEntities textWithEntities) {
if (!hasLetters) {
return true;
}
#ifndef TDESKTOP_DISABLE_SPELLCHECK
const auto result = Platform::Language::Recognize(text);
if (result.unknown) {
return false;
}
const auto settingsLang =
Core::App().settings().skipTranslationForLanguage();
const auto skip = (settingsLang == QLocale::English)
? QLocale(Lang::LanguageIdOrDefault(Lang::Id())).language()
: (settingsLang == QLocale::C)
? QLocale::English
: settingsLang;
return (result.locale.language() == skip);
return ranges::any_of(LocalesFromSettings(), [&](const QLocale &l) {
return result.locale.language() == l.language();
});
#else
return false;
#endif
}
} // namespace Ui

View File

@@ -10,6 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class PeerData;
namespace Ui {
namespace Translate {
[[nodiscard]] std::vector<QLocale> LocalesFromSettings();
} // namespace Translate
class GenericBox;
@@ -26,6 +29,7 @@ void TranslateBox(
void ChooseLanguageBox(
not_null<Ui::GenericBox*> box,
Fn<void(QLocale)> callback);
Fn<void(std::vector<QLocale>)> callback,
std::vector<QLocale> toggled);
} // namespace Ui

View File

@@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/calls_instance.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "mainwidget.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
@@ -209,7 +210,7 @@ void BoxController::Row::refreshStatus() {
return;
}
auto text = [this] {
auto time = QLocale().toString(ItemDateTime(_items.front()).time(), cTimeFormat());
auto time = QLocale().toString(ItemDateTime(_items.front()).time(), QLocale::ShortFormat);
auto today = QDateTime::currentDateTime().date();
if (_date == today) {
return tr::lng_call_box_status_today(tr::now, lt_time, time);

View File

@@ -407,6 +407,7 @@ void Panel::reinitWithCall(Call *call) {
const auto active = _call->isSharingScreen();
_screencast->setProgress(active ? 0. : 1.);
_screencast->setText(tr::lng_call_screencast());
_outgoingVideoBubble->setMirrored(!active);
}
}, _callLifetime);

View File

@@ -152,7 +152,7 @@ void VideoBubble::prepareFrame() {
.resize = size,
.outer = size,
};
const auto frame = _track->frame(request);
const auto frame = _track->frame(request).mirrored(!_mirrored, false);
if (_frame.width() < size.width() || _frame.height() < size.height()) {
_frame = QImage(
size * cIntRetinaFactor(),

View File

@@ -37,6 +37,10 @@ public:
return _content.lifetime();
}
void setMirrored(bool mirrored) {
_mirrored = mirrored;
}
private:
void setup();
void paint();
@@ -59,6 +63,7 @@ private:
RectPart _corner = RectPart::None;
bool _dragging = false;
bool _geometryDirty = false;
bool _mirrored = true;
};

View File

@@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/tooltip.h"
#include "ui/widgets/rp_window.h"
#include "ui/chat/group_call_bar.h"
#include "ui/controls/userpic_button.h"
#include "ui/layers/layer_manager.h"
#include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h"
@@ -35,7 +36,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image_prepare.h"
#include "ui/painter.h"
#include "ui/round_rect.h"
#include "ui/special_buttons.h"
#include "info/profile/info_profile_values.h" // Info::Profile::Value.
#include "core/application.h"
#include "core/core_settings.h"
@@ -1244,7 +1244,6 @@ void Panel::refreshTopButton() {
auto joinAsToggle = object_ptr<Ui::UserpicButton>(
widget(),
joinAs,
Ui::UserpicButton::Role::Custom,
st::groupCallJoinAsToggle);
_joinAsToggle.destroy();
_joinAsToggle = std::move(joinAsToggle);

View File

@@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "boxes/share_box.h"
#include "history/view/history_view_schedule_box.h"
#include "history/history_message.h" // GetErrorTextForSending.
#include "history/history_item_helpers.h" // GetErrorTextForSending.
#include "history/history.h"
#include "data/data_histories.h"
#include "data/data_session.h"

View File

@@ -35,7 +35,7 @@ rpl::producer<QString> StartsWhenText(rpl::producer<TimeId> date) {
const auto time = QLocale().toString(
parsedDate.time(),
Ui::Integration::Instance().timeFormat());
QLocale::ShortFormat);
auto exact = tr::lng_group_call_starts_short_date(
lt_date,
rpl::single(langDayOfMonthFull(dateDay.date())),

View File

@@ -255,7 +255,7 @@ void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pres
bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
if (!to || !to->definesReplyKeyboard()) {
if (_wasForMsgId.msg) {
_maximizeSize = _singleUse = _forceReply = false;
_maximizeSize = _singleUse = _forceReply = _persistent = false;
_wasForMsgId = FullMsgId();
_placeholder = QString();
_impl = nullptr;
@@ -275,6 +275,7 @@ bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
_forceReply = markupFlags & ReplyMarkupFlag::ForceReply;
_maximizeSize = !(markupFlags & ReplyMarkupFlag::Resize);
_singleUse = _forceReply || (markupFlags & ReplyMarkupFlag::SingleUse);
_persistent = (markupFlags & ReplyMarkupFlag::Persistent);
if (const auto markup = to->Get<HistoryMessageReplyMarkup>()) {
_placeholder = markup->data.placeholder;
@@ -326,6 +327,10 @@ bool BotKeyboard::singleUse() const {
return _singleUse;
}
bool BotKeyboard::persistent() const {
return _persistent;
}
void BotKeyboard::updateStyle(int newWidth) {
if (!_impl) return;

View File

@@ -49,6 +49,7 @@ public:
[[nodiscard]] bool maximizeSize() const;
[[nodiscard]] bool singleUse() const;
[[nodiscard]] bool persistent() const;
[[nodiscard]] FullMsgId forMsgId() const {
return _wasForMsgId;
@@ -91,6 +92,7 @@ private:
bool _maximizeSize = false;
bool _singleUse = false;
bool _forceReply = false;
bool _persistent = false;
QPoint _lastMousePos;
std::unique_ptr<ReplyKeyboard> _impl;

View File

@@ -438,9 +438,6 @@ EmojiListWidget::EmojiListWidget(
resizeToWidth(width());
}, lifetime());
if (_mode == Mode::EmojiStatus) {
_emojiStatusColor = std::make_unique<Ui::Text::CustomEmojiColored>();
}
rpl::single(
rpl::empty
) | rpl::then(
@@ -449,12 +446,6 @@ EmojiListWidget::EmojiListWidget(
initButton(_add, tr::lng_stickers_featured_add(tr::now), false);
initButton(_unlock, tr::lng_emoji_featured_unlock(tr::now), true);
initButton(_restore, tr::lng_emoji_premium_restore(tr::now), true);
if (const auto status = _emojiStatusColor.get()) {
status->color = anim::color(
st::stickerPanPremium1,
st::stickerPanPremium2,
0.5);
}
}, lifetime());
if (!descriptor.customRecentList.empty()) {
@@ -842,10 +833,36 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) {
paint(p, {}, clip);
}
void EmojiListWidget::validateEmojiPaintContext(
const ExpandingContext &context) {
auto value = Ui::Text::CustomEmojiPaintContext{
.textColor = (_mode == Mode::EmojiStatus
? anim::color(
st::stickerPanPremium1,
st::stickerPanPremium2,
0.5)
: st::windowFg->c),
.size = QSize(_customSingleSize, _customSingleSize),
.now = crl::now(),
.scale = context.progress,
.paused = paused(),
.scaled = context.expanding,
};
if (!_emojiPaintContext) {
_emojiPaintContext = std::make_unique<
Ui::Text::CustomEmojiPaintContext
>(std::move(value));
} else {
*_emojiPaintContext = std::move(value);
}
}
void EmojiListWidget::paint(
QPainter &p,
ExpandingContext context,
QRect clip) {
validateEmojiPaintContext(context);
auto fromColumn = floorclamp(
clip.x() - _rowsLeft,
_singleSize.width(),
@@ -861,10 +878,7 @@ void EmojiListWidget::paint(
fromColumn = _columnCount - fromColumn;
toColumn = _columnCount - toColumn;
}
const auto expandProgress = context.progress;
const auto paused = this->paused();
const auto now = crl::now();
auto selectedButton = std::get_if<OverButton>(!v::is_null(_pressed)
? &_pressed
: &_selected);
@@ -968,12 +982,12 @@ void EmojiListWidget::paint(
_overBg.paint(p, QRect(tl, st::emojiPanArea));
}
if (info.section == int(Section::Recent)) {
drawRecent(p, context, w, now, paused, index);
drawRecent(p, context, w, index);
} else if (info.section < _staticCount) {
drawEmoji(p, context, w, _emoji[info.section][index]);
} else {
const auto set = info.section - _staticCount;
drawCustom(p, context, w, now, paused, set, index);
drawCustom(p, context, w, set, index);
}
}
}
@@ -1006,24 +1020,15 @@ void EmojiListWidget::drawRecent(
QPainter &p,
const ExpandingContext &context,
QPoint position,
crl::time now,
bool paused,
int index) {
_recentPainted = true;
auto &recent = _recent[index];
if (const auto custom = recent.custom) {
position += _innerPosition + _customPosition;
const auto paintContext = Ui::Text::CustomEmoji::Context{
.preview = st::windowBgRipple->c,
.colored = _emojiStatusColor.get(),
.size = QSize(_customSingleSize, _customSingleSize),
.now = now,
.scale = context.progress,
.position = position,
.paused = paused,
.scaled = context.expanding,
};
custom->paint(p, paintContext);
_emojiPaintContext->scale = context.progress;
_emojiPaintContext->position = position
+ _innerPosition
+ _customPosition;
custom->paint(p, *_emojiPaintContext);
} else if (const auto emoji = std::get_if<EmojiPtr>(&recent.id.data)) {
if (_mode == Mode::EmojiStatus) {
position += QPoint(
@@ -1057,24 +1062,17 @@ void EmojiListWidget::drawCustom(
QPainter &p,
const ExpandingContext &context,
QPoint position,
crl::time now,
bool paused,
int set,
int index) {
position += _innerPosition + _customPosition;
auto &custom = _custom[set];
custom.painted = true;
auto &entry = custom.list[index];
entry.custom->paint(p, {
.preview = st::windowBgRipple->c,
.colored = _emojiStatusColor.get(),
.size = QSize(_customSingleSize, _customSingleSize),
.now = now,
.scale = context.progress,
.position = position,
.paused = paused,
.scaled = context.expanding,
});
_emojiPaintContext->scale = context.progress;
_emojiPaintContext->position = position
+ _innerPosition
+ _customPosition;
entry.custom->paint(p, *_emojiPaintContext);
}
bool EmojiListWidget::checkPickerHide() {

View File

@@ -38,7 +38,7 @@ enum class Section;
} // namespace Ui::Emoji
namespace Ui::Text {
struct CustomEmojiColored;
struct CustomEmojiPaintContext;
} // namespace Ui::Text
namespace Ui::CustomEmoji {
@@ -267,8 +267,6 @@ private:
QPainter &p,
const ExpandingContext &context,
QPoint position,
crl::time now,
bool paused,
int index);
void drawEmoji(
QPainter &p,
@@ -279,10 +277,9 @@ private:
QPainter &p,
const ExpandingContext &context,
QPoint position,
crl::time now,
bool paused,
int set,
int index);
void validateEmojiPaintContext(const ExpandingContext &context);
[[nodiscard]] bool hasRemoveButton(int index) const;
[[nodiscard]] QRect removeButtonRect(int index) const;
[[nodiscard]] QRect removeButtonRect(const SectionInfo &info) const;
@@ -345,7 +342,7 @@ private:
std::vector<RecentOne> _recent;
base::flat_set<DocumentId> _recentCustomIds;
base::flat_set<uint64> _repaintsScheduled;
std::unique_ptr<Ui::Text::CustomEmojiColored> _emojiStatusColor;
std::unique_ptr<Ui::Text::CustomEmojiPaintContext> _emojiPaintContext;
bool _recentPainted = false;
bool _grabbingChosen = false;
QVector<EmojiPtr> _emoji[kEmojiSectionCount];

View File

@@ -341,8 +341,10 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) {
Ui::StickerHoverCorners);
}
const auto now = crl::now();
const auto preview = st::windowBgOver->c;
auto context = Ui::CustomEmoji::Context{
.textColor = st::windowFg->c,
.now = crl::now(),
};
for (auto i = from; i != till; ++i) {
const auto &row = _rows[i];
const auto emoji = row.emoji;
@@ -351,11 +353,8 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) {
const auto x = i * _oneWidth + (_oneWidth - size) / 2;
const auto y = (_oneWidth - size) / 2;
if (row.custom) {
row.custom->paint(p, {
.preview = preview,
.now = now,
.position = { x, y },
});
context.position = { x, y };
row.custom->paint(p, context);
} else {
Ui::Emoji::Draw(p, emoji, esize, x, y);
}

View File

@@ -472,7 +472,9 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
--i;
mrows.push_back({ i->second });
}
} else if (_channel && _channel->isMegagroup()) {
} else if (_channel
&& _channel->isMegagroup()
&& _channel->canViewMembers()) {
if (_channel->lastParticipantsRequestNeeded()) {
_channel->session().api().chatParticipants().requestLast(
_channel);

View File

@@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_widget.h"
#include "history/history.h" // History::session
#include "history/history_item.h" // HistoryItem::originalText
#include "history/history_message.h" // DropCustomEmoji
#include "history/history_item_helpers.h" // DropCustomEmoji
#include "base/qthelp_regex.h"
#include "base/qthelp_url.h"
#include "base/event_filter.h"

View File

@@ -129,7 +129,8 @@ void DicePack::generateLocal(int index, const QString &name) {
nullptr,
SendMediaType::File,
FileLoadTo(0, {}, 0, 0, 0),
{});
{},
false);
task.process({ .generateGoodThumbnail = false });
const auto result = task.peekResult();
Assert(result != nullptr);

View File

@@ -605,6 +605,7 @@ void StickersListFooter::paint(
const auto now = crl::now();
const auto paused = _paused();
p.setPen(st::windowFg);
enumerateVisibleIcons([&](const IconInfo &info) {
paintSetIcon(p, context, info, now, paused);
});
@@ -1251,7 +1252,7 @@ void StickersListFooter::paintSetIcon(
const auto y = _iconsTop + (st().footer - icon.pixh) / 2;
if (icon.custom) {
icon.custom->paint(p, Ui::Text::CustomEmoji::Context{
.preview = st::windowBgRipple->c,
.textColor = st::windowFg->c,
.size = QSize(icon.pixw, icon.pixh),
.now = now,
.scale = context.progress,

View File

@@ -268,7 +268,7 @@ void Application::run() {
Ui::InitTextOptions();
Ui::StartCachedCorners();
Ui::Emoji::Init();
Ui::PrepareTextSpoilerMask();
Ui::PreloadTextSpoilerMask();
startEmojiImageLoader();
startSystemDarkModeViewer();
Media::Player::start(_audio.get());
@@ -284,9 +284,6 @@ void Application::run() {
DEBUG_LOG(("Application Info: inited..."));
cChangeDateFormat(QLocale().dateFormat(QLocale::ShortFormat));
cChangeTimeFormat(QLocale().timeFormat(QLocale::ShortFormat));
DEBUG_LOG(("Application Info: starting app..."));
// Create mime database, so it won't be slow later.

View File

@@ -76,6 +76,15 @@ std::map<int, const char*> BetaLogs() {
"- Fix spoiler revealing in media viewer captions.\n"
"- Fix crash in folder editing on Linux.\n"
},
{
4004002,
"- Send photos and video files hidden by a spoiler effect.\n"
"- Set a public photo for those who are restricted to see "
"your profile photo in the Privacy Settings.\n"
"- Bug fixes and other minor improvements.\n"
}
};
};

View File

@@ -267,7 +267,16 @@ QByteArray Settings::serialize() const {
<< qint32(_hardwareAcceleratedVideo ? 1 : 0)
<< qint32(_suggestAnimatedEmoji ? 1 : 0)
<< qint32(_cornerReaction.current() ? 1 : 0)
<< qint32(_skipTranslationForLanguage);
<< qint32(_translateButtonEnabled ? 1 : 0);
stream
<< qint32(_skipTranslationForLanguages.size());
for (const auto &lang : _skipTranslationForLanguages) {
stream << quint64(lang);
}
stream
<< qint32(_rememberedDeleteMessageOnlyForYou ? 1 : 0);
}
return result;
}
@@ -361,7 +370,10 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 chatQuickAction = static_cast<qint32>(_chatQuickAction);
qint32 suggestAnimatedEmoji = _suggestAnimatedEmoji ? 1 : 0;
qint32 cornerReaction = _cornerReaction.current() ? 1 : 0;
qint32 skipTranslationForLanguage = _skipTranslationForLanguage;
qint32 legacySkipTranslationForLanguage = _translateButtonEnabled ? 1 : 0;
qint32 skipTranslationForLanguagesCount = 0;
std::vector<int> skipTranslationForLanguages;
qint32 rememberedDeleteMessageOnlyForYou = _rememberedDeleteMessageOnlyForYou ? 1 : 0;
stream >> themesAccentColors;
if (!stream.atEnd()) {
@@ -560,7 +572,19 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
stream >> cornerReaction;
}
if (!stream.atEnd()) {
stream >> skipTranslationForLanguage;
stream >> legacySkipTranslationForLanguage;
}
if (!stream.atEnd()) {
stream >> skipTranslationForLanguagesCount;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != skipTranslationForLanguagesCount; ++i) {
quint64 language;
stream >> language;
skipTranslationForLanguages.emplace_back(language);
}
}
stream >> rememberedDeleteMessageOnlyForYou;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
@@ -731,7 +755,19 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
}
_suggestAnimatedEmoji = (suggestAnimatedEmoji == 1);
_cornerReaction = (cornerReaction == 1);
_skipTranslationForLanguage = skipTranslationForLanguage;
{ // Parse the legacy translation setting.
_skipTranslationForLanguages = skipTranslationForLanguages;
if (legacySkipTranslationForLanguage == 0) {
_translateButtonEnabled = false;
} else if (legacySkipTranslationForLanguage == 1) {
_translateButtonEnabled = true;
} else {
_translateButtonEnabled = (legacySkipTranslationForLanguage > 0);
_skipTranslationForLanguages.push_back(
std::abs(legacySkipTranslationForLanguage));
}
}
_rememberedDeleteMessageOnlyForYou = (rememberedDeleteMessageOnlyForYou == 1);
}
QString Settings::getSoundPath(const QString &key) const {
@@ -1042,18 +1078,23 @@ float64 Settings::DefaultDialogsWidthRatio() {
}
void Settings::setTranslateButtonEnabled(bool value) {
_skipTranslationForLanguage = std::abs(_skipTranslationForLanguage)
* (value ? 1 : -1);
_translateButtonEnabled = value;
}
bool Settings::translateButtonEnabled() const {
return _skipTranslationForLanguage > 0;
return _translateButtonEnabled;
}
void Settings::setSkipTranslationForLanguage(QLocale::Language language) {
const auto enabled = translateButtonEnabled();
_skipTranslationForLanguage = language * (enabled ? 1 : -1);
void Settings::setSkipTranslationForLanguages(std::vector<int> languages) {
_skipTranslationForLanguages = std::move(languages);
}
QLocale::Language Settings::skipTranslationForLanguage() const {
return QLocale::Language(std::abs(_skipTranslationForLanguage));
std::vector<int> Settings::skipTranslationForLanguages() const {
return _skipTranslationForLanguages;
}
void Settings::setRememberedDeleteMessageOnlyForYou(bool value) {
_rememberedDeleteMessageOnlyForYou = value;
}
bool Settings::rememberedDeleteMessageOnlyForYou() const {
return _rememberedDeleteMessageOnlyForYou;
}
} // namespace Core

View File

@@ -724,8 +724,11 @@ public:
void setTranslateButtonEnabled(bool value);
[[nodiscard]] bool translateButtonEnabled() const;
void setSkipTranslationForLanguage(QLocale::Language language);
[[nodiscard]] QLocale::Language skipTranslationForLanguage() const;
void setSkipTranslationForLanguages(std::vector<int> languages);
[[nodiscard]] std::vector<int> skipTranslationForLanguages() const;
void setRememberedDeleteMessageOnlyForYou(bool value);
[[nodiscard]] bool rememberedDeleteMessageOnlyForYou() const;
[[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
@@ -841,7 +844,9 @@ private:
#endif // Q_OS_MAC
HistoryView::DoubleClickQuickAction _chatQuickAction =
HistoryView::DoubleClickQuickAction();
int _skipTranslationForLanguage = -int(QLocale::English);
bool _translateButtonEnabled = false;
std::vector<int> _skipTranslationForLanguages;
bool _rememberedDeleteMessageOnlyForYou = false;
bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View File

@@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_theme_editor_box.h" // GenerateSlug.
#include "payments/payments_checkout_process.h"
#include "settings/settings_common.h"
#include "settings/settings_information.h"
#include "settings/settings_global_ttl.h"
#include "settings/settings_folders.h"
#include "settings/settings_main.h"
@@ -488,6 +489,8 @@ bool ResolveSettings(
return ::Settings::ChangePhone::Id();
} else if (section == u"auto_delete"_q) {
return ::Settings::GlobalTTLId();
} else if (section == u"information"_q) {
return ::Settings::Information::Id();
}
return ::Settings::Main::Id();
}();
@@ -846,7 +849,7 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
ResolvePrivatePost
},
{
u"^settings(/language|/devices|/folders|/privacy|/themes|/change_number|/auto_delete)?$"_q,
u"^settings(/language|/devices|/folders|/privacy|/themes|/change_number|/auto_delete|/information)?$"_q,
ResolveSettings
},
{

View File

@@ -137,10 +137,6 @@ bool UiIntegration::screenIsLocked() {
return Core::App().screenIsLocked();
}
QString UiIntegration::timeFormat() {
return cTimeFormat();
}
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
const EntityLinkData &data,
const std::any &context) {

View File

@@ -46,7 +46,6 @@ public:
void activationFromTopPanel() override;
bool screenIsLocked() override;
QString timeFormat() override;
std::shared_ptr<ClickHandler> createLinkHandler(
const EntityLinkData &data,

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