Compare commits

...

84 Commits

Author SHA1 Message Date
John Preston
77d8c7ce01 Version 2.8.11.
- Check shader compilation / linking before using ANGLE.

It fails on default Windows 7 installations.
2021-07-17 12:47:10 +03:00
John Preston
de0897343b Version 2.8.10: Fix media loading. 2021-07-16 20:15:44 +03:00
John Preston
e27399baa6 Pinpoint patches revision, including Dockerfile. 2021-07-16 19:38:54 +03:00
John Preston
42eb74d07a Version 2.8.9: Fix GIF caption edit. 2021-07-16 10:10:58 +03:00
John Preston
aee991f598 Version 2.8.9.
- Fix version on Windows without SetDefaultDllDirectories.
- Fix fonts on Linux.
2021-07-16 09:41:52 +03:00
John Preston
96c3dc4161 Fix Windows version without SetDefaultDllDirectories. 2021-07-16 09:39:52 +03:00
John Preston
77586a1297 Fix font styles on Linux. 2021-07-16 09:27:26 +03:00
John Preston
b69cac3ed6 Version 2.8.8.
- Added an image editor.
Crop photos or highlight parts of screenshots before sending.
2021-07-15 21:22:58 +03:00
John Preston
c4654f1ee8 Update patches revision for Windows build. 2021-07-15 21:22:54 +03:00
John Preston
c45122ab1e Update tgcalls submodule. 2021-07-15 21:08:47 +03:00
John Preston
10e1feb40b Use GL_BGRA_EXT format with ANGLE. 2021-07-15 16:42:38 +03:00
John Preston
4d99c1fd44 Allow sharing system audio with window share. 2021-07-15 16:42:38 +03:00
John Preston
4276b6cce0 Use rpl for Window::Theme::Background updates. 2021-07-15 16:42:36 +03:00
23rd
7e83088a84 Completely refactored EditCaptionBox.
Moved preview content to separate widget.
Increased caption area height.
2021-07-13 22:15:49 +03:00
23rd
47a4f4229d Added ability to hide attach controls. 2021-07-13 22:15:22 +03:00
23rd
7cf5e6d94f Added ability to set controls type for single previews. 2021-07-13 22:15:22 +03:00
23rd
5431541694 Added AbstractSinglePreview. 2021-07-13 22:15:22 +03:00
23rd
c1e86418c2 Added ability to generate single media preview from history item. 2021-07-13 22:15:22 +03:00
23rd
86db29cec7 Added AbstractSingleMediaPreview. 2021-07-13 22:15:22 +03:00
23rd
19139a9a5f Added ability to generate single file preview from history item. 2021-07-13 22:15:22 +03:00
23rd
9509a00664 Added AbstractSingleFilePreview. 2021-07-13 22:15:20 +03:00
John Preston
e2a85e3156 Closed alpha version 2.8.7.1. 2021-07-13 22:09:48 +03:00
John Preston
99353dcfba Update submodules. 2021-07-13 22:09:14 +03:00
John Preston
86a2a4d63a Count unique video senders in limit. 2021-07-13 22:08:10 +03:00
John Preston
ab67aa28b5 Support resampling for loopback audio. 2021-07-13 22:08:10 +03:00
John Preston
db81638656 Allow sharing screen with sound on Windows. 2021-07-13 22:08:09 +03:00
John Preston
402729dc99 Check unmuted video limit in group call. 2021-07-13 22:08:09 +03:00
John Preston
801c8b6220 Screencast with system sound on Windows. 2021-07-13 22:08:09 +03:00
John Preston
881eb4510e Separate test and production RSA keys. 2021-07-13 22:08:09 +03:00
John Preston
cc013305ac Apply local volume / mute to additional audio stream. 2021-07-13 22:08:09 +03:00
John Preston
f17fc0b670 Support additional audio ssrc. 2021-07-13 22:08:09 +03:00
John Preston
5e2cdde2c8 Update API scheme. 2021-07-13 22:08:09 +03:00
John Preston
eea48c7139 Update used public RSA keys. 2021-07-13 22:08:09 +03:00
John Preston
95a7ce4622 New auth key generation algorithm. 2021-07-13 22:08:09 +03:00
John Preston
a0540e0486 Send dependent requests in bunches. 2021-07-13 22:08:09 +03:00
John Preston
e28fb1211e Handle MSG_WAIT_FAILED / MSG_WAIT_TIMEOUT. 2021-07-13 22:08:09 +03:00
John Preston
bae8335285 Always resend messages in a container. 2021-07-13 22:08:09 +03:00
John Preston
8fc7ba7ac1 Handle updateBotCommands. 2021-07-13 22:08:09 +03:00
John Preston
8f5ac0420e Update API scheme to layer 131. 2021-07-13 22:08:09 +03:00
John Preston
b57255297c Clang on Linux build fixes. 2021-07-13 21:56:36 +03:00
Ilya Fedin
79cc797aff Fix -Wunused-variable warnings 2021-07-13 21:43:34 +03:00
Ilya Fedin
b6881022ce Allow to build with -Werror and clang
Fixes -Wdeprecated-enum-enum-conversion, -Wdeprecated-declarations, -Wrange-loop-construct, -Winconsistent-missing-override
2021-07-13 21:32:06 +03:00
Ilya Fedin
89765340c3 Fix -Wunused-function warnings 2021-07-13 21:31:22 +03:00
John Preston
84b1fac0c8 Fix more warnings in submodules. 2021-07-13 21:30:55 +03:00
nyakze
a283049b34 Expand moderator mode + fix
Apparently for commands to work, they have to be bind to 1-9 keys, apart from any other alternative hotkeys. It should address this issue, as well as expanding to ease the usage on numpad.
2021-07-13 16:04:16 +03:00
Ilya Fedin
8ecc98eb03 Right file dialog freeze fix
The freezing is still happening if the service is not accessible
2021-07-12 11:10:16 +03:00
Ilya Fedin
c53564cfdc Set service name for MPRIS 2021-07-10 14:28:04 +03:00
John Preston
cc7f569c77 Fix build on non-Windows. 2021-07-09 21:39:08 +03:00
23rd
7526964904 Simplified calculation of minimum crop size in photo editor.
It also fixes cropping of images with unbalanced ratios.
2021-07-09 13:15:31 +03:00
23rd
f1669674d8 Moved formatting of image size text to single place.
Fixed wrong size display on retina screens.
Replaced "x" with special character.
2021-07-09 13:15:31 +03:00
23rd
cab8a52f8f Fixed visual glitch in image size text from SendFilexBox.
Regression was introduced in f52c6a6daa.
2021-07-09 13:15:31 +03:00
23rd
6b93d8dc41 Refactored and fixed saving scene states between modes in photo editor. 2021-07-09 12:49:07 +03:00
23rd
9be122710d Moved SaveState from Editor::BaseItem to Editor::NumberedItem. 2021-07-09 12:49:07 +03:00
23rd
1e3044fbf4 Moved performing of Undo/Redo from Editor::Paint to Editor::Scene. 2021-07-09 12:49:07 +03:00
23rd
aef2148ed0 Moved hasUndo and hasRedo from Editor::Paint to Editor::Scene. 2021-07-09 12:49:07 +03:00
23rd
fb511c3e03 Added status to Editor::NumberedItem. 2021-07-09 12:49:07 +03:00
23rd
6acd9f18ad Replaced interaction with QGraphicsItem to Editor::NumberedItem. 2021-07-09 12:49:07 +03:00
23rd
78b25c694e Added ability to save and restore items state in photo editor. 2021-07-09 12:49:07 +03:00
23rd
d2d97a3e47 Moved to separate file some structs for internal usage in photo editor. 2021-07-09 12:49:07 +03:00
23rd
bf8f3e42f4 Simplified work with Editor::ItemBase::Data. 2021-07-09 12:49:07 +03:00
23rd
fe8eae09c4 Fixed item handlers size when opening photo editor with modified scene. 2021-07-09 12:49:07 +03:00
23rd
5bbf3a329d Fixed items order when opening photo editor with modified scene. 2021-07-09 12:49:07 +03:00
23rd
8ddbf08a97 Changed max and min sizes of scene items from pixels to ratio. 2021-07-09 12:49:06 +03:00
23rd
d69090bf34 Moved flip and rotation info to Editor::ItemBase struct. 2021-07-09 12:49:06 +03:00
23rd
0c50fbf1b9 Moved Editor::ItemBase arguments to struct. 2021-07-09 12:49:06 +03:00
John Preston
4206ff0483 Don't use MTP* for StickersSet flags. 2021-07-09 09:08:58 +03:00
Ilya Fedin
62fd968409 Don't call gtk_selection_data_get_length on nullptr 2021-07-08 22:09:26 +03:00
Ilya Fedin
2c6e4eed19 Use unique_ptr for GtkSelectionData 2021-07-08 22:09:26 +03:00
John Preston
75090dedaa Don't store MTPInputStickerSet in data. 2021-07-08 22:08:59 +03:00
23rd
9dfb43d525 Fixed build for macOS and Linux. 2021-07-08 20:18:40 +03:00
Ilya Fedin
3b07785f87 Optimize pasting with gtk 2021-07-08 18:58:40 +03:00
John Preston
f22e68fc32 Don't use MTP* for PeerSettings flags. 2021-07-08 17:32:39 +03:00
John Preston
878c890bc2 Bump version to 2.8.7.beta for serialization. 2021-07-08 16:11:30 +03:00
John Preston
a74228acea Don't use MTP* for ChannelData flags. 2021-07-08 16:11:09 +03:00
John Preston
5040c2e766 Don't use MTP* for ChatData flags. 2021-07-08 15:11:46 +03:00
John Preston
e34375405e Don't use MTP* for UserData flags. 2021-07-08 14:19:12 +03:00
John Preston
2ffda9f240 Don't use MTP* for ChatAdminRight / ChatRestriction. 2021-07-08 13:34:06 +03:00
23rd
8e73a6a6ff Fixed Github CI Windows build. 2021-07-07 19:31:36 +03:00
John Preston
b642a80cd8 Fix timers race condition on Windows. 2021-07-07 17:57:31 +03:00
John Preston
94bdae13d8 Fix Qt build instructions on Windows. 2021-07-07 17:29:20 +03:00
Ilya Fedin
ee773a28bb Fix 30s freeze after pasting 2021-07-07 16:40:09 +03:00
John Preston
caddb44a2c Update tg_owt revision. 2021-07-07 16:39:26 +03:00
Ilya Fedin
1b4216803d Add snap permission to own name for gtk integration IPC 2021-07-07 14:26:33 +03:00
Ilya Fedin
17cee8ec56 Set service name for lib_base and lib_webview gtk integration 2021-07-07 12:16:01 +03:00
342 changed files with 4819 additions and 4637 deletions

View File

@@ -104,6 +104,7 @@ jobs:
shell: bash
run: |
curl -o $LibrariesPath/tg_owt-version.json https://api.github.com/repos/desktop-app/tg_owt/git/refs/heads/master
curl -o $LibrariesPath/tg_angle-version.json https://api.github.com/repos/desktop-app/tg_angle/git/refs/heads/master
echo $MANUAL_CACHING >> CACHE_KEY.txt
if [ "$AUTO_CACHING" == "1" ]; then
thisFile=$REPO_NAME/.github/workflows/win.yml
@@ -316,6 +317,33 @@ jobs:
rmdir /S /Q .git
- name: Angle cache.
id: cache-angle
uses: actions/cache@v2
with:
path: ${{ env.LibrariesPath }}/tg_angle
key: ${{ runner.OS }}-angle-${{ env.CACHE_KEY }}-${{ hashFiles('**/tg_angle-version.json') }}
- name: Angle.
if: steps.cache-angle.outputs.cache-hit != 'true'
run: |
%VC%
git clone --recursive %GIT%/desktop-app/tg_angle.git
mkdir tg_angle\out\Debug
cd tg_angle\out\Debug
cmake -G Ninja ^
-DCMAKE_BUILD_TYPE=Debug ^
-DTG_ANGLE_SPECIAL_TARGET=win64 ^
-DTG_ANGLE_ZLIB_INCLUDE_PATH=%cd%/../../../zlib ../..
ninja
:: Cleanup.
cd %LibrariesPath%\tg_angle
move out\Debug\tg_angle.lib tg_angle.lib
rmdir /S /Q out
mkdir out\Debug
move tg_angle.lib out\Debug\tg_angle.lib
- name: Qt 5.15.2 cache.
id: cache-qt
uses: actions/cache@v2
@@ -338,7 +366,12 @@ jobs:
cd ..
SET SSL=%LibrariesPath%\openssl_%OPENSSL_VER%
SET LIBS=libcrypto.lib Ws2_32.lib Gdi32.lib Advapi32.lib Crypt32.lib User32.lib
SET SSL_LIBS=libcrypto.lib Ws2_32.lib Gdi32.lib Advapi32.lib Crypt32.lib User32.lib
SET ANGLE=%LibrariesPath%\tg_angle
SET ANGLE_LIBS=d3d9.lib dxgi.lib dxguid.lib
SET ZLIB=%LibrariesPath%\zlib\contrib\vstudio\vc14\x86
configure ^
-prefix "%LibrariesPath%\Qt-%QT_VER%" ^
@@ -347,18 +380,29 @@ jobs:
-opensource ^
-confirm-license ^
-static ^
-static-runtime -I "%SSL%\include" ^
-opengl dynamic ^
-static-runtime ^
-opengl es2 -no-angle ^
-I "%ANGLE%\include" ^
-D "GL_APICALL=" ^
QMAKE_LIBS_OPENGL_ES2_DEBUG="%ANGLE%\out\Debug\tg_angle.lib %ZLIB%\ZlibStatDebug\zlibstat.lib %ANGLE_LIBS%" ^
QMAKE_LIBS_OPENGL_ES2_RELEASE="%ANGLE%\out\Release\tg_angle.lib %ZLIB%\ZlibStatReleaseWithoutAsm\zlibstat.lib %ANGLE_LIBS%" ^
-egl ^
-D "EGLAPI=" ^
-D "DESKTOP_APP_QT_STATIC_ANGLE=" ^
QMAKE_LIBS_EGL_DEBUG="%ANGLE%\out\Debug\tg_angle.lib %ZLIB%\ZlibStatDebug\zlibstat.lib %ANGLE_LIBS% Gdi32.lib User32.lib" ^
QMAKE_LIBS_EGL_RELEASE="%ANGLE%\out\Release\tg_angle.lib %ZLIB%\ZlibStatReleaseWithoutAsm\zlibstat.lib %ANGLE_LIBS% Gdi32.lib User32.lib" ^
-openssl-linked ^
OPENSSL_LIBS_DEBUG="%SSL%\out32.dbg\libssl.lib %SSL%\out32.dbg\%LIBS%" ^
OPENSSL_LIBS_RELEASE="%SSL%\out32\libssl.lib %SSL%\out32\%LIBS%" ^
-I "%SSL%\include" ^
OPENSSL_LIBS_DEBUG="%SSL%\out32.dbg\libssl.lib %SSL%\out32.dbg\%SSL_LIBS%" ^
OPENSSL_LIBS_RELEASE="%SSL%\out32\libssl.lib %SSL%\out32\%SSL_LIBS%" ^
-I "%LibrariesPath%\mozjpeg" ^
LIBJPEG_LIBS_DEBUG="%LibrariesPath%\mozjpeg\Debug\jpeg-static.lib" ^
LIBJPEG_LIBS_RELEASE="%LibrariesPath%\mozjpeg\Release\jpeg-static.lib" ^
-mp ^
-nomake examples ^
-nomake tests ^
-platform win32-msvc ^
-I "%LibrariesPath%\mozjpeg" ^
LIBJPEG_LIBS_DEBUG="%LibrariesPath%\mozjpeg\Debug\jpeg-static.lib" ^
LIBJPEG_LIBS_RELEASE="%LibrariesPath%\mozjpeg\Release\jpeg-static.lib"
-platform win32-msvc
- name: Qt 5.15.2 build.
if: steps.cache-qt.outputs.cache-hit != 'true'
run: |

View File

@@ -525,6 +525,7 @@ PRIVATE
editor/photo_editor_content.h
editor/photo_editor_controls.cpp
editor/photo_editor_controls.h
editor/photo_editor_inner_common.h
editor/photo_editor_layer_widget.cpp
editor/photo_editor_layer_widget.h
editor/scene/scene.cpp
@@ -1068,6 +1069,10 @@ PRIVATE
support/support_helper.h
support/support_templates.cpp
support/support_templates.h
ui/chat/attach/attach_item_single_file_preview.cpp
ui/chat/attach/attach_item_single_file_preview.h
ui/chat/attach/attach_item_single_media_preview.cpp
ui/chat/attach/attach_item_single_media_preview.h
ui/effects/fireworks_animation.cpp
ui/effects/fireworks_animation.h
ui/effects/round_checkbox.cpp

View File

@@ -2021,6 +2021,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_screen_share_start" = "Share Screen";
"lng_group_call_screen_share_stop" = "Stop Sharing";
"lng_group_call_screen_title" = "Screen {index}";
"lng_group_call_screen_share_audio" = "Share System Audio";
"lng_group_call_unmute_small" = "Unmute";
"lng_group_call_more" = "More";
"lng_group_call_unmute" = "Unmute";

View File

@@ -376,6 +376,7 @@ updateChatParticipant#f3b3781f flags:# chat_id:int date:int actor_id:int user_id
updateChannelParticipant#7fecb1ec flags:# channel_id:int date:int actor_id:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant invite:flags.2?ExportedChatInvite qts:int = Update;
updateBotStopped#7f9488a user_id:int date:int stopped:Bool qts:int = Update;
updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJSON = Update;
updateBotCommands#cf7e0873 peer:Peer bot_id:int commands:Vector<BotCommand> = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@@ -534,7 +535,7 @@ authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true pa
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
account.password#ad2641f8 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes = account.Password;
account.password#185b184f flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int = account.Password;
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
@@ -1205,7 +1206,7 @@ peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
groupCall#653dbaad flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int version:int = GroupCall;
groupCall#d597650c flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int = GroupCall;
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
@@ -1248,7 +1249,7 @@ phone.exportedGroupCallInvite#204bd158 link:string = phone.ExportedGroupCallInvi
groupCallParticipantVideoSourceGroup#dcb118b7 semantics:string sources:Vector<int> = GroupCallParticipantVideoSourceGroup;
groupCallParticipantVideo#78e41663 flags:# paused:flags.0?true endpoint:string source_groups:Vector<GroupCallParticipantVideoSourceGroup> = GroupCallParticipantVideo;
groupCallParticipantVideo#67753ac8 flags:# paused:flags.0?true endpoint:string source_groups:Vector<GroupCallParticipantVideoSourceGroup> audio_source:flags.1?int = GroupCallParticipantVideo;
stickers.suggestedShortName#85fea03f short_name:string = stickers.SuggestedShortName;
@@ -1260,6 +1261,10 @@ botCommandScopePeer#db9d897d peer:InputPeer = BotCommandScope;
botCommandScopePeerAdmins#3fd863d1 peer:InputPeer = BotCommandScope;
botCommandScopePeerUser#a1321f3 peer:InputPeer user_id:InputUser = BotCommandScope;
account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordResult;
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -1281,13 +1286,14 @@ auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int en
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
auth.checkPassword#d18b4d16 password:InputCheckPasswordSRP = auth.Authorization;
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
auth.recoverPassword#37096c70 flags:# code:string new_settings:flags.0?account.PasswordInputSettings = auth.Authorization;
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
auth.exportLoginToken#b1b41517 api_id:int api_hash:string except_ids:Vector<int> = auth.LoginToken;
auth.importLoginToken#95ac5ce4 token:bytes = auth.LoginToken;
auth.acceptLoginToken#e894ad4d token:bytes = Authorization;
auth.checkRecoveryPassword#d36bf79 code:string = Bool;
account.registerDevice#68976c6f flags:# no_muted:flags.0?true token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
@@ -1357,6 +1363,8 @@ account.getMultiWallPapers#65ad71dc wallpapers:Vector<InputWallPaper> = Vector<W
account.getGlobalPrivacySettings#eb2b4cf6 = GlobalPrivacySettings;
account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = GlobalPrivacySettings;
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
account.resetPassword#9308ce1b = account.ResetPasswordResult;
account.declinePasswordReset#4c9409f6 = Bool;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
@@ -1670,4 +1678,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 130
// LAYER 131

View File

@@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="2.8.6.0" />
Version="2.8.11.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 2,8,6,0
PRODUCTVERSION 2,8,6,0
FILEVERSION 2,8,11,0
PRODUCTVERSION 2,8,11,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "2.8.6.0"
VALUE "FileVersion", "2.8.11.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.8.6.0"
VALUE "ProductVersion", "2.8.11.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,8,6,0
PRODUCTVERSION 2,8,6,0
FILEVERSION 2,8,11,0
PRODUCTVERSION 2,8,11,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", "2.8.6.0"
VALUE "FileVersion", "2.8.11.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.8.6.0"
VALUE "ProductVersion", "2.8.11.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -52,8 +52,10 @@ void AttachedStickers::request(
});
const auto setId = (setData->vid().v && setData->vaccess_hash().v)
? MTP_inputStickerSetID(setData->vid(), setData->vaccess_hash())
: MTP_inputStickerSetShortName(setData->vshort_name());
? StickerSetIdentifier{
.id = setData->vid().v,
.accessHash = setData->vaccess_hash().v }
: StickerSetIdentifier{ .shortName = qs(setData->vshort_name()) };
strongController->show(
Box<StickerSetBox>(strongController, setId),
Ui::LayerOption::KeepOther);

View File

@@ -156,7 +156,6 @@ void SendBotCallbackDataWithPassword(
const auto session = &history->session();
const auto owner = &history->owner();
const auto api = &session->api();
const auto bot = item->getMessageBot();
const auto fullId = item->fullId();
const auto getButton = [=] {
return HistoryMessageMarkupButton::Get(

View File

@@ -40,6 +40,7 @@ namespace {
int32 CountStickersHash(
not_null<Main::Session*> session,
bool checkOutdatedInfo) {
using Flag = Data::StickersSetFlag;
auto result = HashInit();
bool foundOutdated = false;
const auto &sets = session->data().stickers().sets();
@@ -50,8 +51,8 @@ int32 CountStickersHash(
const auto set = it->second.get();
if (set->id == Data::Stickers::DefaultSetId) {
foundOutdated = true;
} else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special)
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) {
} else if (!(set->flags & Flag::Special)
&& !(set->flags & Flag::Archived)) {
HashUpdate(result, set->hash);
}
}
@@ -84,7 +85,7 @@ int32 CountFeaturedStickersHash(not_null<Main::Session*> session) {
const auto it = sets.find(setId);
if (it != sets.cend()
&& (it->second->flags & MTPDstickerSet_ClientFlag::f_unread)) {
&& (it->second->flags & Data::StickersSetFlag::Unread)) {
HashUpdate(result, 1);
}
}

View File

@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_media.h"
#include "data/data_document.h"
#include "data/stickers/data_stickers_set.h"
#include "history/history_item.h"
namespace Api {
@@ -47,7 +48,7 @@ MTPVector<MTPDocumentAttribute> ComposeSendingDocumentAttributes(
attributes.push_back(MTP_documentAttributeSticker(
MTP_flags(0),
MTP_string(document->sticker()->alt),
document->sticker()->set,
Data::InputStickerSet(document->sticker()->set),
MTPMaskCoords()));
} else if (const auto song = document->song()) {
const auto flags = MTPDdocumentAttributeAudio::Flag::f_title

View File

@@ -474,7 +474,6 @@ void Updates::differenceDone(const MTPupdates_Difference &result) {
stateDone(d.vstate());
} break;
case mtpc_updates_differenceTooLong: {
auto &d = result.c_updates_differenceTooLong();
LOG(("API Error: updates.differenceTooLong is not supported by Telegram Desktop!"));
} break;
};
@@ -999,8 +998,8 @@ void Updates::handleSendActionUpdate(
const auto chat = peer->asChat();
const auto channel = peer->asChannel();
const auto active = chat
? (chat->flags() & MTPDchat::Flag::f_call_active)
: (channel->flags() & MTPDchannel::Flag::f_call_active);
? (chat->flags() & ChatDataFlag::CallActive)
: (channel->flags() & ChannelDataFlag::CallActive);
if (active) {
_pendingSpeakingCallParticipants.emplace(
peer).first->second[fromId] = now;
@@ -1030,9 +1029,6 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
const auto &d = updates.c_updateShortMessage();
const auto flags = mtpCastFlags(d.vflags().v)
| MTPDmessage::Flag::f_from_id;
const auto peerUserId = d.is_out()
? d.vuser_id()
: MTP_int(_session->userId().bare); // #TODO ids
_session->data().addNewMessage(
MTP_message(
MTP_flags(flags),
@@ -1250,7 +1246,6 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updatePinnedMessages: {
const auto &d = update.c_updatePinnedMessages();
const auto peerId = peerFromMTP(d.vpeer());
for (const auto &msgId : d.vmessages().v) {
const auto item = session().data().message(0, msgId.v);
if (item) {
@@ -1607,7 +1602,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
history->setUnreadMark(data.is_unread());
}
}, [&](const MTPDdialogPeerFolder &dialog) {
const auto id = dialog.vfolder_id().v; // #TODO archive
//const auto id = dialog.vfolder_id().v; // #TODO archive
//if (const auto folder = session().data().folderLoaded(id)) {
// folder->setUnreadMark(data.is_unread());
//}
@@ -1817,11 +1812,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
const auto &d = update.c_updatePeerSettings();
const auto peerId = peerFromMTP(d.vpeer());
if (const auto peer = session().data().peerLoaded(peerId)) {
const auto settings = d.vsettings().match([](
const MTPDpeerSettings &data) {
return data.vflags().v;
});
peer->setSettings(settings);
peer->setSettings(d.vsettings());
}
} break;
@@ -1872,19 +1863,15 @@ void Updates::feedUpdate(const MTPUpdate &update) {
} break;
case mtpc_updateNewEncryptedMessage: {
auto &d = update.c_updateNewEncryptedMessage();
} break;
case mtpc_updateEncryptedChatTyping: {
auto &d = update.c_updateEncryptedChatTyping();
} break;
case mtpc_updateEncryption: {
auto &d = update.c_updateEncryption();
} break;
case mtpc_updateEncryptedMessagesRead: {
auto &d = update.c_updateEncryptedMessagesRead();
} break;
case mtpc_updatePhoneCall:
@@ -1902,6 +1889,26 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
} break;
case mtpc_updateBotCommands: {
const auto &d = update.c_updateBotCommands();
if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) {
const auto botId = UserId(d.vbot_id().v);
if (const auto user = peer->asUser()) {
if (user->isBot() && user->id == peerFromUser(botId)) {
if (Data::UpdateBotCommands(user->botInfo->commands, d.vcommands())) {
session().data().botCommandsChanged(user);
}
}
} else if (const auto chat = peer->asChat()) {
chat->setBotCommands(botId, d.vcommands());
} else if (const auto megagroup = peer->asMegagroup()) {
if (megagroup->mgInfo->updateBotCommands(botId, d.vcommands())) {
session().data().botCommandsChanged(megagroup);
}
}
}
} break;
case mtpc_updateServiceNotification: {
const auto &d = update.c_updateServiceNotification();
const auto text = TextWithEntities {

View File

@@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_cloud_themes.h"
#include "data/data_chat_filters.h"
#include "data/data_histories.h"
#include "data/data_wall_paper.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/dialogs_key.h"
#include "core/core_cloud_password.h"
@@ -62,7 +63,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/notifications_manager.h"
#include "window/window_lock_widgets.h"
#include "window/window_session_controller.h"
#include "window/themes/window_theme.h"
#include "inline_bots/inline_bot_result.h"
#include "chat_helpers/message_field.h"
#include "ui/item_text_options.h"
@@ -1224,9 +1224,7 @@ void ApiWrap::requestPeerSettings(not_null<PeerData*> peer) {
request(MTPmessages_GetPeerSettings(
peer->input
)).done([=](const MTPPeerSettings &result) {
peer->setSettings(result.match([&](const MTPDpeerSettings &data) {
return data.vflags().v;
}));
peer->setSettings(result);
_requestedPeerSettings.erase(peer);
}).fail([=](const MTP::Error &error) {
_requestedPeerSettings.erase(peer);
@@ -1526,7 +1524,6 @@ void ApiWrap::applyLastParticipantsList(
| MegagroupInfo::LastParticipantsOnceReceived;
auto botStatus = channel->mgInfo->botStatus;
const auto emptyAdminRights = MTP_chatAdminRights(MTP_flags(0));
for (const auto &p : list) {
const auto participantId = p.match([](
const MTPDchannelParticipantBanned &data) {
@@ -1547,13 +1544,14 @@ void ApiWrap::applyLastParticipantsList(
? channel->amCreator()
: false;
const auto adminRights = (p.type() == mtpc_channelParticipantAdmin)
? p.c_channelParticipantAdmin().vadmin_rights()
? ChatAdminRightsInfo(p.c_channelParticipantAdmin().vadmin_rights())
: (p.type() == mtpc_channelParticipantCreator)
? p.c_channelParticipantCreator().vadmin_rights()
: emptyAdminRights;
? ChatAdminRightsInfo(p.c_channelParticipantCreator().vadmin_rights())
: ChatAdminRightsInfo();
const auto restrictedRights = (p.type() == mtpc_channelParticipantBanned)
? p.c_channelParticipantBanned().vbanned_rights()
: ChannelData::EmptyRestrictedRights(participant);
? ChatRestrictionsInfo(
p.c_channelParticipantBanned().vbanned_rights())
: ChatRestrictionsInfo();
if (p.type() == mtpc_channelParticipantCreator) {
Assert(user != nullptr);
const auto &creator = p.c_channelParticipantCreator();
@@ -1569,11 +1567,11 @@ void ApiWrap::applyLastParticipantsList(
if (user
&& !base::contains(channel->mgInfo->lastParticipants, user)) {
channel->mgInfo->lastParticipants.push_back(user);
if (adminRights.c_chatAdminRights().vflags().v) {
if (adminRights.flags) {
channel->mgInfo->lastAdmins.emplace(
user,
MegagroupInfo::Admin{ adminRights, adminCanEdit });
} else if (Data::ChatBannedRightsFlags(restrictedRights) != 0) {
} else if (restrictedRights.flags) {
channel->mgInfo->lastRestricted.emplace(
user,
MegagroupInfo::Restricted{ restrictedRights });
@@ -1731,7 +1729,7 @@ void ApiWrap::kickParticipant(
void ApiWrap::kickParticipant(
not_null<ChannelData*> channel,
not_null<PeerData*> participant,
const MTPChatBannedRights &currentRights) {
ChatRestrictionsInfo currentRights) {
const auto kick = KickRequest(channel, participant);
if (_kickRequests.contains(kick)) return;
@@ -1739,7 +1737,10 @@ void ApiWrap::kickParticipant(
const auto requestId = request(MTPchannels_EditBanned(
channel->inputChannel,
participant->input,
rights
MTP_chatBannedRights(
MTP_flags(
MTPDchatBannedRights::Flags::from_raw(uint32(rights.flags))),
MTP_int(rights.until))
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
@@ -1763,7 +1764,7 @@ void ApiWrap::unblockParticipant(
const auto requestId = request(MTPchannels_EditBanned(
channel->inputChannel,
participant->input,
ChannelData::EmptyRestrictedRights(participant)
MTP_chatBannedRights(MTP_flags(0), MTP_int(0))
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
@@ -1945,9 +1946,7 @@ void ApiWrap::saveStickerSets(
? _session->data().stickers().maskSetsOrderRef()
: _session->data().stickers().setsOrderRef();
using Flag = MTPDstickerSet::Flag;
using ClientFlag = MTPDstickerSet_ClientFlag;
using Flag = Data::StickersSetFlag;
for (const auto removedSetId : localRemoved) {
if ((removedSetId == Data::Stickers::CloudRecentSetId)
|| (removedSetId == Data::Stickers::CloudRecentAttachedSetId)) {
@@ -1999,10 +1998,10 @@ void ApiWrap::saveStickerSets(
++i;
}
}
const auto archived = !!(set->flags & Flag::f_archived);
const auto archived = !!(set->flags & Flag::Archived);
if (!archived) {
const auto featured = !!(set->flags & ClientFlag::f_featured);
const auto special = !!(set->flags & ClientFlag::f_special);
const auto featured = !!(set->flags & Flag::Featured);
const auto special = !!(set->flags & Flag::Special);
const auto setId = set->mtpInput();
auto requestId = request(MTPmessages_UninstallStickerSet(
@@ -2025,8 +2024,7 @@ void ApiWrap::saveStickerSets(
if (archived) {
writeArchived = true;
}
set->flags &= ~(Flag::f_installed_date
| Flag::f_archived);
set->flags &= ~(Flag::Installed | Flag::Archived);
set->installDate = TimeId(0);
}
}
@@ -2035,10 +2033,10 @@ void ApiWrap::saveStickerSets(
// Clear all installed flags, set only for sets from order.
for (auto &[id, set] : sets) {
const auto archived = !!(set->flags & Flag::f_archived);
const auto masks = !!(set->flags & MTPDstickerSet::Flag::f_masks);
const auto archived = !!(set->flags & Flag::Archived);
const auto masks = !!(set->flags & Flag::Masks);
if (!archived && (setsMasks == masks)) {
set->flags &= ~Flag::f_installed_date;
set->flags &= ~Flag::Installed;
}
}
@@ -2049,7 +2047,7 @@ void ApiWrap::saveStickerSets(
continue;
}
const auto set = it->second.get();
const auto archived = !!(set->flags & Flag::f_archived);
const auto archived = !!(set->flags & Flag::Archived);
if (archived && !localRemoved.contains(set->id)) {
const auto mtpSetId = set->mtpInput();
@@ -2068,11 +2066,11 @@ void ApiWrap::saveStickerSets(
setDisenableRequests.insert(requestId);
set->flags &= ~Flag::f_archived;
set->flags &= ~Flag::Archived;
writeArchived = true;
}
orderRef.push_back(setId);
set->flags |= Flag::f_installed_date;
set->flags |= Flag::Installed;
if (!set->installDate) {
set->installDate = base::unixtime::now();
}
@@ -2080,10 +2078,10 @@ void ApiWrap::saveStickerSets(
for (auto it = sets.begin(); it != sets.cend();) {
const auto set = it->second.get();
if ((set->flags & ClientFlag::f_featured)
|| (set->flags & Flag::f_installed_date)
|| (set->flags & Flag::f_archived)
|| (set->flags & ClientFlag::f_special)) {
if ((set->flags & Flag::Featured)
|| (set->flags & Flag::Installed)
|| (set->flags & Flag::Archived)
|| (set->flags & Flag::Special)) {
++it;
} else {
it = sets.erase(it);
@@ -3027,11 +3025,16 @@ void ApiWrap::requestRecentStickersForce(bool attached) {
requestRecentStickersWithHash(0, attached);
}
void ApiWrap::setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInputStickerSet &set) {
void ApiWrap::setGroupStickerSet(
not_null<ChannelData*> megagroup,
const StickerSetIdentifier &set) {
Expects(megagroup->mgInfo != nullptr);
megagroup->mgInfo->stickerSet = set;
request(MTPchannels_SetStickers(megagroup->inputChannel, set)).send();
request(MTPchannels_SetStickers(
megagroup->inputChannel,
Data::InputStickerSet(set)
)).send();
_session->data().stickers().notifyUpdated();
}
@@ -3297,7 +3300,7 @@ void ApiWrap::readFeaturedSets() {
for (const auto setId : _featuredSetsRead) {
const auto it = sets.find(setId);
if (it != sets.cend()) {
it->second->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
it->second->flags &= ~Data::StickersSetFlag::Unread;
wrappedIds.append(MTP_long(setId));
if (count) {
--count;
@@ -3871,7 +3874,6 @@ void ApiWrap::forwardMessages(
}
}
const auto newFrom = item->history()->peer;
const auto newGroupId = item->groupId();
if (forwardFrom != newFrom) {
sendAccumulated();
forwardFrom = newFrom;

View File

@@ -20,6 +20,7 @@ struct MessageGroupId;
struct SendingAlbum;
enum class SendMediaType;
struct FileLoadTo;
struct ChatRestrictionsInfo;
namespace Main {
class Session;
@@ -107,7 +108,7 @@ QString RequestKey(Types &&...values) {
} // namespace Api
class ApiWrap : public MTP::Sender, private base::Subscriber {
class ApiWrap final : public MTP::Sender {
public:
using SendAction = Api::SendAction;
using MessageToSend = Api::MessageToSend;
@@ -264,7 +265,7 @@ public:
void kickParticipant(
not_null<ChannelData*> channel,
not_null<PeerData*> participant,
const MTPChatBannedRights &currentRights);
ChatRestrictionsInfo currentRights);
void unblockParticipant(
not_null<ChannelData*> channel,
not_null<PeerData*> participant);
@@ -287,7 +288,7 @@ public:
void requestRecentStickersForce(bool attached = false);
void setGroupStickerSet(
not_null<ChannelData*> megagroup,
const MTPInputStickerSet &set);
const StickerSetIdentifier &set);
std::vector<not_null<DocumentData*>> *stickersByEmoji(
not_null<EmojiPtr> emoji);

View File

@@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_location_manager.h"
#include "history/history_item_components.h"
#include "history/view/history_view_service_message.h"
#include "history/view/history_view_element.h"
#include "media/audio/media_audio.h"
#include "ui/image/image.h"
#include "ui/cached_round_corners.h"
@@ -28,7 +28,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/update_checker.h"
#include "core/sandbox.h"
#include "core/application.h"
#include "window/themes/window_theme.h"
#include "window/notifications_manager.h"
#include "window/window_controller.h"
#include "platform/platform_notifications_manager.h"
@@ -99,16 +98,6 @@ namespace App {
void initMedia() {
Ui::StartCachedCorners();
using Update = Window::Theme::BackgroundUpdate;
static auto subscription = Window::Theme::Background()->add_subscription([](const Update &update) {
if (update.paletteChanged()) {
if (const auto m = App::main()) { // multi good
m->updateScrollColors();
}
HistoryView::serviceColorsUpdated();
}
});
}
void deinitMedia() {

View File

@@ -158,7 +158,7 @@ void ShowAddParticipantsError(
auto box = Box<EditAdminBox>(
channel,
user,
MTP_chatAdminRights(MTP_flags(0)),
ChatAdminRightsInfo(),
QString());
box->setSaveCallback(saveCallback);
*weak = Ui::show(std::move(box));

View File

@@ -145,9 +145,7 @@ private:
};
class SetupChannelBox final
: public Ui::BoxContent
, private base::Subscriber {
class SetupChannelBox final : public Ui::BoxContent {
public:
SetupChannelBox(
QWidget*,
@@ -244,9 +242,7 @@ private:
};
class RevokePublicLinkBox final
: public Ui::BoxContent
, private base::Subscriber {
class RevokePublicLinkBox final : public Ui::BoxContent {
public:
RevokePublicLinkBox(
QWidget*,

View File

@@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/background_preview_box.h"
#include "boxes/confirm_box.h"
#include "window/window_session_controller.h"
#include "window/themes/window_theme.h"
#include "styles/style_overview.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@@ -55,9 +56,7 @@ QImage TakeMiddleSample(QImage original, QSize size) {
} // namespace
class BackgroundBox::Inner final
: public Ui::RpWidget
, private base::Subscriber {
class BackgroundBox::Inner final : public Ui::RpWidget {
public:
Inner(
QWidget *parent,
@@ -203,16 +202,22 @@ BackgroundBox::Inner::Inner(
) | rpl::start_with_next([=] {
update();
}, lifetime());
style::PaletteChanged(
) | rpl::start_with_next([=] {
_check->invalidateCache();
}, lifetime());
using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [=](const Update &update) {
if (update.paletteChanged()) {
_check->invalidateCache();
} else if (update.type == Update::Type::New) {
Window::Theme::Background()->updates(
) | rpl::start_with_next([=](const Update &update) {
if (update.type == Update::Type::New) {
sortPapers();
requestPapers();
this->update();
}
});
}, lifetime());
setMouseTracking(true);
}

View File

@@ -99,12 +99,10 @@ private:
};
ServiceCheck::Generator::Generator() {
*_lifetime.make_state<base::Subscription>() = Window::Theme::Background(
)->add_subscription([=](const Window::Theme::BackgroundUpdate &update) {
if (update.paletteChanged()) {
invalidate();
}
});
style::PaletteChanged(
) | rpl::start_with_next([=] {
invalidate();
}, _lifetime);
}
auto ServiceCheck::Generator::framesForStyle(

View File

@@ -9,11 +9,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
#include "base/binary_guard.h"
#include "window/themes/window_theme.h"
#include "history/admin_log/history_admin_log_item.h"
#include "history/view/history_view_element.h"
#include "ui/effects/animations.h"
#include "ui/effects/radial_animation.h"
#include "data/data_wall_paper.h"
namespace Data {
class DocumentMedia;
@@ -29,8 +29,7 @@ class Checkbox;
class BackgroundPreviewBox
: public Ui::BoxContent
, private HistoryView::SimpleElementDelegate
, private base::Subscriber {
, private HistoryView::SimpleElementDelegate {
public:
BackgroundPreviewBox(
QWidget*,

View File

@@ -901,7 +901,7 @@ void DeleteMessagesBox::deleteAndClear() {
_moderateInChannel->session().api().kickParticipant(
_moderateInChannel,
_moderateFrom,
ChannelData::EmptyRestrictedRights(_moderateFrom));
ChatRestrictionsInfo());
}
if (_reportSpam->checked()) {
_moderateInChannel->session().api().request(

View File

@@ -141,7 +141,7 @@ public:
};
class MaxInviteBox : public Ui::BoxContent, private base::Subscriber {
class MaxInviteBox final : public Ui::BoxContent {
public:
MaxInviteBox(QWidget*, not_null<ChannelData*> channel);

View File

@@ -436,7 +436,6 @@ void Options::Option::updateFieldGeometry() {
const auto skip = st::defaultRadio.diameter
+ st::defaultCheckbox.textPosition.x();
const auto left = anim::interpolate(0, skip, shown);
const auto width = _content->width() - left;
_field->resizeToWidth(_content->width() - left);
_field->moveToLeft(left, 0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "boxes/abstract_box.h"
#include "storage/storage_media_prepare.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/chat/attach/attach_prepare.h"
class Image;
namespace ChatHelpers {
class TabbedPanel;
} // namespace ChatHelpers
@@ -23,36 +19,19 @@ class SessionController;
} // namespace Window
namespace Data {
class Media;
class PhotoMedia;
class DocumentMedia;
} // namespace Data
namespace Ui {
class AbstractButton;
class AbstractSinglePreview;
class InputField;
class EmojiButton;
class IconButton;
class Checkbox;
class VerticalLayout;
class FadeShadow;
enum class AlbumType;
class AttachControlsWidget;
} // namespace Ui
namespace Window {
class SessionController;
} // namespace Window
namespace Media {
namespace Streaming {
class Instance;
class Document;
struct Update;
enum class Error;
struct Information;
} // namespace Streaming
} // namespace Media
class EditCaptionBox final : public Ui::BoxContent, private base::Subscriber {
class EditCaptionBox final : public Ui::BoxContent {
public:
EditCaptionBox(
QWidget*,
@@ -69,15 +48,15 @@ protected:
void keyPressEvent(QKeyEvent *e) override;
private:
void rebuildPreview();
void setupEditEventHandler();
void setupPhotoEditorEventHandler();
void setupShadows();
void setupField();
void setupControls();
void updateBoxSize();
void prepareStreamedPreview();
void checkStreamedIsStarted();
void setupStreamedPreview(
std::shared_ptr<::Media::Streaming::Document> shared);
void handleStreamingUpdate(::Media::Streaming::Update &&update);
void handleStreamingError(::Media::Streaming::Error &&error);
void streamingReady(::Media::Streaming::Information &&info);
void startStreamedPlayer();
void captionResized();
void setupEmojiPanel();
void updateEmojiPanelGeometry();
@@ -86,74 +65,43 @@ private:
void setupDragArea();
void save();
void captionResized();
void setName(QString nameString, qint64 size);
bool fileFromClipboard(not_null<const QMimeData*> data);
void updateEditPreview();
void updateEditMediaButton();
void updateCaptionMaxHeight();
int errorTopSkip() const;
void createEditMediaButton();
bool setPreparedList(Ui::PreparedList &&list);
bool isThumbedLayout() const;
inline QString getNewMediaPath() {
return _preparedList.files.empty()
? QString()
: _preparedList.files.front().path;
}
const not_null<Window::SessionController*> _controller;
const not_null<HistoryItem*> _historyItem;
const bool _isAllowedEditMedia = false;
const Ui::AlbumType _albumType;
FullMsgId _msgId;
std::shared_ptr<Data::PhotoMedia> _photoMedia;
std::shared_ptr<Data::DocumentMedia> _documentMedia;
bool _thumbnailImageLoaded = false;
Fn<void()> _refreshThumbnail;
bool _animated = false;
bool _photo = false;
bool _doc = false;
const base::unique_qptr<Ui::VerticalLayout> _controls;
const base::unique_qptr<Ui::ScrollArea> _scroll;
const base::unique_qptr<Ui::InputField> _field;
const base::unique_qptr<Ui::EmojiButton> _emojiToggle;
const base::unique_qptr<Ui::FadeShadow> _topShadow,_bottomShadow;
QPixmap _thumb;
std::unique_ptr<::Media::Streaming::Instance> _streamed;
object_ptr<Ui::InputField> _field = { nullptr };
object_ptr<Ui::EmojiButton> _emojiToggle = { nullptr };
base::unique_qptr<Ui::AbstractSinglePreview> _content;
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
base::unique_qptr<QObject> _emojiFilter;
base::unique_qptr<Ui::AbstractButton> _photoEditorButton;
int _thumbx = 0;
int _thumbw = 0;
int _thumbh = 0;
Ui::Text::String _name;
QString _status;
bool _isAudio = false;
bool _isImage = false;
int _gifw = 0;
int _gifh = 0;
int _gifx = 0;
std::shared_ptr<Data::PhotoMedia> _photoMedia;
Ui::PreparedList _preparedList;
mtpRequestId _saveRequestId = 0;
object_ptr<Ui::AttachControlsWidget> _editMedia = nullptr;
object_ptr<Ui::IconButton> _editFile = nullptr;
Ui::SlideWrap<Ui::RpWidget> *_wayWrap = nullptr;
Ui::SlideWrap<Ui::RpWidget> *_hintLabel = nullptr;
QString _newMediaPath;
Ui::AlbumType _albumType = Ui::AlbumType();
bool _isAllowedEditMedia = false;
bool _asFile = false;
rpl::event_stream<> _editMediaClicks;
rpl::event_stream<> _photoEditorOpens;
QString _error;
rpl::variable<bool> _isPhoto = false;
rpl::variable<int> _footerHeight = 0;
rpl::event_stream<> _editMediaClicks;
rpl::event_stream<> _photoEditorOpens;
rpl::event_stream<int> _contentHeight;
};

View File

@@ -216,7 +216,6 @@ std::pair<Languages, Languages> PrepareLists() {
Lang::GetInstance().nativeName()
};
};
const auto i = ranges::find(official, current, projId);
recent.insert(begin(recent), generate());
}
}

View File

@@ -516,7 +516,7 @@ void LocalStorageBox::updateMediaLabel() {
}
void LocalStorageBox::setupLimits(not_null<Ui::VerticalLayout*> container) {
const auto shadow = container->add(
container->add(
object_ptr<Ui::PlainShadow>(container),
st::localStorageRowPadding);

View File

@@ -1062,7 +1062,9 @@ void RecoverBox::submit() {
const auto send = crl::guard(this, [=] {
_submitRequest = _api.request(MTPauth_RecoverPassword(
MTP_string(code)
MTP_flags(0),
MTP_string(code),
MTPaccount_PasswordInputSettings()
)).done([=](const MTPauth_Authorization &result) {
codeSubmitDone(result);
}).fail([=](const MTP::Error &error) {

View File

@@ -25,7 +25,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_changes.h"
#include "base/unixtime.h"
#include "window/themes/window_theme.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_dialogs.h"
@@ -738,11 +737,11 @@ PeerListContent::PeerListContent(
}
}, lifetime());
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
if (update.paletteChanged()) {
invalidatePixmapsCache();
}
});
style::PaletteChanged(
) | rpl::start_with_next([=] {
invalidatePixmapsCache();
}, lifetime());
_repaintByStatus.setCallback([this] { update(); });
}

View File

@@ -527,9 +527,7 @@ struct PeerListState {
QString searchQuery;
};
class PeerListContent
: public Ui::RpWidget
, private base::Subscriber {
class PeerListContent : public Ui::RpWidget {
public:
PeerListContent(
QWidget *parent,

View File

@@ -516,7 +516,7 @@ bool AddBotToGroupBoxController::needToCreateRow(
not_null<PeerData*> peer) const {
if (sharingBotGame()) {
if (!peer->canWrite()
|| peer->amRestricted(ChatRestriction::f_send_games)) {
|| peer->amRestricted(ChatRestriction::SendGames)) {
return false;
}
return true;

View File

@@ -626,7 +626,7 @@ void AddSpecialBoxController::showAdmin(
// Finally show the admin.
const auto currentRights = adminRights
? *adminRights
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
: ChatAdminRightsInfo();
auto box = Box<EditAdminBox>(
_peer,
user,
@@ -634,7 +634,7 @@ void AddSpecialBoxController::showAdmin(
_additional.adminRank(user));
if (_additional.canAddOrEditAdmin(user)) {
const auto done = crl::guard(this, [=](
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo newRights,
const QString &rank) {
editAdminDone(user, newRights, rank);
});
@@ -650,7 +650,7 @@ void AddSpecialBoxController::showAdmin(
void AddSpecialBoxController::editAdminDone(
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank) {
if (_editParticipantBox) {
_editParticipantBox->closeBox();
@@ -662,9 +662,11 @@ void AddSpecialBoxController::editAdminDone(
_additional.applyParticipant(MTP_channelParticipantCreator(
MTP_flags(rank.isEmpty() ? Flag(0) : Flag::f_rank),
peerToBareMTPInt(user->id),
rights,
MTP_chatAdminRights(
MTP_flags(MTPDchatAdminRights::Flags::from_raw(
uint32(rights.flags)))),
MTP_string(rank)));
} else if (rights.c_chatAdminRights().vflags().v == 0) {
} else if (!rights.flags) {
_additional.applyParticipant(MTP_channelParticipant(
peerToBareMTPInt(user->id),
MTP_int(date)));
@@ -680,7 +682,9 @@ void AddSpecialBoxController::editAdminDone(
? alreadyPromotedBy->id
: user->session().userPeerId()),
MTP_int(date),
rights,
MTP_chatAdminRights(
MTP_flags(MTPDchatAdminRights::Flags::from_raw(
uint32(rights.flags)))),
MTP_string(rank)));
}
if (const auto callback = _adminDoneCallback) {
@@ -730,7 +734,7 @@ void AddSpecialBoxController::showRestricted(
// Finally edit the restricted.
const auto currentRights = restrictedRights
? *restrictedRights
: ChannelData::EmptyRestrictedRights(user);
: ChatRestrictionsInfo();
auto box = Box<EditRestrictedBox>(
_peer,
user,
@@ -738,7 +742,7 @@ void AddSpecialBoxController::showRestricted(
currentRights);
if (_additional.canRestrictParticipant(user)) {
const auto done = crl::guard(this, [=](
const MTPChatBannedRights &newRights) {
ChatRestrictionsInfo newRights) {
editRestrictedDone(user, newRights);
});
const auto fail = crl::guard(this, [=] {
@@ -754,13 +758,13 @@ void AddSpecialBoxController::showRestricted(
void AddSpecialBoxController::editRestrictedDone(
not_null<PeerData*> participant,
const MTPChatBannedRights &rights) {
ChatRestrictionsInfo rights) {
if (_editParticipantBox) {
_editParticipantBox->closeBox();
}
const auto date = base::unixtime::now(); // Incorrect, but ignored.
if (Data::ChatBannedRightsFlags(rights) == 0) {
if (!rights.flags) {
if (const auto user = participant->asUser()) {
_additional.applyParticipant(MTP_channelParticipant(
peerToBareMTPInt(user->id),
@@ -769,8 +773,7 @@ void AddSpecialBoxController::editRestrictedDone(
_additional.setExternal(participant);
}
} else {
const auto kicked = Data::ChatBannedRightsFlags(rights)
& ChatRestriction::f_view_messages;
const auto kicked = rights.flags & ChatRestriction::ViewMessages;
const auto alreadyRestrictedBy = _additional.restrictedBy(
participant);
_additional.applyParticipant(MTP_channelParticipantBanned(
@@ -782,7 +785,10 @@ void AddSpecialBoxController::editRestrictedDone(
? alreadyRestrictedBy->id
: participant->session().userPeerId()),
MTP_int(date),
rights));
MTP_chatBannedRights(
MTP_flags(MTPDchatBannedRights::Flags::from_raw(
uint32(rights.flags))),
MTP_int(rights.until))));
}
if (const auto callback = _bannedDoneCallback) {
callback(participant, rights);
@@ -839,10 +845,10 @@ void AddSpecialBoxController::kickUser(
const auto restrictedRights = _additional.restrictedRights(participant);
const auto currentRights = restrictedRights
? *restrictedRights
: ChannelData::EmptyRestrictedRights(participant);
: ChatRestrictionsInfo();
const auto done = crl::guard(this, [=](
const MTPChatBannedRights &newRights) {
ChatRestrictionsInfo newRights) {
editRestrictedDone(participant, newRights);
});
const auto fail = crl::guard(this, [=] {

View File

@@ -10,6 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_controllers.h"
#include "boxes/peers/edit_participants_box.h"
struct ChatAdminRightsInfo;
struct ChatRestrictionsInfo;
namespace Window {
class SessionNavigation;
} // namespace Window
@@ -70,18 +73,17 @@ private:
// with search + contacts search + global search.
class AddSpecialBoxController
: public PeerListController
, private base::Subscriber
, public base::has_weak_ptr {
public:
using Role = ParticipantsBoxController::Role;
using AdminDoneCallback = Fn<void(
not_null<UserData*> user,
const MTPChatAdminRights &adminRights,
ChatAdminRightsInfo adminRights,
const QString &rank)>;
using BannedDoneCallback = Fn<void(
not_null<PeerData*> participant,
const MTPChatBannedRights &bannedRights)>;
ChatRestrictionsInfo bannedRights)>;
AddSpecialBoxController(
not_null<PeerData*> peer,
Role role,
@@ -109,12 +111,12 @@ private:
void showAdmin(not_null<UserData*> user, bool sure = false);
void editAdminDone(
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank);
void showRestricted(not_null<UserData*> user, bool sure = false);
void editRestrictedDone(
not_null<PeerData*> participant,
const MTPChatBannedRights &rights);
ChatRestrictionsInfo rights);
void kickUser(not_null<PeerData*> participant, bool sure = false);
bool appendRow(not_null<PeerData*> participant);
bool prependRow(not_null<UserData*> user);
@@ -143,9 +145,7 @@ protected:
};
// Finds chat/channel members, then contacts, then global search results.
class AddSpecialBoxSearchController
: public PeerListSearchController
, private base::Subscriber {
class AddSpecialBoxSearchController : public PeerListSearchController {
public:
using Role = ParticipantsBoxController::Role;

View File

@@ -60,10 +60,9 @@ void SendRequest(
user->username);
user->session().api().applyUpdates(result);
if (const auto settings = user->settings()) {
using Flag = MTPDpeerSettings::Flag;
const auto flags = Flag::f_add_contact
| Flag::f_block_contact
| Flag::f_report_spam;
const auto flags = PeerSetting::AddContact
| PeerSetting::BlockContact
| PeerSetting::ReportSpam;
user->setSettings(*settings & ~flags);
}
if (box) {
@@ -241,9 +240,8 @@ void Controller::setupWarning() {
void Controller::setupSharePhoneNumber() {
const auto settings = _user->settings();
using Setting = MTPDpeerSettings::Flag;
if (!settings
|| !((*settings) & Setting::f_need_contacts_exception)) {
|| !((*settings) & PeerSetting::NeedContactsException)) {
return;
}
_sharePhone = _box->addRow(

View File

@@ -197,43 +197,45 @@ EditAdminBox::EditAdminBox(
QWidget*,
not_null<PeerData*> peer,
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank)
: EditParticipantBox(
nullptr,
peer,
user,
(rights.c_chatAdminRights().vflags().v != 0))
(rights.flags != 0))
, _oldRights(rights)
, _oldRank(rank) {
}
MTPChatAdminRights EditAdminBox::defaultRights() const {
const auto flags = peer()->isChat()
ChatAdminRightsInfo EditAdminBox::defaultRights() const {
using Flag = ChatAdminRight;
return peer()->isChat()
? peer()->asChat()->defaultAdminRights(user())
: peer()->isMegagroup()
? (Flag::f_change_info
| Flag::f_delete_messages
| Flag::f_ban_users
| Flag::f_invite_users
| Flag::f_pin_messages
| Flag::f_manage_call)
: (Flag::f_change_info
| Flag::f_post_messages
| Flag::f_edit_messages
| Flag::f_delete_messages
| Flag::f_invite_users
| Flag::f_manage_call);
return MTP_chatAdminRights(MTP_flags(flags));
? ChatAdminRightsInfo{ (Flag::ChangeInfo
| Flag::DeleteMessages
| Flag::BanUsers
| Flag::InviteUsers
| Flag::PinMessages
| Flag::ManageCall) }
: ChatAdminRightsInfo{ (Flag::ChangeInfo
| Flag::PostMessages
| Flag::EditMessages
| Flag::DeleteMessages
| Flag::InviteUsers
| Flag::ManageCall) };
}
void EditAdminBox::prepare() {
using namespace rpl::mappers;
using Flag = ChatAdminRight;
using Flags = ChatAdminRights;
EditParticipantBox::prepare();
auto hadRights = _oldRights.c_chatAdminRights().vflags().v;
setTitle(hadRights
setTitle(_oldRights.flags
? tr::lng_rights_edit_admin()
: tr::lng_channel_add_admin());
@@ -243,16 +245,18 @@ void EditAdminBox::prepare() {
const auto chat = peer()->asChat();
const auto channel = peer()->asChannel();
const auto prepareRights = hadRights ? _oldRights : defaultRights();
const auto prepareRights = _oldRights.flags
? _oldRights
: defaultRights();
const auto disabledByDefaults = (channel && !channel->isMegagroup())
? MTPDchatAdminRights::Flags(0)
? ChatAdminRights()
: DisabledByDefaultRestrictions(peer());
const auto filterByMyRights = canSave()
&& !hadRights
&& !_oldRights.flags
&& channel
&& !channel->amCreator();
const auto prepareFlags = disabledByDefaults
| (prepareRights.c_chatAdminRights().vflags().v
| (prepareRights.flags
& (filterByMyRights ? channel->adminRights() : ~Flag(0)));
const auto disabledMessages = [&] {
@@ -267,7 +271,7 @@ void EditAdminBox::prepare() {
tr::lng_rights_permission_for_all(tr::now));
if (amCreator() && user()->isSelf()) {
result.emplace(
~Flag::f_anonymous,
~Flag::Anonymous,
tr::lng_rights_permission_cant_edit(tr::now));
} else if (const auto channel = peer()->asChannel()) {
if (!channel->amCreator()) {
@@ -304,7 +308,7 @@ void EditAdminBox::prepare() {
rpl::duplicate(
selectedFlags
) | rpl::map(
(_1 & Flag::f_add_admins) != 0
(_1 & Flag::AddAdmins) != 0
) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool checked) {
refreshAboutAddAdminsText(checked);
@@ -330,13 +334,13 @@ void EditAdminBox::prepare() {
if (!_saveCallback) {
return;
}
const auto newFlags = (value() | ChatAdminRight::f_other)
const auto newFlags = (value() | ChatAdminRight::Other)
& ((!channel || channel->amCreator())
? ~Flags(0)
: channel->adminRights());
_saveCallback(
_oldRights,
MTP_chatAdminRights(MTP_flags(newFlags)),
ChatAdminRightsInfo(newFlags),
rank ? rank->getLastText().trimmed() : QString());
});
addButton(tr::lng_cancel(), [=] { closeBox(); });
@@ -593,12 +597,15 @@ EditRestrictedBox::EditRestrictedBox(
not_null<PeerData*> peer,
not_null<UserData*> user,
bool hasAdminRights,
const MTPChatBannedRights &rights)
ChatRestrictionsInfo rights)
: EditParticipantBox(nullptr, peer, user, hasAdminRights)
, _oldRights(rights) {
}
void EditRestrictedBox::prepare() {
using Flag = ChatRestriction;
using Flags = ChatRestrictions;
EditParticipantBox::prepare();
setTitle(tr::lng_rights_user_restrictions());
@@ -612,14 +619,14 @@ void EditRestrictedBox::prepare() {
const auto defaultRestrictions = chat
? chat->defaultRestrictions()
: channel->defaultRestrictions();
const auto prepareRights = Data::ChatBannedRightsFlags(_oldRights)
const auto prepareRights = _oldRights.flags
? _oldRights
: defaultRights();
const auto prepareFlags = FixDependentRestrictions(
Data::ChatBannedRightsFlags(prepareRights)
prepareRights.flags
| defaultRestrictions
| ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages)
? (Flag::ChangeInfo | Flag::PinMessages)
: Flags(0)));
const auto disabledMessages = [&] {
auto result = std::map<Flags, QString>();
@@ -631,7 +638,7 @@ void EditRestrictedBox::prepare() {
const auto disabled = FixDependentRestrictions(
defaultRestrictions
| ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages)
? (Flag::ChangeInfo | Flag::PinMessages)
: Flags(0)));
result.emplace(
disabled,
@@ -647,7 +654,7 @@ void EditRestrictedBox::prepare() {
disabledMessages);
addControl(std::move(checkboxes), QMargins());
_until = Data::ChatBannedRightsUntilDate(prepareRights);
_until = prepareRights.until;
addControl(object_ptr<Ui::BoxContentDivider>(this), st::rightsUntilMargin);
addControl(
object_ptr<Ui::FlatLabel>(
@@ -670,9 +677,7 @@ void EditRestrictedBox::prepare() {
}
_saveCallback(
_oldRights,
MTP_chatBannedRights(
MTP_flags(value()),
MTP_int(getRealUntilValue())));
ChatRestrictionsInfo{ value(), getRealUntilValue() });
};
addButton(tr::lng_settings_save(), save);
addButton(tr::lng_cancel(), [=] { closeBox(); });
@@ -681,8 +686,8 @@ void EditRestrictedBox::prepare() {
}
}
MTPChatBannedRights EditRestrictedBox::defaultRights() const {
return MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
ChatRestrictionsInfo EditRestrictedBox::defaultRights() const {
return ChatRestrictionsInfo();
}
void EditRestrictedBox::showRestrictUntil() {
@@ -767,7 +772,7 @@ void EditRestrictedBox::createUntilVariants() {
}
};
auto addCurrentVariant = [&](TimeId from, TimeId to) {
auto oldUntil = Data::ChatBannedRightsUntilDate(_oldRights);
auto oldUntil = _oldRights.until;
if (oldUntil < _until) {
addCustomVariant(oldUntil, from, to);
}

View File

@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
#include "base/unique_qptr.h"
#include "data/data_peer.h"
namespace MTP {
class Error;
@@ -73,13 +74,13 @@ public:
QWidget*,
not_null<PeerData*> peer,
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank);
void setSaveCallback(
Fn<void(
MTPChatAdminRights,
MTPChatAdminRights,
ChatAdminRightsInfo,
ChatAdminRightsInfo,
const QString &rank)> callback) {
_saveCallback = std::move(callback);
}
@@ -88,10 +89,7 @@ protected:
void prepare() override;
private:
using Flag = MTPDchatAdminRights::Flag;
using Flags = MTPDchatAdminRights::Flags;
[[nodiscard]] MTPChatAdminRights defaultRights() const;
[[nodiscard]] ChatAdminRightsInfo defaultRights() const;
not_null<Ui::InputField*> addRankInput();
void transferOwnership();
@@ -109,11 +107,11 @@ private:
bool canTransferOwnership() const;
not_null<Ui::SlideWrap<Ui::RpWidget>*> setupTransferButton(bool isGroup);
const MTPChatAdminRights _oldRights;
const ChatAdminRightsInfo _oldRights;
const QString _oldRank;
Fn<void(
MTPChatAdminRights,
MTPChatAdminRights,
ChatAdminRightsInfo,
ChatAdminRightsInfo,
const QString &rank)> _saveCallback;
QPointer<Ui::FlatLabel> _aboutAddAdmins;
@@ -132,10 +130,10 @@ public:
not_null<PeerData*> peer,
not_null<UserData*> user,
bool hasAdminRights,
const MTPChatBannedRights &rights);
ChatRestrictionsInfo rights);
void setSaveCallback(
Fn<void(MTPChatBannedRights, MTPChatBannedRights)> callback) {
Fn<void(ChatRestrictionsInfo, ChatRestrictionsInfo)> callback) {
_saveCallback = std::move(callback);
}
@@ -143,10 +141,7 @@ protected:
void prepare() override;
private:
using Flag = MTPDchatBannedRights::Flag;
using Flags = MTPDchatBannedRights::Flags;
[[nodiscard]] MTPChatBannedRights defaultRights() const;
[[nodiscard]] ChatRestrictionsInfo defaultRights() const;
bool canSave() const {
return !!_saveCallback;
@@ -158,9 +153,9 @@ private:
void createUntilVariants();
TimeId getRealUntilValue() const;
const MTPChatBannedRights _oldRights;
const ChatRestrictionsInfo _oldRights;
TimeId _until = 0;
Fn<void(MTPChatBannedRights, MTPChatBannedRights)> _saveCallback;
Fn<void(ChatRestrictionsInfo, ChatRestrictionsInfo)> _saveCallback;
std::shared_ptr<Ui::RadiobuttonGroup> _untilGroup;
std::vector<base::unique_qptr<Ui::Radiobutton>> _untilVariants;

View File

@@ -43,7 +43,7 @@ constexpr auto kSortByOnlineDelay = crl::time(1000);
void RemoveAdmin(
not_null<ChannelData*> channel,
not_null<UserData*> user,
const MTPChatAdminRights &oldRights,
ChatAdminRightsInfo oldRights,
Fn<void()> onDone,
Fn<void()> onFail) {
const auto newRights = MTP_chatAdminRights(MTP_flags(0));
@@ -54,7 +54,7 @@ void RemoveAdmin(
MTP_string(QString())
)).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result);
channel->applyEditAdmin(user, oldRights, newRights, QString());
channel->applyEditAdmin(user, oldRights, ChatAdminRightsInfo(), QString());
if (onDone) {
onDone();
}
@@ -120,15 +120,16 @@ void SaveChatAdmin(
void SaveChannelAdmin(
not_null<ChannelData*> channel,
not_null<UserData*> user,
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights,
const QString &rank,
Fn<void()> onDone,
Fn<void()> onFail) {
channel->session().api().request(MTPchannels_EditAdmin(
channel->inputChannel,
user->inputUser,
newRights,
MTP_chatAdminRights(MTP_flags(
MTPDchatAdminRights::Flags::from_raw(uint32(newRights.flags)))),
MTP_string(rank)
)).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result);
@@ -147,14 +148,17 @@ void SaveChannelAdmin(
void SaveChannelRestriction(
not_null<ChannelData*> channel,
not_null<PeerData*> participant,
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights,
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights,
Fn<void()> onDone,
Fn<void()> onFail) {
channel->session().api().request(MTPchannels_EditBanned(
channel->inputChannel,
participant->input,
newRights
MTP_chatBannedRights(
MTP_flags(MTPDchatBannedRights::Flags::from_raw(
uint32(newRights.flags))),
MTP_int(newRights.until))
)).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result);
channel->applyEditBanned(participant, oldRights, newRights);
@@ -192,18 +196,18 @@ void SaveChatParticipantKick(
} // namespace
Fn<void(
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights,
const QString &rank)> SaveAdminCallback(
not_null<PeerData*> peer,
not_null<UserData*> user,
Fn<void(
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo newRights,
const QString &rank)> onDone,
Fn<void()> onFail) {
return [=](
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights,
const QString &rank) {
const auto done = [=] { if (onDone) onDone(newRights, rank); };
const auto saveForChannel = [=](not_null<ChannelData*> channel) {
@@ -220,13 +224,10 @@ Fn<void(
const auto saveChatAdmin = [&](bool isAdmin) {
SaveChatAdmin(chat, user, isAdmin, done, onFail);
};
const auto flags = newRights.match([](
const MTPDchatAdminRights &data) {
return data.vflags().v;
});
if (flags == chat->defaultAdminRights(user) && rank.isEmpty()) {
if (newRights.flags == chat->defaultAdminRights(user).flags
&& rank.isEmpty()) {
saveChatAdmin(true);
} else if (!flags) {
} else if (!newRights.flags) {
saveChatAdmin(false);
} else {
peer->session().api().migrateChat(chat, saveForChannel);
@@ -240,15 +241,15 @@ Fn<void(
}
Fn<void(
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights)> SaveRestrictedCallback(
not_null<PeerData*> peer,
not_null<PeerData*> participant,
Fn<void(const MTPChatBannedRights &newRights)> onDone,
Fn<void(ChatRestrictionsInfo newRights)> onDone,
Fn<void()> onFail) {
return [=](
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights) {
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights) {
const auto done = [=] { if (onDone) onDone(newRights); };
const auto saveForChannel = [=](not_null<ChannelData*> channel) {
SaveChannelRestriction(
@@ -260,15 +261,14 @@ Fn<void(
onFail);
};
if (const auto chat = peer->asChatNotMigrated()) {
const auto flags = Data::ChatBannedRightsFlags(newRights);
if (participant->isUser()
&& (flags & MTPDchatBannedRights::Flag::f_view_messages)) {
&& (newRights.flags & ChatRestriction::ViewMessages)) {
SaveChatParticipantKick(
chat,
participant->asUser(),
done,
onFail);
} else if (!flags) {
} else if (!newRights.flags) {
done();
} else {
peer->session().api().migrateChat(chat, saveForChannel);
@@ -373,11 +373,10 @@ bool ParticipantsAdditionalData::canRemoveParticipant(
auto ParticipantsAdditionalData::adminRights(
not_null<UserData*> user) const
-> std::optional<MTPChatAdminRights> {
-> std::optional<ChatAdminRightsInfo> {
if (const auto chat = _peer->asChat()) {
return _admins.contains(user)
? std::make_optional(MTPChatAdminRights(MTP_chatAdminRights(
MTP_flags(chat->defaultAdminRights(user)))))
? std::make_optional(chat->defaultAdminRights(user))
: std::nullopt;
}
const auto i = _adminRights.find(user);
@@ -394,7 +393,7 @@ QString ParticipantsAdditionalData::adminRank(
auto ParticipantsAdditionalData::restrictedRights(
not_null<PeerData*> participant) const
-> std::optional<MTPChatBannedRights> {
-> std::optional<ChatRestrictionsInfo> {
if (_peer->isChat()) {
return std::nullopt;
}
@@ -589,7 +588,7 @@ UserData *ParticipantsAdditionalData::applyCreator(
const MTPDchannelParticipantCreator &data) {
if (const auto user = applyRegular(data.vuser_id())) {
_creator = user;
_adminRights[user] = data.vadmin_rights();
_adminRights[user] = ChatAdminRightsInfo(data.vadmin_rights());
if (user->isSelf()) {
_adminCanEdit.emplace(user);
} else {
@@ -620,7 +619,7 @@ UserData *ParticipantsAdditionalData::applyAdmin(
_restrictedRights.erase(user);
_kicked.erase(user);
_restrictedBy.erase(user);
_adminRights[user] = data.vadmin_rights();
_adminRights[user] = ChatAdminRightsInfo(data.vadmin_rights());
if (data.is_can_edit()) {
_adminCanEdit.emplace(user);
} else {
@@ -684,7 +683,8 @@ PeerData *ParticipantsAdditionalData::applyBanned(
} else {
_kicked.erase(participant);
}
_restrictedRights[participant] = data.vbanned_rights();
_restrictedRights[participant] = ChatRestrictionsInfo(
data.vbanned_rights());
if (const auto by = _peer->owner().userLoaded(data.vkicked_by())) {
const auto i = _restrictedBy.find(participant);
if (i == _restrictedBy.end()) {
@@ -703,9 +703,7 @@ void ParticipantsAdditionalData::migrate(
fillFromChannel(channel);
for (const auto user : _admins) {
_adminRights.emplace(
user,
MTP_chatAdminRights(MTP_flags(chat->defaultAdminRights(user))));
_adminRights.emplace(user, chat->defaultAdminRights(user));
if (channel->amCreator()) {
_adminCanEdit.emplace(user);
}
@@ -940,13 +938,13 @@ void ParticipantsBoxController::addNewItem() {
}
const auto adminDone = crl::guard(this, [=](
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank) {
editAdminDone(user, rights, rank);
});
const auto restrictedDone = crl::guard(this, [=](
not_null<PeerData*> participant,
const MTPChatBannedRights &rights) {
ChatRestrictionsInfo rights) {
editRestrictedDone(participant, rights);
});
const auto initBox = [](not_null<PeerListBox*> box) {
@@ -1457,7 +1455,6 @@ void ParticipantsBoxController::rowActionClicked(
base::unique_qptr<Ui::PopupMenu> ParticipantsBoxController::rowContextMenu(
QWidget *parent,
not_null<PeerListRow*> row) {
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
const auto participant = row->peer();
const auto user = participant->asUser();
@@ -1523,19 +1520,15 @@ base::unique_qptr<Ui::PopupMenu> ParticipantsBoxController::rowContextMenu(
void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
const auto adminRights = _additional.adminRights(user);
const auto currentRights = adminRights
? *adminRights
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
const auto currentRights = adminRights.value_or(ChatAdminRightsInfo());
auto box = Box<EditAdminBox>(
_peer,
user,
currentRights,
_additional.adminRank(user));
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
if (_additional.canAddOrEditAdmin(user)) {
const auto done = crl::guard(this, [=](
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo newRights,
const QString &rank) {
editAdminDone(user, newRights, rank);
});
@@ -1551,7 +1544,7 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
void ParticipantsBoxController::editAdminDone(
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank) {
_addBox = nullptr;
if (_editParticipantBox) {
@@ -1564,9 +1557,11 @@ void ParticipantsBoxController::editAdminDone(
_additional.applyParticipant(MTP_channelParticipantCreator(
MTP_flags(rank.isEmpty() ? Flag(0) : Flag::f_rank),
peerToBareMTPInt(user->id),
rights,
MTP_chatAdminRights(
MTP_flags(MTPDchatAdminRights::Flags::from_raw(
uint32(rights.flags)))),
MTP_string(rank)));
} else if (rights.c_chatAdminRights().vflags().v == 0) {
} else if (!rights.flags) {
_additional.applyParticipant(MTP_channelParticipant(
peerToBareMTPInt(user->id),
MTP_int(date)));
@@ -1585,7 +1580,9 @@ void ParticipantsBoxController::editAdminDone(
? alreadyPromotedBy->id
: user->session().userPeerId()),
MTP_int(date),
rights,
MTP_chatAdminRights(
MTP_flags(MTPDchatAdminRights::Flags::from_raw(
uint32(rights.flags)))),
MTP_string(rank)));
if (_role == Role::Admins) {
prependRow(user);
@@ -1601,18 +1598,16 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
const auto restrictedRights = _additional.restrictedRights(user);
const auto currentRights = restrictedRights
? *restrictedRights
: ChannelData::EmptyRestrictedRights(user);
: ChatRestrictionsInfo();
const auto hasAdminRights = _additional.adminRights(user).has_value();
auto box = Box<EditRestrictedBox>(
_peer,
user,
hasAdminRights,
currentRights);
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
if (_additional.canRestrictParticipant(user)) {
const auto done = crl::guard(this, [=](
const MTPChatBannedRights &newRights) {
ChatRestrictionsInfo newRights) {
editRestrictedDone(user, newRights);
});
const auto fail = crl::guard(this, [=] {
@@ -1628,7 +1623,7 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
void ParticipantsBoxController::editRestrictedDone(
not_null<PeerData*> participant,
const MTPChatBannedRights &rights) {
ChatRestrictionsInfo rights) {
_addBox = nullptr;
if (_editParticipantBox) {
_editParticipantBox->closeBox();
@@ -1636,7 +1631,7 @@ void ParticipantsBoxController::editRestrictedDone(
const auto user = participant->asUser();
const auto date = base::unixtime::now(); // Incorrect, but ignored.
if (Data::ChatBannedRightsFlags(rights) == 0) {
if (!rights.flags) {
if (user) {
_additional.applyParticipant(MTP_channelParticipant(
peerToBareMTPInt(user->id),
@@ -1648,8 +1643,7 @@ void ParticipantsBoxController::editRestrictedDone(
removeRow(participant);
}
} else {
const auto kicked = Data::ChatBannedRightsFlags(rights)
& ChatRestriction::f_view_messages;
const auto kicked = rights.flags & ChatRestriction::ViewMessages;
const auto alreadyRestrictedBy = _additional.restrictedBy(
participant);
_additional.applyParticipant(MTP_channelParticipantBanned(
@@ -1661,7 +1655,10 @@ void ParticipantsBoxController::editRestrictedDone(
? alreadyRestrictedBy->id
: participant->session().userPeerId()),
MTP_int(date),
rights));
MTP_chatBannedRights(
MTP_flags(MTPDchatBannedRights::Flags::from_raw(
uint32(rights.flags))),
MTP_int(rights.until))));
if (kicked) {
if (_role == Role::Kicked) {
prependRow(participant);
@@ -1716,7 +1713,7 @@ void ParticipantsBoxController::kickParticipantSure(
const auto restrictedRights = _additional.restrictedRights(participant);
const auto currentRights = restrictedRights
? *restrictedRights
: ChannelData::EmptyRestrictedRights(participant);
: ChatRestrictionsInfo();
if (const auto row = delegate()->peerListFindRow(participant->id.value)) {
delegate()->peerListRemoveRow(row);
@@ -1749,7 +1746,7 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
SaveChatAdmin(chat, user, false, crl::guard(this, [=] {
editAdminDone(
user,
MTP_chatAdminRights(MTP_flags(0)),
ChatAdminRightsInfo(),
QString());
}), nullptr);
} else if (const auto channel = _peer->asChannel()) {
@@ -1760,7 +1757,7 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
RemoveAdmin(channel, user, *adminRights, crl::guard(this, [=] {
editAdminDone(
user,
MTP_chatAdminRights(MTP_flags(0)),
ChatAdminRightsInfo(),
QString());
}), nullptr);
}
@@ -1961,7 +1958,7 @@ void ParticipantsBoxController::subscribeToCreatorChange(
const auto isCreator = channel->amCreator();
channel->flagsValue(
) | rpl::filter([](const ChannelData::Flags::Change &change) {
return (change.diff & MTPDchannel::Flag::f_creator);
return (change.diff & ChannelDataFlag::Creator);
}) | rpl::filter([=] {
return (isCreator != channel->amCreator());
}) | rpl::start_with_next([=] {

View File

@@ -14,27 +14,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/weak_ptr.h"
#include "info/profile/info_profile_members_controllers.h"
struct ChatAdminRightsInfo;
struct ChatRestrictionsInfo;
namespace Window {
class SessionNavigation;
} // namespace Window
Fn<void(
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights,
const QString &rank)> SaveAdminCallback(
not_null<PeerData*> peer,
not_null<UserData*> user,
Fn<void(
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo newRights,
const QString &rank)> onDone,
Fn<void()> onFail);
Fn<void(
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights)> SaveRestrictedCallback(
not_null<PeerData*> peer,
not_null<PeerData*> participant,
Fn<void(const MTPChatBannedRights &newRights)> onDone,
Fn<void(ChatRestrictionsInfo newRights)> onDone,
Fn<void()> onFail);
void SubscribeToMigration(
@@ -92,10 +95,10 @@ public:
not_null<PeerData*> participant) const;
[[nodiscard]] bool canRemoveParticipant(
not_null<PeerData*> participant) const;
[[nodiscard]] std::optional<MTPChatAdminRights> adminRights(
[[nodiscard]] std::optional<ChatAdminRightsInfo> adminRights(
not_null<UserData*> user) const;
QString adminRank(not_null<UserData*> user) const;
[[nodiscard]] std::optional<MTPChatBannedRights> restrictedRights(
[[nodiscard]] std::optional<ChatRestrictionsInfo> restrictedRights(
not_null<PeerData*> participant) const;
[[nodiscard]] bool isCreator(not_null<UserData*> user) const;
[[nodiscard]] bool isExternal(not_null<PeerData*> participant) const;
@@ -122,11 +125,11 @@ private:
base::flat_set<not_null<UserData*>> _admins;
// Data for channels.
base::flat_map<not_null<UserData*>, MTPChatAdminRights> _adminRights;
base::flat_map<not_null<UserData*>, ChatAdminRightsInfo> _adminRights;
base::flat_map<not_null<UserData*>, QString> _adminRanks;
base::flat_set<not_null<UserData*>> _adminCanEdit;
base::flat_map<not_null<UserData*>, not_null<UserData*>> _adminPromotedBy;
std::map<not_null<PeerData*>, MTPChatBannedRights> _restrictedRights;
std::map<not_null<PeerData*>, ChatRestrictionsInfo> _restrictedRights;
std::set<not_null<PeerData*>> _kicked;
std::map<not_null<PeerData*>, not_null<UserData*>> _restrictedBy;
std::set<not_null<PeerData*>> _external;
@@ -221,12 +224,12 @@ private:
void showAdmin(not_null<UserData*> user);
void editAdminDone(
not_null<UserData*> user,
const MTPChatAdminRights &rights,
ChatAdminRightsInfo rights,
const QString &rank);
void showRestricted(not_null<UserData*> user);
void editRestrictedDone(
not_null<PeerData*> participant,
const MTPChatBannedRights &rights);
ChatRestrictionsInfo rights);
void removeKicked(
not_null<PeerListRow*> row,
not_null<PeerData*> participant);

View File

@@ -64,8 +64,6 @@ void FillContent(
return;
}
const auto channel = peer->asChannel();
historyVisibility->setValue(savedValue);
const auto result = parent->add(

View File

@@ -140,7 +140,7 @@ void AddButtonDelete(
void SaveDefaultRestrictions(
not_null<PeerData*> peer,
MTPChatBannedRights rights,
ChatRestrictions rights,
Fn<void()> done) {
const auto api = &peer->session().api();
const auto key = Api::RequestKey("default_restrictions", peer->id);
@@ -148,7 +148,10 @@ void SaveDefaultRestrictions(
const auto requestId = api->request(
MTPmessages_EditChatDefaultBannedRights(
peer->input,
rights)
MTP_chatBannedRights(
MTP_flags(
MTPDchatBannedRights::Flags::from_raw(uint32(rights))),
MTP_int(0)))
).done([=](const MTPUpdates &result) {
api->clearModifyRequest(key);
api->applyUpdates(result);
@@ -215,52 +218,7 @@ void ShowEditPermissions(
const auto close = crl::guard(box, [=] { box->closeBox(); });
SaveDefaultRestrictions(
peer,
MTP_chatBannedRights(MTP_flags(result.rights), MTP_int(0)),
close);
if (const auto channel = peer->asChannel()) {
SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
}
};
box->saveEvents(
) | rpl::start_with_next([=](EditPeerPermissionsBox::Result result) {
if (*saving) {
return;
}
*saving = true;
const auto saveFor = peer->migrateToOrMe();
const auto chat = saveFor->asChat();
if (!result.slowmodeSeconds || !chat) {
save(saveFor, result);
return;
}
const auto api = &peer->session().api();
api->migrateChat(chat, [=](not_null<ChannelData*> channel) {
save(channel, result);
}, [=](const MTP::Error &error) {
*saving = false;
});
}, box->lifetime());
}
void ShowEditInviteLinks(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer) {
auto content = Box<EditPeerPermissionsBox>(navigation, peer);
const auto box = QPointer<EditPeerPermissionsBox>(content.data());
navigation->parentController()->show(
std::move(content),
Ui::LayerOption::KeepOther);
const auto saving = box->lifetime().make_state<int>(0);
const auto save = [=](
not_null<PeerData*> peer,
EditPeerPermissionsBox::Result result) {
Expects(result.slowmodeSeconds == 0 || peer->isChannel());
const auto close = crl::guard(box, [=] { box->closeBox(); });
SaveDefaultRestrictions(
peer,
MTP_chatBannedRights(MTP_flags(result.rights), MTP_int(0)),
result.rights,
close);
if (const auto channel = peer->asChannel()) {
SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
@@ -1355,7 +1313,6 @@ void Controller::saveLinkedChat() {
channel->setLinkedChat(*_savingData.linkedChat);
continueSave();
}).fail([=](const MTP::Error &error) {
const auto &type = error.type();
cancelSave();
}).send();
}
@@ -1408,7 +1365,6 @@ void Controller::saveTitle() {
}
void Controller::saveDescription() {
const auto channel = _peer->asChannel();
if (!_savingData.description
|| *_savingData.description == _peer->about()) {
return continueSave();
@@ -1468,9 +1424,9 @@ void Controller::togglePreHistoryHidden(
// Update in the result doesn't contain the
// channelFull:flags field which holds this value.
// So after saving we need to update it manually.
const auto flags = channel->fullFlags();
const auto flag = MTPDchannelFull::Flag::f_hidden_prehistory;
channel->setFullFlags(hidden ? (flags | flag) : (flags & ~flag));
const auto flags = channel->flags();
const auto flag = ChannelDataFlag::PreHistoryHidden;
channel->setFlags(hidden ? (flags | flag) : (flags & ~flag));
done();
};

View File

@@ -832,7 +832,6 @@ void CopyInviteLink(const QString &link) {
}
void ShareInviteLinkBox(not_null<PeerData*> peer, const QString &link) {
const auto session = &peer->session();
const auto sending = std::make_shared<bool>();
const auto box = std::make_shared<QPointer<ShareBox>>();
@@ -886,8 +885,6 @@ void ShareInviteLinkBox(not_null<PeerData*> peer, const QString &link) {
}
const auto owner = &peer->owner();
auto &api = peer->session().api();
auto &histories = owner->histories();
const auto requestType = Data::Histories::RequestType::Send;
for (const auto peer : result) {
const auto history = owner->history(peer);
auto message = ApiWrap::MessageToSend(history);
@@ -901,9 +898,6 @@ void ShareInviteLinkBox(not_null<PeerData*> peer, const QString &link) {
(*box)->closeBox();
}
};
auto filterCallback = [](PeerData *peer) {
return peer->canWrite();
};
*box = Ui::show(
Box<ShareBox>(ShareBox::Descriptor{
.session = &peer->session(),

View File

@@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace {
constexpr auto kPreloadPages = 2;
constexpr auto kFullArcLength = 360 * 16;
enum class Color {

View File

@@ -133,26 +133,26 @@ std::vector<std::pair<ChatAdminRights, QString>> AdminRightLabels(
if (isGroup) {
return {
{ Flag::f_change_info, tr::lng_rights_group_info(tr::now) },
{ Flag::f_delete_messages, tr::lng_rights_group_delete(tr::now) },
{ Flag::f_ban_users, tr::lng_rights_group_ban(tr::now) },
{ Flag::f_invite_users, anyoneCanAddMembers
{ Flag::ChangeInfo, tr::lng_rights_group_info(tr::now) },
{ Flag::DeleteMessages, tr::lng_rights_group_delete(tr::now) },
{ Flag::BanUsers, tr::lng_rights_group_ban(tr::now) },
{ Flag::InviteUsers, anyoneCanAddMembers
? tr::lng_rights_group_invite_link(tr::now)
: tr::lng_rights_group_invite(tr::now) },
{ Flag::f_pin_messages, tr::lng_rights_group_pin(tr::now) },
{ Flag::f_manage_call, tr::lng_rights_group_manage_calls(tr::now) },
{ Flag::f_anonymous, tr::lng_rights_group_anonymous(tr::now) },
{ Flag::f_add_admins, tr::lng_rights_add_admins(tr::now) },
{ Flag::PinMessages, tr::lng_rights_group_pin(tr::now) },
{ Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) },
{ Flag::Anonymous, tr::lng_rights_group_anonymous(tr::now) },
{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) },
};
} else {
return {
{ Flag::f_change_info, tr::lng_rights_channel_info(tr::now) },
{ Flag::f_post_messages, tr::lng_rights_channel_post(tr::now) },
{ Flag::f_edit_messages, tr::lng_rights_channel_edit(tr::now) },
{ Flag::f_delete_messages, tr::lng_rights_channel_delete(tr::now) },
{ Flag::f_invite_users, tr::lng_rights_group_invite(tr::now) },
{ Flag::f_manage_call, tr::lng_rights_group_manage_calls(tr::now) },
{ Flag::f_add_admins, tr::lng_rights_add_admins(tr::now) }
{ Flag::ChangeInfo, tr::lng_rights_channel_info(tr::now) },
{ Flag::PostMessages, tr::lng_rights_channel_post(tr::now) },
{ Flag::EditMessages, tr::lng_rights_channel_edit(tr::now) },
{ Flag::DeleteMessages, tr::lng_rights_channel_delete(tr::now) },
{ Flag::InviteUsers, tr::lng_rights_group_invite(tr::now) },
{ Flag::ManageCall, tr::lng_rights_group_manage_calls(tr::now) },
{ Flag::AddAdmins, tr::lng_rights_add_admins(tr::now) }
};
}
}
@@ -163,31 +163,31 @@ auto Dependencies(ChatRestrictions)
return {
// stickers <-> gifs
{ Flag::f_send_gifs, Flag::f_send_stickers },
{ Flag::f_send_stickers, Flag::f_send_gifs },
{ Flag::SendGifs, Flag::SendStickers },
{ Flag::SendStickers, Flag::SendGifs },
// stickers <-> games
{ Flag::f_send_games, Flag::f_send_stickers },
{ Flag::f_send_stickers, Flag::f_send_games },
{ Flag::SendGames, Flag::SendStickers },
{ Flag::SendStickers, Flag::SendGames },
// stickers <-> inline
{ Flag::f_send_inline, Flag::f_send_stickers },
{ Flag::f_send_stickers, Flag::f_send_inline },
{ Flag::SendInline, Flag::SendStickers },
{ Flag::SendStickers, Flag::SendInline },
// stickers -> send_media
{ Flag::f_send_stickers, Flag::f_send_messages },
// stickers -> send_messages
{ Flag::SendStickers, Flag::SendMessages },
// embed_links -> send_media
{ Flag::f_embed_links, Flag::f_send_messages },
// embed_links -> send_messages
{ Flag::EmbedLinks, Flag::SendMessages },
// send_media -> send_messages
{ Flag::f_send_media, Flag::f_send_messages },
{ Flag::SendMedia, Flag::SendMessages },
// send_polls -> send_messages
{ Flag::f_send_polls, Flag::f_send_messages },
{ Flag::SendPolls, Flag::SendMessages },
// send_messages -> view_messages
{ Flag::f_send_messages, Flag::f_view_messages },
{ Flag::SendMessages, Flag::ViewMessages },
};
}
@@ -196,18 +196,18 @@ ChatRestrictions NegateRestrictions(ChatRestrictions value) {
return (~value) & (Flag(0)
// view_messages is always allowed, so it is never in restrictions.
//| Flag::f_view_messages
| Flag::f_change_info
| Flag::f_embed_links
| Flag::f_invite_users
| Flag::f_pin_messages
| Flag::f_send_games
| Flag::f_send_gifs
| Flag::f_send_inline
| Flag::f_send_media
| Flag::f_send_messages
| Flag::f_send_polls
| Flag::f_send_stickers);
//| Flag::ViewMessages
| Flag::ChangeInfo
| Flag::EmbedLinks
| Flag::InviteUsers
| Flag::PinMessages
| Flag::SendGames
| Flag::SendGifs
| Flag::SendInline
| Flag::SendMedia
| Flag::SendMessages
| Flag::SendPolls
| Flag::SendStickers);
}
auto Dependencies(ChatAdminRights)
@@ -236,15 +236,15 @@ ChatRestrictions DisabledByAdminRights(not_null<PeerData*> peer) {
Unexpected("User in DisabledByAdminRights.");
}();
return Flag(0)
| ((adminRights & Admin::f_pin_messages)
| ((adminRights & Admin::PinMessages)
? Flag(0)
: Flag::f_pin_messages)
| ((adminRights & Admin::f_invite_users)
: Flag::PinMessages)
| ((adminRights & Admin::InviteUsers)
? Flag(0)
: Flag::f_invite_users)
| ((adminRights & Admin::f_change_info)
: Flag::InviteUsers)
| ((adminRights & Admin::ChangeInfo)
? Flag(0)
: Flag::f_change_info);
: Flag::ChangeInfo);
}
} // namespace
@@ -262,21 +262,21 @@ ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer) {
Unexpected("User in DisabledByDefaultRestrictions.");
}());
return Flag(0)
| ((restrictions & Restriction::f_pin_messages)
| ((restrictions & Restriction::PinMessages)
? Flag(0)
: Flag::f_pin_messages)
: Flag::PinMessages)
//
// We allow to edit 'invite_users' admin right no matter what
// is chosen in default permissions for 'invite_users', because
// if everyone can 'invite_users' it handles invite link for admins.
//
//| ((restrictions & Restriction::f_invite_users)
//| ((restrictions & Restriction::InviteUsers)
// ? Flag(0)
// : Flag::f_invite_users)
// : Flag::InviteUsers)
//
| ((restrictions & Restriction::f_change_info)
| ((restrictions & Restriction::ChangeInfo)
? Flag(0)
: Flag::f_change_info);
: Flag::ChangeInfo);
}
ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
@@ -284,15 +284,15 @@ ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
// Fix iOS bug of saving send_inline like embed_links.
// We copy send_stickers to send_inline.
if (restrictions & ChatRestriction::f_send_stickers) {
restrictions |= ChatRestriction::f_send_inline;
if (restrictions & ChatRestriction::SendStickers) {
restrictions |= ChatRestriction::SendInline;
} else {
restrictions &= ~ChatRestriction::f_send_inline;
restrictions &= ~ChatRestriction::SendInline;
}
// Apply the strictest.
const auto fixOne = [&] {
for (const auto [first, second] : dependencies) {
for (const auto &[first, second] : dependencies) {
if ((restrictions & second) && !(restrictions & first)) {
restrictions |= first;
return true;
@@ -308,7 +308,7 @@ ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
ChatAdminRights AdminRightsForOwnershipTransfer(bool isGroup) {
auto result = ChatAdminRights();
for (const auto &[flag, label] : AdminRightLabels(isGroup, true)) {
if (!(flag & ChatAdminRight::f_anonymous)) {
if (!(flag & ChatAdminRight::Anonymous)) {
result |= flag;
}
}
@@ -407,7 +407,7 @@ void EditPeerPermissionsBox::prepare() {
} else if (const auto channel = _peer->asChannel()) {
return channel->defaultRestrictions()
| (channel->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
? (Flag::ChangeInfo | Flag::PinMessages)
: Flags(0))
| disabledByAdminRights;
}
@@ -421,7 +421,7 @@ void EditPeerPermissionsBox::prepare() {
if (const auto channel = _peer->asChannel()) {
if (channel->isPublic()) {
result.emplace(
Flag::f_change_info | Flag::f_pin_messages,
Flag::ChangeInfo | Flag::PinMessages,
tr::lng_rights_permission_unavailable(tr::now));
}
}
@@ -533,7 +533,7 @@ Fn<int()> EditPeerPermissionsBox::addSlowmodeSlider(
return has ? aboutInterval : about;
});
const auto about = container->add(
container->add(
object_ptr<Ui::DividerLabel>(
container,
object_ptr<Ui::FlatLabel>(
@@ -753,11 +753,11 @@ EditFlagsControl<Flags> CreateEditFlags(
};
}
EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
QWidget *parent,
rpl::producer<QString> header,
MTPDchatBannedRights::Flags restrictions,
std::map<MTPDchatBannedRights::Flags, QString> disabledMessages) {
ChatRestrictions restrictions,
std::map<ChatRestrictions, QString> disabledMessages) {
auto result = CreateEditFlags(
parent,
header,
@@ -774,11 +774,11 @@ EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
return result;
}
EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
QWidget *parent,
rpl::producer<QString> header,
MTPDchatAdminRights::Flags rights,
std::map<MTPDchatAdminRights::Flags, QString> disabledMessages,
ChatAdminRights rights,
std::map<ChatAdminRights, QString> disabledMessages,
bool isGroup,
bool anyoneCanAddMembers) {
return CreateEditFlags(

View File

@@ -27,7 +27,7 @@ public:
not_null<PeerData*> peer);
struct Result {
MTPDchatBannedRights::Flags rights;
ChatRestrictions rights;
int slowmodeSeconds = 0;
};
@@ -59,17 +59,17 @@ struct EditFlagsControl {
rpl::producer<Flags> changes;
};
EditFlagsControl<MTPDchatBannedRights::Flags> CreateEditRestrictions(
EditFlagsControl<ChatRestrictions> CreateEditRestrictions(
QWidget *parent,
rpl::producer<QString> header,
MTPDchatBannedRights::Flags restrictions,
std::map<MTPDchatBannedRights::Flags, QString> disabledMessages);
ChatRestrictions restrictions,
std::map<ChatRestrictions, QString> disabledMessages);
EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
EditFlagsControl<ChatAdminRights> CreateEditAdminRights(
QWidget *parent,
rpl::producer<QString> header,
MTPDchatAdminRights::Flags rights,
std::map<MTPDchatAdminRights::Flags, QString> disabledMessages,
ChatAdminRights rights,
std::map<ChatAdminRights, QString> disabledMessages,
bool isGroup,
bool anyoneCanAddMembers);

View File

@@ -68,10 +68,6 @@ inline bool CanAddUrls(const QList<QUrl> &urls) {
return !urls.isEmpty() && ranges::all_of(urls, &QUrl::isLocalFile);
}
inline bool IsSingleItem(const Ui::PreparedList &list) {
return list.files.size() == 1;
}
void FileDialogCallback(
FileDialog::OpenResult &&result,
Fn<bool(const Ui::PreparedList&)> checkResult,
@@ -543,7 +539,6 @@ void SendFilesBox::pushBlock(int from, int till) {
return controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer);
};
const auto index = int(_blocks.size());
_blocks.emplace_back(
_inner.data(),
&_list.files,

View File

@@ -27,7 +27,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_message.h"
#include "history/view/history_view_schedule_box.h"
#include "window/themes/window_theme.h"
#include "window/window_session_controller.h"
#include "boxes/peer_list_box.h"
#include "chat_helpers/emoji_suggestions_widget.h"
@@ -42,7 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_boxes.h"
#include "styles/style_chat.h"
class ShareBox::Inner final : public Ui::RpWidget, private base::Subscriber {
class ShareBox::Inner final : public Ui::RpWidget {
public:
Inner(QWidget *parent, const Descriptor &descriptor);
@@ -598,11 +597,10 @@ ShareBox::Inner::Inner(QWidget *parent, const Descriptor &descriptor)
update();
}, lifetime());
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
if (update.paletteChanged()) {
invalidateCache();
}
});
style::PaletteChanged(
) | rpl::start_with_next([=] {
invalidateCache();
}, lifetime());
}
void ShareBox::Inner::invalidateCache() {
@@ -1113,7 +1111,6 @@ QString AppendShareGameScoreUrl(
? session->data().channelLoaded(fullId.channel)
: static_cast<ChannelData*>(nullptr);
auto channelAccessHash = uint64(channel ? channel->access : 0);
auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
shareHashDataInts[0] = session->userId().bare;
shareHashDataInts[1] = fullId.channel.bare;
shareHashDataInts[2] = fullId.msg;

View File

@@ -51,15 +51,16 @@ constexpr auto kStickersPanelPerRow = 5;
using Data::StickersSet;
using Data::StickersPack;
using Data::StickersByEmojiMap;
using SetFlag = Data::StickersSetFlag;
} // namespace
class StickerSetBox::Inner : public Ui::RpWidget, private base::Subscriber {
class StickerSetBox::Inner final : public Ui::RpWidget {
public:
Inner(
QWidget *parent,
not_null<Window::SessionController*> controller,
const MTPInputStickerSet &set);
const StickerSetIdentifier &set);
bool loaded() const;
bool notInstalled() const;
@@ -77,7 +78,7 @@ public:
void archiveStickers();
bool isMasksSet() const {
return (_setFlags & MTPDstickerSet::Flag::f_masks);
return (_setFlags & SetFlag::Masks);
}
~Inner();
@@ -128,13 +129,13 @@ private:
QString _setTitle, _setShortName;
int _setCount = 0;
int32 _setHash = 0;
MTPDstickerSet::Flags _setFlags = 0;
Data::StickersSetFlags _setFlags;
TimeId _setInstallDate = TimeId(0);
ImageWithLocation _setThumbnail;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
MTPInputStickerSet _input;
StickerSetIdentifier _input;
mtpRequestId _installRequest = 0;
@@ -153,7 +154,7 @@ private:
StickerSetBox::StickerSetBox(
QWidget*,
not_null<Window::SessionController*> controller,
const MTPInputStickerSet &set)
const StickerSetIdentifier &set)
: _controller(controller)
, _set(set) {
}
@@ -162,7 +163,7 @@ QPointer<Ui::BoxContent> StickerSetBox::Show(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document) {
if (const auto sticker = document->sticker()) {
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
if (sticker->set) {
return controller->show(
Box<StickerSetBox>(controller, sticker->set),
Ui::LayerOption::KeepOther).data();
@@ -344,28 +345,21 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) {
StickerSetBox::Inner::Inner(
QWidget *parent,
not_null<Window::SessionController*> controller,
const MTPInputStickerSet &set)
const StickerSetIdentifier &set)
: RpWidget(parent)
, _controller(controller)
, _api(&_controller->session().mtp())
, _setId(set.id)
, _setAccess(set.accessHash)
, _setShortName(set.shortName)
, _pathGradient(std::make_unique<Ui::PathShiftGradient>(
st::windowBgRipple,
st::windowBgOver,
[=] { update(); }))
, _input(set)
, _previewTimer([=] { showPreview(); }) {
set.match([&](const MTPDinputStickerSetID &data) {
_setId = data.vid().v;
_setAccess = data.vaccess_hash().v;
}, [&](const MTPDinputStickerSetShortName &data) {
_setShortName = qs(data.vshort_name());
}, [](const MTPDinputStickerSetEmpty &) {
}, [](const MTPDinputStickerSetAnimatedEmoji &) {
}, [](const MTPDinputStickerSetDice &) {
});
_api.request(MTPmessages_GetStickerSet(
_input
Data::InputStickerSet(_input)
)).done([=](const MTPmessages_StickerSet &result) {
gotSet(result);
}).fail([=](const MTP::Error &error) {
@@ -428,7 +422,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
_setAccess = set.vaccess_hash().v;
_setCount = set.vcount().v;
_setHash = set.vhash().v;
_setFlags = set.vflags().v;
_setFlags = Data::ParseStickersSetFlags(set);
_setInstallDate = set.vinstalled_date().value_or(0);
_setThumbnail = [&] {
if (const auto thumbs = set.vthumbs()) {
@@ -448,12 +442,11 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
const auto it = sets.find(_setId);
if (it != sets.cend()) {
const auto set = it->second.get();
using ClientFlag = MTPDstickerSet_ClientFlag;
const auto clientFlags = set->flags
& (ClientFlag::f_featured
| ClientFlag::f_not_loaded
| ClientFlag::f_unread
| ClientFlag::f_special);
& (SetFlag::Featured
| SetFlag::NotLoaded
| SetFlag::Unread
| SetFlag::Special);
_setFlags |= clientFlags;
set->flags = _setFlags;
set->installDate = _setInstallDate;
@@ -499,7 +492,7 @@ void StickerSetBox::Inner::installDone(
auto &sets = stickers.setsRef();
const auto isMasks = isMasksSet();
const bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived);
const bool wasArchived = (_setFlags & SetFlag::Archived);
if (wasArchived) {
const auto index = (isMasks
? stickers.archivedMaskSetsOrderRef()
@@ -511,8 +504,8 @@ void StickerSetBox::Inner::installDone(
}
}
_setInstallDate = base::unixtime::now();
_setFlags &= ~MTPDstickerSet::Flag::f_archived;
_setFlags |= MTPDstickerSet::Flag::f_installed_date;
_setFlags &= ~SetFlag::Archived;
_setFlags |= SetFlag::Installed;
auto it = sets.find(_setId);
if (it == sets.cend()) {
it = sets.emplace(
@@ -695,8 +688,6 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
return;
}
int32 rows = (_elements.size() / kStickersPanelPerRow)
+ ((_elements.size() % kStickersPanelPerRow) ? 1 : 0);
int32 from = qFloor(e->rect().top() / st::stickersSize.height()), to = qFloor(e->rect().bottom() / st::stickersSize.height()) + 1;
_pathGradient->startFrame(0, width(), width() / 2);
@@ -850,8 +841,8 @@ bool StickerSetBox::Inner::notInstalled() const {
const auto &sets = _controller->session().data().stickers().sets();
const auto it = sets.find(_setId);
if ((it == sets.cend())
|| !(it->second->flags & MTPDstickerSet::Flag::f_installed_date)
|| (it->second->flags & MTPDstickerSet::Flag::f_archived)) {
|| !(it->second->flags & SetFlag::Installed)
|| (it->second->flags & SetFlag::Archived)) {
return !_pack.empty();
}
return false;
@@ -881,7 +872,7 @@ void StickerSetBox::Inner::install() {
return;
}
_installRequest = _api.request(MTPmessages_InstallStickerSet(
_input,
Data::InputStickerSet(_input),
MTP_bool(false)
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
installDone(result);
@@ -892,7 +883,7 @@ void StickerSetBox::Inner::install() {
void StickerSetBox::Inner::archiveStickers() {
_api.request(MTPmessages_InstallStickerSet(
_input,
Data::InputStickerSet(_input),
MTP_boolTrue()
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultSuccess) {

View File

@@ -26,7 +26,7 @@ public:
StickerSetBox(
QWidget*,
not_null<Window::SessionController*> controller,
const MTPInputStickerSet &set);
const StickerSetIdentifier &set);
static QPointer<Ui::BoxContent> Show(
not_null<Window::SessionController*> controller,
@@ -49,7 +49,7 @@ private:
void handleError(Error error);
const not_null<Window::SessionController*> _controller;
MTPInputStickerSet _set;
const StickerSetIdentifier _set;
class Inner;
QPointer<Inner> _inner;

View File

@@ -45,6 +45,7 @@ namespace {
using Data::StickersSet;
using Data::StickersSetsOrder;
using Data::StickersSetThumbnailView;
using SetFlag = Data::StickersSetFlag;
constexpr auto kArchivedLimitFirstRequest = 10;
constexpr auto kArchivedLimitPerPage = 30;
@@ -233,7 +234,7 @@ private:
void rebuildMegagroupSet();
void fixupMegagroupSetAddress();
void handleMegagroupSetAddressChange();
void setMegagroupSelectedSet(const MTPInputStickerSet &set);
void setMegagroupSelectedSet(const StickerSetIdentifier &set);
int countMaxNameWidth() const;
@@ -284,7 +285,7 @@ private:
int _scrollbar = 0;
ChannelData *_megagroupSet = nullptr;
MTPInputStickerSet _megagroupSetInput = MTP_inputStickerSetEmpty();
StickerSetIdentifier _megagroupSetInput;
std::unique_ptr<Row> _megagroupSelectedSet;
object_ptr<AddressField> _megagroupSetField = { nullptr };
object_ptr<Ui::PlainShadow> _megagroupSelectedShadow = { nullptr };
@@ -429,8 +430,11 @@ void StickersBox::showAttachedStickers() {
if (const auto set = session().data().stickers().feedSet(*setData)) {
if (_attached.widget()->appendSet(set)) {
addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
session().api().scheduleStickerSetRequest(set->id, set->access);
if (set->stickers.isEmpty()
|| (set->flags & SetFlag::NotLoaded)) {
session().api().scheduleStickerSetRequest(
set->id,
set->access);
}
}
}
@@ -495,8 +499,11 @@ void StickersBox::getArchivedDone(
}
if (_archived.widget()->appendSet(set)) {
addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
session().api().scheduleStickerSetRequest(set->id, set->access);
if (set->stickers.isEmpty()
|| (set->flags & SetFlag::NotLoaded)) {
session().api().scheduleStickerSetRequest(
set->id,
set->access);
}
}
}
@@ -682,7 +689,7 @@ void StickersBox::loadMoreArchived() {
--setIt;
auto it = sets.find(*setIt);
if (it != sets.cend()) {
if (it->second->flags & MTPDstickerSet::Flag::f_archived) {
if (it->second->flags & SetFlag::Archived) {
lastId = it->second->id;
break;
}
@@ -834,8 +841,8 @@ void StickersBox::installSet(uint64 setId) {
}
}
}
if (!(set->flags & MTPDstickerSet::Flag::f_installed_date)
|| (set->flags & MTPDstickerSet::Flag::f_archived)) {
if (!(set->flags & SetFlag::Installed)
|| (set->flags & SetFlag::Archived)) {
_api.request(MTPmessages_InstallStickerSet(
set->mtpInput(),
MTP_boolFalse()
@@ -896,7 +903,8 @@ void StickersBox::requestArchivedSets() {
auto it = sets.find(setId);
if (it != sets.cend()) {
const auto set = it->second.get();
if (set->stickers.isEmpty() && (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
if (set->stickers.isEmpty()
&& (set->flags & SetFlag::NotLoaded)) {
session().api().scheduleStickerSetRequest(setId, set->access);
}
}
@@ -1042,7 +1050,7 @@ bool StickersBox::Inner::Row::isRecentSet() const {
}
bool StickersBox::Inner::Row::isMasksSet() const {
return (set->flags & MTPDstickerSet::Flag::f_masks);
return (set->flags & SetFlag::Masks);
}
StickersBox::Inner::Inner(
@@ -1694,7 +1702,6 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
_installSetCallback(_rows[_actionDown]->set->id);
}
} else if (_dragging >= 0) {
QPoint local(mapFromGlobal(_mouse));
_rows[_dragging]->yadd.start(0.);
_aboveShadowFadeStart = _shiftingStartTimes[_dragging] = crl::now();
_aboveShadowFadeOpacity = anim::value(aboveShadowOpacity(), 0);
@@ -1713,14 +1720,14 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
const auto showSetByRow = [&](const Row &row) {
setSelected(SelectedRow());
_controller->show(
Box<StickerSetBox>(_controller, row.set->mtpInput()),
Box<StickerSetBox>(_controller, row.set->identifier()),
Ui::LayerOption::KeepOther);
};
if (selectedIndex >= 0 && !_inDragArea) {
const auto row = _rows[selectedIndex].get();
if (!row->isRecentSet()) {
if (_megagroupSet) {
setMegagroupSelectedSet(row->set->mtpInput());
setMegagroupSelectedSet(row->set->identifier());
} else {
showSetByRow(*row);
}
@@ -1735,12 +1742,8 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
void StickersBox::Inner::saveGroupSet() {
Expects(_megagroupSet != nullptr);
auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID)
? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v
: 0;
auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID)
? _megagroupSetInput.c_inputStickerSetID().vid().v
: 0;
auto oldId = _megagroupSet->mgInfo->stickerSet.id;
auto newId = _megagroupSetInput.id;
if (newId != oldId) {
session().api().setGroupStickerSet(_megagroupSet, _megagroupSetInput);
session().data().stickers().notifyStickerSetInstalled(
@@ -1877,7 +1880,7 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
const auto &sets = session().data().stickers().sets();
const auto it = sets.find(_megagroupSelectedSet->set->id);
if (it != sets.cend() && !it->second->shortName.isEmpty()) {
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
setMegagroupSelectedSet({});
}
}
} else if (!_megagroupSetRequestId) {
@@ -1886,12 +1889,10 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
)).done([=](const MTPmessages_StickerSet &result) {
_megagroupSetRequestId = 0;
auto set = session().data().stickers().feedSetFull(result);
setMegagroupSelectedSet(MTP_inputStickerSetID(
MTP_long(set->id),
MTP_long(set->access)));
setMegagroupSelectedSet(set->identifier());
}).fail([=](const MTP::Error &error) {
_megagroupSetRequestId = 0;
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
setMegagroupSelectedSet({});
}).send();
} else {
_megagroupSetAddressChangedTimer.callOnce(kHandleMegagroupSetAddressChangeTimeout);
@@ -1900,7 +1901,8 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
void StickersBox::Inner::rebuildMegagroupSet() {
Expects(_megagroupSet != nullptr);
if (_megagroupSetInput.type() != mtpc_inputStickerSetID) {
if (!_megagroupSetInput.id) {
if (_megagroupSelectedSet) {
_megagroupSetField->setText(QString());
_megagroupSetField->finishAnimating();
@@ -1910,15 +1912,14 @@ void StickersBox::Inner::rebuildMegagroupSet() {
_megagroupSelectedShadow.destroy();
return;
}
auto &inputId = _megagroupSetInput.c_inputStickerSetID();
auto setId = inputId.vid().v;
auto setId = _megagroupSetInput.id;
const auto &sets = session().data().stickers().sets();
auto it = sets.find(setId);
if (it == sets.cend()
|| (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|| (it->second->flags & SetFlag::NotLoaded)) {
session().api().scheduleStickerSetRequest(
inputId.vid().v,
inputId.vaccess_hash().v);
_megagroupSetInput.id,
_megagroupSetInput.accessHash);
return;
}
@@ -1954,7 +1955,7 @@ void StickersBox::Inner::rebuildMegagroupSet() {
_megagroupSelectedRemove.create(this, st::groupStickersRemove);
_megagroupSelectedRemove->show(anim::type::instant);
_megagroupSelectedRemove->setClickedCallback([this] {
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
setMegagroupSelectedSet({});
});
_megagroupSelectedShadow.create(this);
updateControlsGeometry();
@@ -2017,7 +2018,7 @@ void StickersBox::Inner::rebuild(bool masks) {
rebuildAppendSet(set, maxNameWidth);
if (set->stickers.isEmpty()
|| (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|| (set->flags & SetFlag::NotLoaded)) {
session().api().scheduleStickerSetRequest(set->id, set->access);
}
}
@@ -2025,7 +2026,7 @@ void StickersBox::Inner::rebuild(bool masks) {
updateSize();
}
void StickersBox::Inner::setMegagroupSelectedSet(const MTPInputStickerSet &set) {
void StickersBox::Inner::setMegagroupSelectedSet(const StickerSetIdentifier &set) {
_megagroupSetInput = set;
rebuild(false);
_scrollsToY.fire(0);
@@ -2232,11 +2233,11 @@ void StickersBox::Inner::fillSetFlags(
bool *outOfficial,
bool *outUnread,
bool *outArchived) {
*outInstalled = (set->flags & MTPDstickerSet::Flag::f_installed_date);
*outOfficial = (set->flags & MTPDstickerSet::Flag::f_official);
*outArchived = (set->flags & MTPDstickerSet::Flag::f_archived);
*outInstalled = (set->flags & SetFlag::Installed);
*outOfficial = (set->flags & SetFlag::Official);
*outArchived = (set->flags & SetFlag::Archived);
if (_section == Section::Featured) {
*outUnread = (set->flags & MTPDstickerSet_ClientFlag::f_unread);
*outUnread = (set->flags & SetFlag::Unread);
} else {
*outUnread = false;
}

View File

@@ -49,7 +49,7 @@ namespace Stickers {
class Set;
} // namespace Stickers
class StickersBox final : public Ui::BoxContent, private base::Subscriber {
class StickersBox final : public Ui::BoxContent {
public:
enum class Section {
Installed,

View File

@@ -1184,6 +1184,16 @@ desktopCaptureSubmit: RoundButton(desktopCaptureCancel) {
color: shadowFg;
}
}
desktopCaptureWithAudio: Checkbox(defaultCheckbox) {
textFg: groupCallMembersFg;
textFgActive: groupCallMembersFg;
rippleBg: groupCallMembersBgRipple;
rippleBgActive: groupCallMembersBgRipple;
style: semiboldTextStyle;
}
desktopCaptureWithAudioCheck: Check(defaultCheck) {
untoggledFg: groupCallActiveFg;
}
groupCallNarrowSkip: 9px;
groupCallNarrowMembersWidth: 204px;

View File

@@ -16,7 +16,7 @@ class SessionController;
namespace Calls {
class BoxController : public PeerListController, private base::Subscriber {
class BoxController : public PeerListController {
public:
explicit BoxController(not_null<Window::SessionController*> window);

View File

@@ -43,7 +43,7 @@ class GroupCall;
class Panel;
struct DhConfig;
class Instance : private base::Subscriber, public base::has_weak_ptr {
class Instance final : public base::has_weak_ptr {
public:
Instance();
~Instance();

View File

@@ -48,7 +48,6 @@ enum class BarState {
namespace {
constexpr auto kMaxUsersInBar = 3;
constexpr auto kUpdateDebugTimeoutMs = crl::time(500);
constexpr auto kSwitchStateDuration = 120;

View File

@@ -210,8 +210,8 @@ void Panel::Incoming::RendererGL::paint(
if (upload) {
uploadTexture(
f,
GL_RGBA,
GL_RGBA,
Ui::GL::kFormatRGBA,
Ui::GL::kFormatRGBA,
data.original.size(),
_rgbaSize,
data.original.bytesPerLine() / 4,

View File

@@ -31,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Calls::Group {
namespace {
constexpr auto kDefaultScheduleDuration = 60 * TimeId(60);
constexpr auto kLabelRefreshInterval = 10 * crl::time(1000);
using Context = ChooseJoinAsProcess::Context;

View File

@@ -74,12 +74,6 @@ constexpr auto kMaxMediumQualities = 16; // 4 Fulls or 16 Mediums.
return msgId / double(1ULL << 32);
}
[[nodiscard]] std::string ReadJsonString(
const QJsonObject &object,
const char *key) {
return object.value(key).toString().toStdString();
}
[[nodiscard]] uint64 FindLocalRaisedHandRating(
const std::vector<Data::GroupCallParticipant> &list) {
const auto i = ranges::max_element(
@@ -230,8 +224,7 @@ GroupCall::VideoTrack::VideoTrack(
if (i == mgInfo->lastAdmins.end()) {
return false;
}
const auto &rights = i->second.rights;
return rights.c_chatAdminRights().is_manage_call();
return (i->second.rights.flags & ChatAdminRight::ManageCall);
}
}
return false;
@@ -240,10 +233,11 @@ GroupCall::VideoTrack::VideoTrack(
struct VideoParams {
std::string endpointId;
std::vector<tgcalls::MediaSsrcGroup> ssrcGroups;
uint32 additionalSsrc = 0;
bool paused = false;
[[nodiscard]] bool empty() const {
return endpointId.empty() || ssrcGroups.empty();
return !additionalSsrc && (endpointId.empty() || ssrcGroups.empty());
}
[[nodiscard]] explicit operator bool() const {
return !empty();
@@ -262,7 +256,8 @@ struct ParticipantVideoParams {
return !was;
}
return now->match([&](const MTPDgroupCallParticipantVideo &data) {
if (data.is_paused() != was.paused) {
if (data.is_paused() != was.paused
|| data.vaudio_source().value_or_empty() != was.additionalSsrc) {
return false;
}
if (gsl::make_span(data.vendpoint().v)
@@ -311,6 +306,7 @@ struct ParticipantVideoParams {
params->match([&](const MTPDgroupCallParticipantVideo &data) {
result.paused = data.is_paused();
result.endpointId = data.vendpoint().v.toStdString();
result.additionalSsrc = data.vaudio_source().value_or_empty();
const auto &list = data.vsource_groups().v;
result.ssrcGroups.reserve(list.size());
for (const auto &group : list) {
@@ -350,6 +346,11 @@ bool IsScreenPaused(const std::shared_ptr<ParticipantVideoParams> &params) {
return params && params->screen.paused;
}
uint32 GetAdditionalAudioSsrc(
const std::shared_ptr<ParticipantVideoParams> &params) {
return params ? params->screen.additionalSsrc : 0;
}
std::shared_ptr<ParticipantVideoParams> ParseVideoParams(
const tl::conditional<MTPGroupCallParticipantVideo> &camera,
const tl::conditional<MTPGroupCallParticipantVideo> &screen,
@@ -612,6 +613,10 @@ QString GroupCall::screenSharingDeviceId() const {
return isSharingScreen() ? _screenDeviceId : QString();
}
bool GroupCall::screenSharingWithAudio() const {
return isSharingScreen() && _screenWithAudio;
}
bool GroupCall::mutedByAdmin() const {
const auto mute = muted();
return mute == MuteState::ForceMuted || mute == MuteState::RaisedHand;
@@ -634,7 +639,9 @@ void GroupCall::toggleVideo(bool active) {
: Webrtc::VideoState::Inactive;
}
void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
void GroupCall::toggleScreenSharing(
std::optional<QString> uniqueId,
bool withAudio) {
if (!_instance || !_id) {
return;
} else if (!uniqueId) {
@@ -644,10 +651,14 @@ void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
const auto changed = (_screenDeviceId != *uniqueId);
const auto wasSharing = isSharingScreen();
_screenDeviceId = *uniqueId;
_screenWithAudio = withAudio;
_screenState = Webrtc::VideoState::Active;
if (changed && wasSharing && isSharingScreen()) {
_screenCapture->switchToDevice(uniqueId->toStdString());
}
if (_screenInstance) {
_screenInstance->setIsMuted(!withAudio);
}
}
bool GroupCall::hasVideoWithFrames() const {
@@ -676,20 +687,6 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
setScheduledDate(date);
}, _lifetime);
// If we joined before you could start video and then you can,
// you have to rejoin so that the server knows your video params.
//real->canStartVideoValue( // ignore can_start_video after call start.
//) | rpl::combine_previous(
//) | rpl::start_with_next([=](bool could, bool can) {
// if (could || !can) {
// return;
// } if (_joinState.action == JoinAction::None) {
// rejoin();
// } else {
// _joinState.nextActionPending = true;
// }
//}, _lifetime);
// Postpone creating video tracks, so that we know if Panel
// supports OpenGL and we don't need ARGB32 frames at all.
Ui::PostponeCall(this, [=] {
@@ -985,22 +982,12 @@ void GroupCall::join(const MTPInputGroupCall &inputCall) {
return (_instance != nullptr);
}) | rpl::start_with_next([=](const Update &update) {
if (!update.now) {
_instance->removeSsrcs({ update.was->ssrc });
_instance->removeSsrcs({
update.was->ssrc,
GetAdditionalAudioSsrc(update.was->videoParams),
});
} else {
const auto &now = *update.now;
const auto &was = update.was;
const auto volumeChanged = was
? (was->volume != now.volume
|| was->mutedByMe != now.mutedByMe)
: (now.volume != Group::kDefaultVolume || now.mutedByMe);
if (volumeChanged) {
_instance->setVolume(
now.ssrc,
(now.mutedByMe
? 0.
: (now.volume
/ float64(Group::kDefaultVolume))));
}
updateInstanceVolume(update.was, *update.now);
}
}, _lifetime);
@@ -1509,7 +1496,6 @@ void GroupCall::applyParticipantLocally(
? participant->canSelfUnmute
: (!mute || IsGroupCallAdmin(_peer, participantPeer));
const auto isMutedByYou = mute && !canManageCall;
const auto mutedCount = 0/*participant->mutedCount*/;
using Flag = MTPDgroupCallParticipant::Flag;
const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0))
| Flag::f_volume // Without flag the volume is reset to 100%.
@@ -1970,14 +1956,37 @@ void GroupCall::setupMediaDevices() {
}, _lifetime);
}
int GroupCall::activeVideoSendersCount() const {
auto result = 0;
for (const auto &[endpoint, track] : _activeVideoTracks) {
if (endpoint.type == VideoEndpointType::Camera) {
++result;
} else {
auto sharesCameraToo = false;
for (const auto &[other, _] : _activeVideoTracks) {
if (other.type == VideoEndpointType::Camera
&& other.peer == endpoint.peer) {
sharesCameraToo = true;
break;
}
}
if (!sharesCameraToo) {
++result;
}
}
}
return result;
}
bool GroupCall::emitShareCameraError() {
const auto emitError = [=](Error error) {
emitShareCameraError(error);
return true;
};
/*if (const auto real = lookupReal(); real && !real->canStartVideo()) {
if (const auto real = lookupReal()
; real && activeVideoSendersCount() >= real->unmutedVideoLimit()) {
return emitError(Error::DisabledNoCamera);
} else */if (!videoIsWorking()) {
} else if (!videoIsWorking()) {
return emitError(Error::DisabledNoCamera);
} else if (mutedByAdmin()) {
return emitError(Error::MutedNoCamera);
@@ -2001,9 +2010,10 @@ bool GroupCall::emitShareScreenError() {
emitShareScreenError(error);
return true;
};
/*if (const auto real = lookupReal(); real && !real->canStartVideo()) {
if (const auto real = lookupReal()
; real && activeVideoSendersCount() >= real->unmutedVideoLimit()) {
return emitError(Error::DisabledNoScreen);
} else */if (!videoIsWorking()) {
} else if (!videoIsWorking()) {
return emitError(Error::DisabledNoScreen);
} else if (mutedByAdmin()) {
return emitError(Error::MutedNoScreen);
@@ -2025,7 +2035,6 @@ void GroupCall::setupOutgoingVideo() {
// Recursive entrance may happen if error happens when activating.
return (previous != state);
}) | rpl::start_with_next([=](VideoState previous, VideoState state) {
const auto wasPaused = (previous == VideoState::Paused);
const auto wasActive = (previous != VideoState::Inactive);
const auto nowPaused = (state == VideoState::Paused);
const auto nowActive = (state != VideoState::Inactive);
@@ -2080,7 +2089,6 @@ void GroupCall::setupOutgoingVideo() {
// Recursive entrance may happen if error happens when activating.
return (previous != state);
}) | rpl::start_with_next([=](VideoState previous, VideoState state) {
const auto wasPaused = (previous == VideoState::Paused);
const auto wasActive = (previous != VideoState::Inactive);
const auto nowPaused = (state == VideoState::Paused);
const auto nowActive = (state != VideoState::Inactive);
@@ -2296,6 +2304,7 @@ bool GroupCall::tryCreateScreencast() {
setScreenInstanceConnected(networkState);
});
},
.createAudioDeviceModule = Webrtc::LoopbackAudioDeviceModuleCreator(),
.videoCapture = _screenCapture,
.videoContentType = tgcalls::VideoContentType::Screencast,
};
@@ -2303,6 +2312,9 @@ bool GroupCall::tryCreateScreencast() {
LOG(("Call Info: Creating group screen instance"));
_screenInstance = std::make_unique<tgcalls::GroupInstanceCustomImpl>(
std::move(descriptor));
_screenInstance->setIsMuted(!_screenWithAudio);
return true;
}
@@ -2379,8 +2391,6 @@ void GroupCall::broadcastPartCancel(not_null<LoadPartTask*> task) {
void GroupCall::mediaChannelDescriptionsStart(
std::shared_ptr<MediaChannelDescriptionsTask> task) {
const auto raw = task.get();
const auto real = lookupReal();
if (!real || (_instanceMode == InstanceMode::None)) {
for (const auto ssrc : task->ssrcs()) {
@@ -2405,7 +2415,6 @@ bool GroupCall::mediaChannelDescriptionsFill(
auto result = false;
const auto real = lookupReal();
Assert(real != nullptr);
const auto &existing = real->participants();
for (const auto ssrc : task->ssrcs()) {
const auto add = [&](
std::optional<Channel> channel,
@@ -2647,15 +2656,33 @@ void GroupCall::updateInstanceVolumes() {
const auto &participants = real->participants();
for (const auto &participant : participants) {
const auto setVolume = participant.mutedByMe
|| (participant.volume != Group::kDefaultVolume);
if (setVolume && participant.ssrc) {
_instance->setVolume(
participant.ssrc,
(participant.mutedByMe
? 0.
: (participant.volume / float64(Group::kDefaultVolume))));
}
updateInstanceVolume(std::nullopt, participant);
}
}
void GroupCall::updateInstanceVolume(
const std::optional<Data::GroupCallParticipant> &was,
const Data::GroupCallParticipant &now) {
const auto nonDefault = now.mutedByMe
|| (now.volume != Group::kDefaultVolume);
const auto volumeChanged = was
? (was->volume != now.volume || was->mutedByMe != now.mutedByMe)
: nonDefault;
const auto additionalSsrc = GetAdditionalAudioSsrc(now.videoParams);
const auto set = now.ssrc
&& (volumeChanged || (was && was->ssrc != now.ssrc));
const auto additionalSet = additionalSsrc
&& (volumeChanged
|| (was && (GetAdditionalAudioSsrc(was->videoParams)
!= additionalSsrc)));
const auto localVolume = now.mutedByMe
? 0.
: (now.volume / float64(Group::kDefaultVolume));
if (set) {
_instance->setVolume(now.ssrc, localVolume);
}
if (additionalSet) {
_instance->setVolume(additionalSsrc, localVolume);
}
}
@@ -2776,7 +2803,7 @@ void GroupCall::checkJoined() {
MTP_vector<MTPint>(std::move(sources))
)).done([=](const MTPVector<MTPint> &result) {
if (!ranges::contains(result.v, MTP_int(_joinState.ssrc))) {
LOG(("Call Info: Rejoin after no _mySsrc in checkGroupCall."));
LOG(("Call Info: Rejoin after no my ssrc in checkGroupCall."));
_joinState.nextActionPending = true;
checkNextJoinAction();
} else {
@@ -2840,8 +2867,6 @@ void GroupCall::setScreenInstanceConnected(
: inTransit
? InstanceState::TransitionToRtc
: InstanceState::Connected;
const auto connected = (screenInstanceState
!= InstanceState::Disconnected);
if (_screenInstanceState.current() == screenInstanceState) {
return;
}
@@ -3085,11 +3110,6 @@ std::variant<int, not_null<UserData*>> GroupCall::inviteUsers(
return 0;
}
const auto owner = &_peer->owner();
const auto &invited = owner->invitedToCallUsers(_id);
auto &&toInvite = users | ranges::views::filter([&](
not_null<UserData*> user) {
return !invited.contains(user) && !real->participantByPeer(user);
});
auto count = 0;
auto slice = QVector<MTPInputUser>();

View File

@@ -169,6 +169,8 @@ struct ParticipantVideoParams;
const std::shared_ptr<ParticipantVideoParams> &params);
[[nodiscard]] bool IsScreenPaused(
const std::shared_ptr<ParticipantVideoParams> &params);
[[nodiscard]] uint32 GetAdditionalAudioSsrc(
const std::shared_ptr<ParticipantVideoParams> &params);
class GroupCall final : public base::has_weak_ptr {
public:
@@ -378,8 +380,11 @@ public:
[[nodiscard]] bool isCameraPaused() const;
[[nodiscard]] const std::string &cameraSharingEndpoint() const;
[[nodiscard]] QString screenSharingDeviceId() const;
[[nodiscard]] bool screenSharingWithAudio() const;
void toggleVideo(bool active);
void toggleScreenSharing(std::optional<QString> uniqueId);
void toggleScreenSharing(
std::optional<QString> uniqueId,
bool withAudio = false);
[[nodiscard]] bool hasVideoWithFrames() const;
[[nodiscard]] rpl::producer<bool> hasVideoWithFramesValue() const;
@@ -482,6 +487,9 @@ private:
void sendSelfUpdate(SendUpdateType type);
void updateInstanceMuteState();
void updateInstanceVolumes();
void updateInstanceVolume(
const std::optional<Data::GroupCallParticipant> &was,
const Data::GroupCallParticipant &now);
void applyMeInCallLocally();
void rejoin();
void leave();
@@ -543,6 +551,8 @@ private:
void markTrackPaused(const VideoEndpoint &endpoint, bool paused);
void markTrackShown(const VideoEndpoint &endpoint, bool shown);
[[nodiscard]] int activeVideoSendersCount() const;
[[nodiscard]] MTPInputGroupCall inputCall() const;
const not_null<Delegate*> _delegate;
@@ -609,6 +619,7 @@ private:
rpl::variable<Webrtc::VideoState> _screenState;
rpl::variable<bool> _isSharingScreen = false;
QString _screenDeviceId;
bool _screenWithAudio = false;
base::flags<SendUpdateType> _pendingSelfUpdates;
bool _requireARGB32 = true;

View File

@@ -106,7 +106,7 @@ std::unique_ptr<PeerListRow> InviteController::createRow(
if (!user
|| user->isSelf()
|| user->isBot()
|| (user->flags() & MTPDuser::Flag::f_deleted)) {
|| user->isInaccessible()) {
return nullptr;
}
auto result = std::make_unique<PeerListRow>(user);

View File

@@ -41,7 +41,6 @@ namespace Calls::Group {
namespace {
constexpr auto kKeepRaisedHandStatusDuration = 3 * crl::time(1000);
constexpr auto kShadowMaxAlpha = 74;
constexpr auto kUserpicSizeForBlur = 40;
constexpr auto kUserpicBlurRadius = 8;
@@ -225,6 +224,7 @@ private:
const Data::GroupCallParticipant &now);
void updateRow(
not_null<Row*> row,
const std::optional<Data::GroupCallParticipant> &was,
const Data::GroupCallParticipant *participant);
void removeRow(not_null<Row*> row);
void updateRowLevel(not_null<Row*> row, float level);
@@ -496,9 +496,8 @@ void Members::Controller::subscribeToChanges(not_null<Data::GroupCall*> real) {
: update.now->peer;
if (!update.now) {
if (const auto row = findRow(participantPeer)) {
const auto owner = &participantPeer->owner();
if (isMe(participantPeer)) {
updateRow(row, nullptr);
updateRow(row, update.was, nullptr);
} else {
removeRow(row);
delegate()->peerListRefreshRows();
@@ -598,7 +597,7 @@ void Members::Controller::updateRow(
if (row->state() == Row::State::Invited) {
reorderIfInvitedBefore = row->absoluteIndex();
}
updateRow(row, &now);
updateRow(row, was, &now);
if ((now.speaking && (!was || !was->speaking))
|| (now.raisedHandRating != (was ? was->raisedHandRating : 0))
|| (!now.canSelfUnmute && was && was->canSelfUnmute)) {
@@ -776,18 +775,25 @@ void Members::Controller::checkRowPosition(not_null<Row*> row) {
void Members::Controller::updateRow(
not_null<Row*> row,
const std::optional<Data::GroupCallParticipant> &was,
const Data::GroupCallParticipant *participant) {
const auto wasSounding = row->sounding();
const auto wasSsrc = row->ssrc();
const auto wasInChat = (row->state() != Row::State::Invited);
const auto wasSsrc = was ? was->ssrc : 0;
const auto wasAdditionalSsrc = was
? GetAdditionalAudioSsrc(was->videoParams)
: 0;
row->setSkipLevelUpdate(_skipRowLevelUpdate);
row->updateState(participant);
const auto nowSounding = row->sounding();
const auto nowSsrc = row->ssrc();
const auto nowSsrc = participant ? participant->ssrc : 0;
const auto nowAdditionalSsrc = participant
? GetAdditionalAudioSsrc(participant->videoParams)
: 0;
const auto wasNoSounding = _soundingRowBySsrc.empty();
if (wasSsrc == nowSsrc) {
if (nowSounding != wasSounding) {
if (nowSsrc && nowSounding != wasSounding) {
if (nowSounding) {
_soundingRowBySsrc.emplace(nowSsrc, row);
} else {
@@ -796,11 +802,25 @@ void Members::Controller::updateRow(
}
} else {
_soundingRowBySsrc.remove(wasSsrc);
if (nowSounding) {
Assert(nowSsrc != 0);
if (nowSounding && nowSsrc) {
_soundingRowBySsrc.emplace(nowSsrc, row);
}
}
if (wasAdditionalSsrc == nowAdditionalSsrc) {
if (nowAdditionalSsrc && nowSounding != wasSounding) {
if (nowSounding) {
_soundingRowBySsrc.emplace(nowAdditionalSsrc, row);
} else {
_soundingRowBySsrc.remove(nowAdditionalSsrc);
}
}
} else {
_soundingRowBySsrc.remove(wasAdditionalSsrc);
if (nowSounding && nowAdditionalSsrc) {
_soundingRowBySsrc.emplace(nowAdditionalSsrc, row);
}
}
const auto nowNoSounding = _soundingRowBySsrc.empty();
if (wasNoSounding && !nowNoSounding) {
_soundingAnimation.start();
@@ -812,7 +832,14 @@ void Members::Controller::updateRow(
}
void Members::Controller::removeRow(not_null<Row*> row) {
_soundingRowBySsrc.remove(row->ssrc());
// There may be 0, 1 or 2 entries for a row.
for (auto i = begin(_soundingRowBySsrc); i != end(_soundingRowBySsrc);) {
if (i->second == row) {
i = _soundingRowBySsrc.erase(i);
} else {
++i;
}
}
delegate()->peerListRemoveRow(row);
}
@@ -1346,11 +1373,17 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
}
}
}
}
if (real->ssrc() != 0
&& (!isMe(participantPeer) || _peer->canManageGroupCall())) {
addMuteActionsToContextMenu(result, participantPeer, admin, real);
if (participant
&& (!isMe(participantPeer) || _peer->canManageGroupCall())
&& (participant->ssrc != 0
|| GetAdditionalAudioSsrc(participant->videoParams) != 0)) {
addMuteActionsToContextMenu(
result,
participantPeer,
admin,
static_cast<Row*>(row.get()));
}
}
if (isMe(participantPeer)) {
@@ -1548,14 +1581,14 @@ void Members::Controller::addMuteActionsToContextMenu(
std::unique_ptr<Row> Members::Controller::createRowForMe() {
auto result = std::make_unique<Row>(this, _call->joinAs());
updateRow(result.get(), nullptr);
updateRow(result.get(), std::nullopt, nullptr);
return result;
}
std::unique_ptr<Row> Members::Controller::createRow(
const Data::GroupCallParticipant &participant) {
auto result = std::make_unique<Row>(this, participant.peer);
updateRow(result.get(), &participant);
updateRow(result.get(), std::nullopt, &participant);
return result;
}
@@ -1565,7 +1598,7 @@ std::unique_ptr<Row> Members::Controller::createInvitedRow(
return nullptr;
}
auto result = std::make_unique<Row>(this, participantPeer);
updateRow(result.get(), nullptr);
updateRow(result.get(), std::nullopt, nullptr);
return result;
}
@@ -1656,7 +1689,7 @@ void Members::setupAddMember(not_null<GroupCall*> call) {
) | rpl::map([=] {
return Data::PeerFlagValue(
channel,
MTPDchannel::Flag::f_username);
ChannelDataFlag::Username);
}) | rpl::flatten_latest());
} else {
_canAddMembers = Data::CanWriteValue(peer.get());

View File

@@ -144,7 +144,6 @@ void MembersRow::setSkipLevelUpdate(bool value) {
void MembersRow::updateState(
const Data::GroupCallParticipant *participant) {
setSsrc(participant ? participant->ssrc : 0);
setVolume(participant
? participant->volume
: Group::kDefaultVolume);
@@ -155,10 +154,16 @@ void MembersRow::updateState(
_mutedByMe = false;
_raisedHandRating = 0;
} else if (!participant->muted
|| (participant->sounding && participant->ssrc != 0)) {
|| (participant->sounding && participant->ssrc != 0)
|| (participant->additionalSounding
&& GetAdditionalAudioSsrc(participant->videoParams) != 0)) {
setState(State::Active);
setSounding(participant->sounding && participant->ssrc != 0);
setSpeaking(participant->speaking && participant->ssrc != 0);
setSounding((participant->sounding && participant->ssrc != 0)
|| (participant->additionalSounding
&& GetAdditionalAudioSsrc(participant->videoParams) != 0));
setSpeaking((participant->speaking && participant->ssrc != 0)
|| (participant->additionalSpeaking
&& GetAdditionalAudioSsrc(participant->videoParams) != 0));
_mutedByMe = participant->mutedByMe;
_raisedHandRating = 0;
} else if (participant->canSelfUnmute) {
@@ -283,10 +288,6 @@ void MembersRow::setState(State state) {
}
}
void MembersRow::setSsrc(uint32 ssrc) {
_ssrc = ssrc;
}
void MembersRow::setVolume(int volume) {
_volume = volume;
if (_statusIcon) {

View File

@@ -85,9 +85,6 @@ public:
[[nodiscard]] State state() const {
return _state;
}
[[nodiscard]] uint32 ssrc() const {
return _ssrc;
}
[[nodiscard]] bool sounding() const {
return _sounding;
}
@@ -179,7 +176,6 @@ private:
void setSounding(bool sounding);
void setSpeaking(bool speaking);
void setState(State state);
void setSsrc(uint32 ssrc);
void setVolume(int volume);
void ensureUserpicCache(
@@ -212,7 +208,6 @@ private:
QString _aboutText;
crl::time _speakingLastTime = 0;
uint64 _raisedHandRating = 0;
uint32 _ssrc = 0;
int _volume = Group::kDefaultVolume;
bool _sounding : 1;
bool _speaking : 1;

View File

@@ -109,34 +109,6 @@ void StopGroupCallRecordingBox(
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
}
[[nodiscard]] auto ToDurationFrom(TimeId startDate) {
return [=] {
const auto now = base::unixtime::now();
const auto elapsed = std::max(now - startDate, 0);
const auto hours = elapsed / 3600;
const auto minutes = (elapsed % 3600) / 60;
const auto seconds = (elapsed % 60);
return hours
? QString("%1:%2:%3"
).arg(hours
).arg(minutes, 2, 10, QChar('0')
).arg(seconds, 2, 10, QChar('0'))
: QString("%1:%2"
).arg(minutes
).arg(seconds, 2, 10, QChar('0'));
};
}
[[nodiscard]] rpl::producer<QString> ToRecordDuration(TimeId startDate) {
return !startDate
? (rpl::single(QString()) | rpl::type_erased())
: rpl::single(
rpl::empty_value()
) | rpl::then(base::timer_each(
crl::time(1000)
)) | rpl::map(ToDurationFrom(startDate));
}
class JoinAsAction final : public Ui::Menu::ItemBase {
public:
JoinAsAction(
@@ -451,7 +423,6 @@ void RecordingAction::prepare(rpl::producer<QString> text) {
std::move(text) | rpl::start_with_next([=](QString text) {
const auto &padding = _st.itemPadding;
_text.setMarkedText(_st.itemStyle, { text }, MenuTextOptions);
const auto textWidth = _text.maxWidth();
_textWidth = w - padding.left() - padding.right();
update();
}, lifetime());

View File

@@ -260,12 +260,26 @@ QString Panel::chooseSourceActiveDeviceId() {
return _call->screenSharingDeviceId();
}
bool Panel::chooseSourceActiveWithAudio() {
return _call->screenSharingWithAudio();
}
bool Panel::chooseSourceWithAudioSupported() {
#ifdef Q_OS_WIN
return true;
#else // Q_OS_WIN
return false;
#endif // Q_OS_WIN
}
rpl::lifetime &Panel::chooseSourceInstanceLifetime() {
return lifetime();
}
void Panel::chooseSourceAccepted(const QString &deviceId) {
_call->toggleScreenSharing(deviceId);
void Panel::chooseSourceAccepted(
const QString &deviceId,
bool withAudio) {
_call->toggleScreenSharing(deviceId, withAudio);
}
void Panel::chooseSourceStop() {
@@ -498,7 +512,6 @@ void Panel::refreshLeftButton() {
}
void Panel::refreshVideoButtons(std::optional<bool> overrideWideMode) {
const auto real = _call->lookupReal();
const auto create = overrideWideMode.value_or(mode() == PanelMode::Wide)
|| (!_call->scheduleDate() && _call->videoIsWorking());
const auto created = _video && _screenShare;
@@ -1104,9 +1117,7 @@ void Panel::refreshTopButton() {
updateButtonsGeometry(); // _wideMenu <-> _settings
return;
}
const auto real = _call->lookupReal();
const auto hasJoinAs = _call->showChooseJoinAs();
const auto wide = (_mode.current() == PanelMode::Wide);
const auto showNarrowMenu = _call->canManage()
|| _call->videoIsWorking();
const auto showNarrowUserpic = !showNarrowMenu && hasJoinAs;
@@ -1188,7 +1199,7 @@ void Panel::chooseShareScreenSource() {
if (_call->isSharingScreen()) {
_call->toggleScreenSharing(std::nullopt);
} else {
chooseSourceAccepted(*source);
chooseSourceAccepted(*source, false);
}
} else {
Ui::DesktopCapture::ChooseSource(this);
@@ -1368,12 +1379,12 @@ void Panel::kickParticipantSure(not_null<PeerData*> participantPeer) {
const auto currentRestrictedRights = [&] {
const auto user = participantPeer->asUser();
if (!channel->mgInfo || !user) {
return ChannelData::EmptyRestrictedRights(participantPeer);
return ChatRestrictionsInfo();
}
const auto i = channel->mgInfo->lastRestricted.find(user);
return (i != channel->mgInfo->lastRestricted.cend())
? i->second.rights
: ChannelData::EmptyRestrictedRights(participantPeer);
: ChatRestrictionsInfo();
}();
channel->session().api().kickParticipant(
channel,
@@ -2146,9 +2157,6 @@ void Panel::refreshTitle() {
_subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
}
if (_subtitle) {
const auto middle = _title
? (_title->x() + _title->width() / 2)
: (widget()->width() / 2);
const auto top = _title
? st::groupCallSubtitleTop
: st::groupCallTitleTop;
@@ -2163,8 +2171,6 @@ void Panel::refreshTitleGeometry() {
return;
}
const auto fullRect = computeTitleRect();
const auto recordingWidth = 2 * st::groupCallRecordingMarkSkip
+ st::groupCallRecordingMark;
const auto titleRect = _recordingMark
? QRect(
fullRect.x(),

View File

@@ -169,8 +169,12 @@ private:
QWidget *chooseSourceParent() override;
QString chooseSourceActiveDeviceId() override;
bool chooseSourceActiveWithAudio() override;
bool chooseSourceWithAudioSupported() override;
rpl::lifetime &chooseSourceInstanceLifetime() override;
void chooseSourceAccepted(const QString &deviceId) override;
void chooseSourceAccepted(
const QString &deviceId,
bool withAudio) override;
void chooseSourceStop() override;
const not_null<GroupCall*> _call;

View File

@@ -53,7 +53,10 @@ namespace Calls::Group {
namespace {
constexpr auto kDelaysCount = 201;
#ifdef Q_OS_MAC
constexpr auto kCheckAccessibilityInterval = crl::time(500);
#endif // Q_OS_MAC
void SaveCallJoinMuted(
not_null<PeerData*> peer,
@@ -96,7 +99,6 @@ object_ptr<ShareBox> ShareInviteLinkBox(
const QString &linkSpeaker,
const QString &linkListener,
Fn<void(QString)> showToast) {
const auto session = &peer->session();
const auto sending = std::make_shared<bool>();
const auto box = std::make_shared<QPointer<ShareBox>>();
@@ -167,8 +169,6 @@ object_ptr<ShareBox> ShareInviteLinkBox(
}
const auto owner = &peer->owner();
auto &api = peer->session().api();
auto &histories = owner->histories();
const auto requestType = Data::Histories::RequestType::Send;
for (const auto peer : result) {
const auto history = owner->history(peer);
auto message = ApiWrap::MessageToSend(history);

View File

@@ -352,7 +352,6 @@ Viewport::Layout Viewport::applyLarge(Layout layout) const {
const auto largeTop = largeRect.y();
const auto largeRight = largeLeft + largeRect.width();
const auto largeBottom = largeTop + largeRect.height();
const auto largeCenter = largeRect.center();
for (auto &geometry : list) {
if (geometry.tile == _large) {
geometry.*field = { QPoint(), layout.outer };

View File

@@ -282,8 +282,6 @@ vec4 background() {
const auto scaled = InterpolateScaledSize(unscaled, size, expandRatio);
const auto left = (size.width() - scaled.width()) / 2;
const auto top = (size.height() - scaled.height()) / 2;
const auto right = left + scaled.width();
const auto bottom = top + scaled.height();
auto dleft = float(left) / scaled.width();
auto dright = float(size.width() - left) / scaled.width();
auto dtop = float(top) / scaled.height();
@@ -511,7 +509,6 @@ void Viewport::RendererGL::paintTile(
const auto fullNameShift = st.namePosition.y() + st::normalFont->height;
const auto nameShift = anim::interpolate(fullNameShift, 0, shown);
const auto row = tile->row();
const auto style = row->computeIconState(MembersRowStyle::Video);
validateOutlineAnimation(tile, tileData);
validatePausedAnimation(tile, tileData);
@@ -976,8 +973,8 @@ void Viewport::RendererGL::bindFrame(
const auto data = image.constBits();
uploadTexture(
f,
GL_RGBA,
GL_RGBA,
Ui::GL::kFormatRGBA,
Ui::GL::kFormatRGBA,
image.size(),
tileData.rgbaSize,
stride,
@@ -1336,7 +1333,6 @@ void Viewport::RendererGL::validateDatas() {
}
for (const auto &request : requests) {
const auto i = request.index;
const auto index = _tileDataIndices[i];
const auto &data = _tileData[_tileDataIndices[i]];
if (data.nameRect.isEmpty()) {
continue;

View File

@@ -75,10 +75,6 @@ MenuVolumeItem::MenuVolumeItem(
_speakerRect = QRect(_itemRect.topLeft(), _stCross.icon.size());
_arcPosition = _speakerRect.center()
+ QPoint(0, st::groupCallMenuSpeakerArcsSkip);
const auto sliderLeft = _arcPosition.x()
+ st::groupCallMenuVolumeSkip
+ _arcs->maxWidth()
+ st::groupCallMenuVolumeSkip;
_slider->setGeometry(
st::groupCallMenuVolumeMargin.left(),
_speakerRect.y(),

View File

@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/effects/ripple_animation.h"
#include "ui/image/image.h"
#include "ui/platform/ui_platform_window_title.h"
@@ -62,6 +63,8 @@ public:
[[nodiscard]] rpl::producer<> activations() const;
void setActive(bool active);
[[nodiscard]] bool isWindow() const;
[[nodiscard]] QString deviceIdKey() const;
[[nodiscard]] rpl::lifetime &lifetime();
private:
@@ -94,6 +97,7 @@ private:
void setupGeometryWithParent(not_null<QWidget*> parent);
void fillSources();
void setupSourcesGeometry();
void updateButtonsVisibility();
void destroy();
static base::flat_map<
@@ -107,6 +111,7 @@ private:
const not_null<RpWidget*> _bottom;
const not_null<RoundButton*> _submit;
const not_null<RoundButton*> _finish;
const not_null<Checkbox*> _withAudio;
std::vector<std::unique_ptr<Source>> _sources;
Source *_selected = nullptr;
@@ -166,6 +171,14 @@ rpl::producer<> Source::activations() const {
return _activations.events();
}
bool Source::isWindow() const {
return _source.isWindow();
}
QString Source::deviceIdKey() const {
return QString::fromStdString(_source.deviceIdKey());
}
void Source::setActive(bool active) {
if (_active != active) {
_active = active;
@@ -255,7 +268,13 @@ ChooseSourceProcess::ChooseSourceProcess(
CreateChild<RoundButton>(
_bottom.get(),
tr::lng_group_call_screen_share_stop(),
st::desktopCaptureFinish)) {
st::desktopCaptureFinish))
, _withAudio(
CreateChild<Checkbox>(
_bottom.get(),
tr::lng_group_call_screen_share_audio(tr::now),
false,
st::desktopCaptureWithAudio)) {
setupPanel();
setupSources();
activate();
@@ -336,7 +355,9 @@ void ChooseSourceProcess::setupPanel() {
return;
}
const auto weak = MakeWeak(_window.get());
_delegate->chooseSourceAccepted(_selectedId);
_delegate->chooseSourceAccepted(
_selectedId,
!_withAudio->isHidden() && _withAudio->checked());
if (const auto strong = weak.data()) {
strong->close();
}
@@ -375,6 +396,18 @@ void ChooseSourceProcess::setupPanel() {
bottomSkip);
}, _bottom->lifetime());
_withAudio->widthValue(
) | rpl::start_with_next([=](int width) {
const auto top = (bottomHeight - _withAudio->heightNoMargins()) / 2;
_withAudio->moveToLeft(bottomSkip, top);
}, _withAudio->lifetime());
_withAudio->setChecked(_delegate->chooseSourceActiveWithAudio());
_withAudio->checkedChanges(
) | rpl::start_with_next([=] {
updateButtonsVisibility();
}, _withAudio->lifetime());
const auto sharing = !_delegate->chooseSourceActiveDeviceId().isEmpty();
_finish->setVisible(sharing);
_submit->setVisible(!sharing);
@@ -420,6 +453,8 @@ void ChooseSourceProcess::fillSources() {
auto screensManager = tgcalls::DesktopCaptureSourceManager(Type::Screen);
auto windowsManager = tgcalls::DesktopCaptureSourceManager(Type::Window);
_withAudio->setVisible(_delegate->chooseSourceWithAudioSupported());
auto screenIndex = 0;
auto windowIndex = 0;
const auto active = _delegate->chooseSourceActiveDeviceId();
@@ -448,15 +483,7 @@ void ChooseSourceProcess::fillSources() {
_selected->setActive(false);
}
_selected = raw;
_selectedId = QString::fromStdString(id);
if (_selectedId == _delegate->chooseSourceActiveDeviceId()) {
_selectedId = QString();
_finish->setVisible(true);
_submit->setVisible(false);
} else {
_finish->setVisible(false);
_submit->setVisible(true);
}
updateButtonsVisibility();
}, raw->lifetime());
};
for (const auto &source : screensManager.sources()) {
@@ -467,6 +494,24 @@ void ChooseSourceProcess::fillSources() {
}
}
void ChooseSourceProcess::updateButtonsVisibility() {
const auto selectedId = _selected
? _selected->deviceIdKey()
: QString();
if (selectedId == _delegate->chooseSourceActiveDeviceId()
&& (!_delegate->chooseSourceWithAudioSupported()
|| (_withAudio->checked()
== _delegate->chooseSourceActiveWithAudio()))) {
_selectedId = QString();
_finish->setVisible(true);
_submit->setVisible(false);
} else {
_selectedId = selectedId;
_finish->setVisible(false);
_submit->setVisible(true);
}
}
void ChooseSourceProcess::setupSourcesGeometry() {
if (_sources.empty()) {
destroy();

View File

@@ -20,8 +20,12 @@ class ChooseSourceDelegate {
public:
virtual QWidget *chooseSourceParent() = 0;
virtual QString chooseSourceActiveDeviceId() = 0;
virtual bool chooseSourceActiveWithAudio() = 0;
virtual bool chooseSourceWithAudioSupported() = 0;
virtual rpl::lifetime &chooseSourceInstanceLifetime() = 0;
virtual void chooseSourceAccepted(const QString &deviceId) = 0;
virtual void chooseSourceAccepted(
const QString &deviceId,
bool withAudio) = 0;
virtual void chooseSourceStop() = 0;
};

View File

@@ -171,11 +171,11 @@ bool BotKeyboard::moderateKeyActivate(int key) {
App::sendBotCommand(user, user, qsl("/pattern"));
} else if (key == Qt::Key_4) {
App::sendBotCommand(user, user, qsl("/abuse"));
} else if (key == Qt::Key_0) {
} else if (key == Qt::Key_0 || key == Qt::Key_E || key == Qt::Key_9) {
App::sendBotCommand(user, user, qsl("/undo"));
} else if (key == Qt::Key_7) {
} else if (key == Qt::Key_Plus || key == Qt::Key_QuoteLeft || key == Qt::Key_7) {
App::sendBotCommand(user, user, qsl("/next"));
} else if (key == Qt::Key_8) {
} else if (key == Qt::Key_Period || key == Qt::Key_S || key == Qt::Key_8) {
App::sendBotCommand(user, user, qsl("/stats"));
}
return true;

View File

@@ -44,10 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QApplication>
class FieldAutocomplete::Inner final
: public Ui::RpWidget
, private base::Subscriber {
class FieldAutocomplete::Inner final : public Ui::RpWidget {
public:
struct ScrollTo {
int top;
@@ -1296,7 +1293,6 @@ void FieldAutocomplete::Inner::selectByMouse(QPoint globalPosition) {
int32 sel = -1, maxSel = 0;
if (!_srows->empty()) {
int32 rows = rowscount(_srows->size(), _stickersPerRow);
int32 row = (mouse.y() >= st::stickerPanPadding) ? ((mouse.y() - st::stickerPanPadding) / st::stickerPanSize.height()) : -1;
int32 col = (mouse.x() >= st::stickerPanPadding) ? ((mouse.x() - st::stickerPanPadding) / st::stickerPanSize.width()) : -1;
if (row >= 0 && col >= 0) {

View File

@@ -919,7 +919,7 @@ bool GifsListWidget::refreshInlineRows(int32 *added) {
int32 GifsListWidget::showInlineRows(bool newResults) {
auto added = 0;
auto clear = !refreshInlineRows(&added);
refreshInlineRows(&added);
if (newResults) {
scrollTo(0);
}

View File

@@ -1,5 +1,4 @@
/*
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.

View File

@@ -48,7 +48,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace ChatHelpers {
namespace {
constexpr auto kInlineItemsMaxPerRow = 5;
constexpr auto kSearchRequestDelay = 400;
constexpr auto kRecentDisplayLimit = 20;
constexpr auto kPreloadOfficialPages = 4;
@@ -57,10 +56,10 @@ constexpr auto kOfficialLoadLimit = 40;
using Data::StickersSet;
using Data::StickersPack;
using Data::StickersSetThumbnailView;
using SetFlag = Data::StickersSetFlag;
bool SetInMyList(MTPDstickerSet::Flags flags) {
return (flags & MTPDstickerSet::Flag::f_installed_date)
&& !(flags & MTPDstickerSet::Flag::f_archived);
[[nodiscard]] bool SetInMyList(Data::StickersSetFlags flags) {
return (flags & SetFlag::Installed) && !(flags & SetFlag::Archived);
}
} // namespace
@@ -218,7 +217,7 @@ auto StickersListWidget::PrepareStickers(
StickersListWidget::Set::Set(
uint64 id,
StickersSet *set,
MTPDstickerSet::Flags flags,
Data::StickersSetFlags flags,
const QString &title,
const QString &shortName,
int count,
@@ -356,7 +355,6 @@ void StickersListWidget::Footer::returnFocus() {
void StickersListWidget::Footer::enumerateVisibleIcons(
Fn<void(const StickerIcon &, int)> callback) {
auto iconsX = qRound(_iconsX.current());
auto index = iconsX / st::stickerIconWidth;
auto x = _iconsLeft - (iconsX % st::stickerIconWidth);
auto first = floorclamp(iconsX, st::stickerIconWidth, 0, _icons.size());
auto last = ceilclamp(
@@ -1110,7 +1108,7 @@ void StickersListWidget::readVisibleFeatured(
const auto rowTo = ceilclamp(visibleBottom, rowHeight, 0, _featuredSetsCount);
for (auto i = rowFrom; i < rowTo; ++i) {
auto &set = _officialSets[i];
if (!(set.flags & MTPDstickerSet_ClientFlag::f_unread)) {
if (!(set.flags & SetFlag::Unread)) {
continue;
}
if (i * rowHeight < visibleTop || (i + 1) * rowHeight > visibleBottom) {
@@ -1604,8 +1602,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
auto &set = sets[info.section];
if (set.externalLayout) {
const auto loadedCount = int(set.stickers.size());
const auto count = (set.flags
& MTPDstickerSet_ClientFlag::f_not_loaded)
const auto count = (set.flags & SetFlag::NotLoaded)
? set.count
: loadedCount;
@@ -1633,7 +1630,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
int checky = add.top() + (add.height() - st::stickersFeaturedInstalled.height()) / 2;
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
}
if (set.flags & MTPDstickerSet_ClientFlag::f_unread) {
if (set.flags & SetFlag::Unread) {
widthForTitle -= st::stickersFeaturedUnreadSize + st::stickersFeaturedUnreadSkip;
}
@@ -1647,7 +1644,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
p.setPen(st::stickersTrendingHeaderFg);
p.drawTextLeft(st::emojiPanHeaderLeft - st::roundRadiusSmall, info.top + st::stickersTrendingHeaderTop, width(), titleText, titleWidth);
if (set.flags & MTPDstickerSet_ClientFlag::f_unread) {
if (set.flags & SetFlag::Unread) {
p.setPen(Qt::NoPen);
p.setBrush(st::stickersFeaturedUnreadBg);
@@ -1709,7 +1706,6 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
paintMegagroupEmptySet(p, info.rowsTop, buttonSelected);
return true;
}
auto special = (set.flags & MTPDstickerSet::Flag::f_official) != 0;
auto fromRow = floorclamp(clip.y() - info.rowsTop, _singleSize.height(), 0, info.rowsCount);
auto toRow = ceilclamp(clip.y() + clip.height() - info.rowsTop, _singleSize.height(), 0, info.rowsCount);
for (int i = fromRow; i < toRow; ++i) {
@@ -1868,7 +1864,6 @@ void StickersListWidget::ensureLottiePlayer(Set &set) {
raw->updates(
) | rpl::start_with_next([=] {
const auto &sets = shownSets();
enumerateSections([&](const SectionInfo &info) {
if (shownSets()[info.section].lottiePlayer.get() == raw) {
update(
@@ -2024,7 +2019,7 @@ bool StickersListWidget::hasRemoveButton(int index) const {
return false;
}
auto flags = set.flags;
if (!(flags & MTPDstickerSet_ClientFlag::f_special)) {
if (!(flags & SetFlag::Special)) {
return true;
}
if (set.id == Data::Stickers::MegagroupSetId) {
@@ -2134,8 +2129,7 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const {
}
void StickersListWidget::showStickerSetBox(not_null<DocumentData*> document) {
if (document->sticker()
&& document->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
if (document->sticker() && document->sticker()->set) {
_displayingSet = true;
checkHideWithBox(StickerSetBox::Show(controller(), document));
}
@@ -2459,8 +2453,8 @@ void StickersListWidget::refreshFeaturedSets() {
auto &set = *i;
auto it = sets.find(set.id);
if (it == sets.cend()
|| ((it->second->flags & MTPDstickerSet::Flag::f_installed_date)
&& !(it->second->flags & MTPDstickerSet::Flag::f_archived)
|| ((it->second->flags & SetFlag::Installed)
&& !(it->second->flags & SetFlag::Archived)
&& !_installedLocallySets.contains(set.id))) {
continue;
}
@@ -2493,7 +2487,7 @@ void StickersListWidget::refreshSearchSets() {
void StickersListWidget::refreshSearchIndex() {
_searchIndex.clear();
for (const auto &set : _mySets) {
if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
if (set.flags & SetFlag::Special) {
continue;
}
const auto string = set.title + ' ' + set.shortName;
@@ -2545,12 +2539,12 @@ bool StickersListWidget::appendSet(
}
const auto set = it->second.get();
if ((skip == AppendSkip::Archived)
&& (set->flags & MTPDstickerSet::Flag::f_archived)) {
&& (set->flags & SetFlag::Archived)) {
return false;
}
if ((skip == AppendSkip::Installed)
&& (set->flags & MTPDstickerSet::Flag::f_installed_date)
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) {
&& (set->flags & SetFlag::Installed)
&& !(set->flags & SetFlag::Archived)) {
if (!_installedLocallySets.contains(setId)) {
return false;
}
@@ -2649,8 +2643,7 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
auto set = Set(
Data::Stickers::RecentSetId,
nullptr,
(MTPDstickerSet::Flag::f_official
| MTPDstickerSet_ClientFlag::f_special),
(SetFlag::Official | SetFlag::Special),
tr::lng_recent_stickers(tr::now),
shortName,
recentPack.size(),
@@ -2692,8 +2685,7 @@ void StickersListWidget::refreshFavedStickers() {
_mySets.insert(_mySets.begin(), Set{
Data::Stickers::FavedSetId,
nullptr,
(MTPDstickerSet::Flag::f_official
| MTPDstickerSet_ClientFlag::f_special),
(SetFlag::Official | SetFlag::Special),
Lang::Hard::FavedSetTitle(),
shortName,
set->count,
@@ -2714,7 +2706,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
auto isShownHere = [place](bool hidden) {
return (hidden == (place == GroupStickersPlace::Hidden));
};
if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetEmpty) {
if (!_megagroupSet->mgInfo->stickerSet) {
if (canEdit) {
auto hidden = session().settings().isGroupStickersSectionHidden(
_megagroupSet->id);
@@ -2725,7 +2717,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
_mySets.emplace_back(
Data::Stickers::MegagroupSetId,
nullptr,
MTPDstickerSet_ClientFlag::f_special | 0,
SetFlag::Special,
tr::lng_group_stickers(tr::now),
shortName,
count,
@@ -2745,16 +2737,16 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
if (canEdit && hidden) {
removeHiddenForGroup();
}
if (_megagroupSet->mgInfo->stickerSet.type() != mtpc_inputStickerSetID) {
const auto &set = _megagroupSet->mgInfo->stickerSet;
if (!set.id) {
return;
}
auto &set = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID();
const auto &sets = session().data().stickers().sets();
const auto it = sets.find(set.vid().v);
const auto it = sets.find(set.id);
if (it != sets.cend()) {
const auto set = it->second.get();
auto isInstalled = (set->flags & MTPDstickerSet::Flag::f_installed_date)
&& !(set->flags & MTPDstickerSet::Flag::f_archived);
auto isInstalled = (set->flags & SetFlag::Installed)
&& !(set->flags & SetFlag::Archived);
if (isInstalled && !canEdit) {
removeHiddenForGroup();
} else if (isShownHere(hidden)) {
@@ -2763,7 +2755,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
_mySets.emplace_back(
Data::Stickers::MegagroupSetId,
set,
MTPDstickerSet_ClientFlag::f_special | 0,
SetFlag::Special,
tr::lng_group_stickers(tr::now),
shortName,
set->count,
@@ -2771,13 +2763,12 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
PrepareStickers(set->stickers));
}
return;
} else if (!isShownHere(hidden)
|| _megagroupSetIdRequested == set.vid().v) {
} else if (!isShownHere(hidden) || _megagroupSetIdRequested == set.id) {
return;
}
_megagroupSetIdRequested = set.vid().v;
_megagroupSetIdRequested = set.id;
_api.request(MTPmessages_GetStickerSet(
_megagroupSet->mgInfo->stickerSet
Data::InputStickerSet(set)
)).done([=](const MTPmessages_StickerSet &result) {
if (const auto set = session().data().stickers().feedSetFull(result)) {
refreshStickers();
@@ -2870,7 +2861,7 @@ void StickersListWidget::updateSelected() {
newSelected = OverButton { section };
} else if (featuredHasAddButton(section) && myrtlrect(featuredAddRect(section)).contains(p.x(), p.y())) {
newSelected = OverButton{ section };
} else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) {
} else if (!(sets[section].flags & SetFlag::Special)) {
newSelected = OverSet { section };
} else if (sets[section].id == Data::Stickers::MegagroupSetId
&& (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) {
@@ -2884,7 +2875,6 @@ void StickersListWidget::updateSelected() {
newSelected = OverGroupAdd {};
}
} else {
auto special = ((set.flags & MTPDstickerSet::Flag::f_official) != 0);
auto rowIndex = qFloor(yOffset / _singleSize.height());
auto columnIndex = qFloor(sx / _singleSize.width());
auto index = rowIndex * _columnCount + columnIndex;
@@ -3083,8 +3073,8 @@ void StickersListWidget::displaySet(uint64 setId) {
Box<StickersBox>(controller(), _megagroupSet),
Ui::LayerOption::KeepOther).data());
return;
} else if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) {
setId = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v;
} else if (_megagroupSet->mgInfo->stickerSet.id) {
setId = _megagroupSet->mgInfo->stickerSet.id;
} else {
return;
}
@@ -3094,7 +3084,7 @@ void StickersListWidget::displaySet(uint64 setId) {
if (it != sets.cend()) {
_displayingSet = true;
checkHideWithBox(controller()->show(
Box<StickerSetBox>(controller(), it->second->mtpInput()),
Box<StickerSetBox>(controller(), it->second->identifier()),
Ui::LayerOption::KeepOther).data());
}
}
@@ -3115,8 +3105,7 @@ void StickersListWidget::installSet(uint64 setId) {
if (it != sets.cend()) {
const auto set = it->second.get();
const auto input = set->mtpInput();
if ((set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)
|| set->stickers.empty()) {
if ((set->flags & SetFlag::NotLoaded) || set->stickers.empty()) {
_api.request(MTPmessages_GetStickerSet(
input
)).done([=](const MTPmessages_StickerSet &result) {
@@ -3160,8 +3149,8 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
controller()->show(Box<ConfirmBox>(tr::lng_stickers_remove_group_set(tr::now), crl::guard(this, [this, group = _megagroupSet] {
Expects(group->mgInfo != nullptr);
if (group->mgInfo->stickerSet.type() != mtpc_inputStickerSetEmpty) {
session().api().setGroupStickerSet(group, MTP_inputStickerSetEmpty());
if (group->mgInfo->stickerSet) {
session().api().setGroupStickerSet(group, {});
}
Ui::hideLayer();
_removingSetId = 0;
@@ -3214,13 +3203,13 @@ void StickersListWidget::removeSet(uint64 setId) {
++i;
}
}
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
set->flags &= ~SetFlag::Installed;
set->installDate = TimeId(0);
//
// Set can be in search results.
//
//if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured)
// && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
//if (!(set->flags & SetFlag::Featured)
// && !(set->flags & SetFlag::Special)) {
// sets.erase(it);
//}
const auto removeIndex = defaultSetsOrder().indexOf(
@@ -3229,7 +3218,7 @@ void StickersListWidget::removeSet(uint64 setId) {
defaultSetsOrderRef().removeAt(removeIndex);
}
refreshStickers();
if (set->flags & MTPDstickerSet::Flag::f_masks) {
if (set->flags & SetFlag::Masks) {
session().local().writeInstalledMasks();
} else {
session().local().writeInstalledStickers();

View File

@@ -43,9 +43,7 @@ namespace ChatHelpers {
struct StickerIcon;
class StickersListWidget
: public TabbedSelector::Inner
, private base::Subscriber {
class StickersListWidget final : public TabbedSelector::Inner {
public:
StickersListWidget(
QWidget *parent,
@@ -192,7 +190,7 @@ private:
Set(
uint64 id,
Data::StickersSet *set,
MTPDstickerSet::Flags flags,
Data::StickersSetFlags flags,
const QString &title,
const QString &shortName,
int count,
@@ -204,7 +202,7 @@ private:
uint64 id = 0;
Data::StickersSet *set = nullptr;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
Data::StickersSetFlags flags;
QString title;
QString shortName;
std::vector<Sticker> stickers;
@@ -218,7 +216,7 @@ private:
};
struct FeaturedSet {
uint64 id = 0;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
Data::StickersSetFlags flags;
std::vector<Sticker> stickers;
};

View File

@@ -161,7 +161,6 @@ void TabbedPanel::updateContentHeight() {
return;
}
auto was = _contentHeight;
_contentHeight = contentHeight;
resize(QRect(0, 0, innerRect().width(), _contentHeight).marginsAdded(innerPadding()).size());

View File

@@ -130,8 +130,6 @@ void TabbedSelector::SlideAnimation::paintFrame(QPainter &p, float64 dt, float64
_frameAlpha = anim::interpolate(1, 256, opacity);
auto frameInts = _frameInts + _innerLeft + _innerTop * _frameIntsPerLine;
auto leftToRight = (_direction == Direction::LeftToRight);
auto easeOut = anim::easeOutCirc(1., dt);
@@ -241,7 +239,7 @@ void TabbedSelector::SlideAnimation::paintFrame(QPainter &p, float64 dt, float64
}
// Debug
//frameInts = _frameInts;
//auto frameInts = _frameInts;
//auto pattern = anim::shifted((static_cast<uint32>(0xFF) << 24) | (static_cast<uint32>(0xFF) << 16) | (static_cast<uint32>(0xFF) << 8) | static_cast<uint32>(0xFF));
//for (auto y = 0; y != _finalHeight; ++y) {
// for (auto x = 0; x != _finalWidth; ++x) {
@@ -803,11 +801,11 @@ void TabbedSelector::checkRestrictedPeer() {
const auto error = (_currentTabType == SelectorTab::Stickers)
? Data::RestrictionError(
_currentPeer,
ChatRestriction::f_send_stickers)
ChatRestriction::SendStickers)
: (_currentTabType == SelectorTab::Gifs)
? Data::RestrictionError(
_currentPeer,
ChatRestriction::f_send_gifs)
ChatRestriction::SendGifs)
: std::nullopt;
if (error) {
if (!_restrictedLabel) {
@@ -938,7 +936,6 @@ void TabbedSelector::switchTab() {
}
const auto wasSectionIcons = hasSectionIcons();
const auto wasTab = _currentTabType;
const auto wasIndex = indexByType(_currentTabType);
currentTab()->saveScrollTop();
@@ -1154,7 +1151,6 @@ int TabbedSelector::Inner::resizeGetHeight(int newWidth) {
}
int TabbedSelector::Inner::minimalHeight() const {
auto result = _minimalHeight;
return (_minimalHeight > 0)
? _minimalHeight
: (st::emojiPanMaxHeight - st::emojiFooterHeight);

View File

@@ -51,7 +51,7 @@ class EmojiListWidget;
class StickersListWidget;
class GifsListWidget;
class TabbedSelector : public Ui::RpWidget, private base::Subscriber {
class TabbedSelector : public Ui::RpWidget {
public:
struct FileChosen {
not_null<DocumentData*> document;

View File

@@ -143,7 +143,7 @@ std::map<int, const char*> BetaLogs() {
"- Use Direct3D 9 backend in ANGLE by default (Windows).\n"
"- Fix \"Show in Finder\" not focusing the Finder window (macOS).\n"
"- Use GTK from a child process (Linux).\n"
},
};

View File

@@ -18,7 +18,7 @@ namespace Core {
[[nodiscard]] QString FormatVersionDisplay(int version);
[[nodiscard]] QString FormatVersionPrecise(int version);
class Changelogs : public base::has_weak_ptr, private base::Subscriber {
class Changelogs final : public base::has_weak_ptr {
public:
Changelogs(not_null<Main::Session*> session, int oldVersion);

View File

@@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/send_files_box.h"
#include "ui/widgets/input_fields.h"
#include "storage/serialize_common.h"
#include "window/themes/window_theme.h"
#include "window/section_widget.h"
#include "base/platform/base_platform_info.h"
#include "webrtc/webrtc_create_adm.h"

View File

@@ -126,7 +126,7 @@ PreLaunchLog::PreLaunchLog(QWidget *parent) : QTextEdit(parent) {
setPalette(p);
setReadOnly(true);
setFrameStyle(QFrame::NoFrame | QFrame::Plain);
setFrameStyle(int(QFrame::NoFrame) | QFrame::Plain);
viewport()->setAutoFillBackground(false);
setContentsMargins(0, 0, 0, 0);
document()->setDocumentMargin(0);

View File

@@ -70,7 +70,7 @@ bool ShowStickerSet(
Core::App().hideMediaView();
controller->show(Box<StickerSetBox>(
controller,
MTP_inputStickerSetShortName(MTP_string(match->captured(1)))));
StickerSetIdentifier{ .shortName = match->captured(1) }));
return true;
}

View File

@@ -63,57 +63,6 @@ struct CRYPTO_dynlock_value {
namespace {
bool _sslInited = false;
QMutex *_sslLocks = nullptr;
void _sslLockingCallback(int mode, int type, const char *file, int line) {
if (!_sslLocks) return; // not inited
if (mode & CRYPTO_LOCK) {
_sslLocks[type].lock();
} else {
_sslLocks[type].unlock();
}
}
void _sslThreadId(CRYPTO_THREADID *id) {
CRYPTO_THREADID_set_pointer(id, QThread::currentThreadId());
}
CRYPTO_dynlock_value *_sslCreateFunction(const char *file, int line) {
return new CRYPTO_dynlock_value();
}
void _sslLockFunction(int mode, CRYPTO_dynlock_value *l, const char *file, int line) {
if (mode & CRYPTO_LOCK) {
l->mutex.lock();
} else {
l->mutex.unlock();
}
}
void _sslDestroyFunction(CRYPTO_dynlock_value *l, const char *file, int line) {
delete l;
}
int _ffmpegLockManager(void **mutex, AVLockOp op) {
switch (op) {
case AV_LOCK_CREATE: {
Assert(*mutex == nullptr);
*mutex = reinterpret_cast<void*>(new QMutex());
} break;
case AV_LOCK_OBTAIN: {
Assert(*mutex != nullptr);
reinterpret_cast<QMutex*>(*mutex)->lock();
} break;
case AV_LOCK_RELEASE: {
Assert(*mutex != nullptr);
reinterpret_cast<QMutex*>(*mutex)->unlock();
}; break;
case AV_LOCK_DESTROY: {
Assert(*mutex != nullptr);
delete reinterpret_cast<QMutex*>(*mutex);
*mutex = nullptr;
} break;
}
return 0;
}
}
namespace ThirdParty {

View File

@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 2008006;
constexpr auto AppVersionStr = "2.8.6";
constexpr auto AppBetaVersion = true;
constexpr auto AppVersion = 2008011;
constexpr auto AppVersionStr = "2.8.11";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -283,7 +283,6 @@ bool Should(
if (document->sticker()) {
return true;
}
const auto size = document->size;
return Should(data, Source::User, document)
|| Should(data, Source::Group, document)
|| Should(data, Source::Channel, document);

View File

@@ -50,6 +50,12 @@ bool MegagroupInfo::updateBotCommands(const MTPVector<MTPBotInfo> &data) {
return Data::UpdateBotCommands(_botCommands, data);
}
bool MegagroupInfo::updateBotCommands(
UserId botId,
const MTPVector<MTPBotCommand> &data) {
return Data::UpdateBotCommands(_botCommands, botId, data);
}
ChannelData::ChannelData(not_null<Data::Session*> owner, PeerId id)
: PeerData(owner, id)
, inputChannel(
@@ -58,14 +64,14 @@ ChannelData::ChannelData(not_null<Data::Session*> owner, PeerId id)
_flags.changes(
) | rpl::start_with_next([=](const Flags::Change &change) {
if (change.diff
& (MTPDchannel::Flag::f_left | MTPDchannel_ClientFlag::f_forbidden)) {
& (Flag::Left | Flag::Forbidden)) {
if (const auto chat = getMigrateFromChat()) {
session().changes().peerUpdated(chat, UpdateFlag::Migration);
session().changes().peerUpdated(this, UpdateFlag::Migration);
}
}
if (change.diff & MTPDchannel::Flag::f_megagroup) {
if (change.value & MTPDchannel::Flag::f_megagroup) {
if (change.diff & Flag::Megagroup) {
if (change.value & Flag::Megagroup) {
if (!mgInfo) {
mgInfo = std::make_unique<MegagroupInfo>();
}
@@ -73,7 +79,7 @@ ChannelData::ChannelData(not_null<Data::Session*> owner, PeerId id)
mgInfo = nullptr;
}
}
if (change.diff & MTPDchannel::Flag::f_call_not_empty) {
if (change.diff & Flag::CallNotEmpty) {
if (const auto history = this->owner().historyLoaded(this)) {
history->updateChatListEntry();
}
@@ -105,7 +111,7 @@ void ChannelData::setInviteLink(const QString &newInviteLink) {
bool ChannelData::canHaveInviteLink() const {
return amCreator()
|| (adminRights() & AdminRight::f_invite_users);
|| (adminRights() & AdminRight::InviteUsers);
}
void ChannelData::setLocation(const MTPChannelLocation &data) {
@@ -189,31 +195,26 @@ void ChannelData::setKickedCount(int newKickedCount) {
}
}
MTPChatBannedRights ChannelData::EmptyRestrictedRights(
ChatRestrictionsInfo ChannelData::KickedRestrictedRights(
not_null<PeerData*> participant) {
return MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
}
MTPChatBannedRights ChannelData::KickedRestrictedRights(
not_null<PeerData*> participant) {
using Flag = MTPDchatBannedRights::Flag;
const auto flags = Flag::f_view_messages
| Flag::f_send_messages
| Flag::f_send_media
| Flag::f_embed_links
| Flag::f_send_stickers
| Flag::f_send_gifs
| Flag::f_send_games
| Flag::f_send_inline;
return MTP_chatBannedRights(
MTP_flags(participant->isUser() ? flags : Flag::f_view_messages),
MTP_int(std::numeric_limits<int32>::max()));
using Flag = ChatRestriction;
const auto flags = Flag::ViewMessages
| Flag::SendMessages
| Flag::SendMedia
| Flag::EmbedLinks
| Flag::SendStickers
| Flag::SendGifs
| Flag::SendGames
| Flag::SendInline;
return ChatRestrictionsInfo(
(participant->isUser() ? flags : Flag::ViewMessages),
std::numeric_limits<int32>::max());
}
void ChannelData::applyEditAdmin(
not_null<UserData*> user,
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights,
const QString &rank) {
if (mgInfo) {
// If rights are empty - still add participant? TODO check
@@ -237,7 +238,7 @@ void ChannelData::applyEditAdmin(
auto userId = peerToUser(user->id);
auto it = mgInfo->lastAdmins.find(user);
if (newRights.c_chatAdminRights().vflags().v != 0) {
if (newRights.flags) {
auto lastAdmin = MegagroupInfo::Admin { newRights };
lastAdmin.canEdit = true;
if (it == mgInfo->lastAdmins.cend()) {
@@ -257,7 +258,7 @@ void ChannelData::applyEditAdmin(
Data::ChannelAdminChanges(this).remove(userId);
}
}
if (oldRights.c_chatAdminRights().vflags().v && !newRights.c_chatAdminRights().vflags().v) {
if (oldRights.flags && !newRights.flags) {
// We removed an admin.
if (adminsCount() > 1) {
setAdminsCount(adminsCount() - 1);
@@ -266,7 +267,7 @@ void ChannelData::applyEditAdmin(
// Removing bot admin removes it from channel.
setMembersCount(membersCount() - 1);
}
} else if (!oldRights.c_chatAdminRights().vflags().v && newRights.c_chatAdminRights().vflags().v) {
} else if (!oldRights.flags && newRights.flags) {
// We added an admin.
setAdminsCount(adminsCount() + 1);
updateFullForced();
@@ -276,13 +277,11 @@ void ChannelData::applyEditAdmin(
void ChannelData::applyEditBanned(
not_null<PeerData*> participant,
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights) {
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights) {
auto flags = UpdateFlag::BannedUsers | UpdateFlag::None;
auto isKicked = Data::ChatBannedRightsFlags(newRights)
& ChatRestriction::f_view_messages;
auto isRestricted = !isKicked
&& (Data::ChatBannedRightsFlags(newRights) != 0);
auto isKicked = newRights.flags & ChatRestriction::ViewMessages;
auto isRestricted = !isKicked && newRights.flags;
const auto user = participant->asUser();
if (mgInfo && user) {
// If rights are empty - still remove admin? TODO check
@@ -401,58 +400,57 @@ void ChannelData::setAvailableMinId(MsgId availableMinId) {
bool ChannelData::canBanMembers() const {
return amCreator()
|| (adminRights() & AdminRight::f_ban_users);
|| (adminRights() & AdminRight::BanUsers);
}
bool ChannelData::canEditMessages() const {
return amCreator()
|| (adminRights() & AdminRight::f_edit_messages);
|| (adminRights() & AdminRight::EditMessages);
}
bool ChannelData::canDeleteMessages() const {
return amCreator()
|| (adminRights() & AdminRight::f_delete_messages);
|| (adminRights() & AdminRight::DeleteMessages);
}
bool ChannelData::anyoneCanAddMembers() const {
return !(defaultRestrictions() & Restriction::f_invite_users);
return !(defaultRestrictions() & Restriction::InviteUsers);
}
bool ChannelData::hiddenPreHistory() const {
return (fullFlags() & MTPDchannelFull::Flag::f_hidden_prehistory);
return (flags() & Flag::PreHistoryHidden);
}
bool ChannelData::canAddMembers() const {
return isMegagroup()
? !amRestricted(ChatRestriction::f_invite_users)
: ((adminRights() & AdminRight::f_invite_users) || amCreator());
? !amRestricted(ChatRestriction::InviteUsers)
: ((adminRights() & AdminRight::InviteUsers) || amCreator());
}
bool ChannelData::canSendPolls() const {
return canWrite() && !amRestricted(ChatRestriction::f_send_polls);
return canWrite() && !amRestricted(ChatRestriction::SendPolls);
}
bool ChannelData::canAddAdmins() const {
return amCreator()
|| (adminRights() & AdminRight::f_add_admins);
|| (adminRights() & AdminRight::AddAdmins);
}
bool ChannelData::canPublish() const {
return amCreator()
|| (adminRights() & AdminRight::f_post_messages);
|| (adminRights() & AdminRight::PostMessages);
}
bool ChannelData::canWrite() const {
// Duplicated in Data::CanWriteValue().
const auto allowed = amIn() || (flags() & MTPDchannel::Flag::f_has_link);
const auto allowed = amIn() || (flags() & Flag::HasLink);
return allowed && (canPublish()
|| (!isBroadcast()
&& !amRestricted(Restriction::f_send_messages)));
&& !amRestricted(Restriction::SendMessages)));
}
bool ChannelData::canViewMembers() const {
return fullFlags()
& MTPDchannelFull::Flag::f_can_view_participants;
return flags() & Flag::CanViewParticipants;
}
bool ChannelData::canViewAdmins() const {
@@ -465,14 +463,14 @@ bool ChannelData::canViewBanned() const {
bool ChannelData::canEditInformation() const {
return isMegagroup()
? !amRestricted(Restriction::f_change_info)
: ((adminRights() & AdminRight::f_change_info) || amCreator());
? !amRestricted(Restriction::ChangeInfo)
: ((adminRights() & AdminRight::ChangeInfo) || amCreator());
}
bool ChannelData::canEditPermissions() const {
return isMegagroup()
&& !isGigagroup()
&& ((adminRights() & AdminRight::f_ban_users) || amCreator());
&& ((adminRights() & AdminRight::BanUsers) || amCreator());
}
bool ChannelData::canEditSignatures() const {
@@ -481,17 +479,17 @@ bool ChannelData::canEditSignatures() const {
bool ChannelData::canEditPreHistoryHidden() const {
return isMegagroup()
&& ((adminRights() & AdminRight::f_ban_users) || amCreator())
&& ((adminRights() & AdminRight::BanUsers) || amCreator())
&& (!isPublic() || canEditUsername());
}
bool ChannelData::canEditUsername() const {
return amCreator()
&& (fullFlags() & MTPDchannelFull::Flag::f_can_set_username);
&& (flags() & Flag::CanSetUsername);
}
bool ChannelData::canEditStickers() const {
return (fullFlags() & MTPDchannelFull::Flag::f_can_set_stickers);
return (flags() & Flag::CanSetStickers);
}
bool ChannelData::canDelete() const {
@@ -521,7 +519,7 @@ bool ChannelData::canEditAdmin(not_null<UserData*> user) const {
} else if (!canEditLastAdmin(user)) {
return false;
}
return adminRights() & AdminRight::f_add_admins;
return adminRights() & AdminRight::AddAdmins;
}
bool ChannelData::canRestrictParticipant(
@@ -536,19 +534,20 @@ bool ChannelData::canRestrictParticipant(
return false;
}
}
return adminRights() & AdminRight::f_ban_users;
return adminRights() & AdminRight::BanUsers;
}
void ChannelData::setAdminRights(const MTPChatAdminRights &rights) {
if (rights.c_chatAdminRights().vflags().v == adminRights()) {
void ChannelData::setAdminRights(ChatAdminRights rights) {
if (rights == adminRights()) {
return;
}
_adminRights.set(rights.c_chatAdminRights().vflags().v);
_adminRights.set(rights);
if (isMegagroup()) {
const auto self = session().user();
if (hasAdminRights()) {
if (!amCreator()) {
auto me = MegagroupInfo::Admin { rights };
auto me = MegagroupInfo::Admin{
ChatAdminRightsInfo{ rights } };
me.canEdit = false;
mgInfo->lastAdmins.emplace(self, me);
}
@@ -562,15 +561,12 @@ void ChannelData::setAdminRights(const MTPChatAdminRights &rights) {
UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
}
void ChannelData::setRestrictions(const MTPChatBannedRights &rights) {
const auto restrictedFlags = Data::ChatBannedRightsFlags(rights);
const auto restrictedUntilDate = Data::ChatBannedRightsUntilDate(rights);
if (restrictedFlags == restrictions()
&& restrictedUntilDate == _restrictedUntil) {
void ChannelData::setRestrictions(ChatRestrictionsInfo rights) {
if (rights.flags == restrictions() && rights.until == _restrictedUntil) {
return;
}
_restrictedUntil = restrictedUntilDate;
_restrictions.set(restrictedFlags);
_restrictedUntil = rights.until;
_restrictions.set(rights.flags);
if (isMegagroup()) {
const auto self = session().user();
if (hasRestrictions()) {
@@ -589,12 +585,11 @@ void ChannelData::setRestrictions(const MTPChatBannedRights &rights) {
UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
}
void ChannelData::setDefaultRestrictions(const MTPChatBannedRights &rights) {
const auto restrictionFlags = Data::ChatBannedRightsFlags(rights);
if (restrictionFlags == defaultRestrictions()) {
void ChannelData::setDefaultRestrictions(ChatRestrictions rights) {
if (rights == defaultRestrictions()) {
return;
}
_defaultRestrictions.set(restrictionFlags);
_defaultRestrictions.set(rights);
session().changes().peerUpdated(this, UpdateFlag::Rights);
}
@@ -698,7 +693,7 @@ void ChannelData::migrateCall(std::unique_ptr<Data::GroupCall> call) {
_call = std::move(call);
_call->setPeer(this);
session().changes().peerUpdated(this, UpdateFlag::GroupCall);
addFlags(MTPDchannel::Flag::f_call_active);
addFlags(Flag::CallActive);
}
void ChannelData::setGroupCall(
@@ -724,7 +719,7 @@ void ChannelData::setGroupCall(
scheduleDate);
owner().registerGroupCall(_call.get());
session().changes().peerUpdated(this, UpdateFlag::GroupCall);
addFlags(MTPDchannel::Flag::f_call_active);
addFlags(Flag::CallActive);
});
}
@@ -735,8 +730,7 @@ void ChannelData::clearGroupCall() {
owner().unregisterGroupCall(_call.get());
_call = nullptr;
session().changes().peerUpdated(this, UpdateFlag::GroupCall);
removeFlags(MTPDchannel::Flag::f_call_active
| MTPDchannel::Flag::f_call_not_empty);
removeFlags(Flag::CallActive | Flag::CallNotEmpty);
}
void ChannelData::setGroupCallDefaultJoinAs(PeerId peerId) {
@@ -765,7 +759,8 @@ void ApplyChannelUpdate(
!= ChannelData::UpdateStatus::Good) {
return;
}
channel->setDefaultRestrictions(update.vdefault_banned_rights());
channel->setDefaultRestrictions(Data::ChatBannedRightsFlags(
update.vdefault_banned_rights()));
}
void ApplyChannelUpdate(
@@ -800,10 +795,21 @@ void ApplyChannelUpdate(
}
channel->setMessagesTTL(update.vttl_period().value_or_empty());
channel->setFullFlags(update.vflags().v);
using Flag = ChannelDataFlag;
const auto mask = Flag::CanSetUsername
| Flag::CanViewParticipants
| Flag::CanSetStickers
| Flag::PreHistoryHidden
| Flag::Location;
channel->setFlags((channel->flags() & ~mask)
| (update.is_can_set_username() ? Flag::CanSetUsername : Flag())
| (update.is_can_view_participants() ? Flag::CanViewParticipants : Flag())
| (update.is_can_set_stickers() ? Flag::CanSetStickers : Flag())
| (update.is_hidden_prehistory() ? Flag::PreHistoryHidden : Flag())
| (update.vlocation() ? Flag::Location : Flag()));
channel->setUserpicPhoto(update.vchat_photo());
if (const auto migratedFrom = update.vmigrated_from_chat_id()) {
channel->addFlags(MTPDchannel::Flag::f_megagroup);
channel->addFlags(Flag::Megagroup);
const auto chat = channel->owner().chat(migratedFrom->v);
Data::ApplyMigration(chat, channel);
}
@@ -868,15 +874,14 @@ void ApplyChannelUpdate(
const auto stickerSet = update.vstickerset();
const auto set = stickerSet ? &stickerSet->c_stickerSet() : nullptr;
const auto newSetId = (set ? set->vid().v : 0);
const auto oldSetId = (channel->mgInfo->stickerSet.type() == mtpc_inputStickerSetID)
? channel->mgInfo->stickerSet.c_inputStickerSetID().vid().v
: 0;
const auto oldSetId = channel->mgInfo->stickerSet.id;
const auto stickersChanged = (canEditStickers != channel->canEditStickers())
|| (oldSetId != newSetId);
if (oldSetId != newSetId) {
channel->mgInfo->stickerSet = set
? MTP_inputStickerSetID(set->vid(), set->vaccess_hash())
: MTP_inputStickerSetEmpty();
channel->mgInfo->stickerSet = StickerSetIdentifier{
.id = set ? set->vid().v : 0,
.accessHash = set ? set->vaccess_hash().v : 0,
};
}
if (stickersChanged) {
session->changes().peerUpdated(channel, UpdateFlag::StickersSet);

View File

@@ -29,25 +29,50 @@ struct ChannelLocation {
}
};
enum class ChannelDataFlag {
Left = (1 << 0),
Creator = (1 << 1),
Forbidden = (1 << 2),
CallActive = (1 << 3),
CallNotEmpty = (1 << 4),
Signatures = (1 << 5),
Verified = (1 << 6),
Scam = (1 << 7),
Fake = (1 << 8),
Megagroup = (1 << 9),
Broadcast = (1 << 10),
Gigagroup = (1 << 11),
Username = (1 << 12),
Location = (1 << 13),
CanSetUsername = (1 << 14),
CanSetStickers = (1 << 15),
PreHistoryHidden = (1 << 16),
CanViewParticipants = (1 << 17),
HasLink = (1 << 18),
SlowmodeEnabled = (1 << 19),
};
inline constexpr bool is_flag_type(ChannelDataFlag) { return true; };
using ChannelDataFlags = base::flags<ChannelDataFlag>;
class MegagroupInfo {
public:
struct Admin {
explicit Admin(MTPChatAdminRights rights)
explicit Admin(ChatAdminRightsInfo rights)
: rights(rights) {
}
Admin(MTPChatAdminRights rights, bool canEdit)
Admin(ChatAdminRightsInfo rights, bool canEdit)
: rights(rights)
, canEdit(canEdit) {
}
MTPChatAdminRights rights;
ChatAdminRightsInfo rights;
bool canEdit = false;
};
struct Restricted {
explicit Restricted(MTPChatBannedRights rights)
explicit Restricted(ChatRestrictionsInfo rights)
: rights(rights) {
}
MTPChatBannedRights rights;
ChatRestrictionsInfo rights;
};
ChatData *getMigrateFromChat() const;
@@ -57,6 +82,9 @@ public:
void setLocation(const ChannelLocation &location);
bool updateBotCommands(const MTPVector<MTPBotInfo> &data);
bool updateBotCommands(
UserId botId,
const MTPVector<MTPBotCommand> &data);
[[nodiscard]] auto botCommands() const
-> const base::flat_map<UserId, std::vector<BotCommand>> & {
return _botCommands;
@@ -75,7 +103,7 @@ public:
QString creatorRank;
int botStatus = 0; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
bool joinedMessageFound = false;
MTPInputStickerSet stickerSet = MTP_inputStickerSetEmpty();
StickerSetIdentifier stickerSet;
enum LastParticipantsStatus {
LastParticipantsUpToDate = 0x00,
@@ -94,35 +122,8 @@ private:
class ChannelData : public PeerData {
public:
static constexpr auto kEssentialFlags = 0
| MTPDchannel::Flag::f_creator
| MTPDchannel::Flag::f_left
| MTPDchannel_ClientFlag::f_forbidden
| MTPDchannel::Flag::f_broadcast
| MTPDchannel::Flag::f_verified
| MTPDchannel::Flag::f_scam
| MTPDchannel::Flag::f_fake
| MTPDchannel::Flag::f_megagroup
| MTPDchannel::Flag::f_gigagroup
| MTPDchannel::Flag::f_restricted
| MTPDchannel::Flag::f_signatures
| MTPDchannel::Flag::f_username
| MTPDchannel::Flag::f_call_not_empty
| MTPDchannel::Flag::f_slowmode_enabled;
using Flags = Data::Flags<
MTPDchannel::Flags,
kEssentialFlags>;
static constexpr auto kEssentialFullFlags = 0
| MTPDchannelFull::Flag::f_can_view_participants
| MTPDchannelFull::Flag::f_can_set_username
| MTPDchannelFull::Flag::f_can_set_stickers
| MTPDchannelFull::Flag::f_location
| MTPDchannelFull::Flag::f_slowmode_seconds
| MTPDchannelFull::Flag::f_slowmode_next_send_date;
using FullFlags = Data::Flags<
MTPDchannelFull::Flags,
kEssentialFullFlags>;
using Flag = ChannelDataFlag;
using Flags = Data::Flags<ChannelDataFlags>;
using AdminRight = ChatAdminRight;
using Restriction = ChatRestriction;
@@ -137,13 +138,13 @@ public:
void setPhoto(const MTPChatPhoto &photo);
void setAccessHash(uint64 accessHash);
void setFlags(MTPDchannel::Flags which) {
void setFlags(ChannelDataFlags which) {
_flags.set(which);
}
void addFlags(MTPDchannel::Flags which) {
void addFlags(ChannelDataFlags which) {
_flags.add(which);
}
void removeFlags(MTPDchannel::Flags which) {
void removeFlags(ChannelDataFlags which) {
_flags.remove(which);
}
[[nodiscard]] auto flags() const {
@@ -153,22 +154,6 @@ public:
return _flags.value();
}
void setFullFlags(MTPDchannelFull::Flags which) {
_fullFlags.set(which);
}
void addFullFlags(MTPDchannelFull::Flags which) {
_fullFlags.add(which);
}
void removeFullFlags(MTPDchannelFull::Flags which) {
_fullFlags.remove(which);
}
[[nodiscard]] auto fullFlags() const {
return _fullFlags.current();
}
[[nodiscard]] auto fullFlagsValue() const {
return _fullFlags.value();
}
[[nodiscard]] int membersCount() const {
return std::max(_membersCount, 1);
}
@@ -193,30 +178,28 @@ public:
void setKickedCount(int newKickedCount);
[[nodiscard]] bool haveLeft() const {
return flags() & MTPDchannel::Flag::f_left;
return flags() & Flag::Left;
}
[[nodiscard]] bool amIn() const {
return !isForbidden() && !haveLeft();
}
[[nodiscard]] bool addsSignature() const {
return flags() & MTPDchannel::Flag::f_signatures;
return flags() & Flag::Signatures;
}
[[nodiscard]] bool isForbidden() const {
return flags() & MTPDchannel_ClientFlag::f_forbidden;
return flags() & Flag::Forbidden;
}
[[nodiscard]] bool isVerified() const {
return flags() & MTPDchannel::Flag::f_verified;
return flags() & Flag::Verified;
}
[[nodiscard]] bool isScam() const {
return flags() & MTPDchannel::Flag::f_scam;
return flags() & Flag::Scam;
}
[[nodiscard]] bool isFake() const {
return flags() & MTPDchannel::Flag::f_fake;
return flags() & Flag::Fake;
}
static MTPChatBannedRights EmptyRestrictedRights(
not_null<PeerData*> participant);
static MTPChatBannedRights KickedRestrictedRights(
[[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights(
not_null<PeerData*> participant);
static constexpr auto kRestrictUntilForever = TimeId(INT_MAX);
[[nodiscard]] static bool IsRestrictedForever(TimeId until) {
@@ -224,38 +207,38 @@ public:
}
void applyEditAdmin(
not_null<UserData*> user,
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights,
ChatAdminRightsInfo oldRights,
ChatAdminRightsInfo newRights,
const QString &rank);
void applyEditBanned(
not_null<PeerData*> participant,
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights);
ChatRestrictionsInfo oldRights,
ChatRestrictionsInfo newRights);
void markForbidden();
[[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const;
[[nodiscard]] bool lastParticipantsRequestNeeded() const;
[[nodiscard]] bool isMegagroup() const {
return flags() & MTPDchannel::Flag::f_megagroup;
return flags() & Flag::Megagroup;
}
[[nodiscard]] bool isBroadcast() const {
return flags() & MTPDchannel::Flag::f_broadcast;
return flags() & Flag::Broadcast;
}
[[nodiscard]] bool isGigagroup() const {
return flags() & MTPDchannel::Flag::f_gigagroup;
return flags() & Flag::Gigagroup;
}
[[nodiscard]] bool hasUsername() const {
return flags() & MTPDchannel::Flag::f_username;
return flags() & Flag::Username;
}
[[nodiscard]] bool hasLocation() const {
return fullFlags() & MTPDchannelFull::Flag::f_location;
return flags() & Flag::Location;
}
[[nodiscard]] bool isPublic() const {
return hasUsername() || hasLocation();
}
[[nodiscard]] bool amCreator() const {
return flags() & MTPDchannel::Flag::f_creator;
return flags() & Flag::Creator;
}
[[nodiscard]] auto adminRights() const {
@@ -264,7 +247,7 @@ public:
[[nodiscard]] auto adminRightsValue() const {
return _adminRights.value();
}
void setAdminRights(const MTPChatAdminRights &rights);
void setAdminRights(ChatAdminRights rights);
[[nodiscard]] bool hasAdminRights() const {
return (adminRights() != 0);
}
@@ -278,7 +261,7 @@ public:
[[nodiscard]] TimeId restrictedUntil() const {
return _restrictedUntil;
}
void setRestrictions(const MTPChatBannedRights &rights);
void setRestrictions(ChatRestrictionsInfo rights);
[[nodiscard]] bool hasRestrictions() const {
return (restrictions() != 0);
}
@@ -293,7 +276,7 @@ public:
[[nodiscard]] auto defaultRestrictionsValue() const {
return _defaultRestrictions.value();
}
void setDefaultRestrictions(const MTPChatBannedRights &rights);
void setDefaultRestrictions(ChatRestrictions rights);
// Like in ChatData.
[[nodiscard]] bool canWrite() const;
@@ -448,8 +431,7 @@ private:
-> const std::vector<Data::UnavailableReason> & override;
bool canEditLastAdmin(not_null<UserData*> user) const;
Flags _flags = Flags(MTPDchannel_ClientFlag::f_forbidden | 0);
FullFlags _fullFlags;
Flags _flags = ChannelDataFlags(Flag::Forbidden);
PtsWaiter _ptsWaiter;

View File

@@ -28,7 +28,7 @@ ChatData::ChatData(not_null<Data::Session*> owner, PeerId id)
, inputChat(MTP_int(peerToChat(id).bare)) {
_flags.changes(
) | rpl::start_with_next([=](const Flags::Change &change) {
if (change.diff & MTPDchat::Flag::f_call_not_empty) {
if (change.diff & ChatDataFlag::CallNotEmpty) {
if (const auto history = this->owner().historyLoaded(this)) {
history->updateChatListEntry();
}
@@ -44,37 +44,37 @@ void ChatData::setPhoto(const MTPChatPhoto &photo) {
});
}
auto ChatData::defaultAdminRights(not_null<UserData*> user) -> AdminRights {
ChatAdminRightsInfo ChatData::defaultAdminRights(not_null<UserData*> user) {
const auto isCreator = (creator == peerToUser(user->id))
|| (user->isSelf() && amCreator());
using Flag = AdminRight;
return Flag::f_other
| Flag::f_change_info
| Flag::f_delete_messages
| Flag::f_ban_users
| Flag::f_invite_users
| Flag::f_pin_messages
| Flag::f_manage_call
| (isCreator ? Flag::f_add_admins : Flag(0));
return ChatAdminRightsInfo(Flag::Other
| Flag::ChangeInfo
| Flag::DeleteMessages
| Flag::BanUsers
| Flag::InviteUsers
| Flag::PinMessages
| Flag::ManageCall
| (isCreator ? Flag::AddAdmins : Flag(0)));
}
bool ChatData::canWrite() const {
// Duplicated in Data::CanWriteValue().
return amIn() && !amRestricted(Restriction::f_send_messages);
return amIn() && !amRestricted(Restriction::SendMessages);
}
bool ChatData::canEditInformation() const {
return amIn() && !amRestricted(Restriction::f_change_info);
return amIn() && !amRestricted(Restriction::ChangeInfo);
}
bool ChatData::canEditPermissions() const {
return amIn()
&& (amCreator() || (adminRights() & AdminRight::f_ban_users));
&& (amCreator() || (adminRights() & AdminRight::BanUsers));
}
bool ChatData::canEditUsername() const {
return amCreator()
&& (fullFlags() & MTPDchatFull::Flag::f_can_set_username);
&& (flags() & ChatDataFlag::CanSetUsername);
}
bool ChatData::canEditPreHistoryHidden() const {
@@ -83,15 +83,15 @@ bool ChatData::canEditPreHistoryHidden() const {
bool ChatData::canDeleteMessages() const {
return amCreator()
|| (adminRights() & AdminRight::f_delete_messages);
|| (adminRights() & AdminRight::DeleteMessages);
}
bool ChatData::canAddMembers() const {
return amIn() && !amRestricted(Restriction::f_invite_users);
return amIn() && !amRestricted(Restriction::InviteUsers);
}
bool ChatData::canSendPolls() const {
return amIn() && !amRestricted(Restriction::f_send_polls);
return amIn() && !amRestricted(Restriction::SendPolls);
}
bool ChatData::canAddAdmins() const {
@@ -100,11 +100,11 @@ bool ChatData::canAddAdmins() const {
bool ChatData::canBanMembers() const {
return amCreator()
|| (adminRights() & AdminRight::f_ban_users);
|| (adminRights() & AdminRight::BanUsers);
}
bool ChatData::anyoneCanAddMembers() const {
return !(defaultRestrictions() & Restriction::f_invite_users);
return !(defaultRestrictions() & Restriction::InviteUsers);
}
void ChatData::setName(const QString &newName) {
@@ -123,8 +123,8 @@ void ChatData::applyEditAdmin(not_null<UserData*> user, bool isAdmin) {
void ChatData::invalidateParticipants() {
participants.clear();
admins.clear();
setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
//setDefaultRestrictions(MTP_chatBannedRights(MTP_flags(0), MTP_int(0)));
setAdminRights(ChatAdminRights());
//setDefaultRestrictions(ChatRestrictions());
invitedByMe.clear();
botStatus = 0;
session().changes().peerUpdated(
@@ -138,25 +138,24 @@ void ChatData::setInviteLink(const QString &newInviteLink) {
bool ChatData::canHaveInviteLink() const {
return amCreator()
|| (adminRights() & AdminRight::f_invite_users);
|| (adminRights() & AdminRight::InviteUsers);
}
void ChatData::setAdminRights(const MTPChatAdminRights &rights) {
if (rights.c_chatAdminRights().vflags().v == adminRights()) {
void ChatData::setAdminRights(ChatAdminRights rights) {
if (rights == adminRights()) {
return;
}
_adminRights.set(rights.c_chatAdminRights().vflags().v);
_adminRights.set(rights);
session().changes().peerUpdated(
this,
UpdateFlag::Rights | UpdateFlag::Admins | UpdateFlag::BannedUsers);
}
void ChatData::setDefaultRestrictions(const MTPChatBannedRights &rights) {
const auto restrictionFlags = Data::ChatBannedRightsFlags(rights);
if (restrictionFlags == defaultRestrictions()) {
void ChatData::setDefaultRestrictions(ChatRestrictions rights) {
if (rights == defaultRestrictions()) {
return;
}
_defaultRestrictions.set(restrictionFlags);
_defaultRestrictions.set(rights);
session().changes().peerUpdated(this, UpdateFlag::Rights);
}
@@ -220,7 +219,7 @@ void ChatData::setGroupCall(
scheduleDate);
owner().registerGroupCall(_call.get());
session().changes().peerUpdated(this, UpdateFlag::GroupCall);
addFlags(MTPDchat::Flag::f_call_active);
addFlags(ChatDataFlag::CallActive);
});
}
@@ -234,8 +233,7 @@ void ChatData::clearGroupCall() {
_call = nullptr;
}
session().changes().peerUpdated(this, UpdateFlag::GroupCall);
removeFlags(MTPDchat::Flag::f_call_active
| MTPDchat::Flag::f_call_not_empty);
removeFlags(ChatDataFlag::CallActive | ChatDataFlag::CallNotEmpty);
}
void ChatData::setGroupCallDefaultJoinAs(PeerId peerId) {
@@ -252,6 +250,14 @@ void ChatData::setBotCommands(const MTPVector<MTPBotInfo> &data) {
}
}
void ChatData::setBotCommands(
UserId botId,
const MTPVector<MTPBotCommand> &data) {
if (Data::UpdateBotCommands(_botCommands, botId, data)) {
owner().botCommandsChanged(this);
}
}
namespace Data {
void ApplyChatUpdate(
@@ -329,7 +335,7 @@ void ApplyChatUpdate(
chat->invitedByMe.remove(user);
chat->admins.remove(user);
if (user->isSelf()) {
chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
chat->setAdminRights(ChatAdminRights());
}
if (const auto history = chat->owner().historyLoaded(chat)) {
if (history->lastKeyboardFrom == user->id) {
@@ -357,9 +363,9 @@ void ApplyChatUpdate(
return;
}
if (user->isSelf()) {
chat->setAdminRights(MTP_chatAdminRights(mtpIsTrue(update.vis_admin())
? MTP_flags(chat->defaultAdminRights(user))
: MTP_flags(0)));
chat->setAdminRights(mtpIsTrue(update.vis_admin())
? chat->defaultAdminRights(user).flags
: ChatAdminRights());
}
if (mtpIsTrue(update.vis_admin())) {
if (chat->noParticipantInfo()) {
@@ -380,7 +386,8 @@ void ApplyChatUpdate(
!= ChatData::UpdateStatus::Good) {
return;
}
chat->setDefaultRestrictions(update.vdefault_banned_rights());
chat->setDefaultRestrictions(Data::ChatBannedRightsFlags(
update.vdefault_banned_rights()));
}
void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
@@ -403,7 +410,10 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
} else {
chat->setBotCommands(MTP_vector<MTPBotInfo>());
}
chat->setFullFlags(update.vflags().v);
using Flag = ChatDataFlag;
const auto mask = Flag::CanSetUsername;
chat->setFlags((chat->flags() & ~mask)
| (update.is_can_set_username() ? Flag::CanSetUsername : Flag()));
if (const auto photo = update.vchat_photo()) {
chat->setUserpicPhoto(*photo);
} else {
@@ -450,7 +460,7 @@ void ApplyChatUpdate(
chat->participants.clear();
chat->invitedByMe.clear();
chat->admins.clear();
chat->setAdminRights(MTP_chatAdminRights(MTP_flags(0)));
chat->setAdminRights(ChatAdminRights());
const auto selfUserId = session->userId();
for (const auto &participant : list) {
const auto userId = participant.match([&](const auto &data) {
@@ -479,8 +489,8 @@ void ApplyChatUpdate(
}, [&](const MTPDchatParticipantAdmin &data) {
chat->admins.emplace(user);
if (user->isSelf()) {
chat->setAdminRights(MTP_chatAdminRights(
MTP_flags(chat->defaultAdminRights(user))));
chat->setAdminRights(
chat->defaultAdminRights(user).flags);
}
}, [](const MTPDchatParticipant &) {
});

View File

@@ -9,26 +9,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h"
enum class ChatDataFlag {
Left = (1 << 0),
Kicked = (1 << 1),
Creator = (1 << 2),
Deactivated = (1 << 3),
Forbidden = (1 << 4),
CallActive = (1 << 5),
CallNotEmpty = (1 << 6),
CanSetUsername = (1 << 7),
};
inline constexpr bool is_flag_type(ChatDataFlag) { return true; };
using ChatDataFlags = base::flags<ChatDataFlag>;
class ChatData : public PeerData {
public:
static constexpr auto kEssentialFlags = 0
| MTPDchat::Flag::f_creator
| MTPDchat::Flag::f_kicked
| MTPDchat::Flag::f_left
| MTPDchat::Flag::f_deactivated
| MTPDchat::Flag::f_migrated_to
| MTPDchat::Flag::f_admin_rights
| MTPDchat::Flag::f_call_not_empty
| MTPDchat::Flag::f_default_banned_rights;
using Flags = Data::Flags<
MTPDchat::Flags,
kEssentialFlags>;
static constexpr auto kEssentialFullFlags = 0
| MTPDchatFull::Flag::f_can_set_username;
using FullFlags = Data::Flags<
MTPDchatFull::Flags,
kEssentialFullFlags>;
using Flag = ChatDataFlag;
using Flags = Data::Flags<ChatDataFlags>;
using AdminRight = ChatAdminRight;
using Restriction = ChatRestriction;
@@ -47,13 +44,13 @@ public:
return (count > 0 || amIn()) && participants.empty();
}
void setFlags(MTPDchat::Flags which) {
void setFlags(ChatDataFlags which) {
_flags.set(which);
}
void addFlags(MTPDchat::Flags which) {
void addFlags(ChatDataFlags which) {
_flags.add(which);
}
void removeFlags(MTPDchat::Flags which) {
void removeFlags(ChatDataFlags which) {
_flags.remove(which);
}
[[nodiscard]] auto flags() const {
@@ -63,29 +60,13 @@ public:
return _flags.value();
}
void setFullFlags(MTPDchatFull::Flags which) {
_fullFlags.set(which);
}
void addFullFlags(MTPDchatFull::Flags which) {
_fullFlags.add(which);
}
void removeFullFlags(MTPDchatFull::Flags which) {
_fullFlags.remove(which);
}
[[nodiscard]] auto fullFlags() const {
return _fullFlags.current();
}
[[nodiscard]] auto fullFlagsValue() const {
return _fullFlags.value();
}
[[nodiscard]] auto adminRights() const {
return _adminRights.current();
}
[[nodiscard]] auto adminRightsValue() const {
return _adminRights.value();
}
void setAdminRights(const MTPChatAdminRights &rights);
void setAdminRights(ChatAdminRights rights);
[[nodiscard]] bool hasAdminRights() const {
return (adminRights() != 0);
}
@@ -96,10 +77,10 @@ public:
[[nodiscard]] auto defaultRestrictionsValue() const {
return _defaultRestrictions.value();
}
void setDefaultRestrictions(const MTPChatBannedRights &rights);
void setDefaultRestrictions(ChatRestrictions rights);
[[nodiscard]] bool isForbidden() const {
return flags() & MTPDchat_ClientFlag::f_forbidden;
return flags() & Flag::Forbidden;
}
[[nodiscard]] bool amIn() const {
return !isForbidden()
@@ -108,22 +89,23 @@ public:
&& !wasKicked();
}
[[nodiscard]] bool haveLeft() const {
return flags() & MTPDchat::Flag::f_left;
return flags() & ChatDataFlag::Left;
}
[[nodiscard]] bool wasKicked() const {
return flags() & MTPDchat::Flag::f_kicked;
return flags() & ChatDataFlag::Kicked;
}
[[nodiscard]] bool amCreator() const {
return flags() & MTPDchat::Flag::f_creator;
return flags() & ChatDataFlag::Creator;
}
[[nodiscard]] bool isDeactivated() const {
return flags() & MTPDchat::Flag::f_deactivated;
return flags() & ChatDataFlag::Deactivated;
}
[[nodiscard]] bool isMigrated() const {
return flags() & MTPDchat::Flag::f_migrated_to;
return (_migratedTo != nullptr);
}
[[nodiscard]] AdminRights defaultAdminRights(not_null<UserData*> user);
[[nodiscard]] ChatAdminRightsInfo defaultAdminRights(
not_null<UserData*> user);
// Like in ChannelData.
[[nodiscard]] bool canWrite() const;
@@ -174,6 +156,9 @@ public:
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
void setBotCommands(const MTPVector<MTPBotInfo> &data);
void setBotCommands(
UserId botId,
const MTPVector<MTPBotCommand> &data);
[[nodiscard]] auto botCommands() const
-> const base::flat_map<UserId, std::vector<BotCommand>> & {
return _botCommands;
@@ -195,7 +180,6 @@ public:
private:
Flags _flags;
FullFlags _fullFlags;
QString _inviteLink;
RestrictionFlags _defaultRestrictions;

View File

@@ -63,8 +63,7 @@ void CloudThemes::setupReload() {
if (needReload()) {
_reloadCurrentTimer.callOnce(kFirstReloadTimeout);
}
base::ObservableViewer(
*Background()
Background()->updates(
) | rpl::filter([](const BackgroundUpdate &update) {
return (update.type == BackgroundUpdate::Type::ApplyingTheme);
}) | rpl::map([=] {

View File

@@ -257,12 +257,10 @@ QString DocumentFileNameForSave(
}
Data::FileOrigin StickerData::setOrigin() const {
return set.match([&](const MTPDinputStickerSetID &data) {
return Data::FileOrigin(
Data::FileOriginStickerSet(data.vid().v, data.vaccess_hash().v));
}, [&](const auto &) {
return Data::FileOrigin();
});
return set.id
? Data::FileOrigin(
Data::FileOriginStickerSet(set.id, set.accessHash))
: Data::FileOrigin();
}
VoiceData::~VoiceData() {
@@ -320,9 +318,21 @@ void DocumentData::setattributes(
}
if (sticker()) {
sticker()->alt = qs(data.valt());
if (sticker()->set.type() != mtpc_inputStickerSetID
if (!sticker()->set.id
|| data.vstickerset().type() == mtpc_inputStickerSetID) {
sticker()->set = data.vstickerset();
sticker()->set = data.vstickerset().match([&](
const MTPDinputStickerSetID &data) {
return StickerSetIdentifier{
.id = data.vid().v,
.accessHash = data.vaccess_hash().v,
};
}, [&](const MTPDinputStickerSetShortName &data) {
return StickerSetIdentifier{
.shortName = qs(data.vshort_name()),
};
}, [](const auto &) {
return StickerSetIdentifier();
});
}
}
}, [&](const MTPDdocumentAttributeVideo &data) {
@@ -1041,28 +1051,26 @@ bool DocumentData::saveFromDataChecked() {
bool DocumentData::isStickerSetInstalled() const {
Expects(sticker() != nullptr);
using SetFlag = Data::StickersSetFlag;
const auto &sets = _owner->stickers().sets();
return sticker()->set.match([&](const MTPDinputStickerSetID &data) {
const auto i = sets.find(data.vid().v);
if (const auto id = sticker()->set.id) {
const auto i = sets.find(id);
return (i != sets.cend())
&& !(i->second->flags & MTPDstickerSet::Flag::f_archived)
&& (i->second->flags & MTPDstickerSet::Flag::f_installed_date);
}, [&](const MTPDinputStickerSetShortName &data) {
const auto name = qs(data.vshort_name()).toLower();
&& !(i->second->flags & SetFlag::Archived)
&& (i->second->flags & SetFlag::Installed);
} else if (!sticker()->set.shortName.isEmpty()) {
const auto name = sticker()->set.shortName.toLower();
for (const auto &[id, set] : sets) {
if (set->shortName.toLower() == name) {
return !(set->flags & MTPDstickerSet::Flag::f_archived)
&& (set->flags & MTPDstickerSet::Flag::f_installed_date);
return !(set->flags & SetFlag::Archived)
&& (set->flags & SetFlag::Installed);
}
}
return false;
}, [](const MTPDinputStickerSetEmpty &) {
} else {
return false;
}, [](const MTPDinputStickerSetAnimatedEmoji &) {
return false;
}, [](const MTPDinputStickerSetDice &) {
return false;
});
}
}
Image *DocumentData::getReplyPreview(Data::FileOrigin origin) {

View File

@@ -62,7 +62,7 @@ struct StickerData : public DocumentAdditionalData {
bool animated = false;
QString alt;
MTPInputStickerSet set = MTP_inputStickerSetEmpty();
StickerSetIdentifier set;
};
struct SongData : public DocumentAdditionalData {

View File

@@ -33,11 +33,6 @@ constexpr auto kWaitForUpdatesTimeout = 3 * crl::time(1000);
});
}
[[nodiscard]] const std::string &EmptyEndpoint() {
static const auto result = std::string();
return result;
}
} // namespace
const std::string &GroupCallParticipant::cameraEndpoint() const {
@@ -174,8 +169,8 @@ void GroupCall::setServerParticipantsCount(int count) {
void GroupCall::changePeerEmptyCallFlag() {
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
constexpr auto chatFlag = MTPDchat::Flag::f_call_not_empty;
constexpr auto channelFlag = MTPDchannel::Flag::f_call_not_empty;
constexpr auto chatFlag = ChatDataFlag::CallNotEmpty;
constexpr auto channelFlag = ChannelDataFlag::CallNotEmpty;
if (_peer->groupCall() != this) {
return;
} else if (_serverParticipantsCount > 0) {
@@ -397,7 +392,7 @@ void GroupCall::applyCallFields(const MTPDgroupCall &data) {
_recordStartDate = data.vrecord_start_date().value_or_empty();
_scheduleDate = data.vschedule_date().value_or_empty();
_scheduleStartSubscribed = data.is_schedule_start_subscribed();
_canStartVideo = data.is_can_start_video();
_unmutedVideoLimit = data.vunmuted_video_limit().v;
_allParticipantsLoaded
= (_serverParticipantsCount == _participants.size());
}
@@ -533,10 +528,6 @@ bool GroupCall::requestParticipantsAfterReload(
void GroupCall::applyParticipantsSlice(
const QVector<MTPGroupCallParticipant> &list,
ApplySliceSource sliceSource) {
const auto amInCall = inCall();
const auto now = base::unixtime::now();
const auto speakingAfterActive = TimeId(kSpeakingAfterActive / 1000);
for (const auto &participant : list) {
participant.match([&](const MTPDgroupCallParticipant &data) {
const auto participantPeerId = peerFromMTP(data.vpeer());
@@ -552,6 +543,8 @@ void GroupCall::applyParticipantsSlice(
.was = *i,
};
_participantPeerByAudioSsrc.erase(i->ssrc);
_participantPeerByAudioSsrc.erase(
GetAdditionalAudioSsrc(i->videoParams));
_speakingByActiveFinishes.remove(participantPeer);
_participants.erase(i);
if (sliceSource != ApplySliceSource::FullReloaded) {
@@ -573,10 +566,6 @@ void GroupCall::applyParticipantsSlice(
|| data.is_can_self_unmute();
const auto lastActive = data.vactive_date().value_or(
was ? was->lastActive : 0);
const auto speaking = canSelfUnmute
&& ((was ? was->speaking : false)
|| (!amInCall
&& (lastActive + speakingAfterActive > now)));
const auto volume = (was
&& !was->applyVolumeFromMin
&& data.is_min())
@@ -612,18 +601,33 @@ void GroupCall::applyParticipantsSlice(
.raisedHandRating = raisedHandRating,
.ssrc = uint32(data.vsource().v),
.volume = volume,
.applyVolumeFromMin = applyVolumeFromMin,
.speaking = canSelfUnmute && (was ? was->speaking : false),
.sounding = canSelfUnmute && was && was->sounding,
.speaking = canSelfUnmute && was && was->speaking,
.additionalSounding = (canSelfUnmute
&& was
&& was->additionalSounding),
.additionalSpeaking = (canSelfUnmute
&& was
&& was->additionalSpeaking),
.muted = data.is_muted(),
.mutedByMe = mutedByMe,
.canSelfUnmute = canSelfUnmute,
.onlyMinLoaded = onlyMinLoaded,
.videoJoined = videoJoined,
.applyVolumeFromMin = applyVolumeFromMin,
};
if (i == end(_participants)) {
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
if (value.ssrc) {
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
}
if (const auto additional = GetAdditionalAudioSsrc(
value.videoParams)) {
_participantPeerByAudioSsrc.emplace(
additional,
participantPeer);
}
_participants.push_back(value);
if (const auto user = participantPeer->asUser()) {
_peer->owner().unregisterInvitedToCallUser(_id, user);
@@ -631,9 +635,22 @@ void GroupCall::applyParticipantsSlice(
} else {
if (i->ssrc != value.ssrc) {
_participantPeerByAudioSsrc.erase(i->ssrc);
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
if (value.ssrc) {
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
}
}
if (GetAdditionalAudioSsrc(i->videoParams)
!= GetAdditionalAudioSsrc(value.videoParams)) {
_participantPeerByAudioSsrc.erase(
GetAdditionalAudioSsrc(i->videoParams));
if (const auto additional = GetAdditionalAudioSsrc(
value.videoParams)) {
_participantPeerByAudioSsrc.emplace(
additional,
participantPeer);
}
}
*i = value;
}
@@ -675,11 +692,22 @@ void GroupCall::applyLastSpoke(
if (speaking) {
_participantSpeaking.fire({ participant });
}
if (participant->sounding != sounding
|| participant->speaking != speaking) {
const auto useAdditional = (ssrc != participant->ssrc);
const auto nowSounding = useAdditional
? participant->additionalSounding
: participant->sounding;
const auto nowSpeaking = useAdditional
? participant->additionalSpeaking
: participant->speaking;
if (nowSounding != sounding || nowSpeaking != speaking) {
const auto was = *participant;
participant->sounding = sounding;
participant->speaking = speaking;
if (useAdditional) {
participant->additionalSounding = sounding;
participant->additionalSpeaking = speaking;
} else {
participant->sounding = sounding;
participant->speaking = speaking;
}
_participantUpdates.fire({
.was = was,
.now = *participant,

View File

@@ -32,14 +32,16 @@ struct GroupCallParticipant {
uint64 raisedHandRating = 0;
uint32 ssrc = 0;
int volume = 0;
bool applyVolumeFromMin = true;
bool sounding = false;
bool speaking = false;
bool muted = false;
bool mutedByMe = false;
bool canSelfUnmute = false;
bool onlyMinLoaded = false;
bool sounding : 1;
bool speaking : 1;
bool additionalSounding : 1;
bool additionalSpeaking : 1;
bool muted : 1;
bool mutedByMe : 1;
bool canSelfUnmute : 1;
bool onlyMinLoaded : 1;
bool videoJoined = false;
bool applyVolumeFromMin = true;
[[nodiscard]] const std::string &cameraEndpoint() const;
[[nodiscard]] const std::string &screenEndpoint() const;
@@ -93,11 +95,8 @@ public:
[[nodiscard]] rpl::producer<bool> scheduleStartSubscribedValue() const {
return _scheduleStartSubscribed.value();
}
[[nodiscard]] bool canStartVideo() const {
return _canStartVideo.current();
}
[[nodiscard]] rpl::producer<bool> canStartVideoValue() const {
return _canStartVideo.value();
[[nodiscard]] int unmutedVideoLimit() const {
return _unmutedVideoLimit.current();
}
void setPeer(not_null<PeerData*> peer);
@@ -214,10 +213,10 @@ private:
QString _nextOffset;
int _serverParticipantsCount = 0;
rpl::variable<int> _fullCount = 0;
rpl::variable<int> _unmutedVideoLimit = 0;
rpl::variable<TimeId> _recordStartDate = 0;
rpl::variable<TimeId> _scheduleDate = 0;
rpl::variable<bool> _scheduleStartSubscribed = false;
rpl::variable<bool> _canStartVideo = false;
base::flat_map<uint32, LastSpokeTimes> _unknownSpokenSsrcs;
base::flat_map<PeerId, LastSpokeTimes> _unknownSpokenPeerIds;

View File

@@ -360,7 +360,7 @@ bool MediaPhoto::allowsEditMedia() const {
QString MediaPhoto::errorTextForForward(not_null<PeerData*> peer) const {
return Data::RestrictionError(
peer,
ChatRestriction::f_send_media
ChatRestriction::SendMedia
).value_or(QString());
}
@@ -629,26 +629,26 @@ QString MediaFile::errorTextForForward(not_null<PeerData*> peer) const {
if (const auto sticker = _document->sticker()) {
if (const auto error = Data::RestrictionError(
peer,
ChatRestriction::f_send_stickers)) {
ChatRestriction::SendStickers)) {
return *error;
}
} else if (_document->isAnimation()) {
if (_document->isVideoMessage()) {
if (const auto error = Data::RestrictionError(
peer,
ChatRestriction::f_send_media)) {
ChatRestriction::SendMedia)) {
return *error;
}
} else {
if (const auto error = Data::RestrictionError(
peer,
ChatRestriction::f_send_gifs)) {
ChatRestriction::SendGifs)) {
return *error;
}
}
} else if (const auto error = Data::RestrictionError(
peer,
ChatRestriction::f_send_media)) {
ChatRestriction::SendMedia)) {
return *error;
}
return QString();
@@ -1135,7 +1135,7 @@ TextForMimeData MediaGame::clipboardText() const {
QString MediaGame::errorTextForForward(not_null<PeerData*> peer) const {
return Data::RestrictionError(
peer,
ChatRestriction::f_send_games
ChatRestriction::SendGames
).value_or(QString());
}
@@ -1289,7 +1289,7 @@ QString MediaPoll::errorTextForForward(not_null<PeerData*> peer) const {
}
return Data::RestrictionError(
peer,
ChatRestriction::f_send_polls
ChatRestriction::SendPolls
).value_or(QString());
}

View File

@@ -268,7 +268,6 @@ bool MessagesList::empty() const {
rpl::producer<MessagesResult> MessagesList::viewer(
MessagesQuery &&query) const {
auto copy = query;
return rpl::single(
queryCurrent(query)
) | rpl::then(sliceUpdated() | rpl::map([=] {

View File

@@ -13,7 +13,6 @@ namespace Data {
namespace {
MTPinputPeerNotifySettings DefaultSettings() {
const auto flags = MTPDpeerNotifySettings::Flag::f_show_previews;
return MTP_inputPeerNotifySettings(
MTP_flags(0),
MTPBool(),

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