Compare commits

...

405 Commits

Author SHA1 Message Date
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
John Preston
3cdd115317 Beta version 2.8.6: Fix build for Linux. 2021-07-07 00:54:56 +03:00
John Preston
bdd1d2484c Beta version 2.8.6: Update build script. 2021-07-06 20:32:08 +03:00
John Preston
d5a416d5ea Beta version 2.8.6: Fix build for macOS. 2021-07-06 20:25:46 +03:00
John Preston
46d393ea0f Beta version 2.8.6.
- Added a simple image editor.
Crop photos or highlight parts of screenshots before sending.
- Use Direct3D 9 backend in ANGLE by default (Windows).
- Fix "Show in Finder" not focusing the Finder window (macOS).
- Use GTK from a child process (Linux).
2021-07-06 17:17:23 +03:00
nyakze
68e351b7c8 Attempt to fix not working commands
Attempt to fix not working commands by using more conventional keys
2021-07-06 17:16:46 +03:00
John Preston
6f9c911faa Fix Qt build instructions with ANGLE. 2021-07-06 17:04:05 +03:00
John Preston
dd381d9b56 Show vector elements count in DebugLogs. 2021-07-06 16:54:26 +03:00
John Preston
8eedc7b2ba Fix build on Windows. 2021-07-06 15:56:43 +03:00
John Preston
9ba1af2eb9 Use tg_angle fork. 2021-07-06 15:55:49 +03:00
23rd
f567328a60 Fixed deleting item after saving result of scene in photo editor. 2021-07-06 14:15:07 +03:00
23rd
953fa52490 Fixed updating of undo state on deleting item in photo editor. 2021-07-06 14:15:07 +03:00
23rd
b1477260f0 Improved content margins in photo editor. 2021-07-06 14:15:07 +03:00
23rd
038de9ef15 Changed behavior to keep StickerSetBox until pack is archived. 2021-07-06 12:13:06 +03:00
23rd
4701c5d6e3 Added ability to archive mask packs. 2021-07-06 12:13:06 +03:00
23rd
8420b7dc17 Disabled ability to use hotkeys when selecting color in photo editor. 2021-07-06 12:13:06 +03:00
23rd
9dacf69d41 Fixed line drawing on mode switching in photo editor. 2021-07-06 12:13:06 +03:00
23rd
a91efd9164 Fixed ability to draw blank lines in photo editor. 2021-07-06 12:13:06 +03:00
23rd
a631a28092 Removed App::pixmapFromImageInPlace. 2021-07-06 12:13:06 +03:00
23rd
7bcb1fc8b2 Fixed borders of drawn lines in photo editor. 2021-07-06 12:13:06 +03:00
23rd
cdafd8f171 Fixed width of preview for small media in SendFilesBox.
Regression was introduced in 42d4fdb89f.
2021-07-06 12:13:06 +03:00
23rd
116aa01e51 Refactored column width in SingleMediaPreview. 2021-07-06 12:13:06 +03:00
23rd
96b40f43e9 Added ability to drag and drop images in photo editor. 2021-07-06 12:13:06 +03:00
23rd
a93ec9c2c2 Added Escape hotkey to clear selection in photo editor. 2021-07-06 12:13:06 +03:00
23rd
3ee3919d50 Added hotkeys for switching between modes in photo editor. 2021-07-06 12:13:06 +03:00
23rd
b4410c49b9 Added background color in photo editor. 2021-07-06 12:13:06 +03:00
23rd
82bf6ca94f Fixed display of sticker panel on mode change in photo editor. 2021-07-06 12:13:06 +03:00
23rd
785ebfee34 Added animation to button bars in photo editor. 2021-07-06 12:13:06 +03:00
23rd
a60f8d75a0 Added second button bar for paint mode in photo editor. 2021-07-06 12:13:06 +03:00
23rd
5976a7ed19 Moved edge buttons to bar in photo editor. 2021-07-06 12:13:06 +03:00
23rd
df7026b59c Made alignment to bottom for button strip in photo editor. 2021-07-06 12:13:06 +03:00
23rd
edfd9bedc1 Improved style for controls in EditCaptionBox. 2021-07-06 12:13:06 +03:00
23rd
f52c6a6daa Improved style for controls in SendFilesBox. 2021-07-06 12:13:06 +03:00
23rd
af10b6d487 Added icons for SendFilesBox. 2021-07-06 12:13:06 +03:00
23rd
e30eacff41 Added photo editor hint to SendFilesBox. 2021-07-06 12:13:06 +03:00
23rd
18154e403a Added ability to open photo editor in SendFilesBox with left-click. 2021-07-06 12:13:06 +03:00
23rd
6975b04e6b Fixed triggering of pressed buttons in album preview. 2021-07-06 12:13:06 +03:00
23rd
948302cf02 Added setting to hide photo editor hint. 2021-07-06 12:13:06 +03:00
23rd
e4cff8cb4b Added photo editor hint to EditCaptionBox. 2021-07-06 12:13:06 +03:00
23rd
5bd17ae1b2 Fixed caption area height in EditCaptionBox.
Regression was introduced in 51f960442e.
2021-07-06 12:13:06 +03:00
23rd
22213a71c1 Added ability to open photo editor in EditCaptionBox with left-click. 2021-07-06 12:13:06 +03:00
23rd
e926e5f882 Slightly improved style of controls in photo editor. 2021-07-06 12:13:06 +03:00
23rd
221d45b500 Updated control icons for photo editor. 2021-07-06 12:13:06 +03:00
23rd
6bb7e2c2eb Removed using of hardcoded numbers of tray menu actions. 2021-07-06 12:13:06 +03:00
23rd
2a86ce596d Added shortcuts for actions of items in photo editor. 2021-07-06 12:13:06 +03:00
23rd
f936e484cc Removed unused types from scene items. 2021-07-06 12:13:05 +03:00
23rd
b2a1c10036 Removed masks panel when there are no masks. 2021-07-06 12:13:05 +03:00
23rd
2a58d01927 Removed search and featured buttons from masks panel. 2021-07-06 12:13:05 +03:00
23rd
7cd6b821b3 Fixed update of recently attached stickers after sending. 2021-07-06 12:13:05 +03:00
23rd
de108c8efe Fixed removing masks set from StickersListWidget. 2021-07-06 12:13:05 +03:00
23rd
e7104b5ebe Added support for archived masks. 2021-07-06 12:13:05 +03:00
23rd
2d17bd02a3 Moved mask management to separate box. 2021-07-06 12:13:05 +03:00
23rd
2a3115f461 Fixed phrases to display mask count. 2021-07-06 12:13:05 +03:00
23rd
8d62800e77 Moved stickerSetInstalled from ApiWrap to Data::Stickers. 2021-07-06 12:13:05 +03:00
23rd
7e04bf9533 Added ability to install mask sets. 2021-07-06 12:13:05 +03:00
23rd
2bd3a8aaff Added ability to delete and reorder mask sets.
Moved ApiWrap::stickerSetDisenabled and ApiWrap::stickersSaveOrder
to ApiWrap::saveStickerSets as lambdas.
2021-07-06 12:13:05 +03:00
23rd
70f92a7817 Added initial masks tab to manage stickers box. 2021-07-06 12:13:05 +03:00
23rd
8e08f69508 Added support updateNewStickerSet and updateStickerSets for masks. 2021-07-06 12:13:05 +03:00
23rd
abe62475cb Added support updateStickerSetsOrder for masks. 2021-07-06 12:13:05 +03:00
23rd
1cdb83462e Added initial implementation of masks panel. 2021-07-06 12:13:05 +03:00
23rd
d9a29b6f15 Fixed item pen width in big images. 2021-07-06 12:13:05 +03:00
23rd
1504f92a64 Fixed size limits of item on big images. 2021-07-06 12:13:05 +03:00
23rd
36e5056b59 Fixed selection of items on mode switching. 2021-07-06 12:13:05 +03:00
23rd
c5c707f0fd Fixed independence of item and scene transforms when adding. 2021-07-06 12:13:05 +03:00
23rd
832dd8d50c Moved some photo editor files to separate directories. 2021-07-06 12:13:05 +03:00
23rd
7d2b20e624 Made TabbedSelector more flexible. 2021-07-06 12:13:05 +03:00
23rd
049945a9b9 Added ability to duplicate items in photo editor. 2021-07-06 12:13:05 +03:00
23rd
808c9e3d2c Added ability to flip items in photo editor. 2021-07-06 12:13:05 +03:00
23rd
fde7cef9c8 Removed using of raw pointers for QGraphicsItem in photo editor.
Now all items are wrapped in the shared_ptr,
and the Scene loses ownership of all items before being destroyed.
2021-07-06 12:13:05 +03:00
23rd
2791f89f30 Added initial context menu to items in photo editor. 2021-07-06 12:13:05 +03:00
23rd
858b5831e8 Fixed clearing of redo list after adding sticker item in photo editor. 2021-07-06 12:13:05 +03:00
23rd
9166423598 Fixed multi selection of items in photo editor. 2021-07-06 12:13:05 +03:00
23rd
184d984336 Added ability to snap rotation of items with Shift key in photo editor. 2021-07-06 12:13:05 +03:00
23rd
0b5044f064 Fixed size of handles of base item in photo editor. 2021-07-06 12:13:05 +03:00
23rd
274b66f74b Added ability to create items in photo editor with different ratios. 2021-07-06 12:13:05 +03:00
23rd
e05343d721 Added sending info of stickered photos. 2021-07-06 12:13:05 +03:00
23rd
bc316a2536 Removed Storage::UploadedThumbDocument struct. 2021-07-06 12:13:05 +03:00
23rd
a6904be81d Slightly optimized mouse painting in photo editor. 2021-07-06 12:13:05 +03:00
23rd
690a7d1608 Fixed undo and redo paint actions. 2021-07-06 12:13:05 +03:00
23rd
a3e54fcd7c Moved draft painting in photo editor to separate files. 2021-07-06 12:13:05 +03:00
23rd
23c67bb2a2 Added ability to add stickers to photo in photo editor. 2021-07-06 12:13:05 +03:00
23rd
75367f0488 Added sticker panel to photo editor. 2021-07-06 12:13:05 +03:00
23rd
216ffad80e Added container of controllers for photo editor. 2021-07-06 12:13:05 +03:00
23rd
c312607ff8 Added stickers panel controller for photo editor. 2021-07-06 12:13:05 +03:00
23rd
812d616f66 Added scene base item for photo editor. 2021-07-06 12:13:05 +03:00
23rd
183408cb2d Added button highlighting for flipped image to photo editor. 2021-07-06 12:13:05 +03:00
23rd
1a7d5b7c95 Removed unused photo crop box. 2021-07-06 12:13:05 +03:00
23rd
17465e1082 Replaced old photo crop box with photo editor for profile photos. 2021-07-06 12:13:05 +03:00
23rd
a996b14291 Fixed keeping of aspect ratio in crop widget. 2021-07-06 12:13:05 +03:00
23rd
2045252cfd Added ability to pass data for photo editor. 2021-07-06 12:13:05 +03:00
23rd
a2e674bdb6 Added Window::Controller pointer to data of intro widget. 2021-07-06 12:13:05 +03:00
23rd
cc4055a5e3 Added method to Window::Controller to show custom layer widget. 2021-07-06 12:13:05 +03:00
23rd
d1b6cf1fae Added draft menu to EditCaptionBox to open photo editor. 2021-07-06 12:13:05 +03:00
23rd
671a06c407 Replaced using of QPixmap in photo editor with Image. 2021-07-06 12:13:05 +03:00
23rd
3ce315111f Added draft menu to SendFilesBox to open photo editor. 2021-07-06 12:13:05 +03:00
23rd
09768ce28a Refactored crop widget in photo editor. 2021-07-06 12:13:05 +03:00
23rd
c9affe0da5 Added custom layer widget with photo editor. 2021-07-06 12:13:05 +03:00
23rd
4909ba5a1e Added ability to pass custom layer widgets to stack. 2021-07-06 12:13:05 +03:00
23rd
e322733e20 Added saving of color and size of brush from photo editor to settings. 2021-07-06 12:13:05 +03:00
23rd
dc7f440902 Added color picker to photo editor. 2021-07-06 12:13:05 +03:00
23rd
4849376347 Added ability to undo and to redo paint actions in photo editor. 2021-07-06 12:13:05 +03:00
23rd
8eca57f419 Added saving and discarding between modes in photo editor. 2021-07-06 12:13:05 +03:00
23rd
0adcd37030 Added edge buttons to controls of photo editor. 2021-07-06 12:13:05 +03:00
23rd
2bdb9af146 Added dummy control icons for photo editor. 2021-07-06 12:13:05 +03:00
23rd
5b6bddd7fc Added initial implementation of mouse drawing in photo editor. 2021-07-06 12:13:05 +03:00
23rd
e1ea833ad6 Added ability to crop images in photo editor. 2021-07-06 12:13:05 +03:00
23rd
85c21ba0e4 Added ability to open photo editor with saved modifications. 2021-07-06 12:13:05 +03:00
23rd
4d72d20398 Added ability to send modified images. 2021-07-06 12:13:04 +03:00
23rd
9d3d16a725 Added initial ability to rotate and flip image to photo editor. 2021-07-06 12:13:04 +03:00
23rd
99deaf6005 Added dummy buttons to PhotoEditorControls. 2021-07-06 12:13:04 +03:00
23rd
d8921c7cf5 Added HorizontalContainer for buttons to PhotoEditorControls. 2021-07-06 12:13:04 +03:00
23rd
f7fa36ca1d Added photo painting to PhotoEditorContent. 2021-07-06 12:13:04 +03:00
23rd
45f8e68203 Initialized empty files of photo editor. 2021-07-06 12:13:04 +03:00
John Preston
2b47d6d63f Add depot_tools information to build instructions. 2021-07-06 12:05:45 +03:00
John Preston
aaefeed3f1 Support custom keyboard placeholders. 2021-07-05 21:12:52 +03:00
John Preston
7f00065bd8 Update API scheme to layer 130. 2021-07-05 21:12:52 +03:00
Ilya Fedin
6f031a715e Revert "Use QMenuBar instead of own global menu implementation on Linux"
This reverts commit 79f96480c2.
2021-07-05 21:01:20 +03:00
John Preston
6981ae605a Fix fake unread status reset on account change. 2021-07-05 19:48:06 +03:00
John Preston
d91c21fb26 Try enabling OpenGL back after switching to ANGLE. 2021-07-05 19:48:06 +03:00
John Preston
c95f052e60 Fix "Show in Finder" app focus bug by a Qt patch. 2021-07-05 19:31:21 +03:00
John Preston
c33be27b3c Update lib_webview submodule. 2021-07-05 15:57:55 +03:00
John Preston
6be9b25e99 Submit voice chat boxes by Enter. 2021-07-05 15:37:34 +03:00
Ilya Fedin
0bb391937e Update lib_webview 2021-07-04 20:05:53 +03:00
Ilya Fedin
75ff7a6637 Control GtkOpenWithDialog lifetime from outside 2021-07-04 20:05:53 +03:00
John Preston
aece7c1096 Remove testing code in stickers view. 2021-07-02 22:11:34 +03:00
John Preston
d2e6e7adf2 Fix build on macOS. 2021-07-02 22:11:23 +03:00
John Preston
b930bc0e6d Track bot commands separately in different chats. 2021-07-02 20:41:48 +03:00
John Preston
93d99d6173 Track only strings in BotCommand struct. 2021-07-02 20:41:46 +03:00
John Preston
a8df3dcf91 Remove test code for animated path thumbnails. 2021-07-02 20:40:32 +03:00
John Preston
b22e2ffe1d Animate inline path thumbnails with sliding gradient. 2021-07-02 20:40:32 +03:00
Ilya Fedin
22d23c8be1 Add missed signalId check 2021-07-02 20:11:28 +03:00
Ilya Fedin
b335741f99 Use gsl::finally to pop thread context where appropriate 2021-07-02 20:11:28 +03:00
Ilya Fedin
1261c775d4 Fix freeze after creating file dialog 2021-07-02 15:51:58 +03:00
John Preston
01b4a24ac7 Save sticker path thumbnails to local storage. 2021-07-02 13:39:08 +03:00
John Preston
4124c2eb57 Show inline path thumbnails for stickers. 2021-07-02 13:13:48 +03:00
John Preston
f09b91ebb5 Beta version 2.8.5: Fix build on non-Windows. 2021-07-02 04:45:58 +03:00
John Preston
57b147e0c8 Beta version 2.8.5.
- Use ANGLE for OpenGL over DirectX 9 / DirectX 11 (Windows).
- Use GTK from a child process (Linux).
2021-07-02 00:59:51 +03:00
Ilya Fedin
551ea7d879 Move GTK integration out of process with D-Bus 2021-07-02 00:59:36 +03:00
John Preston
d3c9bb0bc6 Try disabling native child OpenGL workaround. 2021-07-02 00:37:27 +03:00
John Preston
c711b1f1df Fix build on non-Linux systems. 2021-07-02 00:27:25 +03:00
23rd
af7ea90246 Added floating panel of playing playlist for scheduled audio files. 2021-07-01 23:53:45 +03:00
23rd
348cf4829c Added ability to scroll media in section of scheduled messages.
Fixed #8388.
2021-07-01 23:53:45 +03:00
23rd
4753a57091 Added ability to validate playlists in section of scheduled messages. 2021-07-01 23:53:45 +03:00
23rd
1a93f4fa4c Added ability to sparse id slices of scheduled media. 2021-07-01 23:53:45 +03:00
23rd
118fd187e3 Added abstract class for sparse ids slices. 2021-07-01 23:53:45 +03:00
23rd
baa47bde7f Removed unused MsgRange from SparseIdsSlice. 2021-07-01 23:53:45 +03:00
John Preston
18b48df9ce Allow to choose ANGLE backend. 2021-07-01 23:48:18 +03:00
John Preston
e71fc60d22 Use exact revision of ANGLE. 2021-07-01 23:48:16 +03:00
John Preston
148af59615 Don't check dll-s if "SetDefaultDllDirectories" is available. 2021-07-01 23:47:12 +03:00
John Preston
5b2db4112f Don't allow any .dll-s near Telegram.exe 2021-07-01 23:47:12 +03:00
John Preston
7cedc1f7a5 Add dynamic DirectX loading helper. 2021-07-01 23:47:08 +03:00
John Preston
6cea7d4a52 Fix YUV->RGB on D3D9 ANGLE backend. 2021-07-01 23:46:52 +03:00
John Preston
bd93aed393 Test build with statically linked ANGLE. 2021-07-01 23:46:52 +03:00
John Preston
348666de6d Use media viewer size hack only when required. 2021-07-01 23:46:52 +03:00
Ilya Fedin
47e32bebe4 Remove not really needed gtk scale factor query 2021-07-01 22:13:50 +03:00
Ilya Fedin
0b21c04489 Remove the copy of gtk file dialog 2021-07-01 22:13:50 +03:00
Ilya Fedin
85f013ebdb Revert "Avoid removing portal platformtheme plugin in snap"
This reverts commit 12db51fe75.
2021-07-01 22:13:50 +03:00
Ilya Fedin
832cc6ac69 Build Qt with gtk integration 2021-07-01 22:13:50 +03:00
Ilya Fedin
30ce049f51 Update submodules 2021-07-01 22:13:20 +03:00
Ilya Fedin
d42fb6d1b9 Switch from mallocng to jemalloc
Now it's known how to make it free the memory in an expected manner and it's better maintained
2021-07-01 22:13:20 +03:00
John Preston
cade53aa0a Version 2.8.4.
- Crash fixes in WebView on Windows.
2021-07-01 11:05:21 +03:00
GitHub Action
2fdcda7536 Update User-Agent for DNS to Chrome 91.0.4472.114. 2021-07-01 10:48:17 +03:00
Ilya Fedin
7e6439e4f8 Fix counting screen bottom point when restoring geometry 2021-06-30 00:27:39 +03:00
Ilya Fedin
f07ee7f590 Update lib_base and cmake_helpers 2021-06-29 17:35:39 +03:00
Ilya Fedin
02db4e01fa Get rid of qt5ct 2021-06-29 17:35:39 +03:00
Ilya Fedin
8d75078a42 Use Glib::MainLoop instead of QEventLoop in glib code 2021-06-29 15:10:08 +03:00
John Preston
0e25ef7524 Handle WinRT exceptions in WebView. 2021-06-29 14:08:50 +03:00
John Preston
8608d8aa4d Crash Fix: Destroy WebView before the container. 2021-06-29 11:07:47 +03:00
sammiee5311
c1a7332a5e Shorten if statement
Shorten if statement
2021-06-29 10:38:35 +03:00
Ilya Fedin
c3fb392906 Clean dbus-specific code in main_window_linux.h 2021-06-29 10:30:48 +03:00
Ilya Fedin
a59bfdb2f8 Fix handleNativeSurfaceChanged when dbus integration is disabled 2021-06-29 10:30:48 +03:00
Ilya Fedin
79f96480c2 Use QMenuBar instead of own global menu implementation on Linux 2021-06-29 10:30:48 +03:00
John Preston
60cbd96d91 Version 2.8.3.
- Fix crashes in OpenSSL on macOS.
2021-06-28 13:51:06 +03:00
John Preston
ee0400f1ac Version 2.8.2.
- Attempt to fix random crashes on macOS.

Fixes #16504.
2021-06-28 08:57:40 +03:00
John Preston
b8a3746558 Version 2.8.1: Fix NuGet WinRT header generation. 2021-06-26 13:26:39 +03:00
John Preston
14f25fc997 Version 2.8.1.
- Fix crash in audio player volume slider.
2021-06-26 13:03:40 +03:00
John Preston
27da6ee9eb Update patches revision in instructions. 2021-06-26 13:00:16 +03:00
John Preston
48d482006a Fix crash fix. 2021-06-26 12:33:18 +03:00
John Preston
9afee2620a Fix crash in vertical sliders.
Regression was introduced in 90ff8ecd0f.
2021-06-26 08:20:37 +03:00
John Preston
baca3047d4 Version 2.8: Fix build on Windows x64. 2021-06-24 18:39:41 +04:00
John Preston
43a5265e0c Version 2.8.
- Start video conferences from Voice Chats in any group.
- Share your screen or video from your camera
with up to 30 participants (limit to be increased soon).
- Talk without video with an unlimited number of participants.
- Create voice chats from the info page
of any group where you are an admin.
- Group video calls are supported natively on all devices,
including iPads and laptops.
2021-06-24 17:57:09 +04:00
John Preston
5519bb3523 Allow reporting private groups as well.
Fixes #7451.
2021-06-24 17:44:55 +04:00
John Preston
ff213d1386 Enable /LARGEADDRESSAWARE for 32 bit Windows build. 2021-06-24 17:44:55 +04:00
John Preston
55b3f99653 Fix new formatting mixing with emoji. 2021-06-24 17:44:55 +04:00
John Preston
8a6ff3f414 Add separator above volume control in voice chats. 2021-06-24 17:44:55 +04:00
John Preston
feb8624d05 Don't use private Hunspell headers. 2021-06-24 17:44:55 +04:00
John Preston
a2c33545d4 Improve some paddings. 2021-06-24 17:44:28 +04:00
23rd
7decf68122 Fixed possible crash in OverlayWidget when video continues from PiP. 2021-06-24 17:44:28 +04:00
John Preston
6b62ec97c6 Fix possible crash in export panel management. 2021-06-24 11:57:27 +04:00
Ilya Fedin
ea3dab4a06 Update lib_base 2021-06-24 11:26:24 +04:00
Ilya Fedin
5c8f08fc92 Move preview support from QGtkDialog to GtkFileDialog 2021-06-24 11:26:24 +04:00
Ilya Fedin
00a0b2c8b6 Get rid of GTK cast templates 2021-06-24 11:26:24 +04:00
Ilya Fedin
007218cc13 Use C++ wrappers in GtkOpenWithDialog 2021-06-24 11:26:24 +04:00
Ilya Fedin
8afe495a4f Avoid using g_unix_fd_list_new_from_array 2021-06-24 11:26:24 +04:00
Ilya Fedin
257f2086d1 Get rid of gtk2 header compatibility 2021-06-24 11:26:24 +04:00
Ilya Fedin
f011c84ce8 Make Linux file dialog API better 2021-06-24 11:26:24 +04:00
Ilya Fedin
8b839f46b2 Fix crash report window scale 2021-06-24 11:26:08 +04:00
23rd
c1067d8fe1 Fixed possible crash in notifications manager. 2021-06-24 11:25:36 +04:00
23rd
bb76818cc8 Split adaptive changed rpl::producer into two. 2021-06-24 11:25:35 +04:00
John Preston
5dcc219f1c For large video tile always request full quality. 2021-06-24 10:57:23 +04:00
John Preston
4ff9e90153 Add some assertions and logging for a crash debugging. 2021-06-24 10:49:01 +04:00
John Preston
28fe98af80 Add some assertions for a strange crash debugging. 2021-06-24 10:24:52 +04:00
John Preston
5eba65aaa0 Remove unused legacy protocol code. 2021-06-24 09:55:57 +04:00
John Preston
d1e3e7d240 Don't show pinned tooltips if only one video. 2021-06-23 20:14:49 +04:00
John Preston
90ff8ecd0f Fix volume slider in voice chats. 2021-06-23 20:14:22 +04:00
John Preston
468e75a572 Update submodules. 2021-06-23 20:13:19 +04:00
John Preston
ae3e5487d7 Fix editing messages with monospace parts. 2021-06-23 15:55:29 +04:00
John Preston
03147a5426 Fix possible crash in case of API error. 2021-06-23 14:29:38 +04:00
John Preston
14a2b10989 Show error if camera could not be enabled. 2021-06-23 12:04:05 +04:00
John Preston
b29f8aa1e6 Remove background over highlight in volume change item. 2021-06-23 11:07:23 +04:00
John Preston
f9bb932cd8 Fix voice chat window expanding near the screen edges. 2021-06-23 10:52:04 +04:00
John Preston
a38cbbf7e8 Fix disappearing icons after popup menu display. 2021-06-23 10:43:51 +04:00
John Preston
d5bb1717e0 Beta version 2.7.10: Fix link on macOS. 2021-06-22 23:07:33 +04:00
John Preston
520ff8f2ce Beta version 2.7.10: Fix build with Xcode. 2021-06-22 21:25:03 +04:00
John Preston
b3848f6a84 Beta version 2.7.10: Fix screencasts. 2021-06-22 21:23:01 +04:00
John Preston
518f387e0c Beta version 2.7.10: Update version. 2021-06-22 20:00:35 +04:00
John Preston
635f76a312 Beta version 2.7.10.
- Added ability to mix together bold, italic and other formatting.
- Fix voice chats and video calls OpenGL with some drivers on Windows.
- Several bug fixes.
2021-06-22 19:59:22 +04:00
John Preston
ff14ac68ee Always show tooltip about the muted microphone. 2021-06-22 19:50:26 +04:00
John Preston
948c5d50cb Add C++/WinRT library helper to lib_base. 2021-06-22 19:47:02 +04:00
John Preston
6b520ecc05 Add overlapping markup support. 2021-06-22 19:05:27 +04:00
John Preston
bb474686eb Use NuGet package for WinRT headers generation. 2021-06-22 09:53:20 +04:00
John Preston
659ddae9a8 Use native child window in video calls on Windows. 2021-06-21 11:29:29 +04:00
John Preston
b70276912e Use native child window in group calls on Windows. 2021-06-21 09:23:10 +04:00
23rd
858c575782 Fixed Hunspell license. 2021-06-21 09:23:10 +04:00
23rd
62fe14d592 Fixed lock icon display when switching layers in one column mode. 2021-06-21 09:23:10 +04:00
Ilya Fedin
6ad037e556 Update lib_waylandshells and cmake_helpers 2021-06-20 10:39:42 +04:00
Ilya Fedin
a55b41faa1 Provide a list of shell integrations in QT_WAYLAND_SHELL_INTEGRATION 2021-06-20 10:39:42 +04:00
Ilya Fedin
a26d769304 Set QT_WAYLAND_SHELL_INTEGRATION to custom value 2021-06-19 08:16:38 +04:00
John Preston
e1120d1cb5 Optimize out most of LastUserInputTime() calls.
Fixes #16118.
2021-06-18 19:22:36 +04:00
John Preston
8897f9e46a Limit requested qualities to 4 Full / 16 Medium. 2021-06-18 18:43:13 +04:00
John Preston
7a588be54f Add a hint to unmute your microphone. 2021-06-18 17:47:07 +04:00
John Preston
1cb1f1cbc1 Add a hint to turn on the camera. 2021-06-18 16:11:32 +04:00
John Preston
5827d6ffdb Update lib_ui submodule. 2021-06-18 12:15:01 +04:00
Ilya Fedin
766bc90921 Adapt for Ui::DisableCustomScaling changes 2021-06-18 12:15:01 +04:00
23rd
eb228eb744 Removed unused methods from file click handler. 2021-06-18 09:48:39 +03:00
23rd
7c02d67665 Moved cancelUploadLayer from MainWidget to SessionController. 2021-06-18 09:39:10 +03:00
23rd
23c54896e5 Removed App::main() from file click handlers. 2021-06-18 09:20:49 +03:00
23rd
460baa54d8 Fixed switching between PiP and OverlayWidget. 2021-06-18 07:30:54 +03:00
23rd
6c56fad180 Fixed updating of parent id for file click handlers.
Fixed #16447.
2021-06-18 07:30:54 +03:00
23rd
3fd772ce17 Moved file click handlers to separated file. 2021-06-18 07:30:54 +03:00
John Preston
8834ec8bf2 Disable audio device tracking on macOS. 2021-06-17 17:15:13 +04:00
John Preston
003fb52fb9 Make 100% volume value more sticky. 2021-06-17 16:42:50 +04:00
John Preston
ec234cdc43 Improve volume slider design in group calls. 2021-06-17 16:22:51 +04:00
John Preston
55e494f55a Beta version 2.7.9.
- Added "Enable noise suppression" option to group calls Settings.
- Fix media viewer with Retina + Non-Retina dual monitor setup on macOS.
- Several bug and crash fixes.
2021-06-17 12:11:08 +04:00
John Preston
0b4605a656 Don't pass Quality::Medium for screencast to tgcalls. 2021-06-17 12:03:26 +04:00
John Preston
18a86e500b Update tgcalls and tg_owt. 2021-06-17 11:55:10 +04:00
John Preston
e19af1257c Improve video in voice chats controls layout. 2021-06-17 11:52:53 +04:00
John Preston
e0159e15b2 Close StickerSetBox on error. 2021-06-17 11:06:17 +04:00
23rd
b6e77537e2 Fixed logo size in box of invite link QR code generation. 2021-06-17 10:57:46 +04:00
23rd
beaa4190eb Removed Q_OBJECT from GroupMembersWidget.
Removed unused onlineCountUpdated since d93c1ccbaa.
2021-06-17 10:57:46 +04:00
23rd
7924979dfb Removed Ui::showPeerHistoryAtItem from facades. 2021-06-17 10:57:46 +04:00
23rd
570ed5691d Added Window::Controller pointer to data of intro widget. 2021-06-17 10:57:45 +04:00
23rd
c25779b844 Removed showDocument and showPhoto from Media::View::OverlayWidget. 2021-06-17 10:57:45 +04:00
23rd
7304f2b695 Removed Application::showTheme. 2021-06-17 10:57:45 +04:00
23rd
b4bff939b1 Removed showDocument and showPhoto from Application. 2021-06-17 10:57:45 +04:00
23rd
1f816c249b Replaced DocumentOpenClickHandler. 2021-06-17 10:57:45 +04:00
23rd
8591d58798 Added ability to show content from Controller for Shared Media. 2021-06-17 10:57:45 +04:00
23rd
9290cd3a16 Added SessionController pointer to Media::View::OverlayWidget. 2021-06-17 10:57:45 +04:00
23rd
dc0aaec4a4 Added ability to show document from Controller for sections. 2021-06-17 10:57:45 +04:00
23rd
eefa7263b5 Added ability to show photo from Controller for sections. 2021-06-17 10:57:45 +04:00
23rd
7885be4a94 Added ability to show content from Controller for inline results. 2021-06-17 10:57:45 +04:00
23rd
583c3d3429 Moved static functions from DocumentData to separated file. 2021-06-17 10:57:45 +04:00
23rd
6d0d399250 Added initial ability to show documents in OverlayWidget from Controller. 2021-06-17 10:57:45 +04:00
23rd
0e89c93993 Added initial ability to show content in OverlayWidget from Controller. 2021-06-17 10:57:45 +04:00
23rd
b422ec025e Removed Ui::show from classes that have pointer to Controller. 2021-06-17 10:57:45 +04:00
John Preston
c8535acad8 Fix crash in hunspell initialization. 2021-06-17 10:11:08 +04:00
John Preston
e2a97e2ae9 Fix possible crash in media viewer. 2021-06-17 10:09:22 +04:00
John Preston
77a019325d Show information about unsupported gradient backgrounds. 2021-06-16 11:30:33 +04:00
23rd
115dc460ac Removed unused variables from LastCrashedWindow. 2021-06-16 09:31:32 +03:00
23rd
3df1a73cf5 Removed Q_OBJECT from LastCrashedWindow. 2021-06-16 09:31:32 +03:00
23rd
5cf69366d1 Removed Q_OBJECT from NetworkSettingsWindow. 2021-06-16 09:31:32 +03:00
23rd
8c2b1168af Fixed background color of input fields in crash reports with dark theme. 2021-06-16 09:31:32 +03:00
23rd
a425024f21 Fixed userpic updating of pinned peers in touchbar. 2021-06-16 09:31:32 +03:00
23rd
e85026ec46 Removed observable in Intro::details::Step. 2021-06-16 09:31:32 +03:00
23rd
1c6e2eae04 Removed unused enum from local legacy storage settings scheme. 2021-06-16 09:31:32 +03:00
23rd
4db5624beb Completely removed Global namespace. 2021-06-16 09:31:32 +03:00
23rd
6d08542afa Moved proxy global variables from facades to core settings. 2021-06-16 09:31:32 +03:00
23rd
707b36dc12 Moved DBIWorkMode to Core::Settings. 2021-06-16 09:31:32 +03:00
23rd
da3e140069 Moved DBINotifyView to Core::Settings. 2021-06-16 09:31:32 +03:00
23rd
5334372671 Moved WorkMode global variable from facades to core settings. 2021-06-16 09:31:32 +03:00
23rd
16db8468fa Moved ScreenIsLocked variable from facades to application. 2021-06-16 09:31:32 +03:00
23rd
2ed3543b53 Renamed class back from AdaptiveModern to Adaptive. 2021-06-16 09:31:32 +03:00
23rd
5b4d442799 Removed Adaptive namespace and related global variables from facades. 2021-06-16 09:31:32 +03:00
23rd
9669a8a44a Moved Core::Settings:chatWide to Window::Adaptive. 2021-06-16 09:31:32 +03:00
23rd
80fe2f57e9 Removed Adaptive namespace from Window::Controller and MainWidget. 2021-06-16 09:31:32 +03:00
23rd
824fbc21e8 Removed Adaptive namespace from peer context menu. 2021-06-16 09:31:32 +03:00
23rd
bf7f117323 Removed Adaptive namespace from Window::HistoryHider. 2021-06-16 09:31:32 +03:00
23rd
9b488f03a1 Removed Adaptive namespace from Settings::Chat. 2021-06-16 09:31:32 +03:00
23rd
295a863d69 Removed Adaptive namespace from Profile::BackButton. 2021-06-16 09:31:32 +03:00
23rd
0d814066d6 Removed Adaptive namespace from top bar widgets. 2021-06-16 09:31:32 +03:00
23rd
1af8e89eb9 Removed Adaptive namespace from HistoryWidget. 2021-06-16 09:31:32 +03:00
23rd
7cf79e1f8a Removed Adaptive namespace from sections. 2021-06-16 09:31:32 +03:00
23rd
019fd83c8a Removed Adaptive namespace from Dialogs::Widget. 2021-06-16 09:31:32 +03:00
23rd
65779ec37e Removed Adaptive namespace from FieldAutocomplete. 2021-06-16 09:31:32 +03:00
23rd
2d90a06078 Added new Adaptive class to replace legacy Adaptive namespace.
Temporarily named class as AdaptiveModern.
2021-06-16 09:31:32 +03:00
23rd
d2c8780c0f Removed NotificationsDemoIsShown global variable from facades. 2021-06-16 09:31:32 +03:00
23rd
54dd63d61a Removed LocalPasscode global variable from facades. 2021-06-16 09:31:32 +03:00
23rd
7852c82eab Simplified updating of autolock time in Settings::PrivacySecurity. 2021-06-16 09:31:32 +03:00
23rd
77c8bf8176 Removed PeerChooseCancel global variable from facades. 2021-06-16 09:31:32 +03:00
23rd
daa14466e5 Replaced observable in Lang::CloudManager with rpl. 2021-06-16 09:31:32 +03:00
23rd
aad38c2809 Replaced observable in Window::Notifications::System with rpl. 2021-06-16 09:31:32 +03:00
23rd
2c50d3d87b Replaced observable in Intro::details::Data with rpl. 2021-06-16 09:31:32 +03:00
23rd
0fe7c07007 Replaced observable with rpl in FixedBar of admin log. 2021-06-16 09:31:32 +03:00
23rd
c22d200c17 Removed unused observable trackFinished from Media::Audio::Instance. 2021-06-16 09:31:32 +03:00
23rd
9e6afa0d4e Removed observable dragFinished from MainWindow. 2021-06-16 09:31:32 +03:00
23rd
3340b2dc03 Replaced observable in Dialogs::InnerWidget with rpl. 2021-06-16 09:31:32 +03:00
23rd
386fae952b Replaced observable in SessionController with rpl. 2021-06-16 09:31:32 +03:00
23rd
a164cb9480 Removed unused observable passcodedChanged from Application. 2021-06-16 09:31:32 +03:00
23rd
bc9b288617 Replaced observable in StickersBox with rpl. 2021-06-16 09:31:32 +03:00
23rd
5c7229f875 Replaced observable in EditColorBox with rpl. 2021-06-16 09:31:31 +03:00
John Preston
658d5a1322 Fix move between Retina / Non-Retina. 2021-06-16 10:30:08 +04:00
John Preston
52e841ec29 Select correct quality for incoming screencast. 2021-06-16 08:59:15 +04:00
John Preston
df28da4d97 Show "Video is paused" in wide panel mode. 2021-06-15 16:49:53 +04:00
John Preston
8dac6896d6 Set Send/Receive buffer size for download TCP sockets. 2021-06-15 16:45:48 +04:00
John Preston
f18e157e46 Add video placeholder if can't receive it. 2021-06-15 14:30:51 +04:00
John Preston
b2bf8244dd Add "Enable noise suppression" setting to group calls. 2021-06-15 12:33:02 +04:00
John Preston
4e0355d09f Fix semi-transparent .webp in media viewer. 2021-06-14 15:28:39 +04:00
John Preston
7059336ff0 Show red mute icon for force-muted. 2021-06-14 15:15:33 +04:00
John Preston
94f10ce72e Fix dropping self level around mute button. 2021-06-14 14:57:25 +04:00
John Preston
68be54288c Fix working using OpenGLES / ANGLE. 2021-06-14 12:16:00 +04:00
John Preston
10636d931f Validate video speed before applying. 2021-06-14 11:22:57 +04:00
John Preston
3b1aa55d21 Don't send OpenGL initialization crash reports. 2021-06-14 11:22:39 +04:00
mid-kid
37f59095f4 Fix building with LINK_TO_GTK 2021-06-12 15:08:11 +04:00
603 changed files with 18926 additions and 10368 deletions

View File

@@ -93,6 +93,9 @@ jobs:
DEFINE=""
if [ -n "${{ matrix.defines }}" ]; then
DEFINE="-D ${{ matrix.defines }}=ON"
if [ "${{ matrix.defines }}" == "DESKTOP_APP_DISABLE_DBUS_INTEGRATION" ]; then
DEFINE="$DEFINE -D DESKTOP_APP_DISABLE_GTK_INTEGRATION=ON"
fi
echo Define from matrix: $DEFINE
echo "ARTIFACT_NAME=Telegram_${{ matrix.defines }}" >> $GITHUB_ENV
else

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: |

6
.gitmodules vendored
View File

@@ -76,9 +76,6 @@
[submodule "Telegram/ThirdParty/hime"]
path = Telegram/ThirdParty/hime
url = https://github.com/hime-ime/hime.git
[submodule "Telegram/ThirdParty/qt5ct"]
path = Telegram/ThirdParty/qt5ct
url = https://github.com/desktop-app/qt5ct.git
[submodule "Telegram/ThirdParty/fcitx5-qt"]
path = Telegram/ThirdParty/fcitx5-qt
url = https://github.com/fcitx/fcitx5-qt.git
@@ -91,9 +88,6 @@
[submodule "Telegram/lib_webview"]
path = Telegram/lib_webview
url = https://github.com/desktop-app/lib_webview.git
[submodule "Telegram/ThirdParty/mallocng"]
path = Telegram/ThirdParty/mallocng
url = https://github.com/desktop-app/mallocng.git
[submodule "Telegram/lib_waylandshells"]
path = Telegram/lib_waylandshells
url = https://github.com/desktop-app/lib_waylandshells.git

View File

@@ -31,6 +31,7 @@ include(cmake/target_link_static_libraries.cmake)
include(cmake/target_link_frameworks.cmake)
include(cmake/init_target.cmake)
include(cmake/generate_target.cmake)
include(cmake/nuget.cmake)
include(cmake/options.cmake)

View File

@@ -59,7 +59,7 @@ Version **1.8.15** was the last that supports older systems
* xxHash ([BSD License](https://github.com/Cyan4973/xxHash/blob/dev/LICENSE))
* QR Code generator ([MIT License](https://github.com/nayuki/QR-Code-generator#license))
* CMake ([New BSD License](https://github.com/Kitware/CMake/blob/master/Copyright.txt))
* Hunspell ([GPL](https://github.com/hunspell/hunspell/blob/master/COPYING))
* Hunspell ([LGPL](https://github.com/hunspell/hunspell/blob/master/COPYING.LESSER))
## Build instructions

View File

@@ -82,17 +82,11 @@ PRIVATE
desktop-app::external_xxhash
)
if (WIN32)
target_link_libraries(Telegram
PRIVATE
desktop-app::lib_webview_winrt
)
elseif (LINUX)
if (LINUX)
target_link_libraries(Telegram
PRIVATE
desktop-app::external_glibmm
desktop-app::external_glib
desktop-app::external_mallocng
)
if (NOT DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
@@ -119,6 +113,7 @@ elseif (LINUX)
endif()
if (NOT DESKTOP_APP_DISABLE_GTK_INTEGRATION)
target_link_libraries(Telegram PRIVATE rt)
find_package(PkgConfig REQUIRED)
if (DESKTOP_APP_USE_PACKAGED AND NOT DESKTOP_APP_USE_PACKAGED_LAZY)
@@ -130,7 +125,7 @@ elseif (LINUX)
target_link_libraries(Telegram PRIVATE PkgConfig::X11)
endif()
else()
pkg_search_module(GTK REQUIRED gtk+-3.0 gtk+-2.0)
pkg_check_modules(GTK REQUIRED gtk+-3.0)
target_include_directories(Telegram PRIVATE ${GTK_INCLUDE_DIRS})
if (NOT DESKTOP_APP_DISABLE_X11_INTEGRATION)
@@ -256,8 +251,6 @@ PRIVATE
boxes/peer_lists_box.h
boxes/passcode_box.cpp
boxes/passcode_box.h
boxes/photo_crop_box.cpp
boxes/photo_crop_box.h
boxes/rate_call_box.cpp
boxes/rate_call_box.h
boxes/self_destruction_box.cpp
@@ -373,6 +366,8 @@ PRIVATE
core/core_cloud_password.h
core/core_settings.cpp
core/core_settings.h
core/core_settings_proxy.cpp
core/core_settings_proxy.h
core/crash_report_window.cpp
core/crash_report_window.h
core/crash_reports.cpp
@@ -398,6 +393,7 @@ PRIVATE
data/stickers/data_stickers_set.h
data/stickers/data_stickers.cpp
data/stickers/data_stickers.h
data/data_abstract_sparse_ids.h
data/data_abstract_structure.cpp
data/data_abstract_structure.h
data/data_auto_download.cpp
@@ -420,10 +416,14 @@ PRIVATE
data/data_document.h
data/data_document_media.cpp
data/data_document_media.h
data/data_document_resolver.cpp
data/data_document_resolver.h
data/data_drafts.cpp
data/data_drafts.h
data/data_folder.cpp
data/data_folder.h
data/data_file_click_handler.cpp
data/data_file_click_handler.h
data/data_file_origin.cpp
data/data_file_origin.h
data/data_flags.h
@@ -506,6 +506,40 @@ PRIVATE
dialogs/dialogs_search_from_controllers.h
dialogs/dialogs_widget.cpp
dialogs/dialogs_widget.h
editor/color_picker.cpp
editor/color_picker.h
editor/controllers/controllers.h
editor/controllers/stickers_panel_controller.cpp
editor/controllers/stickers_panel_controller.h
editor/controllers/undo_controller.cpp
editor/controllers/undo_controller.h
editor/editor_crop.cpp
editor/editor_crop.h
editor/editor_paint.cpp
editor/editor_paint.h
editor/photo_editor.cpp
editor/photo_editor.h
editor/photo_editor_common.cpp
editor/photo_editor_common.h
editor/photo_editor_content.cpp
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
editor/scene/scene.h
editor/scene/scene_item_base.cpp
editor/scene/scene_item_base.h
editor/scene/scene_item_canvas.cpp
editor/scene/scene_item_canvas.h
editor/scene/scene_item_image.cpp
editor/scene/scene_item_image.h
editor/scene/scene_item_line.cpp
editor/scene/scene_item_line.h
editor/scene/scene_item_sticker.cpp
editor/scene/scene_item_sticker.h
export/export_manager.cpp
export/export_manager.h
export/view/export_view_content.cpp
@@ -803,6 +837,7 @@ PRIVATE
media/view/media_view_playback_controls.h
media/view/media_view_playback_progress.cpp
media/view/media_view_playback_progress.h
media/view/media_view_open_common.h
mtproto/config_loader.cpp
mtproto/config_loader.h
mtproto/connection_abstract.cpp
@@ -861,8 +896,6 @@ PRIVATE
platform/linux/linux_gdk_helper.h
platform/linux/linux_gsd_media_keys.cpp
platform/linux/linux_gsd_media_keys.h
platform/linux/linux_gtk_file_dialog.cpp
platform/linux/linux_gtk_file_dialog.h
platform/linux/linux_gtk_integration_dummy.cpp
platform/linux/linux_gtk_integration_p.h
platform/linux/linux_gtk_integration.cpp
@@ -1036,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
@@ -1086,6 +1123,8 @@ PRIVATE
window/section_memento.h
window/section_widget.cpp
window/section_widget.h
window/window_adaptive.cpp
window/window_adaptive.h
window/window_connecting_widget.cpp
window/window_connecting_widget.h
window/window_controller.cpp
@@ -1192,8 +1231,6 @@ if (DESKTOP_APP_DISABLE_GTK_INTEGRATION)
remove_target_sources(Telegram ${src_loc}
platform/linux/linux_gdk_helper.cpp
platform/linux/linux_gdk_helper.h
platform/linux/linux_gtk_file_dialog.cpp
platform/linux/linux_gtk_file_dialog.h
platform/linux/linux_gtk_integration_p.h
platform/linux/linux_gtk_integration.cpp
platform/linux/linux_gtk_open_with_dialog.cpp
@@ -1358,6 +1395,32 @@ endif()
set_target_properties(Telegram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
if (WIN32)
target_link_options(Telegram
PRIVATE
/DELAYLOAD:secur32.dll
/DELAYLOAD:winmm.dll
/DELAYLOAD:ws2_32.dll
/DELAYLOAD:user32.dll
/DELAYLOAD:gdi32.dll
/DELAYLOAD:advapi32.dll
/DELAYLOAD:shell32.dll
/DELAYLOAD:ole32.dll
/DELAYLOAD:oleaut32.dll
/DELAYLOAD:shlwapi.dll
/DELAYLOAD:iphlpapi.dll
/DELAYLOAD:gdiplus.dll
/DELAYLOAD:version.dll
/DELAYLOAD:dwmapi.dll
/DELAYLOAD:crypt32.dll
/DELAYLOAD:bcrypt.dll
/DELAYLOAD:imm32.dll
/DELAYLOAD:netapi32.dll
/DELAYLOAD:userenv.dll
/DELAYLOAD:wtsapi32.dll
)
endif()
if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR APPLE) AND NOT build_macstore AND NOT build_winstore)
add_executable(Updater WIN32)
init_target(Updater)
@@ -1374,8 +1437,26 @@ if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR APPLE) AND NOT build_macstore AND NOT
set_target_properties(Updater PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
if (WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_link_options(Updater PRIVATE -municode)
if (WIN32)
get_filename_component(lib_base_loc lib_base REALPATH)
nice_target_sources(Updater ${lib_base_loc}
PRIVATE
base/platform/win/base_windows_safe_library.cpp
base/platform/win/base_windows_safe_library.h
)
target_include_directories(Updater PRIVATE ${lib_base_loc})
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_link_options(Updater
PRIVATE
/DELAYLOAD:user32.dll
/DELAYLOAD:advapi32.dll
/DELAYLOAD:shell32.dll
/DELAYLOAD:ole32.dll
/DELAYLOAD:shlwapi.dll
)
else()
target_link_options(Updater PRIVATE -municode)
endif()
endif()
if (LINUX)

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -184,6 +184,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_media_album_error" = "This file cannot be saved as a part of an album.";
"lng_edit_media_invalid_file" = "Sorry, no way to use this file.";
"lng_edit_photo_editor_hint" = "Left-click on the photo to edit.";
"lng_edit_caption_attach" = "Sorry, you can't attach a new media while you're editing your message.";
"lng_edit_caption_voice" = "Sorry, you can't edit your message while you're having an unsent voice message.";
@@ -452,6 +453,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_performance" = "Performance";
"lng_settings_enable_animations" = "Enable animations";
"lng_settings_enable_opengl" = "Enable OpenGL rendering for media";
"lng_settings_angle_backend" = "ANGLE graphics backend";
"lng_settings_angle_backend_auto" = "Auto";
"lng_settings_angle_backend_d3d9" = "Direct3D 9";
"lng_settings_angle_backend_d3d11" = "Direct3D 11";
"lng_settings_angle_backend_d3d11on12" = "D3D11on12";
"lng_settings_angle_backend_opengl" = "OpenGL";
"lng_settings_angle_backend_disabled" = "Disabled";
"lng_settings_sensitive_title" = "Sensitive content";
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
@@ -497,6 +505,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_background_text1" = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!";
"lng_background_text2" = "I can't even take you seriously right now.";
"lng_background_bad_link" = "This background link appears to be invalid.";
"lng_background_gradient_unsupported" = "Telegram Desktop doesn't support gradient backgrounds yet.";
"lng_background_apply" = "Apply";
"lng_background_share" = "Share";
"lng_background_link_copied" = "Link copied to clipboard";
@@ -1006,6 +1015,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_report_group_title" = "Report group";
"lng_report_bot_title" = "Report bot";
"lng_report_message_title" = "Report message";
"lng_report_please_select_messages" = "Please select messages to report.";
"lng_report_select_messages" = "Select messages";
"lng_report_messages_none" = "Select Messages";
"lng_report_messages_count#one" = "Report {count} Message";
@@ -1370,6 +1380,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_switch_stickers" = "Stickers";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIFs";
"lng_switch_masks" = "Masks";
"lng_stickers_featured_add" = "Add";
"lng_gifs_search" = "Search GIFs";
"lng_gifs_no_saved" = "You have no saved GIFs yet.";
@@ -1380,11 +1391,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_box_remove" = "Remove";
"lng_stickers_installed_tab" = "Stickers";
"lng_stickers_masks_tab" = "Masks";
"lng_stickers_featured_tab" = "Trending";
"lng_stickers_archived_tab" = "Archived";
"lng_stickers_remove_pack" = "Remove «{sticker_pack}»?";
"lng_stickers_add_pack" = "Add stickers";
"lng_stickers_add_masks" = "Add masks";
"lng_stickers_share_pack" = "Share Stickers";
"lng_stickers_share_masks" = "Share Masks";
"lng_stickers_not_found" = "Sticker pack not found.";
"lng_stickers_packs_archived" = "Some of your unused stickers have been archived to make room for the sets you've activated.";
"lng_stickers_copied" = "Sticker pack link copied to clipboard.";
@@ -1393,7 +1407,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stickers_return" = "Undo";
"lng_stickers_count#one" = "{count} sticker";
"lng_stickers_count#other" = "{count} stickers";
"lng_stickers_masks_pack" = "This is a pack of mask stickers. You can use them in the photo editor on our mobile apps.";
"lng_masks_count#one" = "{count} mask";
"lng_masks_count#other" = "{count} masks";
"lng_stickers_attached_sets" = "Sets of attached stickers";
"lng_stickers_group_set" = "Group sticker set";
"lng_stickers_remove_group_set" = "Remove group sticker set?";
@@ -1404,6 +1419,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stickers_remove_pack_confirm" = "Remove";
"lng_stickers_archive_pack" = "Archive Stickers";
"lng_stickers_has_been_archived" = "Sticker pack has been archived.";
"lng_masks_archive_pack" = "Archive Masks";
"lng_masks_has_been_archived" = "Mask pack has been archived.";
"lng_masks_installed" = "Mask pack has been installed.";
"lng_in_dlg_photo" = "Photo";
"lng_in_dlg_album" = "Album";
@@ -2003,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";
@@ -2029,6 +2048,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_chat_no_camera" = "You can't turn on video in this chat.";
"lng_group_call_chat_no_screen" = "You can't share your screen in this chat.";
"lng_group_call_failed_screen" = "An error occured. Screencast has stopped.";
"lng_group_call_failed_camera" = "Could not enable camera. Perhaps another app is using the camera already. Try closing other apps.";
"lng_group_call_tooltip_screen" = "Share screen";
"lng_group_call_tooltip_camera" = "Your camera is off. Click here to enable camera.";
"lng_group_call_tooltip_microphone" = "You are on mute. Click here to speak.";
@@ -2057,6 +2077,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_ptt_delay_s" = "{amount}s";
"lng_group_call_ptt_delay" = "Push to Talk release delay: {delay}";
"lng_group_call_share" = "Share Invite Link";
"lng_group_call_noise_suppression" = "Enable Noise Suppression";
"lng_group_call_limit#one" = "Video is only available\nfor the first {count} member";
"lng_group_call_limit#other" = "Video is only available\nfor the first {count} members";
"lng_group_call_video_paused" = "Video is paused";
"lng_group_call_share_speaker" = "Users with this link can speak";
"lng_group_call_copy_speaker_link" = "Copy Speaker Link";
"lng_group_call_copy_listener_link" = "Copy Listener Link";
@@ -2753,6 +2777,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_filters_remove_sure" = "This will remove the folder, your chats will not be deleted.";
"lng_filters_remove_yes" = "Remove";
"lng_photo_editor_menu_delete" = "Delete";
"lng_photo_editor_menu_flip" = "Flip";
"lng_photo_editor_menu_duplicate" = "Duplicate";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose Default Program...";

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;
@@ -579,8 +580,8 @@ keyboardButtonRequestPoll#bbc7515d flags:# quiz:flags.0?Bool text:string = Keybo
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup;
replyKeyboardForceReply#f4108aa0 flags:# single_use:flags.1?true selective:flags.2?true = ReplyMarkup;
replyKeyboardMarkup#3502758c flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector<KeyboardButtonRow> = ReplyMarkup;
replyKeyboardForceReply#86b40b08 flags:# single_use:flags.1?true selective:flags.2?true placeholder:flags.3?string = ReplyMarkup;
replyKeyboardMarkup#85dd99d1 flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector<KeyboardButtonRow> placeholder:flags.3?string = ReplyMarkup;
replyInlineMarkup#48a30254 rows:Vector<KeyboardButtonRow> = ReplyMarkup;
messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity;
@@ -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,21 @@ 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;
botCommandScopeDefault#2f6cb2ab = BotCommandScope;
botCommandScopeUsers#3c4f04d8 = BotCommandScope;
botCommandScopeChats#6fe1a881 = BotCommandScope;
botCommandScopeChatAdmins#b9aa606a = BotCommandScope;
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---
@@ -1271,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;
@@ -1347,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;
@@ -1596,7 +1614,9 @@ channels.convertToGigagroup#b290c69 channel:InputChannel = Updates;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
bots.setBotCommands#805d46f6 commands:Vector<BotCommand> = Bool;
bots.setBotCommands#517165a scope:BotCommandScope lang_code:string commands:Vector<BotCommand> = Bool;
bots.resetBotCommands#3d8de0f9 scope:BotCommandScope lang_code:string = Bool;
bots.getBotCommands#e34c0dd6 scope:BotCommandScope lang_code:string = Vector<BotCommand>;
payments.getPaymentForm#8a333c8d flags:# peer:InputPeer msg_id:int theme_params:flags.0?DataJSON = payments.PaymentForm;
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
@@ -1606,11 +1626,13 @@ payments.getSavedInfo#227d824b = payments.SavedInfo;
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
stickers.createStickerSet#f1036780 flags:# masks:flags.0?true animated:flags.1?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> = messages.StickerSet;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = messages.StickerSet;
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
stickers.setStickerSetThumb#9a364e30 stickerset:InputStickerSet thumb:InputDocument = messages.StickerSet;
stickers.checkShortName#284b3639 short_name:string = Bool;
stickers.suggestShortName#4dafc503 title:string = stickers.SuggestedShortName;
phone.getCallConfig#55451fa9 = DataJSON;
phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
@@ -1656,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 129
// LAYER 131

View File

@@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="2.7.8.0" />
Version="2.8.10.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,7,8,0
PRODUCTVERSION 2,7,8,0
FILEVERSION 2,8,10,0
PRODUCTVERSION 2,8,10,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.7.8.0"
VALUE "FileVersion", "2.8.10.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.7.8.0"
VALUE "ProductVersion", "2.8.10.0"
END
END
BLOCK "VarFileInfo"

View File

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

View File

@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "updater.h"
#include "base/platform/win/base_windows_safe_library.h"
bool _debug = false;
wstring updaterName, updaterDir, updateTo, exeName, customWorkingDir, customKeyFile;
@@ -329,6 +331,8 @@ void updateRegistry() {
}
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
base::Platform::InitDynamicLibraries();
openLog();
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);

View File

@@ -36,10 +36,12 @@ void AttachedStickers::request(
return;
}
if (result.v.isEmpty()) {
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
strongController->show(
Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
return;
} else if (result.v.size() > 1) {
Ui::show(Box<StickersBox>(strongController, result));
strongController->show(
Box<StickersBox>(strongController, result));
return;
}
// Single attached sticker pack.
@@ -50,14 +52,19 @@ 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());
Ui::show(
? 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);
}).fail([=](const MTP::Error &error) {
_requestId = 0;
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
if (const auto strongController = weak.get()) {
strongController->show(
Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
}
}).send();
}

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

@@ -34,7 +34,11 @@ void CheckChatInvite(
session->api().checkChatInvite(hash, [=](const MTPChatInvite &result) {
Core::App().hideMediaView();
result.match([=](const MTPDchatInvite &data) {
const auto box = Ui::show(Box<ConfirmInviteBox>(
const auto strongController = weak.get();
if (!strongController) {
return;
}
const auto box = strongController->show(Box<ConfirmInviteBox>(
session,
data,
invitePeekChannel,
@@ -80,7 +84,10 @@ void CheckChatInvite(
return;
}
Core::App().hideMediaView();
Ui::show(Box<InformBox>(tr::lng_group_invite_bad_link(tr::now)));
if (const auto strong = weak.get()) {
strong->show(
Box<InformBox>(tr::lng_group_invite_bad_link(tr::now)));
}
});
}

View File

@@ -52,6 +52,10 @@ mtpRequestId EditMessage(
ConvertOption::SkipLocal);
const auto media = item->media();
const auto updateRecentStickers = inputMedia.has_value()
? Api::HasAttachedStickers(*inputMedia)
: false;
const auto emptyFlag = MTPmessages_EditMessage::Flag(0);
const auto flags = emptyFlag
| (!text.isEmpty() || media
@@ -97,6 +101,10 @@ mtpRequestId EditMessage(
} else {
apply();
}
if (updateRecentStickers) {
api->requestRecentStickersForce(true);
}
}).fail(
fail
).send();
@@ -165,22 +173,30 @@ void EditMessageWithUploadedDocument(
HistoryItem *item,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
SendOptions options) {
SendOptions options,
std::vector<MTPInputDocument> attachedStickers) {
if (!item || !item->media() || !item->media()->document()) {
return;
}
const auto media = PrepareUploadedDocument(item, file, thumb);
const auto media = PrepareUploadedDocument(
item,
file,
thumb,
std::move(attachedStickers));
EditMessageWithUploadedMedia(item, options, media);
}
void EditMessageWithUploadedPhoto(
HistoryItem *item,
const MTPInputFile &file,
SendOptions options) {
SendOptions options,
std::vector<MTPInputDocument> attachedStickers) {
if (!item || !item->media() || !item->media()->photo()) {
return;
}
const auto media = PrepareUploadedPhoto(file);
const auto media = PrepareUploadedPhoto(
file,
std::move(attachedStickers));
EditMessageWithUploadedMedia(item, options, media);
}

View File

@@ -31,12 +31,14 @@ void EditMessageWithUploadedDocument(
HistoryItem *item,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
SendOptions options);
SendOptions options,
std::vector<MTPInputDocument> attachedStickers);
void EditMessageWithUploadedPhoto(
HistoryItem *item,
const MTPInputFile &file,
SendOptions options);
SendOptions options,
std::vector<MTPInputDocument> attachedStickers);
mtpRequestId EditCaption(
not_null<HistoryItem*> item,

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);
}
}
@@ -61,10 +62,14 @@ int32 CountStickersHash(
: 0;
}
int32 CountRecentStickersHash(not_null<Main::Session*> session) {
int32 CountRecentStickersHash(
not_null<Main::Session*> session,
bool attached) {
return CountSpecialStickerSetHash(
session,
Data::Stickers::CloudRecentSetId);
attached
? Data::Stickers::CloudRecentAttachedSetId
: Data::Stickers::CloudRecentSetId);
}
int32 CountFavedStickersHash(not_null<Main::Session*> session) {
@@ -80,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

@@ -17,7 +17,8 @@ namespace Api {
not_null<Main::Session*> session,
bool checkOutdatedInfo = false);
[[nodiscard]] int32 CountRecentStickersHash(
not_null<Main::Session*> session);
not_null<Main::Session*> session,
bool attached = false);
[[nodiscard]] int32 CountFavedStickersHash(not_null<Main::Session*> session);
[[nodiscard]] int32 CountFeaturedStickersHash(
not_null<Main::Session*> session);

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
@@ -73,18 +74,24 @@ MTPVector<MTPDocumentAttribute> ComposeSendingDocumentAttributes(
} // namespace
MTPInputMedia PrepareUploadedPhoto(const MTPInputFile &file) {
MTPInputMedia PrepareUploadedPhoto(
const MTPInputFile &file,
std::vector<MTPInputDocument> attachedStickers) {
const auto flags = attachedStickers.empty()
? MTPDinputMediaUploadedPhoto::Flags(0)
: MTPDinputMediaUploadedPhoto::Flag::f_stickers;
return MTP_inputMediaUploadedPhoto(
MTP_flags(0),
MTP_flags(flags),
file,
MTPVector<MTPInputDocument>(),
MTP_vector<MTPInputDocument>(ranges::to<QVector>(attachedStickers)),
MTP_int(0));
}
MTPInputMedia PrepareUploadedDocument(
not_null<HistoryItem*> item,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb) {
const std::optional<MTPInputFile> &thumb,
std::vector<MTPInputDocument> attachedStickers) {
if (!item || !item->media() || !item->media()->document()) {
return MTP_inputMediaEmpty();
}
@@ -92,7 +99,8 @@ MTPInputMedia PrepareUploadedDocument(
using DocFlags = MTPDinputMediaUploadedDocument::Flag;
const auto flags = emptyFlag
| (thumb ? DocFlags::f_thumb : emptyFlag)
| (item->groupId() ? DocFlags::f_nosound_video : emptyFlag);
| (item->groupId() ? DocFlags::f_nosound_video : emptyFlag)
| (attachedStickers.empty() ? DocFlags::f_stickers : emptyFlag);
const auto document = item->media()->document();
return MTP_inputMediaUploadedDocument(
MTP_flags(flags),
@@ -100,8 +108,20 @@ MTPInputMedia PrepareUploadedDocument(
thumb.value_or(MTPInputFile()),
MTP_string(document->mimeString()),
ComposeSendingDocumentAttributes(document),
MTPVector<MTPInputDocument>(),
MTP_vector<MTPInputDocument>(ranges::to<QVector>(attachedStickers)),
MTP_int(0));
}
bool HasAttachedStickers(MTPInputMedia media) {
return media.match([&](const MTPDinputMediaUploadedPhoto &photo) -> bool {
return (photo.vflags().v
& MTPDinputMediaUploadedPhoto::Flag::f_stickers);
}, [&](const MTPDinputMediaUploadedDocument &document) -> bool {
return (document.vflags().v
& MTPDinputMediaUploadedDocument::Flag::f_stickers);
}, [](const auto &d) {
return false;
});
}
} // namespace Api

View File

@@ -11,11 +11,16 @@ class HistoryItem;
namespace Api {
MTPInputMedia PrepareUploadedPhoto(const MTPInputFile &file);
MTPInputMedia PrepareUploadedPhoto(
const MTPInputFile &file,
std::vector<MTPInputDocument> attachedStickers);
MTPInputMedia PrepareUploadedDocument(
not_null<HistoryItem*> item,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb);
const std::optional<MTPInputFile> &thumb,
std::vector<MTPInputDocument> attachedStickers);
bool HasAttachedStickers(MTPInputMedia media);
} // namespace Api

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;
};
@@ -862,8 +861,8 @@ int32 Updates::pts() const {
return _ptsWaiter.current();
}
void Updates::updateOnline() {
updateOnline(false);
void Updates::updateOnline(crl::time lastNonIdleTime) {
updateOnline(lastNonIdleTime, false);
}
bool Updates::isIdle() const {
@@ -874,15 +873,20 @@ rpl::producer<bool> Updates::isIdleValue() const {
return _isIdle.value();
}
void Updates::updateOnline(bool gotOtherOffline) {
crl::on_main(&session(), [] { Core::App().checkAutoLock(); });
void Updates::updateOnline(crl::time lastNonIdleTime, bool gotOtherOffline) {
if (!lastNonIdleTime) {
lastNonIdleTime = Core::App().lastNonIdleTime();
}
crl::on_main(&session(), [=] {
Core::App().checkAutoLock(lastNonIdleTime);
});
const auto &config = _session->serverConfig();
bool isOnline = Core::App().hasActiveWindow(&session());
int updateIn = config.onlineUpdatePeriod;
Assert(updateIn >= 0);
if (isOnline) {
const auto idle = crl::now() - Core::App().lastNonIdleTime();
const auto idle = crl::now() - lastNonIdleTime;
if (idle >= config.offlineIdleTimeout) {
isOnline = false;
if (!isIdle()) {
@@ -933,10 +937,13 @@ void Updates::updateOnline(bool gotOtherOffline) {
_onlineTimer.callOnce(updateIn);
}
void Updates::checkIdleFinish() {
if (crl::now() - Core::App().lastNonIdleTime()
void Updates::checkIdleFinish(crl::time lastNonIdleTime) {
if (!lastNonIdleTime) {
lastNonIdleTime = Core::App().lastNonIdleTime();
}
if (crl::now() - lastNonIdleTime
< _session->serverConfig().offlineIdleTimeout) {
updateOnline();
updateOnline(lastNonIdleTime);
_idleFinishTimer.cancel();
_isIdle = false;
} else {
@@ -957,9 +964,10 @@ bool Updates::isQuitPrevent() {
return false;
}
LOG(("Api::Updates prevents quit, sending offline status..."));
updateOnline();
updateOnline(crl::now());
return true;
}
void Updates::handleSendActionUpdate(
PeerId peerId,
MsgId rootId,
@@ -990,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;
@@ -1021,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),
@@ -1241,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) {
@@ -1598,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());
//}
@@ -1750,7 +1754,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
if (UserId(d.vuser_id()) == session().userId()) {
if (d.vstatus().type() == mtpc_userStatusOffline
|| d.vstatus().type() == mtpc_userStatusEmpty) {
updateOnline(true);
updateOnline(Core::App().lastNonIdleTime(), true);
if (d.vstatus().type() == mtpc_userStatusOffline) {
cSetOtherOnline(
d.vstatus().c_userStatusOffline().vwas_online().v);
@@ -1808,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;
@@ -1863,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:
@@ -1893,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 {
@@ -2132,31 +2148,46 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateStickerSetsOrder: {
auto &d = update.c_updateStickerSetsOrder();
if (!d.is_masks()) {
const auto &order = d.vorder().v;
const auto &sets = session().data().stickers().sets();
Data::StickersSetsOrder result;
for (const auto &item : order) {
if (sets.find(item.v) == sets.cend()) {
break;
}
result.push_back(item.v);
auto &stickers = session().data().stickers();
const auto isMasks = d.is_masks();
const auto &order = d.vorder().v;
const auto &sets = stickers.sets();
Data::StickersSetsOrder result;
for (const auto &item : order) {
if (sets.find(item.v) == sets.cend()) {
break;
}
if (result.size() != session().data().stickers().setsOrder().size()
|| result.size() != order.size()) {
session().data().stickers().setLastUpdate(0);
session().api().updateStickers();
result.push_back(item.v);
}
const auto localSize = isMasks
? stickers.maskSetsOrder().size()
: stickers.setsOrder().size();
if ((result.size() != localSize) || (result.size() != order.size())) {
if (isMasks) {
stickers.setLastMasksUpdate(0);
session().api().updateMasks();
} else {
session().data().stickers().setsOrderRef() = std::move(result);
session().local().writeInstalledStickers();
session().data().stickers().notifyUpdated();
stickers.setLastUpdate(0);
session().api().updateStickers();
}
} else {
if (isMasks) {
stickers.maskSetsOrderRef() = std::move(result);
session().local().writeInstalledMasks();
} else {
stickers.setsOrderRef() = std::move(result);
session().local().writeInstalledStickers();
}
stickers.notifyUpdated();
}
} break;
case mtpc_updateStickerSets: {
// Can't determine is it masks or stickers, so update both.
session().data().stickers().setLastUpdate(0);
session().api().updateStickers();
session().data().stickers().setLastMasksUpdate(0);
session().api().updateMasks();
} break;
case mtpc_updateRecentStickers: {

View File

@@ -38,10 +38,10 @@ public:
[[nodiscard]] int32 pts() const;
void updateOnline();
void updateOnline(crl::time lastNonIdleTime = 0);
[[nodiscard]] bool isIdle() const;
[[nodiscard]] rpl::producer<bool> isIdleValue() const;
void checkIdleFinish();
void checkIdleFinish(crl::time lastNonIdleTime = 0);
bool lastWasOnline() const;
crl::time lastSetOnline() const;
bool isQuitPrevent();
@@ -87,7 +87,7 @@ private:
MsgRange range,
const MTPupdates_ChannelDifference &result);
void updateOnline(bool gotOtherOffline);
void updateOnline(crl::time lastNonIdleTime, bool gotOtherOffline);
void sendPing();
void getDifferenceByPts();
void getDifferenceAfterFail();

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"
@@ -212,6 +212,11 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
}, _session->lifetime());
setupSupportMode();
Core::App().settings().proxy().connectionTypeValue(
) | rpl::start_with_next([=] {
refreshTopPromotion();
}, _session->lifetime());
});
}
@@ -261,10 +266,10 @@ void ApiWrap::refreshTopPromotion() {
return;
}
const auto key = [&]() -> std::pair<QString, uint32> {
if (Global::ProxySettings() != MTP::ProxyData::Settings::Enabled) {
if (!Core::App().settings().proxy().isEnabled()) {
return {};
}
const auto &proxy = Global::SelectedProxy();
const auto &proxy = Core::App().settings().proxy().selected();
if (proxy.type != MTP::ProxyData::Type::Mtproto) {
return {};
}
@@ -1219,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);
@@ -1521,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) {
@@ -1542,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();
@@ -1564,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 });
@@ -1726,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;
@@ -1734,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);
@@ -1758,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);
@@ -1852,9 +1858,14 @@ void ApiWrap::requestStickerSets() {
if (i.value().second) continue;
auto waitMs = (j == e) ? 0 : kSmallDelayMs;
i.value().second = request(MTPmessages_GetStickerSet(MTP_inputStickerSetID(MTP_long(i.key()), MTP_long(i.value().first)))).done([this, setId = i.key()](const MTPmessages_StickerSet &result) {
const auto id = MTP_inputStickerSetID(
MTP_long(i.key()),
MTP_long(i.value().first));
i.value().second = request(MTPmessages_GetStickerSet(
id
)).done([=, setId = i.key()](const MTPmessages_StickerSet &result) {
gotStickerSet(setId, result);
}).fail([this, setId = i.key()](const MTP::Error &error) {
}).fail([=, setId = i.key()](const MTP::Error &error) {
_stickerSetRequests.remove(setId);
}).afterDelay(waitMs).send();
}
@@ -1862,23 +1873,89 @@ void ApiWrap::requestStickerSets() {
void ApiWrap::saveStickerSets(
const Data::StickersSetsOrder &localOrder,
const Data::StickersSetsOrder &localRemoved) {
for (auto requestId : base::take(_stickerSetDisenableRequests)) {
const Data::StickersSetsOrder &localRemoved,
bool setsMasks) {
auto &setDisenableRequests = setsMasks
? _maskSetDisenableRequests
: _stickerSetDisenableRequests;
const auto reorderRequestId = [=]() -> mtpRequestId & {
return setsMasks
? _masksReorderRequestId
: _stickersReorderRequestId;
};
for (auto requestId : base::take(setDisenableRequests)) {
request(requestId).cancel();
}
request(base::take(_stickersReorderRequestId)).cancel();
request(base::take(reorderRequestId())).cancel();
request(base::take(_stickersClearRecentRequestId)).cancel();
request(base::take(_stickersClearRecentAttachedRequestId)).cancel();
auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false;
const auto stickersSaveOrder = [=] {
if (localOrder.size() < 2) {
return;
}
QVector<MTPlong> mtpOrder;
mtpOrder.reserve(localOrder.size());
for (const auto setId : std::as_const(localOrder)) {
mtpOrder.push_back(MTP_long(setId));
}
const auto flags = setsMasks
? MTPmessages_ReorderStickerSets::Flag::f_masks
: MTPmessages_ReorderStickerSets::Flags(0);
reorderRequestId() = request(MTPmessages_ReorderStickerSets(
MTP_flags(flags),
MTP_vector<MTPlong>(mtpOrder)
)).done([=](const MTPBool &result) {
reorderRequestId() = 0;
}).fail([=](const MTP::Error &error) {
reorderRequestId() = 0;
if (setsMasks) {
_session->data().stickers().setLastMasksUpdate(0);
updateMasks();
} else {
_session->data().stickers().setLastUpdate(0);
updateStickers();
}
}).send();
};
const auto stickerSetDisenabled = [=](mtpRequestId requestId) {
auto &setDisenableRequests = setsMasks
? _maskSetDisenableRequests
: _stickerSetDisenableRequests;
setDisenableRequests.remove(requestId);
if (setDisenableRequests.empty()) {
stickersSaveOrder();
}
};
auto writeInstalled = true,
writeRecent = false,
writeCloudRecent = false,
writeCloudRecentAttached = false,
writeFaved = false,
writeArchived = false;
auto &recent = _session->data().stickers().getRecentPack();
auto &sets = _session->data().stickers().setsRef();
_stickersOrder = localOrder;
auto &order = setsMasks
? _session->data().stickers().maskSetsOrder()
: _session->data().stickers().setsOrder();
auto &orderRef = setsMasks
? _session->data().stickers().maskSetsOrderRef()
: _session->data().stickers().setsOrderRef();
using Flag = Data::StickersSetFlag;
for (const auto removedSetId : localRemoved) {
if (removedSetId == Data::Stickers::CloudRecentSetId) {
if ((removedSetId == Data::Stickers::CloudRecentSetId)
|| (removedSetId == Data::Stickers::CloudRecentAttachedSetId)) {
if (sets.remove(Data::Stickers::CloudRecentSetId) != 0) {
writeCloudRecent = true;
}
if (sets.remove(Data::Stickers::CloudRecentAttachedSetId) != 0) {
writeCloudRecentAttached = true;
}
if (sets.remove(Data::Stickers::CustomSetId)) {
writeInstalled = true;
}
@@ -1887,12 +1964,25 @@ void ApiWrap::saveStickerSets(
writeRecent = true;
}
_stickersClearRecentRequestId = request(MTPmessages_ClearRecentStickers(
MTP_flags(0)
)).done([this](const MTPBool &result) {
_stickersClearRecentRequestId = 0;
}).fail([this](const MTP::Error &error) {
_stickersClearRecentRequestId = 0;
const auto isAttached =
(removedSetId == Data::Stickers::CloudRecentAttachedSetId);
const auto flags = isAttached
? MTPmessages_ClearRecentStickers::Flag::f_attached
: MTPmessages_ClearRecentStickers::Flags(0);
auto &requestId = isAttached
? _stickersClearRecentAttachedRequestId
: _stickersClearRecentRequestId;
const auto finish = [=] {
(isAttached
? _stickersClearRecentAttachedRequestId
: _stickersClearRecentRequestId) = 0;
};
requestId = request(MTPmessages_ClearRecentStickers(
MTP_flags(flags)
)).done([=](const MTPBool &result) {
finish();
}).fail([=](const MTP::Error &error) {
finish();
}).send();
continue;
}
@@ -1908,27 +1998,33 @@ void ApiWrap::saveStickerSets(
++i;
}
}
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
const auto archived = !!(set->flags & Flag::Archived);
if (!archived) {
const auto featured = !!(set->flags & Flag::Featured);
const auto special = !!(set->flags & Flag::Special);
const auto setId = set->mtpInput();
auto requestId = request(MTPmessages_UninstallStickerSet(setId)).done([this](const MTPBool &result, mtpRequestId requestId) {
auto requestId = request(MTPmessages_UninstallStickerSet(
setId
)).done([=](const MTPBool &result, mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).fail([this](const MTP::Error &error, mtpRequestId requestId) {
}).fail([=](const MTP::Error &error, mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).afterDelay(kSmallDelayMs).send();
_stickerSetDisenableRequests.insert(requestId);
setDisenableRequests.insert(requestId);
int removeIndex = _session->data().stickers().setsOrder().indexOf(set->id);
if (removeIndex >= 0) _session->data().stickers().setsOrderRef().removeAt(removeIndex);
if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured)
&& !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
const auto removeIndex = order.indexOf(set->id);
if (removeIndex >= 0) {
orderRef.removeAt(removeIndex);
}
if (!featured && !special) {
sets.erase(it);
} else {
if (set->flags & MTPDstickerSet::Flag::f_archived) {
if (archived) {
writeArchived = true;
}
set->flags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet::Flag::f_archived);
set->flags &= ~(Flag::Installed | Flag::Archived);
set->installDate = TimeId(0);
}
}
@@ -1937,51 +2033,55 @@ void ApiWrap::saveStickerSets(
// Clear all installed flags, set only for sets from order.
for (auto &[id, set] : sets) {
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
const auto archived = !!(set->flags & Flag::Archived);
const auto masks = !!(set->flags & Flag::Masks);
if (!archived && (setsMasks == masks)) {
set->flags &= ~Flag::Installed;
}
}
auto &order = _session->data().stickers().setsOrderRef();
order.clear();
for (const auto setId : std::as_const(_stickersOrder)) {
orderRef.clear();
for (const auto setId : std::as_const(localOrder)) {
auto it = sets.find(setId);
if (it != sets.cend()) {
const auto set = it->second.get();
if ((set->flags & MTPDstickerSet::Flag::f_archived) && !localRemoved.contains(set->id)) {
const auto mtpSetId = set->mtpInput();
if (it == sets.cend()) {
continue;
}
const auto set = it->second.get();
const auto archived = !!(set->flags & Flag::Archived);
if (archived && !localRemoved.contains(set->id)) {
const auto mtpSetId = set->mtpInput();
const auto requestId = request(MTPmessages_InstallStickerSet(
mtpSetId,
MTP_boolFalse()
)).done([=](
const MTPmessages_StickerSetInstallResult &result,
mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).fail([=](
const MTP::Error &error,
mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).afterDelay(kSmallDelayMs).send();
const auto requestId = request(MTPmessages_InstallStickerSet(
mtpSetId,
MTP_boolFalse()
)).done([=](
const MTPmessages_StickerSetInstallResult &result,
mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).fail([=](
const MTP::Error &error,
mtpRequestId requestId) {
stickerSetDisenabled(requestId);
}).afterDelay(kSmallDelayMs).send();
_stickerSetDisenableRequests.insert(requestId);
setDisenableRequests.insert(requestId);
set->flags &= ~MTPDstickerSet::Flag::f_archived;
writeArchived = true;
}
order.push_back(setId);
set->flags |= MTPDstickerSet::Flag::f_installed_date;
if (!set->installDate) {
set->installDate = base::unixtime::now();
}
set->flags &= ~Flag::Archived;
writeArchived = true;
}
orderRef.push_back(setId);
set->flags |= Flag::Installed;
if (!set->installDate) {
set->installDate = base::unixtime::now();
}
}
for (auto it = sets.begin(); it != sets.cend();) {
const auto set = it->second.get();
if ((set->flags & MTPDstickerSet_ClientFlag::f_featured)
|| (set->flags & MTPDstickerSet::Flag::f_installed_date)
|| (set->flags & MTPDstickerSet::Flag::f_archived)
|| (set->flags & MTPDstickerSet_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);
@@ -1989,27 +2089,40 @@ void ApiWrap::saveStickerSets(
}
auto &storage = local();
if (writeInstalled) storage.writeInstalledStickers();
if (writeRecent) session().saveSettings();
if (writeArchived) storage.writeArchivedStickers();
if (writeCloudRecent) storage.writeRecentStickers();
if (writeFaved) storage.writeFavedStickers();
if (writeInstalled && !setsMasks) {
storage.writeInstalledStickers();
}
if (writeInstalled && setsMasks) {
storage.writeInstalledMasks();
}
if (writeRecent) {
session().saveSettings();
}
if (writeArchived) {
if (setsMasks) {
storage.writeArchivedMasks();
} else {
storage.writeArchivedStickers();
}
}
if (writeCloudRecent) {
storage.writeRecentStickers();
}
if (writeCloudRecentAttached) {
storage.writeRecentMasks();
}
if (writeFaved) {
storage.writeFavedStickers();
}
_session->data().stickers().notifyUpdated();
if (_stickerSetDisenableRequests.empty()) {
if (setDisenableRequests.empty()) {
stickersSaveOrder();
} else {
requestSendDelayed();
}
}
void ApiWrap::stickerSetDisenabled(mtpRequestId requestId) {
_stickerSetDisenableRequests.remove(requestId);
if (_stickerSetDisenableRequests.empty()) {
stickersSaveOrder();
}
};
void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
if (channel->amIn()) {
session().changes().peerUpdated(
@@ -2820,12 +2933,24 @@ void ApiWrap::refreshFileReference(
}, [&](Data::FileOriginPeerPhoto data) {
fail();
}, [&](Data::FileOriginStickerSet data) {
const auto isRecentAttached =
(data.setId == Data::Stickers::CloudRecentAttachedSetId);
if (data.setId == Data::Stickers::CloudRecentSetId
|| data.setId == Data::Stickers::RecentSetId) {
|| data.setId == Data::Stickers::RecentSetId
|| isRecentAttached) {
auto done = [=] { crl::on_main(_session, [=] {
if (isRecentAttached) {
local().writeRecentMasks();
} else {
local().writeRecentStickers();
}
}); };
request(MTPmessages_GetRecentStickers(
MTP_flags(0),
MTP_flags(isRecentAttached
? MTPmessages_GetRecentStickers::Flag::f_attached
: MTPmessages_GetRecentStickers::Flags(0)),
MTP_int(0)),
[=] { crl::on_main(_session, [=] { local().writeRecentStickers(); }); });
std::move(done));
} else if (data.setId == Data::Stickers::FavedSetId) {
request(MTPmessages_GetFavedStickers(MTP_int(0)),
[=] { crl::on_main(_session, [=] { local().writeFavedStickers(); }); });
@@ -2881,30 +3006,8 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &resu
_session->data().sendWebPageGamePollNotifications();
}
void ApiWrap::stickersSaveOrder() {
if (_stickersOrder.size() < 2) {
return;
}
QVector<MTPlong> mtpOrder;
mtpOrder.reserve(_stickersOrder.size());
for (const auto setId : std::as_const(_stickersOrder)) {
mtpOrder.push_back(MTP_long(setId));
}
_stickersReorderRequestId = request(MTPmessages_ReorderStickerSets(
MTP_flags(0),
MTP_vector<MTPlong>(mtpOrder)
)).done([=](const MTPBool &result) {
_stickersReorderRequestId = 0;
}).fail([=](const MTP::Error &error) {
_stickersReorderRequestId = 0;
_session->data().stickers().setLastUpdate(0);
updateStickers();
}).send();
}
void ApiWrap::updateStickers() {
auto now = crl::now();
const auto now = crl::now();
requestStickers(now);
requestRecentStickers(now);
requestFavedStickers(now);
@@ -2912,15 +3015,26 @@ void ApiWrap::updateStickers() {
requestSavedGifs(now);
}
void ApiWrap::requestRecentStickersForce() {
requestRecentStickersWithHash(0);
void ApiWrap::updateMasks() {
const auto now = crl::now();
requestStickers(now, true);
requestRecentStickers(now, true);
}
void ApiWrap::setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInputStickerSet &set) {
void ApiWrap::requestRecentStickersForce(bool attached) {
requestRecentStickersWithHash(0, attached);
}
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();
}
@@ -2972,17 +3086,29 @@ std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
return nullptr;
}
void ApiWrap::requestStickers(TimeId now) {
if (!_session->data().stickers().updateNeeded(now)
|| _stickersUpdateRequest) {
void ApiWrap::requestStickers(TimeId now, bool masks) {
const auto requestId = [=]() -> mtpRequestId & {
return masks
? _masksUpdateRequest
: _stickersUpdateRequest;
};
const auto needed = masks
? _session->data().stickers().masksUpdateNeeded(now)
: _session->data().stickers().updateNeeded(now);
if (!needed || requestId()) {
return;
}
auto onDone = [this](const MTPmessages_AllStickers &result) {
_session->data().stickers().setLastUpdate(crl::now());
_stickersUpdateRequest = 0;
const auto onDone = [=](const MTPmessages_AllStickers &result) {
if (masks) {
_session->data().stickers().setLastMasksUpdate(crl::now());
} else {
_session->data().stickers().setLastUpdate(crl::now());
}
requestId() = 0;
switch (result.type()) {
case mtpc_messages_allStickersNotModified: return;
case mtpc_messages_getMaskStickers:
case mtpc_messages_allStickers: {
auto &d = result.c_messages_allStickers();
_session->data().stickers().setsReceived(
@@ -2992,39 +3118,67 @@ void ApiWrap::requestStickers(TimeId now) {
default: Unexpected("Type in ApiWrap::stickersDone()");
}
};
_stickersUpdateRequest = request(MTPmessages_GetAllStickers(
MTP_int(Api::CountStickersHash(_session, true))
)).done(onDone).fail([=](const MTP::Error &error) {
LOG(("App Fail: Failed to get stickers!"));
const auto onFail = [=](const MTP::Error &error) {
LOG(("App Fail: Failed to get %1!"
).arg(masks ? "masks" : "stickers"));
onDone(MTP_messages_allStickersNotModified());
}).send();
};
auto hash = MTP_int(Api::CountStickersHash(_session, true));
requestId() = masks
? request(MTPmessages_GetMaskStickers(
std::move(hash))
).done(onDone).fail(onFail).send()
: request(MTPmessages_GetAllStickers(
std::move(hash))
).done(onDone).fail(onFail).send();
}
void ApiWrap::requestRecentStickers(TimeId now) {
if (!_session->data().stickers().recentUpdateNeeded(now)) {
void ApiWrap::requestRecentStickers(TimeId now, bool attached) {
const auto needed = attached
? _session->data().stickers().recentAttachedUpdateNeeded(now)
: _session->data().stickers().recentUpdateNeeded(now);
if (!needed) {
return;
}
requestRecentStickersWithHash(
Api::CountRecentStickersHash(_session));
Api::CountRecentStickersHash(_session, attached), attached);
}
void ApiWrap::requestRecentStickersWithHash(int32 hash) {
if (_recentStickersUpdateRequest) {
void ApiWrap::requestRecentStickersWithHash(int32 hash, bool attached) {
const auto requestId = [=]() -> mtpRequestId & {
return attached
? _recentAttachedStickersUpdateRequest
: _recentStickersUpdateRequest;
};
if (requestId()) {
return;
}
_recentStickersUpdateRequest = request(MTPmessages_GetRecentStickers(
MTP_flags(0),
const auto finish = [=] {
auto &stickers = _session->data().stickers();
if (attached) {
stickers.setLastRecentAttachedUpdate(crl::now());
} else {
stickers.setLastRecentUpdate(crl::now());
}
requestId() = 0;
};
const auto flags = attached
? MTPmessages_getRecentStickers::Flag::f_attached
: MTPmessages_getRecentStickers::Flags(0);
requestId() = request(MTPmessages_GetRecentStickers(
MTP_flags(flags),
MTP_int(hash)
)).done([=](const MTPmessages_RecentStickers &result) {
_session->data().stickers().setLastRecentUpdate(crl::now());
_recentStickersUpdateRequest = 0;
finish();
switch (result.type()) {
case mtpc_messages_recentStickersNotModified: return;
case mtpc_messages_recentStickers: {
auto &d = result.c_messages_recentStickers();
_session->data().stickers().specialSetReceived(
Data::Stickers::CloudRecentSetId,
attached
? Data::Stickers::CloudRecentAttachedSetId
: Data::Stickers::CloudRecentSetId,
tr::lng_recent_stickers(tr::now),
d.vstickers().v,
d.vhash().v,
@@ -3034,8 +3188,7 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) {
default: Unexpected("Type in ApiWrap::recentStickersDone()");
}
}).fail([=](const MTP::Error &error) {
_session->data().stickers().setLastRecentUpdate(crl::now());
_recentStickersUpdateRequest = 0;
finish();
LOG(("App Fail: Failed to get recent stickers!"));
}).send();
@@ -3147,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;
@@ -3721,7 +3874,6 @@ void ApiWrap::forwardMessages(
}
}
const auto newFrom = item->history()->peer;
const auto newGroupId = item->groupId();
if (forwardFrom != newFrom) {
sendAccumulated();
forwardFrom = newFrom;
@@ -3942,9 +4094,12 @@ void ApiWrap::sendFile(
void ApiWrap::sendUploadedPhoto(
FullMsgId localId,
const MTPInputFile &file,
Api::SendOptions options) {
Api::SendOptions options,
std::vector<MTPInputDocument> attachedStickers) {
if (const auto item = _session->data().message(localId)) {
const auto media = Api::PrepareUploadedPhoto(file);
const auto media = Api::PrepareUploadedPhoto(
file,
std::move(attachedStickers));
if (const auto groupId = item->groupId()) {
uploadAlbumMedia(item, groupId, media);
} else {
@@ -3957,12 +4112,17 @@ void ApiWrap::sendUploadedDocument(
FullMsgId localId,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
Api::SendOptions options) {
Api::SendOptions options,
std::vector<MTPInputDocument> attachedStickers) {
if (const auto item = _session->data().message(localId)) {
if (!item->media() || !item->media()->document()) {
return;
}
const auto media = Api::PrepareUploadedDocument(item, file, thumb);
const auto media = Api::PrepareUploadedDocument(
item,
file,
thumb,
std::move(attachedStickers));
const auto groupId = item->groupId();
if (groupId) {
uploadAlbumMedia(item, groupId, media);
@@ -4363,6 +4523,8 @@ void ApiWrap::sendMediaWithRandomId(
caption.entities,
Api::ConvertOption::SkipLocal);
const auto updateRecentStickers = Api::HasAttachedStickers(media);
const auto flags = MTPmessages_SendMedia::Flags(0)
| (replyTo
? MTPmessages_SendMedia::Flag::f_reply_to_msg_id
@@ -4395,6 +4557,10 @@ void ApiWrap::sendMediaWithRandomId(
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
finish();
if (updateRecentStickers) {
requestRecentStickersForce(true);
}
}).fail([=](const MTP::Error &error) {
sendMessageFail(error, peer, randomId, itemId);
finish();

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);
@@ -280,12 +281,14 @@ public:
void requestStickerSets();
void saveStickerSets(
const Data::StickersSetsOrder &localOrder,
const Data::StickersSetsOrder &localRemoved);
const Data::StickersSetsOrder &localRemoved,
bool setsMasks);
void updateStickers();
void requestRecentStickersForce();
void updateMasks();
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);
@@ -339,12 +342,6 @@ public:
not_null<UserData*> user,
PhotoId afterId);
void stickerSetInstalled(uint64 setId) {
_stickerSetInstalled.fire_copy(setId);
}
auto stickerSetInstalled() const {
return _stickerSetInstalled.events();
}
void readFeaturedSetDelayed(uint64 setId);
void parseChannelParticipants(
@@ -410,12 +407,14 @@ public:
void sendUploadedPhoto(
FullMsgId localId,
const MTPInputFile &file,
Api::SendOptions options);
Api::SendOptions options,
std::vector<MTPInputDocument> attachedStickers);
void sendUploadedDocument(
FullMsgId localId,
const MTPInputFile &file,
const std::optional<MTPInputFile> &thumb,
Api::SendOptions options);
Api::SendOptions options,
std::vector<MTPInputDocument> attachedStickers);
void cancelLocalItem(not_null<HistoryItem*> item);
@@ -542,12 +541,9 @@ private:
mtpRequestId req);
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
void stickerSetDisenabled(mtpRequestId requestId);
void stickersSaveOrder();
void requestStickers(TimeId now);
void requestRecentStickers(TimeId now);
void requestRecentStickersWithHash(int32 hash);
void requestStickers(TimeId now, bool masks = false);
void requestRecentStickers(TimeId now, bool attached = false);
void requestRecentStickersWithHash(int32 hash, bool attached = false);
void requestFavedStickers(TimeId now);
void requestFeaturedStickers(TimeId now);
void requestSavedGifs(TimeId now);
@@ -685,12 +681,16 @@ private:
base::Timer _draftsSaveTimer;
base::flat_set<mtpRequestId> _stickerSetDisenableRequests;
Data::StickersSetsOrder _stickersOrder;
base::flat_set<mtpRequestId> _maskSetDisenableRequests;
mtpRequestId _masksReorderRequestId = 0;
mtpRequestId _stickersReorderRequestId = 0;
mtpRequestId _stickersClearRecentRequestId = 0;
mtpRequestId _stickersClearRecentAttachedRequestId = 0;
mtpRequestId _stickersUpdateRequest = 0;
mtpRequestId _masksUpdateRequest = 0;
mtpRequestId _recentStickersUpdateRequest = 0;
mtpRequestId _recentAttachedStickersUpdateRequest = 0;
mtpRequestId _favedStickersUpdateRequest = 0;
mtpRequestId _featuredStickersUpdateRequest = 0;
mtpRequestId _savedGifsUpdateRequest = 0;
@@ -731,8 +731,6 @@ private:
base::Observable<PeerData*> _fullPeerUpdated;
rpl::event_stream<uint64> _stickerSetInstalled;
mtpRequestId _topPromotionRequestId = 0;
std::pair<QString, uint32> _topPromotionKey;
TimeId _topPromotionNextRequestTime = TimeId(0);

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() {
@@ -282,8 +271,4 @@ namespace App {
return result;
}
QPixmap pixmapFromImageInPlace(QImage &&image) {
return QPixmap::fromImage(std::move(image), Qt::ColorOnly);
}
}

View File

@@ -45,6 +45,5 @@ namespace App {
constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif
QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr);
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);
QPixmap pixmapFromImageInPlace(QImage &&image);
};

View File

@@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/openssl_help.h"
#include "boxes/confirm_box.h"
#include "boxes/confirm_phone_box.h" // ExtractPhonePrefix.
#include "boxes/photo_crop_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/peers/add_participants_box.h"
#include "boxes/peers/edit_participant_box.h"
@@ -159,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));
@@ -466,6 +465,7 @@ void GroupInfoBox::prepare() {
_photo.create(
this,
&_navigation->parentController()->window(),
((_type == Type::Channel)
? tr::lng_create_channel_crop
: tr::lng_create_group_crop)(tr::now),

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

@@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "mainwindow.h"
#include "ui/widgets/checkbox.h"
#include "facades.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@@ -45,8 +44,7 @@ void AutoLockBox::prepare() {
void AutoLockBox::durationChanged(int seconds) {
Core::App().settings().setAutoLock(seconds);
Core::App().saveSettingsDelayed();
Global::RefLocalPasscodeChanged().notify();
Core::App().checkAutoLock();
Core::App().checkAutoLock(crl::now());
closeBox();
}

View File

@@ -21,7 +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 "app.h"
#include "window/themes/window_theme.h"
#include "styles/style_overview.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@@ -56,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,
@@ -151,7 +149,7 @@ void BackgroundBox::prepare() {
_inner->chooseEvents(
) | rpl::start_with_next([=](const Data::WallPaper &paper) {
Ui::show(
_controller->show(
Box<BackgroundPreviewBox>(_controller, paper),
Ui::LayerOption::KeepOther);
}, _inner->lifetime());
@@ -176,7 +174,7 @@ void BackgroundBox::removePaper(const Data::WallPaper &paper) {
paper.mtpSettings()
)).send();
};
Ui::show(
_controller->show(
Box<ConfirmBox>(
tr::lng_background_sure_delete(tr::now),
tr::lng_selected_delete(tr::now),
@@ -204,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);
}
@@ -337,7 +341,7 @@ void BackgroundBox::Inner::validatePaperThumbnail(
Data::PatternColor(color),
paper.data.patternIntensity());
}
paper.thumbnail = App::pixmapFromImageInPlace(TakeMiddleSample(
paper.thumbnail = Ui::PixmapFromImage(TakeMiddleSample(
original,
st::backgroundSize));
paper.thumbnail.setDevicePixelRatio(cRetinaFactor());

View File

@@ -23,12 +23,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_document_resolver.h"
#include "data/data_file_origin.h"
#include "base/unixtime.h"
#include "boxes/confirm_box.h"
#include "boxes/background_preview_box.h"
#include "window/window_session_controller.h"
#include "app.h"
#include "styles/style_chat.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
@@ -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(
@@ -398,7 +396,7 @@ BackgroundPreviewBox::BackgroundPreviewBox(
QWidget*,
not_null<Window::SessionController*> controller,
const Data::WallPaper &paper)
: SimpleElementDelegate(controller)
: SimpleElementDelegate(controller, [=] { update(); })
, _controller(controller)
, _text1(GenerateTextItem(
delegate(),
@@ -687,8 +685,8 @@ void BackgroundPreviewBox::setScaledFromImage(
if (!_full.isNull()) {
startFadeInFrom(std::move(_scaled));
}
_scaled = App::pixmapFromImageInPlace(std::move(image));
_blurred = App::pixmapFromImageInPlace(std::move(blurred));
_scaled = Ui::PixmapFromImage(std::move(image));
_blurred = Ui::PixmapFromImage(std::move(blurred));
if (_blur && (!_paper.document() || !_full.isNull())) {
_blur->setDisabled(false);
}
@@ -769,23 +767,25 @@ bool BackgroundPreviewBox::Start(
const QString &slug,
const QMap<QString, QString> &params) {
if (const auto paper = Data::WallPaper::FromColorSlug(slug)) {
Ui::show(Box<BackgroundPreviewBox>(
controller->show(Box<BackgroundPreviewBox>(
controller,
paper->withUrlParams(params)));
return true;
}
if (!IsValidWallPaperSlug(slug)) {
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
controller->show(
Box<InformBox>(tr::lng_background_bad_link(tr::now)));
return false;
}
controller->session().api().requestWallPaper(slug, crl::guard(controller, [=](
const Data::WallPaper &result) {
Ui::show(Box<BackgroundPreviewBox>(
controller->show(Box<BackgroundPreviewBox>(
controller,
result.withUrlParams(params)));
}), [](const MTP::Error &error) {
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
});
}), crl::guard(controller, [=](const MTP::Error &error) {
controller->show(
Box<InformBox>(tr::lng_background_bad_link(tr::now)));
}));
return true;
}

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

@@ -76,10 +76,6 @@ defaultFeedUserpicButton: FeedUserpicButton {
innerPart: defaultUserpicButton;
}
cropPointSize: 10px;
cropSkip: 13px;
cropMinSize: 20px;
confirmInviteTitle: FlatLabel(defaultFlatLabel) {
align: align(center);
minWidth: 320px;
@@ -386,6 +382,7 @@ confirmCaptionArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 31px, 4px);
heightMax: 158px;
}
confirmEditCaptionAreaHeightMax: 78px;
confirmBg: windowBgOver;
confirmMaxHeight: 245px;
confirmMaxHeightSkip: 25px;
@@ -427,33 +424,42 @@ backgroundScroll: ScrollArea(boxScroll) {
deltab: 10px;
}
editMediaButtonSize: 28px;
editMediaButtonSkip: 8px;
sendMediaPreviewSize: 308px;
sendMediaPreviewHeightMax: 1280;
sendMediaRowSkip: 10px;
editMediaButtonSize: 32px;
editMediaButtonSkip: 5px;
editMediaButtonFileSkipRight: 1px;
editMediaButtonFileSkipTop: 7px;
editMediaButtonIconFile: icon {{ "settings_edit", menuIconFg }};
editMediaButtonIconPhoto: icon {{ "settings_edit", roundedFg }};
editMediaButton: IconButton {
editMediaButtonIconFile: icon {{ "send_media/send_media_replace", menuIconFg }};
editMediaButton: IconButton(defaultIconButton) {
width: editMediaButtonSize;
height: editMediaButtonSize;
icon: editMediaButtonIconPhoto;
icon: editMediaButtonIconFile;
rippleAreaSize: editMediaButtonSize;
ripple: defaultRippleAnimation;
}
editMediaHintLabel: FlatLabel(defaultFlatLabel) {
textFg: windowSubTextFg;
minWidth: sendMediaPreviewSize;
}
// SendFilesBox
sendBoxAlbumGroupEditInternalSkip: 8px;
sendBoxAlbumGroupSkipRight: 6px;
sendBoxAlbumGroupSkipTop: 6px;
sendBoxAlbumGroupRadius: 13px;
sendBoxAlbumGroupHeight: 26px;
sendBoxAlbumGroupSkipRight: 5px;
sendBoxAlbumGroupSkipTop: 5px;
sendBoxAlbumGroupRadius: 4px;
sendBoxAlbumGroupSize: size(62px, 25px);
sendBoxAlbumSmallGroupSize: size(30px, 25px);
sendBoxFileGroupSkipTop: 2px;
sendBoxFileGroupSkipRight: 8px;
sendBoxFileGroupSkipRight: 5px;
sendBoxFileGroupEditInternalSkip: -1px;
sendBoxAlbumGroupButtonFile: IconButton(editMediaButton) {
@@ -462,16 +468,11 @@ sendBoxAlbumGroupButtonFile: IconButton(editMediaButton) {
}
}
sendBoxAlbumGroupEditButtonIconFile: editMediaButtonIconFile;
sendBoxAlbumGroupDeleteButtonIconFile: icon {{ "history_file_cancel", menuIconFg, point(6px, 6px) }};
sendBoxAlbumGroupDeleteButtonIconFile: icon {{ "send_media/send_media_delete", menuIconFg }};
sendBoxAlbumGroupButtonMediaEdit: icon {{ "settings_edit", roundedFg, point(3px, -2px) }};
sendBoxAlbumGroupButtonMediaDelete: icon {{ "history_file_cancel", roundedFg, point(2px, 5px) }};
sendBoxAlbumGroupButtonMedia: IconButton {
width: sendBoxAlbumGroupHeight;
height: sendBoxAlbumGroupHeight;
icon: sendBoxAlbumGroupButtonMediaEdit;
}
sendBoxAlbumButtonMediaEdit: icon {{ "send_media/send_media_replace", roundedFg }};
sendBoxAlbumGroupButtonMediaEdit: icon {{ "send_media/send_media_replace", roundedFg, point(4px, 1px) }};
sendBoxAlbumGroupButtonMediaDelete: icon {{ "send_media/send_media_delete", roundedFg }};
// End of SendFilesBox
@@ -523,6 +524,7 @@ usernameTextStyle: TextStyle(boxTextStyle, passcodeTextStyle) {
}
usernameDefaultFg: windowSubTextFg;
editMediaLabelMargins: margins(0px, 11px, 0px, 0px);
editMediaCheckboxMargins: margins(0px, 15px, 23px, 15px);
downloadPathSkip: 10px;
@@ -649,10 +651,6 @@ groupStickersField: InputField(defaultMultiSelectSearchField) {
}
groupStickersSubTitleHeight: 36px;
sendMediaPreviewSize: 308px;
sendMediaPreviewHeightMax: 1280;
sendMediaRowSkip: 10px;
proxyUsePadding: margins(22px, 6px, 22px, 5px);
proxyTryIPv6Padding: margins(22px, 8px, 22px, 5px);
proxyRowPadding: margins(22px, 8px, 8px, 8px);

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

@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/qthelp_url.h"
#include "base/call_delayed.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "main/main_account.h"
#include "mtproto/facade.h"
#include "ui/widgets/checkbox.h"
@@ -27,7 +28,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/radial_animation.h"
#include "ui/text/text_options.h"
#include "ui/basic_click_handlers.h"
#include "facades.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
@@ -186,7 +186,10 @@ class ProxiesBox : public Ui::BoxContent {
public:
using View = ProxiesBoxController::ItemView;
ProxiesBox(QWidget*, not_null<ProxiesBoxController*> controller);
ProxiesBox(
QWidget*,
not_null<ProxiesBoxController*> controller,
Core::SettingsProxy &settings);
protected:
void prepare() override;
@@ -201,6 +204,7 @@ private:
void refreshProxyForCalls();
not_null<ProxiesBoxController*> _controller;
Core::SettingsProxy &_settings;
QPointer<Ui::Checkbox> _tryIPv6;
std::shared_ptr<Ui::RadioenumGroup<ProxyData::Settings>> _proxySettings;
QPointer<Ui::SlideWrap<Ui::Checkbox>> _proxyForCalls;
@@ -566,8 +570,10 @@ void ProxyRow::showMenu() {
ProxiesBox::ProxiesBox(
QWidget*,
not_null<ProxiesBoxController*> controller)
not_null<ProxiesBoxController*> controller,
Core::SettingsProxy &settings)
: _controller(controller)
, _settings(settings)
, _initialWrap(this) {
_controller->views(
) | rpl::start_with_next([=](View &&view) {
@@ -591,11 +597,11 @@ void ProxiesBox::setupContent() {
object_ptr<Ui::Checkbox>(
inner,
tr::lng_connection_try_ipv6(tr::now),
Global::TryIPv6()),
_settings.tryIPv6()),
st::proxyTryIPv6Padding);
_proxySettings
= std::make_shared<Ui::RadioenumGroup<ProxyData::Settings>>(
Global::ProxySettings());
_settings.settings());
inner->add(
object_ptr<Ui::Radioenum<ProxyData::Settings>>(
inner,
@@ -623,7 +629,7 @@ void ProxiesBox::setupContent() {
object_ptr<Ui::Checkbox>(
inner,
tr::lng_proxy_use_for_calls(tr::now),
Global::UseProxyForCalls()),
_settings.useProxyForCalls()),
style::margins(
0,
st::proxyUsePadding.top(),
@@ -652,7 +658,7 @@ void ProxiesBox::setupContent() {
_proxySettings->setChangedCallback([=](ProxyData::Settings value) {
if (!_controller->setProxySettings(value)) {
_proxySettings->setValue(Global::ProxySettings());
_proxySettings->setValue(_settings.settings());
addNewProxy();
}
refreshProxyForCalls();
@@ -1051,20 +1057,22 @@ void ProxyBox::addLabel(
ProxiesBoxController::ProxiesBoxController(not_null<Main::Account*> account)
: _account(account)
, _settings(Core::App().settings().proxy())
, _saveTimer([] { Local::writeSettings(); }) {
_list = ranges::views::all(
Global::ProxiesList()
_settings.list()
) | ranges::views::transform([&](const ProxyData &proxy) {
return Item{ ++_idCounter, proxy };
}) | ranges::to_vector;
subscribe(Global::RefConnectionTypeChanged(), [=] {
_proxySettingsChanges.fire_copy(Global::ProxySettings());
const auto i = findByProxy(Global::SelectedProxy());
_settings.connectionTypeChanges(
) | rpl::start_with_next([=] {
_proxySettingsChanges.fire_copy(_settings.settings());
const auto i = findByProxy(_settings.selected());
if (i != end(_list)) {
updateView(*i);
}
});
}, _lifetime);
for (auto &item : _list) {
refreshChecker(item);
@@ -1112,7 +1120,7 @@ void ProxiesBoxController::ShowApplyConfirmation(
? "\n\n" + tr::lng_proxy_sponsor_warning(tr::now)
: QString());
auto callback = [=](Fn<void()> &&close) {
auto &proxies = Global::RefProxiesList();
auto &proxies = Core::App().settings().proxy().list();
if (!ranges::contains(proxies, proxy)) {
proxies.push_back(proxy);
}
@@ -1139,7 +1147,7 @@ void ProxiesBoxController::ShowApplyConfirmation(
auto ProxiesBoxController::proxySettingsValue() const
-> rpl::producer<ProxyData::Settings> {
return _proxySettingsChanges.events_starting_with_copy(
Global::ProxySettings()
_settings.settings()
) | rpl::distinct_until_changed();
}
@@ -1150,6 +1158,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
: Variants::Tcp;
const auto mtproto = &_account->mtp();
const auto dcId = mtproto->mainDcId();
const auto forFiles = false;
item.state = ItemState::Checking;
const auto setup = [&](Checker &checker, const bytes::vector &secret) {
@@ -1168,7 +1177,8 @@ void ProxiesBoxController::refreshChecker(Item &item) {
item.data.host,
item.data.port,
secret,
dcId);
dcId,
forFiles);
item.checkerv6 = nullptr;
} else {
const auto options = mtproto->dcOptions().lookup(
@@ -1180,7 +1190,8 @@ void ProxiesBoxController::refreshChecker(Item &item) {
Variants::Address address) {
const auto &list = options.data[address][type];
if (list.empty()
|| (address == Variants::IPv6 && !Global::TryIPv6())) {
|| ((address == Variants::IPv6)
&& !Core::App().settings().proxy().tryIPv6())) {
checker = nullptr;
return;
}
@@ -1190,7 +1201,8 @@ void ProxiesBoxController::refreshChecker(Item &item) {
QString::fromStdString(endpoint.ip),
endpoint.port,
endpoint.secret,
dcId);
dcId,
forFiles);
};
connect(item.checker, Variants::IPv4);
connect(item.checkerv6, Variants::IPv6);
@@ -1241,7 +1253,7 @@ object_ptr<Ui::BoxContent> ProxiesBoxController::CreateOwningBox(
}
object_ptr<Ui::BoxContent> ProxiesBoxController::create() {
auto result = Box<ProxiesBox>(this);
auto result = Box<ProxiesBox>(this, _settings);
for (const auto &item : _list) {
updateView(item);
}
@@ -1279,14 +1291,13 @@ void ProxiesBoxController::shareItem(int id) {
void ProxiesBoxController::applyItem(int id) {
auto item = findById(id);
if ((Global::ProxySettings() == ProxyData::Settings::Enabled)
&& Global::SelectedProxy() == item->data) {
if (_settings.isEnabled() && (_settings.selected() == item->data)) {
return;
} else if (item->deleted) {
return;
}
auto j = findByProxy(Global::SelectedProxy());
auto j = findByProxy(_settings.selected());
Core::App().setCurrentProxy(
item->data,
@@ -1304,12 +1315,13 @@ void ProxiesBoxController::setDeleted(int id, bool deleted) {
item->deleted = deleted;
if (deleted) {
auto &proxies = Global::RefProxiesList();
auto &proxies = _settings.list();
proxies.erase(ranges::remove(proxies, item->data), end(proxies));
if (item->data == Global::SelectedProxy()) {
_lastSelectedProxy = base::take(Global::RefSelectedProxy());
if (Global::ProxySettings() == ProxyData::Settings::Enabled) {
if (item->data == _settings.selected()) {
_lastSelectedProxy = _settings.selected();
_settings.setSelected(MTP::ProxyData());
if (_settings.isEnabled()) {
_lastSelectedProxyUsed = true;
Core::App().setCurrentProxy(
ProxyData(),
@@ -1320,7 +1332,7 @@ void ProxiesBoxController::setDeleted(int id, bool deleted) {
}
}
} else {
auto &proxies = Global::RefProxiesList();
auto &proxies = _settings.list();
if (ranges::find(proxies, item->data) == end(proxies)) {
auto insertBefore = item + 1;
while (insertBefore != end(_list) && insertBefore->deleted) {
@@ -1332,15 +1344,15 @@ void ProxiesBoxController::setDeleted(int id, bool deleted) {
proxies.insert(insertBeforeIt, item->data);
}
if (!Global::SelectedProxy() && _lastSelectedProxy == item->data) {
Assert(Global::ProxySettings() != ProxyData::Settings::Enabled);
if (!_settings.selected() && _lastSelectedProxy == item->data) {
Assert(!_settings.isEnabled());
if (base::take(_lastSelectedProxyUsed)) {
Core::App().setCurrentProxy(
base::take(_lastSelectedProxy),
ProxyData::Settings::Enabled);
} else {
Global::SetSelectedProxy(base::take(_lastSelectedProxy));
_settings.setSelected(base::take(_lastSelectedProxy));
}
}
}
@@ -1368,7 +1380,7 @@ object_ptr<Ui::BoxContent> ProxiesBoxController::editItemBox(int id) {
void ProxiesBoxController::replaceItemWith(
std::vector<Item>::iterator which,
std::vector<Item>::iterator with) {
auto &proxies = Global::RefProxiesList();
auto &proxies = _settings.list();
proxies.erase(ranges::remove(proxies, which->data), end(proxies));
_views.fire({ which->id });
@@ -1388,7 +1400,7 @@ void ProxiesBoxController::replaceItemValue(
restoreItem(which->id);
}
auto &proxies = Global::RefProxiesList();
auto &proxies = _settings.list();
const auto i = ranges::find(proxies, which->data);
Assert(i != end(proxies));
*i = proxy;
@@ -1419,7 +1431,7 @@ object_ptr<Ui::BoxContent> ProxiesBoxController::addNewItemBox() {
}
void ProxiesBoxController::addNewItem(const ProxyData &proxy) {
auto &proxies = Global::RefProxiesList();
auto &proxies = _settings.list();
proxies.push_back(proxy);
_list.push_back({ ++_idCounter, proxy });
@@ -1428,43 +1440,42 @@ void ProxiesBoxController::addNewItem(const ProxyData &proxy) {
}
bool ProxiesBoxController::setProxySettings(ProxyData::Settings value) {
if (Global::ProxySettings() == value) {
if (_settings.settings() == value) {
return true;
} else if (value == ProxyData::Settings::Enabled) {
if (Global::ProxiesList().empty()) {
if (_settings.list().empty()) {
return false;
} else if (!Global::SelectedProxy()) {
Global::SetSelectedProxy(Global::ProxiesList().back());
auto j = findByProxy(Global::SelectedProxy());
} else if (!_settings.selected()) {
_settings.setSelected(_settings.list().back());
auto j = findByProxy(_settings.selected());
if (j != end(_list)) {
updateView(*j);
}
}
}
Core::App().setCurrentProxy(Global::SelectedProxy(), value);
Core::App().setCurrentProxy(_settings.selected(), value);
saveDelayed();
return true;
}
void ProxiesBoxController::setProxyForCalls(bool enabled) {
if (Global::UseProxyForCalls() == enabled) {
if (_settings.useProxyForCalls() == enabled) {
return;
}
Global::SetUseProxyForCalls(enabled);
if ((Global::ProxySettings() == ProxyData::Settings::Enabled)
&& Global::SelectedProxy().supportsCalls()) {
Global::RefConnectionTypeChanged().notify();
_settings.setUseProxyForCalls(enabled);
if (_settings.isEnabled() && _settings.selected().supportsCalls()) {
_settings.connectionTypeChangesNotify();
}
saveDelayed();
}
void ProxiesBoxController::setTryIPv6(bool enabled) {
if (Global::TryIPv6() == enabled) {
if (Core::App().settings().proxy().tryIPv6() == enabled) {
return;
}
Global::SetTryIPv6(enabled);
Core::App().settings().proxy().setTryIPv6(enabled);
_account->mtp().restart();
Global::RefConnectionTypeChanged().notify();
_settings.connectionTypeChangesNotify();
saveDelayed();
}
@@ -1477,7 +1488,7 @@ auto ProxiesBoxController::views() const -> rpl::producer<ItemView> {
}
void ProxiesBoxController::updateView(const Item &item) {
const auto selected = (Global::SelectedProxy() == item.data);
const auto selected = (_settings.selected() == item.data);
const auto deleted = item.deleted;
const auto type = [&] {
switch (item.data.type) {
@@ -1491,8 +1502,7 @@ void ProxiesBoxController::updateView(const Item &item) {
Unexpected("Proxy type in ProxiesBoxController::updateView.");
}();
const auto state = [&] {
if (!selected
|| (Global::ProxySettings() != ProxyData::Settings::Enabled)) {
if (!selected || !_settings.isEnabled()) {
return item.state;
} else if (_account->mtp().dcstate() == MTP::ConnectedState) {
return ItemState::Online;

View File

@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h"
#include "base/object_ptr.h"
#include "core/core_settings.h"
#include "mtproto/connection_abstract.h"
#include "mtproto/mtproto_proxy_data.h"
@@ -28,7 +29,7 @@ namespace Main {
class Account;
} // namespace Main
class ProxiesBoxController : public base::Subscriber {
class ProxiesBoxController {
public:
using ProxyData = MTP::ProxyData;
using Type = ProxyData::Type;
@@ -110,6 +111,7 @@ private:
void addNewItem(const ProxyData &proxy);
const not_null<Main::Account*> _account;
Core::SettingsProxy &_settings;
int _idCounter = 0;
std::vector<Item> _list;
rpl::event_stream<ItemView> _views;
@@ -119,4 +121,6 @@ private:
ProxyData _lastSelectedProxy;
bool _lastSelectedProxyUsed = false;
rpl::lifetime _lifetime;
};

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);
}
@@ -1085,7 +1084,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
send({ .silent = true });
};
const auto sendScheduled = [=] {
Ui::show(
_controller->show(
HistoryView::PrepareScheduleBox(
this,
SendMenu::Type::Scheduled,

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,34 +19,19 @@ class SessionController;
} // namespace Window
namespace Data {
class Media;
class PhotoMedia;
class DocumentMedia;
} // namespace Data
namespace Ui {
class AbstractSinglePreview;
class InputField;
class EmojiButton;
class IconButton;
class Checkbox;
class VerticalLayout;
class FadeShadow;
enum class AlbumType;
} // 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*,
@@ -67,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();
@@ -84,69 +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();
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;
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::IconButton> _editMedia = nullptr;
Ui::SlideWrap<Ui::RpWidget> *_wayWrap = nullptr;
QString _newMediaPath;
Ui::AlbumType _albumType = Ui::AlbumType();
bool _isAllowedEditMedia = false;
bool _asFile = false;
rpl::event_stream<> _editMediaClicks;
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

@@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/input_fields.h"
#include "ui/ui_utility.h"
#include "base/platform/base_platform_info.h"
#include "app.h"
#include "styles/style_boxes.h"
#include "styles/style_media_view.h"
@@ -27,8 +26,8 @@ public:
return _y;
}
base::Observable<void> &changed() {
return _changed;
rpl::producer<> changed() const {
return _changed.events();
}
void setHSB(HSB hsb);
void setRGB(int red, int green, int blue);
@@ -61,7 +60,7 @@ private:
float64 _y = 0.;
bool _choosing = false;
base::Observable<void> _changed;
rpl::event_stream<> _changed;
};
@@ -234,7 +233,7 @@ void EditColorBox::Picker::updateCurrentPoint(QPoint localPosition) {
_x = x;
_y = y;
update();
_changed.notify();
_changed.fire({});
}
}
@@ -284,8 +283,8 @@ public:
};
Slider(QWidget *parent, Direction direction, Type type, QColor color);
base::Observable<void> &changed() {
return _changed;
rpl::producer<> changed() const {
return _changed.events();
}
float64 value() const {
return _value;
@@ -335,7 +334,7 @@ private:
QBrush _transparent;
bool _choosing = false;
base::Observable<void> _changed;
rpl::event_stream<> _changed;
};
@@ -423,7 +422,7 @@ void EditColorBox::Slider::generatePixmap() {
if (!isHorizontal()) {
image = std::move(image).transformed(QTransform(0, -1, 1, 0, 0, 0));
}
_pixmap = App::pixmapFromImageInPlace(std::move(image));
_pixmap = Ui::PixmapFromImage(std::move(image));
} else if (_type == Type::Opacity) {
auto color = anim::shifted(QColor(255, 255, 255, 255));
auto transparent = anim::shifted(QColor(255, 255, 255, 0));
@@ -459,7 +458,7 @@ void EditColorBox::Slider::generatePixmap() {
if (!isHorizontal()) {
image = std::move(image).transformed(QTransform(0, -1, 1, 0, 0, 0));
}
_pixmap = App::pixmapFromImageInPlace(std::move(image));
_pixmap = Ui::PixmapFromImage(std::move(image));
}
}
@@ -530,7 +529,7 @@ void EditColorBox::Slider::setLightnessLimits(int min, int max) {
}
void EditColorBox::Slider::updatePixmapFromMask() {
_pixmap = App::pixmapFromImageInPlace(style::colorizeImage(_mask, _color));
_pixmap = Ui::PixmapFromImage(style::colorizeImage(_mask, _color));
}
void EditColorBox::Slider::updateCurrentPoint(QPoint localPosition) {
@@ -540,7 +539,7 @@ void EditColorBox::Slider::updateCurrentPoint(QPoint localPosition) {
if (_value != value) {
_value = value;
update();
_changed.notify();
_changed.fire({});
}
}
@@ -826,16 +825,14 @@ void EditColorBox::prepare() {
auto height = st::colorEditSkip + st::colorPickerSize + st::colorEditSkip + st::colorSliderWidth + st::colorEditSkip;
setDimensions(st::colorEditWidth, height);
subscribe(_picker->changed(), [=] { updateFromControls(); });
if (_hueSlider) {
subscribe(_hueSlider->changed(), [=] { updateFromControls(); });
}
if (_opacitySlider) {
subscribe(_opacitySlider->changed(), [=] { updateFromControls(); });
}
if (_lightnessSlider) {
subscribe(_lightnessSlider->changed(), [=] { updateFromControls(); });
}
rpl::merge(
_picker->changed(),
(_hueSlider ? _hueSlider->changed() : rpl::never<>()),
(_opacitySlider ? _opacitySlider->changed() : rpl::never<>()),
(_lightnessSlider ? _lightnessSlider->changed() : rpl::never<>())
) | rpl::start_with_next([=] {
updateFromControls();
}, lifetime());
boxClosing() | rpl::start_with_next([=] {
if (_cancelCallback) {

View File

@@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
class EditColorBox : public Ui::BoxContent, private base::Subscriber {
class EditColorBox : public Ui::BoxContent {
public:
enum class Mode {
RGBA,

View File

@@ -165,7 +165,7 @@ void EditPrivacyBox::editExceptions(
}));
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
};
Ui::show(
_window->show(
Box<PeerListBox>(std::move(controller), std::move(initBox)),
Ui::LayerOption::KeepOther);
}

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());
}
}
@@ -1166,15 +1165,19 @@ base::binary_guard LanguageBox::Show() {
if (manager.languageList().empty()) {
auto guard = std::make_shared<base::binary_guard>(
result.make_guard());
auto alive = std::make_shared<std::unique_ptr<base::Subscription>>(
std::make_unique<base::Subscription>());
**alive = manager.languageListChanged().add_subscription([=] {
auto lifetime = std::make_shared<rpl::lifetime>();
manager.languageListChanged(
) | rpl::take(
1
) | rpl::start_with_next([=]() mutable {
const auto show = guard->alive();
*alive = nullptr;
if (lifetime) {
base::take(lifetime)->destroy();
}
if (show) {
Ui::show(Box<LanguageBox>());
}
});
}, *lifetime);
} else {
Ui::show(Box<LanguageBox>());
}

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

@@ -27,7 +27,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "passport/passport_encryption.h"
#include "passport/passport_panel_edit_contact.h"
#include "settings/settings_privacy_security.h"
#include "facades.h"
#include "styles/style_layers.h"
#include "styles/style_passport.h"
#include "styles/style_boxes.h"
@@ -119,7 +118,12 @@ PasscodeBox::PasscodeBox(
, _turningOff(turningOff)
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
, _oldPasscode(this, st::defaultInputField, tr::lng_passcode_enter_old())
, _newPasscode(this, st::defaultInputField, Global::LocalPasscode() ? tr::lng_passcode_enter_new() : tr::lng_passcode_enter_first())
, _newPasscode(
this,
st::defaultInputField,
session->domain().local().hasLocalPasscode()
? tr::lng_passcode_enter_new()
: tr::lng_passcode_enter_first())
, _reenterPasscode(this, st::defaultInputField, tr::lng_passcode_confirm_new())
, _passwordHint(this, st::defaultInputField, tr::lng_cloud_password_hint())
, _recoverEmail(this, st::defaultInputField, tr::lng_cloud_password_email())
@@ -164,7 +168,9 @@ rpl::producer<> PasscodeBox::clearUnconfirmedPassword() const {
}
bool PasscodeBox::currentlyHave() const {
return _cloudPwd ? (!!_cloudFields.curRequest) : Global::LocalPasscode();
return _cloudPwd
? (!!_cloudFields.curRequest)
: _session->domain().local().hasLocalPasscode();
}
bool PasscodeBox::onlyCheckCurrent() const {
@@ -520,7 +526,7 @@ void PasscodeBox::save(bool force) {
return;
}
if (Core::App().domain().local().checkPasscode(old.toUtf8())) {
if (_session->domain().local().checkPasscode(old.toUtf8())) {
cSetPasscodeBadTries(0);
if (_turningOff) pwd = conf = QString();
} else {
@@ -588,7 +594,7 @@ void PasscodeBox::save(bool force) {
closeReplacedBy();
const auto weak = Ui::MakeWeak(this);
cSetPasscodeBadTries(0);
Core::App().domain().local().setPasscode(pwd.toUtf8());
_session->domain().local().setPasscode(pwd.toUtf8());
Core::App().localPasscodeChanged();
if (weak) {
closeBox();
@@ -1056,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);
@@ -201,8 +204,10 @@ void SaveSlowmodeSeconds(
void ShowEditPermissions(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer) {
const auto box = Ui::show(
Box<EditPeerPermissionsBox>(navigation, 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 = [=](
@@ -213,50 +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) {
const auto box = Ui::show(
Box<EditPeerPermissionsBox>(navigation, peer),
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);
@@ -491,6 +453,7 @@ object_ptr<Ui::RpWidget> Controller::createPhotoEdit() {
_wrap,
object_ptr<Ui::UserpicButton>(
_wrap,
&_navigation->parentController()->window(),
_peer,
Ui::UserpicButton::Role::ChangePhoto,
st::defaultUserpicButton),
@@ -612,7 +575,7 @@ object_ptr<Ui::RpWidget> Controller::createStickersEdit() {
tr::lng_group_stickers_add(tr::now),
st::editPeerInviteLinkButton)
)->addClickHandler([=] {
Ui::show(
_navigation->parentController()->show(
Box<StickersBox>(_navigation->parentController(), channel),
Ui::LayerOption::KeepOther);
});
@@ -649,7 +612,7 @@ void Controller::showEditPeerTypeBox(
_usernameSavedValue = publicLink;
refreshHistoryVisibility();
});
Ui::show(
_navigation->parentController()->show(
Box<EditPeerTypeBox>(
_peer,
_channelHasLocationOriginalValue,
@@ -681,7 +644,7 @@ void Controller::showEditLinkedChatBox() {
|| channel->canEditPreHistoryHidden()));
if (const auto chat = *_linkedChatSavedValue) {
*box = Ui::show(
*box = _navigation->parentController()->show(
EditLinkedChatBox(
_navigation,
channel,
@@ -709,7 +672,7 @@ void Controller::showEditLinkedChatBox() {
for (const auto &item : list) {
chats.emplace_back(_peer->owner().processChat(item));
}
*box = Ui::show(
*box = _navigation->parentController()->show(
EditLinkedChatBox(
_navigation,
channel,
@@ -858,7 +821,7 @@ void Controller::fillHistoryVisibilityButton() {
_historyVisibilitySavedValue = checked;
});
const auto buttonCallback = [=] {
Ui::show(
_navigation->parentController()->show(
Box<EditPeerHistoryVisibilityBox>(
_peer,
boxCallback,
@@ -1023,9 +986,15 @@ void Controller::fillManageSection() {
wrap->entity(),
tr::lng_manage_peer_invite_links(),
rpl::duplicate(count) | ToPositiveNumberString(),
[=] { Ui::show(
Box(ManageInviteLinksBox, _peer, _peer->session().user(), 0, 0),
Ui::LayerOption::KeepOther);
[=] {
_navigation->parentController()->show(
Box(
ManageInviteLinksBox,
_peer,
_peer->session().user(),
0,
0),
Ui::LayerOption::KeepOther);
},
st::infoIconInviteLinks);
@@ -1344,7 +1313,6 @@ void Controller::saveLinkedChat() {
channel->setLinkedChat(*_savingData.linkedChat);
continueSave();
}).fail([=](const MTP::Error &error) {
const auto &type = error.type();
cancelSave();
}).send();
}
@@ -1397,7 +1365,6 @@ void Controller::saveTitle() {
}
void Controller::saveDescription() {
const auto channel = _peer->asChannel();
if (!_savingData.description
|| *_savingData.description == _peer->about()) {
return continueSave();
@@ -1457,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();
};
@@ -1520,7 +1487,7 @@ void Controller::deleteWithConfirmation() {
const auto deleteCallback = crl::guard(this, [=] {
deleteChannel();
});
Ui::show(
_navigation->parentController()->show(
Box<ConfirmBox>(
text,
tr::lng_box_delete(tr::now),

View File

@@ -133,8 +133,8 @@ QImage QrExact(const Qr::Data &data, int pixel, QColor color) {
skip,
skip,
Intro::details::TelegramLogoImage().scaled(
logoSize,
logoSize,
logoSize * cIntRetinaFactor(),
logoSize * cIntRetinaFactor(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
}
@@ -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

@@ -1,270 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/photo_crop_box.h"
#include "lang/lang_keys.h"
#include "ui/widgets/buttons.h"
#include "ui/ui_utility.h"
#include "app.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
PhotoCropBox::PhotoCropBox(
QWidget*,
const QImage &img,
const QString &title)
: _title(title)
, _img(img) {
}
void PhotoCropBox::prepare() {
addButton(tr::lng_settings_save(), [this] { sendPhoto(); });
addButton(tr::lng_cancel(), [this] { closeBox(); });
int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
_thumb = App::pixmapFromImageInPlace(_img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor());
_mask = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied);
_mask.setDevicePixelRatio(cRetinaFactor());
_fade = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied);
_fade.setDevicePixelRatio(cRetinaFactor());
_thumbw = _thumb.width() / cIntRetinaFactor();
_thumbh = _thumb.height() / cIntRetinaFactor();
if (_thumbw > _thumbh) {
_cropw = _thumbh - 20;
} else {
_cropw = _thumbw - 20;
}
_cropx = (_thumbw - _cropw) / 2;
_cropy = (_thumbh - _cropw) / 2;
_thumbx = (st::boxWideWidth - _thumbw) / 2;
_thumby = st::boxPhotoPadding.top();
setMouseTracking(true);
setDimensions(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip);
}
void PhotoCropBox::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton) {
_downState = mouseState(e->pos());
_fromposx = e->pos().x();
_fromposy = e->pos().y();
_fromcropx = _cropx;
_fromcropy = _cropy;
_fromcropw = _cropw;
}
return BoxContent::mousePressEvent(e);
}
int PhotoCropBox::mouseState(QPoint p) {
p -= QPoint(_thumbx, _thumby);
int32 delta = st::cropPointSize, mdelta(-delta / 2);
if (QRect(_cropx + mdelta, _cropy + mdelta, delta, delta).contains(p)) {
return 1;
} else if (QRect(_cropx + _cropw + mdelta, _cropy + mdelta, delta, delta).contains(p)) {
return 2;
} else if (QRect(_cropx + _cropw + mdelta, _cropy + _cropw + mdelta, delta, delta).contains(p)) {
return 3;
} else if (QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta).contains(p)) {
return 4;
} else if (QRect(_cropx, _cropy, _cropw, _cropw).contains(p)) {
return 5;
}
return 0;
}
rpl::producer<QImage> PhotoCropBox::ready() const {
return _readyImages.events();
}
void PhotoCropBox::mouseReleaseEvent(QMouseEvent *e) {
if (_downState) {
_downState = 0;
mouseMoveEvent(e);
}
}
void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
if (_downState && !(e->buttons() & Qt::LeftButton)) {
mouseReleaseEvent(e);
}
if (_downState) {
if (_downState == 1) {
int32 dx = e->pos().x() - _fromposx, dy = e->pos().y() - _fromposy, d = (dx < dy) ? dx : dy;
if (_fromcropx + d < 0) {
d = -_fromcropx;
}
if (_fromcropy + d < 0) {
d = -_fromcropy;
}
if (_fromcropw - d < st::cropMinSize) {
d = _fromcropw - st::cropMinSize;
}
if (_cropx != _fromcropx + d || _cropy != _fromcropy + d || _cropw != _fromcropw - d) {
_cropx = _fromcropx + d;
_cropy = _fromcropy + d;
_cropw = _fromcropw - d;
update();
}
} else if (_downState == 2) {
int32 dx = _fromposx - e->pos().x(), dy = e->pos().y() - _fromposy, d = (dx < dy) ? dx : dy;
if (_fromcropx + _fromcropw - d > _thumbw) {
d = _fromcropx + _fromcropw - _thumbw;
}
if (_fromcropy + d < 0) {
d = -_fromcropy;
}
if (_fromcropw - d < st::cropMinSize) {
d = _fromcropw - st::cropMinSize;
}
if (_cropy != _fromcropy + d || _cropw != _fromcropw - d) {
_cropy = _fromcropy + d;
_cropw = _fromcropw - d;
update();
}
} else if (_downState == 3) {
int32 dx = _fromposx - e->pos().x(), dy = _fromposy - e->pos().y(), d = (dx < dy) ? dx : dy;
if (_fromcropx + _fromcropw - d > _thumbw) {
d = _fromcropx + _fromcropw - _thumbw;
}
if (_fromcropy + _fromcropw - d > _thumbh) {
d = _fromcropy + _fromcropw - _thumbh;
}
if (_fromcropw - d < st::cropMinSize) {
d = _fromcropw - st::cropMinSize;
}
if (_cropw != _fromcropw - d) {
_cropw = _fromcropw - d;
update();
}
} else if (_downState == 4) {
int32 dx = e->pos().x() - _fromposx, dy = _fromposy - e->pos().y(), d = (dx < dy) ? dx : dy;
if (_fromcropx + d < 0) {
d = -_fromcropx;
}
if (_fromcropy + _fromcropw - d > _thumbh) {
d = _fromcropy + _fromcropw - _thumbh;
}
if (_fromcropw - d < st::cropMinSize) {
d = _fromcropw - st::cropMinSize;
}
if (_cropx != _fromcropx + d || _cropw != _fromcropw - d) {
_cropx = _fromcropx + d;
_cropw = _fromcropw - d;
update();
}
} else if (_downState == 5) {
int32 dx = e->pos().x() - _fromposx, dy = e->pos().y() - _fromposy;
if (_fromcropx + dx < 0) {
dx = -_fromcropx;
} else if (_fromcropx + _fromcropw + dx > _thumbw) {
dx = _thumbw - _fromcropx - _fromcropw;
}
if (_fromcropy + dy < 0) {
dy = -_fromcropy;
} else if (_fromcropy + _fromcropw + dy > _thumbh) {
dy = _thumbh - _fromcropy - _fromcropw;
}
if (_cropx != _fromcropx + dx || _cropy != _fromcropy + dy) {
_cropx = _fromcropx + dx;
_cropy = _fromcropy + dy;
update();
}
}
}
int32 cursorState = _downState ? _downState : mouseState(e->pos());
QCursor cur(style::cur_default);
if (cursorState == 1 || cursorState == 3) {
cur = style::cur_sizefdiag;
} else if (cursorState == 2 || cursorState == 4) {
cur = style::cur_sizebdiag;
} else if (cursorState == 5) {
cur = style::cur_sizeall;
}
setCursor(cur);
}
void PhotoCropBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
sendPhoto();
} else {
BoxContent::keyPressEvent(e);
}
}
void PhotoCropBox::paintEvent(QPaintEvent *e) {
BoxContent::paintEvent(e);
Painter p(this);
p.setFont(st::boxTextFont);
p.setPen(st::boxPhotoTextFg);
p.drawText(QRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom(), width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), st::boxTextFont->height), _title, style::al_top);
p.translate(_thumbx, _thumby);
p.drawPixmap(0, 0, _thumb);
_mask.fill(Qt::white);
{
Painter p(&_mask);
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(Qt::black);
p.drawEllipse(_cropx, _cropy, _cropw, _cropw);
}
style::colorizeImage(_mask, st::photoCropFadeBg->c, &_fade);
p.drawImage(0, 0, _fade);
int delta = st::cropPointSize;
int mdelta = -delta / 2;
p.fillRect(QRect(_cropx + mdelta, _cropy + mdelta, delta, delta), st::photoCropPointFg);
p.fillRect(QRect(_cropx + _cropw + mdelta, _cropy + mdelta, delta, delta), st::photoCropPointFg);
p.fillRect(QRect(_cropx + _cropw + mdelta, _cropy + _cropw + mdelta, delta, delta), st::photoCropPointFg);
p.fillRect(QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta), st::photoCropPointFg);
}
void PhotoCropBox::sendPhoto() {
auto from = _img;
if (_img.width() < _thumb.width()) {
from = _thumb.toImage();
}
float64 x = float64(_cropx) / _thumbw, y = float64(_cropy) / _thumbh, w = float64(_cropw) / _thumbw;
int32 ix = int32(x * from.width()), iy = int32(y * from.height()), iw = int32(w * from.width());
if (ix < 0) {
ix = 0;
}
if (ix + iw > from.width()) {
iw = from.width() - ix;
}
if (iy < 0) {
iy = 0;
}
if (iy + iw > from.height()) {
iw = from.height() - iy;
}
int32 offset = ix * from.depth() / 8 + iy * from.bytesPerLine();
QImage cropped(from.constBits() + offset, iw, iw, from.bytesPerLine(), from.format()), tosend;
if (from.format() == QImage::Format_Indexed8) {
cropped.setColorCount(from.colorCount());
cropped.setColorTable(from.colorTable());
}
if (cropped.width() > 1280) {
tosend = cropped.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation);
} else if (cropped.width() < 320) {
tosend = cropped.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation);
} else {
tosend = cropped.copy();
}
auto weak = Ui::MakeWeak(this);
_readyImages.fire(std::move(tosend));
if (weak) {
closeBox();
}
}

View File

@@ -1,42 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
class PhotoCropBox : public Ui::BoxContent {
public:
PhotoCropBox(QWidget*, const QImage &img, const QString &title);
int32 mouseState(QPoint p);
rpl::producer<QImage> ready() const;
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
private:
void sendPhoto();
QString _title;
int32 _downState = 0;
int32 _thumbx, _thumby, _thumbw, _thumbh;
int32 _cropx, _cropy, _cropw;
int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw;
QImage _img;
QPixmap _thumb;
QImage _mask, _fade;
rpl::event_stream<QImage> _readyImages;
};

View File

@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_media_prepare.h"
#include "mainwidget.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "mtproto/mtproto_config.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/send_context_menu.h"
@@ -20,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h"
#include "confirm_box.h"
#include "editor/photo_editor_layer_widget.h"
#include "history/history_drag_area.h"
#include "history/view/history_view_schedule_box.h"
#include "core/file_utilities.h"
@@ -66,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,
@@ -187,6 +185,22 @@ rpl::producer<int> SendFilesBox::Block::itemReplaceRequest() const {
}
}
rpl::producer<int> SendFilesBox::Block::itemModifyRequest() const {
using namespace rpl::mappers;
const auto preview = _preview.get();
const auto from = _from;
if (_isAlbum) {
const auto album = static_cast<Ui::AlbumPreview*>(preview);
return album->thumbModified() | rpl::map(_1 + from);
} else if (_isSingleMedia) {
const auto media = static_cast<Ui::SingleMediaPreview*>(preview);
return media->modifyRequests() | rpl::map_to(from);
} else {
return rpl::never<int>();
}
}
void SendFilesBox::Block::setSendWay(Ui::SendFilesWay way) {
if (!_isAlbum) {
return;
@@ -525,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,
@@ -601,6 +614,16 @@ void SendFilesBox::pushBlock(int from, int till) {
FileDialog::AllOrImagesFilter(),
crl::guard(this, callback));
}, widget->lifetime());
block.itemModifyRequest(
) | rpl::start_with_next([=, controller = _controller](int index) {
Editor::OpenWithPreparedFile(
this,
controller,
&_list.files[index],
st::sendMediaPreviewSize,
[=] { refreshAllAfterChanges(from); });
}, widget->lifetime());
}
void SendFilesBox::refreshControls() {
@@ -640,6 +663,11 @@ void SendFilesBox::setupSendWayControls() {
sendWay.setSendImagesAsPhotos(_sendImagesAsPhotos->checked());
_sendWay = sendWay;
}, lifetime());
_hintLabel.create(
this,
tr::lng_edit_photo_editor_hint(tr::now),
st::editMediaHintLabel);
}
void SendFilesBox::updateSendWayControlsVisibility() {
@@ -647,6 +675,11 @@ void SendFilesBox::updateSendWayControlsVisibility() {
_groupFiles->setVisible(_list.hasGroupOption(onlyOne));
_sendImagesAsPhotos->setVisible(
_list.hasSendImagesAsPhotosOption(onlyOne));
_hintLabel->setVisible(
_controller->session().settings().photoEditorHintShown()
? _list.hasSendImagesAsPhotosOption(false)
: false);
}
void SendFilesBox::setupCaption() {
@@ -850,14 +883,15 @@ void SendFilesBox::updateBoxSize() {
if (_caption) {
footerHeight += st::boxPhotoCaptionSkip + _caption->height();
}
const auto pointers = {
_groupFiles.data(),
_sendImagesAsPhotos.data(),
};
for (auto pointer : pointers) {
const auto pairs = std::array<std::pair<RpWidget*, int>, 3>{ {
{ _groupFiles.data(), st::boxPhotoCompressedSkip },
{ _sendImagesAsPhotos.data(), st::boxPhotoCompressedSkip },
{ _hintLabel.data(), st::editMediaLabelMargins.top() },
} };
for (const auto &pair : pairs) {
const auto pointer = pair.first;
if (pointer && !pointer->isHidden()) {
footerHeight += st::boxPhotoCompressedSkip
+ pointer->heightNoMargins();
footerHeight += pair.second + pointer->heightNoMargins();
}
}
_footerHeight = footerHeight;
@@ -916,16 +950,18 @@ void SendFilesBox::updateControlsGeometry() {
_emojiToggle->update();
}
}
const auto pointers = {
_groupFiles.data(),
_sendImagesAsPhotos.data(),
};
for (const auto pointer : ranges::views::reverse(pointers)) {
const auto pairs = std::array<std::pair<RpWidget*, int>, 3>{ {
{ _hintLabel.data(), st::editMediaLabelMargins.top() },
{ _groupFiles.data(), st::boxPhotoCompressedSkip },
{ _sendImagesAsPhotos.data(), st::boxPhotoCompressedSkip },
} };
for (const auto &pair : ranges::views::reverse(pairs)) {
const auto pointer = pair.first;
if (pointer && !pointer->isHidden()) {
pointer->moveToLeft(
st::boxPhotoPadding.left(),
bottom - pointer->heightNoMargins());
bottom -= st::boxPhotoCompressedSkip + pointer->heightNoMargins();
bottom -= pair.second + pointer->heightNoMargins();
}
}
_scroll->resize(width(), bottom - _titleHeight.current());
@@ -976,6 +1012,12 @@ void SendFilesBox::send(
for (auto &block : _blocks) {
block.applyAlbumOrder();
}
if (Storage::ApplyModifications(_list)) {
_controller->session().settings().incrementPhotoEditorHintShown();
_controller->session().saveSettings();
}
_confirmed = true;
if (_confirmedCallback) {
auto caption = (_caption && !_caption->isHidden())
@@ -1002,7 +1044,7 @@ void SendFilesBox::sendScheduled() {
? SendMenu::Type::ScheduledToUser
: _sendMenuType;
const auto callback = [=](Api::SendOptions options) { send(options); };
Ui::show(
_controller->show(
HistoryView::PrepareScheduleBox(this, type, callback),
Ui::LayerOption::KeepOther);
}

View File

@@ -35,6 +35,7 @@ struct GroupMediaLayout;
class EmojiButton;
class AlbumPreview;
class VerticalLayout;
class FlatLabel;
} // namespace Ui
namespace Window {
@@ -102,6 +103,7 @@ private:
[[nodiscard]] rpl::producer<int> itemDeleteRequest() const;
[[nodiscard]] rpl::producer<int> itemReplaceRequest() const;
[[nodiscard]] rpl::producer<int> itemModifyRequest() const;
void setSendWay(Ui::SendFilesWay way);
void applyAlbumOrder();
@@ -183,6 +185,7 @@ private:
object_ptr<Ui::Checkbox> _groupFiles = { nullptr };
object_ptr<Ui::Checkbox> _sendImagesAsPhotos = { nullptr };
object_ptr<Ui::FlatLabel> _hintLabel = { nullptr };
rpl::variable<Ui::SendFilesWay> _sendWay = Ui::SendFilesWay();
rpl::variable<int> _footerHeight = 0;

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

@@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/image/image_location_factory.h"
#include "ui/text/text_utilities.h"
#include "ui/effects/path_shift_gradient.h"
#include "ui/emoji_config.h"
#include "ui/toast/toast.h"
#include "ui/widgets/popup_menu.h"
@@ -50,25 +51,35 @@ 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;
bool official() const;
rpl::producer<TextWithEntities> title() const;
QString shortName() const;
[[nodiscard]] rpl::producer<TextWithEntities> title() const;
[[nodiscard]] QString shortName() const;
void install();
rpl::producer<uint64> setInstalled() const;
rpl::producer<> updateControls() const;
[[nodiscard]] rpl::producer<uint64> setInstalled() const;
[[nodiscard]] rpl::producer<uint64> setArchived() const;
[[nodiscard]] rpl::producer<> updateControls() const;
[[nodiscard]] rpl::producer<Error> errors() const;
void archiveStickers();
bool isMasksSet() const {
return (_setFlags & SetFlag::Masks);
}
~Inner();
@@ -102,10 +113,6 @@ private:
void gotSet(const MTPmessages_StickerSet &set);
void installDone(const MTPmessages_StickerSetInstallResult &result);
bool isMasksSet() const {
return (_setFlags & MTPDstickerSet::Flag::f_masks);
}
not_null<Lottie::MultiPlayer*> getLottiePlayer();
void showPreview();
@@ -122,11 +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;
MTPInputStickerSet _input;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
StickerSetIdentifier _input;
mtpRequestId _installRequest = 0;
@@ -136,14 +145,16 @@ private:
int _previewShown = -1;
rpl::event_stream<uint64> _setInstalled;
rpl::event_stream<uint64> _setArchived;
rpl::event_stream<> _updateControls;
rpl::event_stream<Error> _errors;
};
StickerSetBox::StickerSetBox(
QWidget*,
not_null<Window::SessionController*> controller,
const MTPInputStickerSet &set)
const StickerSetIdentifier &set)
: _controller(controller)
, _set(set) {
}
@@ -152,8 +163,8 @@ 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) {
return Ui::show(
if (sticker->set) {
return controller->show(
Box<StickerSetBox>(controller, sticker->set),
Ui::LayerOption::KeepOther).data();
}
@@ -183,7 +194,47 @@ void StickerSetBox::prepare() {
_inner->setInstalled(
) | rpl::start_with_next([=](uint64 setId) {
_controller->session().api().stickerSetInstalled(setId);
if (_inner->isMasksSet()) {
Ui::Toast::Show(tr::lng_masks_installed(tr::now));
} else {
auto &stickers = _controller->session().data().stickers();
stickers.notifyStickerSetInstalled(setId);
}
closeBox();
}, lifetime());
_inner->errors(
) | rpl::start_with_next([=](Error error) {
handleError(error);
}, lifetime());
_inner->setArchived(
) | rpl::start_with_next([=](uint64 setId) {
const auto isMasks = _inner->isMasksSet();
Ui::Toast::Show(isMasks
? tr::lng_masks_has_been_archived(tr::now)
: tr::lng_stickers_has_been_archived(tr::now));
auto &order = isMasks
? _controller->session().data().stickers().maskSetsOrderRef()
: _controller->session().data().stickers().setsOrderRef();
const auto index = order.indexOf(setId);
if (index != -1) {
order.removeAt(index);
auto &local = _controller->session().local();
if (isMasks) {
local.writeInstalledMasks();
local.writeArchivedMasks();
} else {
local.writeInstalledStickers();
local.writeArchivedStickers();
}
}
_controller->session().data().stickers().notifyUpdated();
closeBox();
}, lifetime());
}
@@ -198,36 +249,18 @@ void StickerSetBox::copyStickersLink() {
QGuiApplication::clipboard()->setText(url);
}
void StickerSetBox::archiveStickers() {
const auto weak = base::make_weak(_controller.get());
const auto setId = _set.c_inputStickerSetID().vid().v;
_controller->session().api().request(MTPmessages_InstallStickerSet(
_set,
MTP_boolTrue()
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
const auto controller = weak.get();
if (!controller) {
return;
}
if (result.type() == mtpc_messages_stickerSetInstallResultSuccess) {
Ui::Toast::Show(tr::lng_stickers_has_been_archived(tr::now));
const auto &session = controller->session();
auto &order = session.data().stickers().setsOrderRef();
const auto index = order.indexOf(setId);
if (index == -1) {
return;
}
order.removeAt(index);
session.local().writeInstalledStickers();
session.local().writeArchivedStickers();
session.data().stickers().notifyUpdated();
}
}).fail([](const MTP::Error &error) {
Ui::Toast::Show(Lang::Hard::ServerError());
}).send();
void StickerSetBox::handleError(Error error) {
const auto guard = gsl::finally(crl::guard(this, [=] {
closeBox();
}));
switch (error) {
case Error::NotFound:
_controller->show(
Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
break;
default: Unexpected("Error in StickerSetBox::handleError.");
}
}
void StickerSetBox::updateTitleAndButtons() {
@@ -238,8 +271,12 @@ void StickerSetBox::updateTitleAndButtons() {
void StickerSetBox::updateButtons() {
clearButtons();
if (_inner->loaded()) {
const auto isMasks = _inner->isMasksSet();
if (_inner->notInstalled()) {
addButton(tr::lng_stickers_add_pack(), [=] { addStickers(); });
auto addText = isMasks
? tr::lng_stickers_add_masks()
: tr::lng_stickers_add_pack();
addButton(std::move(addText), [=] { addStickers(); });
addButton(tr::lng_cancel(), [=] { closeBox(); });
if (!_inner->shortName().isEmpty()) {
@@ -254,7 +291,9 @@ void StickerSetBox::updateButtons() {
top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>(top);
(*menu)->addAction(
tr::lng_stickers_share_pack(tr::now),
(isMasks
? tr::lng_stickers_share_masks
: tr::lng_stickers_share_pack)(tr::now),
share);
(*menu)->popup(QCursor::pos());
return true;
@@ -267,21 +306,25 @@ void StickerSetBox::updateButtons() {
copyStickersLink();
Ui::Toast::Show(tr::lng_stickers_copied(tr::now));
};
addButton(tr::lng_stickers_share_pack(), std::move(share));
auto shareText = isMasks
? tr::lng_stickers_share_masks()
: tr::lng_stickers_share_pack();
addButton(std::move(shareText), std::move(share));
addButton(tr::lng_cancel(), [=] { closeBox(); });
if (!_inner->shortName().isEmpty()) {
const auto top = addTopButton(st::infoTopBarMenu);
const auto archive = [=] {
archiveStickers();
closeBox();
_inner->archiveStickers();
};
const auto menu =
std::make_shared<base::unique_qptr<Ui::PopupMenu>>();
top->setClickedCallback([=] {
*menu = base::make_unique_q<Ui::PopupMenu>(top);
(*menu)->addAction(
tr::lng_stickers_archive_pack(tr::now),
isMasks
? tr::lng_masks_archive_pack(tr::now)
: tr::lng_stickers_archive_pack(tr::now),
archive);
(*menu)->popup(QCursor::pos());
return true;
@@ -302,29 +345,26 @@ 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) {
_loaded = true;
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
_errors.fire(Error::NotFound);
}).send();
_controller->session().api().updateStickers();
@@ -382,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()) {
@@ -402,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;
@@ -419,7 +458,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
});
if (_pack.isEmpty()) {
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
_errors.fire(Error::NotFound);
return;
} else {
int32 rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
@@ -435,24 +474,38 @@ rpl::producer<uint64> StickerSetBox::Inner::setInstalled() const {
return _setInstalled.events();
}
rpl::producer<uint64> StickerSetBox::Inner::setArchived() const {
return _setArchived.events();
}
rpl::producer<> StickerSetBox::Inner::updateControls() const {
return _updateControls.events();
}
rpl::producer<StickerSetBox::Error> StickerSetBox::Inner::errors() const {
return _errors.events();
}
void StickerSetBox::Inner::installDone(
const MTPmessages_StickerSetInstallResult &result) {
auto &sets = _controller->session().data().stickers().setsRef();
auto &stickers = _controller->session().data().stickers();
auto &sets = stickers.setsRef();
const auto isMasks = isMasksSet();
bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived);
const bool wasArchived = (_setFlags & SetFlag::Archived);
if (wasArchived) {
auto index = _controller->session().data().stickers().archivedSetsOrderRef().indexOf(_setId);
const auto index = (isMasks
? stickers.archivedMaskSetsOrderRef()
: stickers.archivedSetsOrderRef()).indexOf(_setId);
if (index >= 0) {
_controller->session().data().stickers().archivedSetsOrderRef().removeAt(index);
(isMasks
? stickers.archivedMaskSetsOrderRef()
: stickers.archivedSetsOrderRef()).removeAt(index);
}
}
_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(
@@ -476,8 +529,10 @@ void StickerSetBox::Inner::installDone(
set->stickers = _pack;
set->emoji = _emoji;
auto &order = _controller->session().data().stickers().setsOrderRef();
int insertAtIndex = 0, currentIndex = order.indexOf(_setId);
auto &order = isMasks
? stickers.maskSetsOrderRef()
: stickers.setsOrderRef();
const auto insertAtIndex = 0, currentIndex = order.indexOf(_setId);
if (currentIndex != insertAtIndex) {
if (currentIndex > 0) {
order.removeAt(currentIndex);
@@ -489,8 +544,10 @@ void StickerSetBox::Inner::installDone(
if (customIt != sets.cend()) {
const auto custom = customIt->second.get();
for (const auto sticker : std::as_const(_pack)) {
int removeIndex = custom->stickers.indexOf(sticker);
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
const int removeIndex = custom->stickers.indexOf(sticker);
if (removeIndex >= 0) {
custom->stickers.removeAt(removeIndex);
}
}
if (custom->stickers.isEmpty()) {
sets.erase(customIt);
@@ -498,14 +555,23 @@ void StickerSetBox::Inner::installDone(
}
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
_controller->session().data().stickers().applyArchivedResult(
stickers.applyArchivedResult(
result.c_messages_stickerSetInstallResultArchive());
} else {
auto &storage = _controller->session().local();
if (wasArchived) {
_controller->session().local().writeArchivedStickers();
if (isMasks) {
storage.writeArchivedMasks();
} else {
storage.writeArchivedStickers();
}
}
_controller->session().local().writeInstalledStickers();
_controller->session().data().stickers().notifyUpdated();
if (isMasks) {
storage.writeInstalledMasks();
} else {
storage.writeInstalledStickers();
}
stickers.notifyUpdated();
}
_setInstalled.fire_copy(_setId);
}
@@ -622,10 +688,10 @@ 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);
for (int32 i = from; i < to; ++i) {
for (int32 j = 0; j < kStickersPanelPerRow; ++j) {
int32 index = i * kStickersPanelPerRow + j;
@@ -721,7 +787,8 @@ void StickerSetBox::Inner::paintSticker(
const auto &media = element.documentMedia;
media->checkStickerSmall();
if (document->sticker()->animated
const auto isAnimated = document->sticker()->animated;
if (isAnimated
&& !element.animated
&& media->loaded()) {
const_cast<Inner*>(this)->setupLottie(index);
@@ -729,7 +796,7 @@ void StickerSetBox::Inner::paintSticker(
auto w = 1;
auto h = 1;
if (element.animated && !document->dimensions.isEmpty()) {
if (isAnimated && !document->dimensions.isEmpty()) {
const auto request = Lottie::FrameRequest{ boundingBoxSize() * cIntRetinaFactor() };
const auto size = request.size(document->dimensions, true) / cIntRetinaFactor();
w = std::max(size.width(), 1);
@@ -741,6 +808,7 @@ void StickerSetBox::Inner::paintSticker(
h = std::max(qRound(coef * document->dimensions.height()), 1);
}
QPoint ppos = position + QPoint((st::stickersSize.width() - w) / 2, (st::stickersSize.height() - h) / 2);
if (element.animated && element.animated->ready()) {
const auto frame = element.animated->frame();
p.drawImage(
@@ -753,6 +821,12 @@ void StickerSetBox::Inner::paintSticker(
ppos,
width(),
image->pix(w, h));
} else {
ChatHelpers::PaintStickerThumbnailPath(
p,
media.get(),
QRect(ppos, QSize(w, h)),
_pathGradient.get());
}
}
@@ -767,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;
@@ -794,21 +868,29 @@ QString StickerSetBox::Inner::shortName() const {
}
void StickerSetBox::Inner::install() {
if (isMasksSet()) {
Ui::show(
Box<InformBox>(tr::lng_stickers_masks_pack(tr::now)),
Ui::LayerOption::KeepOther);
return;
} else if (_installRequest) {
if (_installRequest) {
return;
}
_installRequest = _api.request(MTPmessages_InstallStickerSet(
_input,
Data::InputStickerSet(_input),
MTP_bool(false)
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
installDone(result);
}).fail([=](const MTP::Error &error) {
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
_errors.fire(Error::NotFound);
}).send();
}
void StickerSetBox::Inner::archiveStickers() {
_api.request(MTPmessages_InstallStickerSet(
Data::InputStickerSet(_input),
MTP_boolTrue()
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultSuccess) {
_setArchived.fire_copy(_setId);
}
}).fail([](const MTP::Error &error) {
Ui::Toast::Show(Lang::Hard::ServerError());
}).send();
}

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,
@@ -38,14 +38,18 @@ protected:
void resizeEvent(QResizeEvent *e) override;
private:
enum class Error {
NotFound,
};
void updateTitleAndButtons();
void updateButtons();
void addStickers();
void copyStickersLink();
void archiveStickers();
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;
@@ -68,9 +69,7 @@ private:
};
// This class is hold in header because it requires Qt preprocessing.
class StickersBox::Inner
: public Ui::RpWidget
, private base::Subscriber {
class StickersBox::Inner : public Ui::RpWidget {
public:
using Section = StickersBox::Section;
@@ -85,12 +84,14 @@ public:
[[nodiscard]] Main::Session &session() const;
base::Observable<int> scrollToY;
rpl::producer<int> scrollsToY() const {
return _scrollsToY.events();
}
void setInnerFocus();
void saveGroupSet();
void rebuild();
void rebuild(bool masks);
void updateSize(int newWidth = 0);
void updateRows(); // refresh only pack cover stickers
bool appendSet(not_null<StickersSet*> set);
@@ -152,6 +153,7 @@ private:
~Row();
bool isRecentSet() const;
bool isMasksSet() const;
const not_null<StickersSet*> set;
DocumentData *sticker = nullptr;
@@ -232,14 +234,15 @@ private:
void rebuildMegagroupSet();
void fixupMegagroupSetAddress();
void handleMegagroupSetAddressChange();
void setMegagroupSelectedSet(const MTPInputStickerSet &set);
void setMegagroupSelectedSet(const StickerSetIdentifier &set);
int countMaxNameWidth() const;
const not_null<Window::SessionController*> _controller;
MTP::Sender _api;
Section _section;
const Section _section;
const bool _isInstalled;
int32 _rowHeight;
@@ -276,11 +279,13 @@ private:
int _above = -1;
rpl::event_stream<int> _draggingScrollDelta;
rpl::event_stream<int> _scrollsToY;
int _minHeight = 0;
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 };
@@ -349,7 +354,7 @@ void StickersBox::Tab::returnWidget(object_ptr<Inner> widget) {
Assert(_widget == _weak);
}
StickersBox::Inner *StickersBox::Tab::widget() {
StickersBox::Inner *StickersBox::Tab::widget() const {
return _weak;
}
@@ -364,7 +369,8 @@ void StickersBox::Tab::saveScrollTop() {
StickersBox::StickersBox(
QWidget*,
not_null<Window::SessionController*> controller,
Section section)
Section section,
bool masks)
: _controller(controller)
, _api(&controller->session().mtp())
, _tabs(this, st::stickersTabs)
@@ -372,9 +378,11 @@ StickersBox::StickersBox(
this,
controller->session().data().stickers().featuredSetsUnreadCountValue())
, _section(section)
, _installed(0, this, controller, Section::Installed)
, _featured(1, this, controller, Section::Featured)
, _archived(2, this, controller, Section::Archived) {
, _isMasks(masks)
, _installed(_isMasks ? Tab() : Tab(0, this, controller, Section::Installed))
, _masks(_isMasks ? Tab(0, this, controller, Section::Masks) : Tab())
, _featured(_isMasks ? Tab() : Tab(1, this, controller, Section::Featured))
, _archived((_isMasks ? 1 : 2), this, controller, Section::Archived) {
_tabs->setRippleTopRoundRadius(st::boxRadius);
}
@@ -385,11 +393,13 @@ StickersBox::StickersBox(
: _controller(controller)
, _api(&controller->session().mtp())
, _section(Section::Installed)
, _isMasks(false)
, _installed(0, this, controller, megagroup)
, _megagroupSet(megagroup) {
subscribe(_installed.widget()->scrollToY, [=](int y) {
_installed.widget()->scrollsToY(
) | rpl::start_with_next([=](int y) {
onScrollToY(y);
});
}, lifetime());
}
StickersBox::StickersBox(
@@ -399,6 +409,7 @@ StickersBox::StickersBox(
: _controller(controller)
, _api(&controller->session().mtp())
, _section(Section::Attached)
, _isMasks(false)
, _attached(0, this, controller, Section::Attached)
, _attachedSets(attachedSets) {
}
@@ -419,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);
}
}
}
@@ -444,7 +458,7 @@ void StickersBox::getArchivedDone(
}
auto &stickers = result.c_messages_archivedStickers();
auto &archived = session().data().stickers().archivedSetsOrderRef();
auto &archived = archivedSetsOrderRef();
if (offsetId) {
auto index = archived.indexOf(offsetId);
if (index >= 0) {
@@ -485,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);
}
}
}
@@ -511,7 +528,11 @@ void StickersBox::getArchivedDone(
void StickersBox::prepare() {
if (_section == Section::Installed) {
if (_tabs) {
session().local().readArchivedStickers();
if (_isMasks) {
session().local().readArchivedMasks();
} else {
session().local().readArchivedStickers();
}
} else {
setTitle(tr::lng_stickers_group_set());
}
@@ -521,7 +542,7 @@ void StickersBox::prepare() {
setTitle(tr::lng_stickers_attached_sets());
}
if (_tabs) {
if (session().data().stickers().archivedSetsOrder().isEmpty()) {
if (archivedSetsOrder().isEmpty()) {
preloadArchivedSets();
}
setNoContentMargin(true);
@@ -531,21 +552,33 @@ void StickersBox::prepare() {
lifetime());
refreshTabs();
}
if (_installed.widget() && _section != Section::Installed) _installed.widget()->hide();
if (_featured.widget() && _section != Section::Featured) _featured.widget()->hide();
if (_archived.widget() && _section != Section::Archived) _archived.widget()->hide();
if (_attached.widget() && _section != Section::Attached) _attached.widget()->hide();
if (_installed.widget() && _section != Section::Installed) {
_installed.widget()->hide();
}
if (_masks.widget() && _section != Section::Masks) {
_masks.widget()->hide();
}
if (_featured.widget() && _section != Section::Featured) {
_featured.widget()->hide();
}
if (_archived.widget() && _section != Section::Archived) {
_archived.widget()->hide();
}
if (_attached.widget() && _section != Section::Attached) {
_attached.widget()->hide();
}
const auto installCallback = [=](uint64 setId) { installSet(setId); };
if (_featured.widget()) {
_featured.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
_featured.widget()->setInstallSetCallback(installCallback);
}
if (_archived.widget()) {
_archived.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
_archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); });
_archived.widget()->setInstallSetCallback(installCallback);
_archived.widget()->setLoadMoreCallback([=] { loadMoreArchived(); });
}
if (_attached.widget()) {
_attached.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
_attached.widget()->setLoadMoreCallback([this] { showAttachedStickers(); });
_attached.widget()->setInstallSetCallback(installCallback);
_attached.widget()->setLoadMoreCallback([=] { showAttachedStickers(); });
}
if (_megagroupSet) {
@@ -562,6 +595,8 @@ void StickersBox::prepare() {
if (_section == Section::Installed) {
_tab = &_installed;
} else if (_section == Section::Masks) {
_tab = &_masks;
} else if (_section == Section::Archived) {
_tab = &_archived;
} else if (_section == Section::Attached) {
@@ -577,18 +612,21 @@ void StickersBox::prepare() {
[this] { handleStickersUpdated(); },
lifetime());
session().api().updateStickers();
session().api().updateMasks();
if (_installed.widget()) {
_installed.widget()->draggingScrollDelta(
) | rpl::start_with_next([=](int delta) {
scrollByDraggingDelta(delta);
}, _installed.widget()->lifetime());
if (!_megagroupSet) {
boxClosing() | rpl::start_with_next([=] {
saveChanges();
}, lifetime());
for (const auto &widget : { _installed.widget(), _masks.widget() }) {
if (widget) {
widget->draggingScrollDelta(
) | rpl::start_with_next([=](int delta) {
scrollByDraggingDelta(delta);
}, widget->lifetime());
}
}
if (!_megagroupSet) {
boxClosing() | rpl::start_with_next([=] {
saveChanges();
}, lifetime());
}
if (_tabs) {
_tabs->raise();
@@ -598,28 +636,41 @@ void StickersBox::prepare() {
}
void StickersBox::refreshTabs() {
if (!_tabs) return;
if (!_tabs) {
return;
}
auto &stickers = session().data().stickers();
_tabIndices.clear();
auto sections = QStringList();
sections.push_back(tr::lng_stickers_installed_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Installed);
if (!session().data().stickers().featuredSetsOrder().isEmpty()) {
auto sections = std::vector<QString>();
if (_installed.widget()) {
sections.push_back(tr::lng_stickers_installed_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Installed);
}
if (_masks.widget()) {
sections.push_back(tr::lng_stickers_masks_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Masks);
}
if (!stickers.featuredSetsOrder().isEmpty() && _featured.widget()) {
sections.push_back(tr::lng_stickers_featured_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Featured);
}
if (!session().data().stickers().archivedSetsOrder().isEmpty()) {
if (!archivedSetsOrder().isEmpty() && _archived.widget()) {
sections.push_back(tr::lng_stickers_archived_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Archived);
}
_tabs->setSections(sections);
if ((_tab == &_archived && !_tabIndices.contains(Section::Archived))
|| (_tab == &_featured && !_tabIndices.contains(Section::Featured))) {
|| (_tab == &_featured && !_tabIndices.contains(Section::Featured))
|| (_tab == &_masks && !_tabIndices.contains(Section::Masks))) {
switchTab();
} else if (_tab == &_archived) {
_tabs->setActiveSectionFast(_tabIndices.indexOf(Section::Archived));
} else if (_tab == &_featured) {
_tabs->setActiveSectionFast(_tabIndices.indexOf(Section::Featured));
} else if (_tab == &_masks) {
_tabs->setActiveSectionFast(_tabIndices.indexOf(Section::Masks));
}
updateTabsGeometry();
}
@@ -632,20 +683,23 @@ void StickersBox::loadMoreArchived() {
}
uint64 lastId = 0;
const auto &order = session().data().stickers().archivedSetsOrder();
const auto &order = archivedSetsOrder();
const auto &sets = session().data().stickers().sets();
for (auto setIt = order.cend(), e = order.cbegin(); setIt != e;) {
--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;
}
}
}
const auto flags = _isMasks
? MTPmessages_GetArchivedStickers::Flag::f_masks
: MTPmessages_GetArchivedStickers::Flags(0);
_archivedRequestId = _api.request(MTPmessages_GetArchivedStickers(
MTP_flags(0),
MTP_flags(flags),
MTP_long(lastId),
MTP_int(kArchivedLimitPerPage)
)).done([=](const MTPmessages_ArchivedStickers &result) {
@@ -671,13 +725,15 @@ void StickersBox::paintEvent(QPaintEvent *e) {
void StickersBox::updateTabsGeometry() {
if (!_tabs) return;
_tabs->resizeToWidth(_tabIndices.size() * width() / 3);
const auto maxTabs = _isMasks ? 2 : 3;
_tabs->resizeToWidth(_tabIndices.size() * width() / maxTabs);
_unreadBadge->setVisible(_tabIndices.contains(Section::Featured));
setInnerTopSkip(getTopSkip());
auto featuredLeft = width() / 3;
auto featuredRight = 2 * width() / 3;
auto featuredLeft = width() / maxTabs;
auto featuredRight = 2 * width() / maxTabs;
auto featuredTextWidth = st::stickersTabs.labelStyle.font->width(tr::lng_stickers_featured_tab(tr::now).toUpper());
auto featuredTextRight = featuredLeft + (featuredRight - featuredLeft - featuredTextWidth) / 2 + featuredTextWidth;
auto unreadBadgeLeft = featuredTextRight - st::stickersFeaturedBadgeSkip;
@@ -709,6 +765,9 @@ void StickersBox::switchTab() {
} else if (newSection == Section::Archived) {
newTab = &_archived;
requestArchivedSets();
} else if (newSection == Section::Masks) {
newTab = &_masks;
session().api().updateMasks();
}
if (_tab == newTab) {
onScrollToY(0);
@@ -741,7 +800,7 @@ void StickersBox::switchTab() {
_slideAnimation = std::make_unique<Ui::SlideAnimation>();
_slideAnimation->setSnapshots(std::move(wasCache), std::move(nowCache));
auto slideLeft = wasIndex > nowIndex;
_slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration);
_slideAnimation->start(slideLeft, [=] { update(); }, st::slideDuration);
setInnerVisible(false);
setFocus();
@@ -755,6 +814,16 @@ QPixmap StickersBox::grabContentCache() {
return result;
}
std::array<StickersBox::Inner*, 5> StickersBox::widgets() const {
return {
_installed.widget(),
_featured.widget(),
_archived.widget(),
_attached.widget(),
_masks.widget()
};
}
void StickersBox::installSet(uint64 setId) {
const auto &sets = session().data().stickers().sets();
const auto it = sets.find(setId);
@@ -766,13 +835,14 @@ void StickersBox::installSet(uint64 setId) {
const auto set = it->second.get();
if (_localRemoved.contains(setId)) {
_localRemoved.removeOne(setId);
if (_installed.widget()) _installed.widget()->setRemovedSets(_localRemoved);
if (_featured.widget()) _featured.widget()->setRemovedSets(_localRemoved);
if (_archived.widget()) _archived.widget()->setRemovedSets(_localRemoved);
if (_attached.widget()) _attached.widget()->setRemovedSets(_localRemoved);
for (const auto &widget : widgets()) {
if (widget) {
widget->setRemovedSets(_localRemoved);
}
}
}
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()
@@ -808,8 +878,11 @@ void StickersBox::preloadArchivedSets() {
return;
}
if (!_archivedRequestId) {
const auto flags = _isMasks
? MTPmessages_GetArchivedStickers::Flag::f_masks
: MTPmessages_GetArchivedStickers::Flags(0);
_archivedRequestId = _api.request(MTPmessages_GetArchivedStickers(
MTP_flags(0),
MTP_flags(flags),
MTP_long(0),
MTP_int(kArchivedLimitFirstRequest)
)).done([=](const MTPmessages_ArchivedStickers &result) {
@@ -825,12 +898,13 @@ void StickersBox::requestArchivedSets() {
}
const auto &sets = session().data().stickers().sets();
const auto &order = session().data().stickers().archivedSetsOrder();
const auto &order = archivedSetsOrder();
for (const auto setId : order) {
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);
}
}
@@ -847,19 +921,22 @@ void StickersBox::resizeEvent(QResizeEvent *e) {
if (_titleShadow) {
_titleShadow->setGeometry(0, 0, width(), st::lineWidth);
}
if (_installed.widget()) _installed.widget()->resize(width(), _installed.widget()->height());
if (_featured.widget()) _featured.widget()->resize(width(), _featured.widget()->height());
if (_archived.widget()) _archived.widget()->resize(width(), _archived.widget()->height());
if (_attached.widget()) _attached.widget()->resize(width(), _attached.widget()->height());
for (const auto &widget : widgets()) {
if (widget) {
widget->resize(width(), widget->height());
}
}
}
void StickersBox::handleStickersUpdated() {
if (_section == Section::Installed || _section == Section::Featured) {
if (_section == Section::Installed
|| _section == Section::Featured
|| _section == Section::Masks) {
rebuildList();
} else {
_tab->widget()->updateRows();
}
if (session().data().stickers().archivedSetsOrder().isEmpty()) {
if (archivedSetsOrder().isEmpty()) {
preloadArchivedSets();
} else {
refreshTabs();
@@ -867,28 +944,55 @@ void StickersBox::handleStickersUpdated() {
}
void StickersBox::rebuildList(Tab *tab) {
if (_section == Section::Attached) return;
if (!tab) tab = _tab;
if (_section == Section::Attached) {
return;
}
if (!tab) {
tab = _tab;
}
if (tab == &_installed) {
if ((tab == &_installed) || (tab == &_masks)) {
_localOrder = tab->widget()->getFullOrder();
_localRemoved = tab->widget()->getRemovedSets();
}
tab->widget()->rebuild();
if (tab == &_installed) {
tab->widget()->rebuild(_isMasks);
if ((tab == &_installed) || (tab == &_masks)) {
tab->widget()->setFullOrder(_localOrder);
}
tab->widget()->setRemovedSets(_localRemoved);
}
void StickersBox::saveChanges() {
const auto installed = _installed.widget();
const auto masks = _masks.widget();
// Make sure that our changes in other tabs are applied in the Installed tab.
rebuildList(&_installed);
if (installed) {
rebuildList(&_installed);
}
if (masks) {
rebuildList(&_masks);
}
if (_someArchivedLoaded) {
session().local().writeArchivedStickers();
if (_isMasks) {
session().local().writeArchivedMasks();
} else {
session().local().writeArchivedStickers();
}
}
if (installed) {
session().api().saveStickerSets(
installed->getOrder(),
installed->getRemovedSets(),
false);
}
if (masks) {
session().api().saveStickerSets(
masks->getOrder(),
masks->getRemovedSets(),
true);
}
session().api().saveStickerSets(_installed.widget()->getOrder(), _installed.widget()->getRemovedSets());
}
void StickersBox::setInnerFocus() {
@@ -897,6 +1001,18 @@ void StickersBox::setInnerFocus() {
}
}
const Data::StickersSetsOrder &StickersBox::archivedSetsOrder() const {
return !_isMasks
? session().data().stickers().archivedSetsOrder()
: session().data().stickers().archivedMaskSetsOrder();
}
Data::StickersSetsOrder &StickersBox::archivedSetsOrderRef() {
return !_isMasks
? session().data().stickers().archivedSetsOrderRef()
: session().data().stickers().archivedMaskSetsOrderRef();
}
StickersBox::~StickersBox() = default;
StickersBox::Inner::Row::Row(
@@ -929,7 +1045,12 @@ StickersBox::Inner::Row::Row(
StickersBox::Inner::Row::~Row() = default;
bool StickersBox::Inner::Row::isRecentSet() const {
return (set->id == Data::Stickers::CloudRecentSetId);
return (set->id == Data::Stickers::CloudRecentSetId)
|| (set->id == Data::Stickers::CloudRecentAttachedSetId);
}
bool StickersBox::Inner::Row::isMasksSet() const {
return (set->flags & SetFlag::Masks);
}
StickersBox::Inner::Inner(
@@ -940,6 +1061,7 @@ StickersBox::Inner::Inner(
, _controller(controller)
, _api(&_controller->session().mtp())
, _section(section)
, _isInstalled(_section == Section::Installed || _section == Section::Masks)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _shiftingAnimation([=](crl::time now) {
return shiftingAnimationCallback(now);
@@ -960,6 +1082,7 @@ StickersBox::Inner::Inner(
, _controller(controller)
, _api(&_controller->session().mtp())
, _section(StickersBox::Section::Installed)
, _isInstalled(_section == Section::Installed || _section == Section::Masks)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _shiftingAnimation([=](crl::time now) {
return shiftingAnimationCallback(now);
@@ -1084,8 +1207,10 @@ QRect StickersBox::Inner::relativeButtonRect(bool removeButton) const {
auto buttonh = st::stickersRemove.height;
auto buttonshift = st::stickersRemoveSkip;
if (!removeButton) {
auto &st = (_section == Section::Installed) ? st::stickersUndoRemove : st::stickersTrendingAdd;
auto textWidth = (_section == Section::Installed) ? _undoWidth : _addWidth;
const auto &st = _isInstalled
? st::stickersUndoRemove
: st::stickersTrendingAdd;
const auto textWidth = _isInstalled ? _undoWidth : _addWidth;
buttonw = textWidth - st.width;
buttonh = st.height;
buttonshift = 0;
@@ -1114,7 +1239,7 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
}
}
if (_section == Section::Installed) {
if (_isInstalled) {
if (index >= 0 && index == _above) {
auto current = _aboveShadowFadeOpacity.current();
if (_started >= 0) {
@@ -1141,13 +1266,13 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
paintFakeButton(p, row, index);
}
if (row->removed && _section == Section::Installed) {
if (row->removed && _isInstalled) {
p.setOpacity(st::stickersRowDisabledOpacity);
}
auto stickerx = st::contactsPadding.left();
if (!_megagroupSet && _section == Section::Installed) {
if (!_megagroupSet && _isInstalled) {
stickerx += st::stickersReorderIcon.width() + st::stickersReorderSkip;
if (!row->isRecentSet()) {
st::stickersReorderIcon.paint(p, st::contactsPadding.left(), (_rowHeight - st::stickersReorderIcon.height()) / 2, width());
@@ -1178,7 +1303,11 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
}
}
auto statusText = (row->count > 0) ? tr::lng_stickers_count(tr::now, lt_count, row->count) : tr::lng_contacts_loading(tr::now);
const auto statusText = (row->count == 0)
? tr::lng_contacts_loading(tr::now)
: row->isMasksSet()
? tr::lng_masks_count(tr::now, lt_count, row->count)
: tr::lng_stickers_count(tr::now, lt_count, row->count);
p.setFont(st::contactsStatusFont);
p.setPen(st::contactsStatusFg);
@@ -1278,7 +1407,7 @@ void StickersBox::Inner::updateRowThumbnail(not_null<Row*> row) {
Unexpected("StickersBox::Inner::updateRowThumbnail: row not found");
}();
const auto left = st::contactsPadding.left()
+ ((!_megagroupSet && _section == Section::Installed)
+ ((!_megagroupSet && _isInstalled)
? st::stickersReorderIcon.width() + st::stickersReorderSkip
: 0);
update(
@@ -1289,9 +1418,9 @@ void StickersBox::Inner::updateRowThumbnail(not_null<Row*> row) {
}
void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int index) {
auto removeButton = (_section == Section::Installed && !row->removed);
auto removeButton = (_isInstalled && !row->removed);
auto rect = relativeButtonRect(removeButton);
if (_section != Section::Installed && row->installed && !row->archived && !row->removed) {
if (!_isInstalled && row->installed && !row->archived && !row->removed) {
// Checkbox after installed from Trending or Archived.
int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() + (rect.width() + st::stickersFeaturedInstalled.width()) / 2);
int checky = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersFeaturedInstalled.height()) / 2;
@@ -1314,10 +1443,12 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int ind
} else {
// Round button ADD when not installed from Trending or Archived.
// Or round button UNDO after disabled from Installed.
auto &st = (_section == Section::Installed) ? st::stickersUndoRemove : st::stickersTrendingAdd;
auto textWidth = (_section == Section::Installed) ? _undoWidth : _addWidth;
auto &text = (_section == Section::Installed) ? _undoText : _addText;
auto &textBg = selected ? st.textBgOver : st.textBg;
const auto &st = _isInstalled
? st::stickersUndoRemove
: st::stickersTrendingAdd;
const auto textWidth = _isInstalled ? _undoWidth : _addWidth;
const auto &text = _isInstalled ? _undoText : _addText;
const auto &textBg = selected ? st.textBgOver : st.textBg;
Ui::FillRoundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
if (row->ripple) {
row->ripple->paint(p, rect.x(), rect.y(), width());
@@ -1342,7 +1473,7 @@ void StickersBox::Inner::mousePressEvent(QMouseEvent *e) {
setActionDown(_actionSel);
update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
} else if (auto selectedIndex = std::get_if<int>(&_selected)) {
if (_section == Section::Installed && !_rows[*selectedIndex]->isRecentSet() && _inDragArea) {
if (_isInstalled && !_rows[*selectedIndex]->isRecentSet() && _inDragArea) {
_above = _dragging = _started = *selectedIndex;
_dragStart = mapFromGlobal(_mouse);
}
@@ -1364,9 +1495,9 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
if (_actionDown >= 0 && _actionDown < _rows.size()) {
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
const auto row = _rows[_actionDown].get();
auto removeButton = (_section == Section::Installed && !row->removed);
auto removeButton = (_isInstalled && !row->removed);
if (!row->ripple) {
if (_section == Section::Installed) {
if (_isInstalled) {
if (row->removed) {
auto rippleSize = QSize(_undoWidth - st::stickersUndoRemove.width, st::stickersUndoRemove.height);
auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::roundRadiusSmall);
@@ -1509,14 +1640,14 @@ void StickersBox::Inner::updateSelected() {
selected = selectedIndex;
local.setY(local.y() - _itemsTop - selectedIndex * _rowHeight);
const auto row = _rows[selectedIndex].get();
if (!_megagroupSet && (_section == Section::Installed || !row->installed || row->archived || row->removed)) {
auto removeButton = (_section == Section::Installed && !row->removed);
if (!_megagroupSet && (_isInstalled || !row->installed || row->archived || row->removed)) {
auto removeButton = (_isInstalled && !row->removed);
auto rect = myrtlrect(relativeButtonRect(removeButton));
actionSel = rect.contains(local) ? selectedIndex : -1;
} else {
actionSel = -1;
}
if (!_megagroupSet && _section == Section::Installed && !row->isRecentSet()) {
if (!_megagroupSet && _isInstalled && !row->isRecentSet()) {
auto dragAreaWidth = st::contactsPadding.left() + st::stickersReorderIcon.width() + st::stickersReorderSkip;
auto dragArea = myrtlrect(0, 0, dragAreaWidth, _rowHeight);
inDragArea = dragArea.contains(local);
@@ -1540,7 +1671,7 @@ void StickersBox::Inner::updateSelected() {
void StickersBox::Inner::updateCursor() {
setCursor(_inDragArea
? style::cur_sizeall
: (!_megagroupSet && _section == Section::Installed)
: (!_megagroupSet && _isInstalled)
? ((_actionSel >= 0 && (_actionDown < 0 || _actionDown == _actionSel))
? style::cur_pointer
: style::cur_default)
@@ -1565,13 +1696,12 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
_mouse = e->globalPos();
updateSelected();
if (_actionDown == _actionSel && _actionSel >= 0) {
if (_section == Section::Installed) {
if (_isInstalled) {
setRowRemoved(_actionDown, !_rows[_actionDown]->removed);
} else if (_installSetCallback) {
_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);
@@ -1589,15 +1719,15 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
}();
const auto showSetByRow = [&](const Row &row) {
setSelected(SelectedRow());
Ui::show(
Box<StickerSetBox>(_controller, row.set->mtpInput()),
_controller->show(
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);
}
@@ -1612,15 +1742,12 @@ 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().api().stickerSetInstalled(Data::Stickers::MegagroupSetId);
session().data().stickers().notifyStickerSetInstalled(
Data::Stickers::MegagroupSetId);
}
}
@@ -1753,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) {
@@ -1762,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);
@@ -1776,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();
@@ -1786,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;
}
@@ -1830,14 +1955,14 @@ 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();
}
}
void StickersBox::Inner::rebuild() {
void StickersBox::Inner::rebuild(bool masks) {
_itemsTop = st::membersMarginTop;
if (_megagroupSet) {
@@ -1856,10 +1981,14 @@ void StickersBox::Inner::rebuild() {
return session().data().stickers().featuredSetsOrder();
}
return result;
} else if (_section == Section::Masks) {
return session().data().stickers().maskSetsOrder();
} else if (_section == Section::Featured) {
return session().data().stickers().featuredSetsOrder();
}
return session().data().stickers().archivedSetsOrder();
return masks
? session().data().stickers().archivedMaskSetsOrder()
: session().data().stickers().archivedSetsOrder();
})();
_rows.reserve(order.size() + 1);
_shiftingStartTimes.reserve(order.size() + 1);
@@ -1871,8 +2000,10 @@ void StickersBox::Inner::rebuild() {
? tr::lng_stickers_group_from_featured(tr::now)
: tr::lng_stickers_group_from_your(tr::now));
updateControlsGeometry();
} else if (_section == Section::Installed) {
auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId);
} else if (_isInstalled) {
const auto cloudIt = sets.find((_section == Section::Masks)
? Data::Stickers::CloudRecentAttachedSetId
: Data::Stickers::CloudRecentSetId); // Section::Installed.
if (cloudIt != sets.cend() && !cloudIt->second->stickers.isEmpty()) {
rebuildAppendSet(cloudIt->second.get(), maxNameWidth);
}
@@ -1887,7 +2018,7 @@ void StickersBox::Inner::rebuild() {
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);
}
}
@@ -1895,10 +2026,10 @@ void StickersBox::Inner::rebuild() {
updateSize();
}
void StickersBox::Inner::setMegagroupSelectedSet(const MTPInputStickerSet &set) {
void StickersBox::Inner::setMegagroupSelectedSet(const StickerSetIdentifier &set) {
_megagroupSetInput = set;
rebuild();
scrollToY.notify(0, true);
rebuild(false);
_scrollsToY.fire(0);
updateSelected();
}
@@ -1941,7 +2072,7 @@ void StickersBox::Inner::updateRows() {
auto wasInstalled = row->installed;
auto wasArchived = row->archived;
fillSetFlags(set, &row->installed, &row->official, &row->unread, &row->archived);
if (_section == Section::Installed) {
if (_isInstalled) {
row->archived = false;
}
if (row->installed != wasInstalled || row->archived != wasArchived) {
@@ -1966,11 +2097,11 @@ bool StickersBox::Inner::appendSet(not_null<StickersSet*> set) {
int StickersBox::Inner::countMaxNameWidth() const {
int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
if (!_megagroupSet && _section == Section::Installed) {
if (!_megagroupSet && _isInstalled) {
namex += st::stickersReorderIcon.width() + st::stickersReorderSkip;
}
int namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x();
if (_section == Section::Installed) {
if (_isInstalled) {
if (!_megagroupSet) {
namew -= _undoWidth - st::stickersUndoRemove.width;
}
@@ -1990,7 +2121,7 @@ void StickersBox::Inner::rebuildAppendSet(
if (set->id != Data::Stickers::CloudRecentSetId) {
fillSetFlags(set, &installed, &official, &unread, &archived);
}
if (_section == Section::Installed && archived) {
if (_isInstalled && archived) {
return;
}
@@ -2102,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,19 +49,21 @@ 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,
Featured,
Archived,
Attached,
Masks,
};
StickersBox(
QWidget*,
not_null<Window::SessionController*> controller,
Section section);
Section section,
bool masks = false);
StickersBox(
QWidget*,
not_null<Window::SessionController*> controller,
@@ -94,7 +96,7 @@ private:
object_ptr<Inner> takeWidget();
void returnWidget(object_ptr<Inner> widget);
[[nodiscard]] Inner *widget();
[[nodiscard]] Inner *widget() const;
[[nodiscard]] int index() const;
void saveScrollTop();
@@ -103,7 +105,7 @@ private:
}
private:
int _index = 0;
const int _index = 0;
object_ptr<Inner> _widget = { nullptr };
QPointer<Inner> _weak;
int _scrollTop = 0;
@@ -132,6 +134,11 @@ private:
uint64 offsetId);
void showAttachedStickers();
const Data::StickersSetsOrder &archivedSetsOrder() const;
Data::StickersSetsOrder &archivedSetsOrderRef();
std::array<Inner*, 5> widgets() const;
const not_null<Window::SessionController*> _controller;
MTP::Sender _api;
@@ -142,8 +149,10 @@ private:
object_ptr<CounterWidget> _unreadBadge = { nullptr };
Section _section;
const bool _isMasks;
Tab _installed;
Tab _masks;
Tab _featured;
Tab _archived;
Tab _attached;

View File

@@ -490,6 +490,7 @@ groupCallMenu: Menu(defaultMenu) {
itemFgShortcutDisabled: groupCallMemberNotJoinedStatus;
separatorFg: groupCallMenuBgOver;
separatorPadding: margins(0px, 4px, 0px, 4px);
arrow: icon {{ "dropdown_submenu_arrow", groupCallMemberNotJoinedStatus }};
@@ -513,6 +514,16 @@ groupCallPopupMenu: PopupMenu(defaultPopupMenu) {
menu: groupCallMenu;
animation: groupCallPanelAnimation;
}
groupCallPopupMenuWithVolume: PopupMenu(groupCallPopupMenu) {
scrollPadding: margins(0px, 3px, 0px, 8px);
menu: Menu(groupCallMenu) {
widthMin: 210px;
}
}
groupCallPopupVolumeMenu: Menu(groupCallMenu) {
widthMin: 210px;
itemBgOver: groupCallMenuBg;
}
groupCallRecordingTimerPadding: margins(0px, 4px, 0px, 4px);
groupCallRecordingTimerFont: font(12px);
@@ -862,7 +873,7 @@ groupCallButtonSkip: 40px;
groupCallButtonSkipSmall: 5px;
groupCallButtonBottomSkip: 113px;
groupCallButtonBottomSkipSmall: 95px;
groupCallButtonBottomSkipWide: 122px;
groupCallButtonBottomSkipWide: 108px;
groupCallControlsBackMargin: margins(10px, 0px, 10px, 0px);
groupCallControlsBackRadius: 12px;
groupCallMuteBottomSkip: 116px;
@@ -1071,13 +1082,17 @@ groupCallMuteCrossLine: CrossLineAnimation {
groupCallMenuSpeakerArcsSkip: 1px;
groupCallMenuVolumeSkip: 5px;
groupCallMenuVolumePadding: margins(17px, 6px, 17px, 5px);
groupCallMenuVolumeMargin: margins(55px, 0px, 15px, 0px);
groupCallMenuVolumeSlider: MediaSlider(defaultContinuousSlider) {
activeFg: groupCallMembersFg;
inactiveFg: groupCallMemberInactiveIcon;
inactiveFg: groupCallMembersBgOver;
activeFgOver: groupCallMembersFg;
inactiveFgOver: groupCallMemberInactiveIcon;
activeFgDisabled: groupCallMemberInactiveIcon;
receivedTillFg: groupCallMemberInactiveIcon;
inactiveFgOver: groupCallMembersBgOver;
activeFgDisabled: groupCallMembersBgOver;
receivedTillFg: groupCallMembersBgOver;
width: 7px;
seekSize: size(7px, 7px);
}
groupCallSpeakerArcsAnimation: ArcsAnimation {
@@ -1169,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;
@@ -1229,6 +1254,9 @@ groupCallVideoTile: GroupCallVideoTile {
groupCallVideoSmallSkip: 4px;
groupCallVideoLargeSkip: 6px;
groupCallVideoPlaceholderHeight: 212px;
groupCallVideoPlaceholderIconTop: 50px;
groupCallVideoPlaceholderTextTop: 120px;
groupCallTooltip: Tooltip(defaultTooltip) {
textBg: groupCallMembersBg;
@@ -1248,5 +1276,16 @@ groupCallNiceTooltipLabel: FlatLabel(defaultImportantTooltipLabel) {
linkFontOver: font(11px underline);
}
}
groupCallStickedTooltip: ImportantTooltip(groupCallNiceTooltip) {
padding: margins(10px, 1px, 6px, 3px);
}
groupCallStickedTooltipClose: IconButton(defaultIconButton) {
width: 20px;
height: 20px;
iconPosition: point(4px, 3px);
icon: icon {{ "calls/video_tooltip", importantTooltipFg }};
iconOver: icon {{ "calls/video_tooltip", importantTooltipFg }};
ripple: emptyRippleAnimation;
}
groupCallNiceTooltipTop: 4px;
groupCallPaused: icon {{ "calls/video_large_paused", groupCallVideoTextFg }};

View File

@@ -357,7 +357,7 @@ base::unique_qptr<Ui::PopupMenu> BoxController::rowContextMenu(
auto result = base::make_unique_q<Ui::PopupMenu>(parent);
result->addAction(tr::lng_context_delete_selected(tr::now), [=] {
Ui::show(
_window->show(
Box<DeleteMessagesBox>(session, base::duplicate(ids)),
Ui::LayerOption::KeepOther);
});

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

@@ -28,7 +28,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "webrtc/webrtc_create_adm.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "facades.h"
#include <tgcalls/Instance.h>
#include <tgcalls/VideoCaptureInterface.h>
@@ -805,16 +804,19 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
AppendServer(descriptor.rtcServers, connection);
}
if (Global::UseProxyForCalls()
&& (Global::ProxySettings() == MTP::ProxyData::Settings::Enabled)) {
const auto &selected = Global::SelectedProxy();
if (selected.supportsCalls() && !selected.host.isEmpty()) {
Assert(selected.type == MTP::ProxyData::Type::Socks5);
descriptor.proxy = std::make_unique<tgcalls::Proxy>();
descriptor.proxy->host = selected.host.toStdString();
descriptor.proxy->port = selected.port;
descriptor.proxy->login = selected.user.toStdString();
descriptor.proxy->password = selected.password.toStdString();
{
auto &settingsProxy = Core::App().settings().proxy();
using ProxyData = MTP::ProxyData;
if (settingsProxy.useProxyForCalls() && settingsProxy.isEnabled()) {
const auto &selected = settingsProxy.selected();
if (selected.supportsCalls() && !selected.host.isEmpty()) {
Assert(selected.type == ProxyData::Type::Socks5);
descriptor.proxy = std::make_unique<tgcalls::Proxy>();
descriptor.proxy->host = selected.host.toStdString();
descriptor.proxy->port = selected.port;
descriptor.proxy->login = selected.user.toStdString();
descriptor.proxy->password = selected.password.toStdString();
}
}
}

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

@@ -42,7 +42,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_specific.h"
#include "base/platform/base_platform_info.h"
#include "window/main_window.h"
#include "media/view/media_view_pip.h" // Utilities for frame rotation.
#include "app.h"
#include "webrtc/webrtc_video_track.h"
#include "styles/style_calls.h"
@@ -51,16 +50,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QDesktopWidget>
#include <QtWidgets/QApplication>
#include <QtGui/QWindow>
#include <QtCore/QTimer>
namespace Calls {
Panel::Panel(not_null<Call*> call)
: _call(call)
, _user(call->user())
, _window(createWindow())
#ifndef Q_OS_MAC
, _controls(std::make_unique<Ui::Platform::TitleControls>(
_window->body(),
widget(),
st::callTitle,
[=](bool maximized) { toggleFullScreen(maximized); }))
#endif // !Q_OS_MAC
@@ -86,46 +85,27 @@ Panel::Panel(not_null<Call*> call)
Panel::~Panel() = default;
std::unique_ptr<Ui::Window> Panel::createWindow() {
auto result = std::make_unique<Ui::Window>();
const auto capabilities = Ui::GL::CheckCapabilities(result.get());
const auto use = Platform::IsMac()
? true
: Platform::IsWindows()
? capabilities.supported
: capabilities.transparency;
LOG(("OpenGL: %1 (Incoming)").arg(Logs::b(use)));
_backend = use ? Ui::GL::Backend::OpenGL : Ui::GL::Backend::Raster;
if (use) {
return result;
}
// We have to create a new window, if OpenGL initialization failed.
return std::make_unique<Ui::Window>();
}
bool Panel::isActive() const {
return _window->isActiveWindow()
&& _window->isVisible()
&& !(_window->windowState() & Qt::WindowMinimized);
return window()->isActiveWindow()
&& window()->isVisible()
&& !(window()->windowState() & Qt::WindowMinimized);
}
void Panel::showAndActivate() {
if (_window->isHidden()) {
_window->show();
if (window()->isHidden()) {
window()->show();
}
const auto state = _window->windowState();
const auto state = window()->windowState();
if (state & Qt::WindowMinimized) {
_window->setWindowState(state & ~Qt::WindowMinimized);
window()->setWindowState(state & ~Qt::WindowMinimized);
}
_window->raise();
_window->activateWindow();
_window->setFocus();
window()->raise();
window()->activateWindow();
window()->setFocus();
}
void Panel::minimize() {
_window->setWindowState(_window->windowState() | Qt::WindowMinimized);
window()->setWindowState(window()->windowState() | Qt::WindowMinimized);
}
void Panel::replaceCall(not_null<Call*> call) {
@@ -134,26 +114,26 @@ void Panel::replaceCall(not_null<Call*> call) {
}
void Panel::initWindow() {
_window->setAttribute(Qt::WA_OpaquePaintEvent);
_window->setAttribute(Qt::WA_NoSystemBackground);
_window->setWindowIcon(
window()->setAttribute(Qt::WA_OpaquePaintEvent);
window()->setAttribute(Qt::WA_NoSystemBackground);
window()->setWindowIcon(
QIcon(QPixmap::fromImage(Image::Empty()->original(), Qt::ColorOnly)));
_window->setTitle(u" "_q);
_window->setTitleStyle(st::callTitle);
window()->setTitle(u" "_q);
window()->setTitleStyle(st::callTitle);
_window->events(
window()->events(
) | rpl::start_with_next([=](not_null<QEvent*> e) {
if (e->type() == QEvent::Close) {
handleClose();
} else if (e->type() == QEvent::KeyPress) {
if ((static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Escape)
&& _window->isFullScreen()) {
_window->showNormal();
&& window()->isFullScreen()) {
window()->showNormal();
}
}
}, _window->lifetime());
}, window()->lifetime());
_window->setBodyTitleArea([=](QPoint widgetPoint) {
window()->setBodyTitleArea([=](QPoint widgetPoint) {
using Flag = Ui::WindowTitleHitTestFlag;
if (!widget()->rect().contains(widgetPoint)) {
return Flag::None | Flag(0);
@@ -179,28 +159,31 @@ void Panel::initWindow() {
: (Flag::Move | Flag::FullScreen);
});
#ifdef Q_OS_WIN
// On Windows we replace snap-to-top maximizing with fullscreen.
//
// We have to switch first to showNormal, so that showFullScreen
// will remember correct normal window geometry and next showNormal
// will show it instead of a moving maximized window.
//
// We have to do it in InvokeQueued, otherwise it still captures
// the maximized window geometry and saves it.
//
// I couldn't find a less glitchy way to do that *sigh*.
const auto object = _window->windowHandle();
const auto signal = &QWindow::windowStateChanged;
QObject::connect(object, signal, [=](Qt::WindowState state) {
if (state == Qt::WindowMaximized) {
InvokeQueued(object, [=] {
_window->showNormal();
_window->showFullScreen();
});
}
});
#endif // Q_OS_WIN
// Don't do that, it looks awful :(
//#ifdef Q_OS_WIN
// // On Windows we replace snap-to-top maximizing with fullscreen.
// //
// // We have to switch first to showNormal, so that showFullScreen
// // will remember correct normal window geometry and next showNormal
// // will show it instead of a moving maximized window.
// //
// // We have to do it in InvokeQueued, otherwise it still captures
// // the maximized window geometry and saves it.
// //
// // I couldn't find a less glitchy way to do that *sigh*.
// const auto object = window()->windowHandle();
// const auto signal = &QWindow::windowStateChanged;
// QObject::connect(object, signal, [=](Qt::WindowState state) {
// if (state == Qt::WindowMaximized) {
// InvokeQueued(object, [=] {
// window()->showNormal();
// InvokeQueued(object, [=] {
// window()->showFullScreen();
// });
// });
// }
// });
//#endif // Q_OS_WIN
}
void Panel::initWidget() {
@@ -339,7 +322,7 @@ void Panel::reinitWithCall(Call *call) {
_incoming = std::make_unique<Incoming>(
widget(),
_call->videoIncoming(),
_backend);
_window.backend());
_incoming->widget()->hide();
_call->mutedValue(
@@ -519,16 +502,20 @@ void Panel::showControls() {
}
void Panel::closeBeforeDestroy() {
_window->close();
window()->close();
reinitWithCall(nullptr);
}
rpl::lifetime &Panel::lifetime() {
return window()->lifetime();
}
void Panel::initGeometry() {
const auto center = Core::App().getPointForCallPanelCenter();
const auto initRect = QRect(0, 0, st::callWidth, st::callHeight);
_window->setGeometry(initRect.translated(center - initRect.center()));
_window->setMinimumSize({ st::callWidthMin, st::callHeightMin });
_window->show();
window()->setGeometry(initRect.translated(center - initRect.center()));
window()->setMinimumSize({ st::callWidthMin, st::callHeightMin });
window()->show();
updateControlsGeometry();
}
@@ -546,9 +533,9 @@ void Panel::refreshOutgoingPreviewInBody(State state) {
void Panel::toggleFullScreen(bool fullscreen) {
if (fullscreen) {
_window->showFullScreen();
window()->showFullScreen();
} else {
_window->showNormal();
window()->showNormal();
}
}
@@ -724,8 +711,12 @@ void Panel::handleClose() {
}
}
not_null<Ui::Window*> Panel::window() const {
return _window.window();
}
not_null<Ui::RpWidget*> Panel::widget() const {
return _window->body();
return _window.widget();
}
void Panel::stateChanged(State state) {
@@ -741,7 +732,7 @@ void Panel::stateChanged(State state) {
auto toggleButton = [&](auto &&button, bool visible) {
button->toggle(
visible,
_window->isHidden()
window()->isHidden()
? anim::type::instant
: anim::type::normal);
};

View File

@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/object_ptr.h"
#include "calls/calls_call.h"
#include "ui/effects/animations.h"
#include "ui/gl/gl_window.h"
#include "ui/rp_widget.h"
class Image;
@@ -60,6 +61,8 @@ public:
void replaceCall(not_null<Call*> call);
void closeBeforeDestroy();
rpl::lifetime &lifetime();
private:
class Incoming;
using State = Call::State;
@@ -70,7 +73,7 @@ private:
Redial,
};
std::unique_ptr<Ui::Window> createWindow();
[[nodiscard]] not_null<Ui::Window*> window() const;
[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
void paint(QRect clip);
@@ -106,8 +109,7 @@ private:
Call *_call = nullptr;
not_null<UserData*> _user;
Ui::GL::Backend _backend = Ui::GL::Backend();
const std::unique_ptr<Ui::Window> _window;
Ui::GL::Window _window;
std::unique_ptr<Incoming> _incoming;
#ifndef Q_OS_MAC

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