Compare commits

...

603 commits
v5.11.1 ... dev

Author SHA1 Message Date
AlexeyZavar
3be793032f fix: use usinfobot for username resolving & update README 2025-06-02 15:52:31 +03:00
Crd5
0fab18e8e8
chore: add homebrew as a download source for macOS 2025-06-02 15:48:52 +03:00
kuro neko
c91f41e988
fix: upstream docker build
Same as 88ce676c46
2025-05-26 04:55:51 +03:00
AlexeyZavar
3c7f3e8740 chore: change links 2025-05-20 22:59:22 +03:00
AlexeyZavar
3a9899529a fix: reordering crashes 2025-05-20 22:56:30 +03:00
AlexeyZavar
5a015888d4 chore: remove workflows 2025-05-20 17:35:57 +03:00
AlexeyZavar
be378eaacb feat: simple files reordering in send box 2025-05-19 15:44:02 +03:00
AlexeyZavar
631f5a1043 feat: restore caption from send files box 2025-05-19 00:59:34 +03:00
AlexeyZavar
353e9adec1 fix: make it build 2025-05-19 00:32:36 +03:00
AlexeyZavar
e572da4927 Merge tag 'v5.14.3' into dev 2025-05-18 22:30:24 +03:00
John Preston
d22afa36c3 Version 5.14.3.
- Fix stale birthday suggestions removing.
- Fix notification click opening a new window.
2025-05-18 20:32:39 +04:00
John Preston
a7296f15ac Suggest to reset gifts filter. 2025-05-18 20:32:39 +04:00
John Preston
b20caee548 Check if the resale gift price changed. 2025-05-18 14:12:18 +04:00
John Preston
519832edd7 Show warnings for dangerous business bot rights. 2025-05-18 14:12:17 +04:00
John Preston
a2cea1e5bc More robust business bot editing. 2025-05-18 14:12:16 +04:00
John Preston
b3c198f0d2 Improve layout of media albums with likes. 2025-05-18 14:12:15 +04:00
23rd
b45a696b5d Fixed build of macOS on Github CI. 2025-05-17 09:22:12 +03:00
Mehran
a2b3fe6411 Add and slightly improve cloud languages 2025-05-16 12:38:04 +04:00
Ilya Fedin
13d4f37726 Use CMAKE_MSVC_DEBUG_INFORMATION_FORMAT in Windows action 2025-05-16 11:36:16 +04:00
23rd
71f34f4e31 Added ability to jump from code to phone input in intro with Space. 2025-05-15 18:19:49 +03:00
23rd
018f147de6 Slightly improved position of code input in intro step. 2025-05-15 17:58:14 +03:00
23rd
da012cbf8b Added lottie emoji to box for validate phone number in settings. 2025-05-15 17:58:14 +03:00
John Preston
3907a103fc Fix possible notification click problem.
Fixes #29293.
2025-05-15 15:34:23 +04:00
John Preston
efb566bcc7 Don't show resale gifts as "sold out". 2025-05-15 14:50:27 +04:00
John Preston
53e8df3542 Sort resale gifts by Price by default. 2025-05-15 14:50:22 +04:00
23rd
a00d262773 Added support of suggestion to validate phone number to settings. 2025-05-15 13:22:54 +03:00
23rd
b64db54793 Fixed possible incorrect display of low credits balance in top bar. 2025-05-15 10:09:24 +03:00
23rd
97c0e3d4a9 Added support of custom emoji to top bar suggestion. 2025-05-15 10:09:01 +03:00
23rd
ba31bbace8 Added refresh of top bar suggestion on day changed for birthdays. 2025-05-15 10:08:44 +03:00
23rd
606dfd29d3 Moved out data of contact birthdays to promo suggestions class. 2025-05-15 10:08:22 +03:00
23rd
9411d0781b Removed birthday suggestions for self, blocked and deleted accounts. 2025-05-15 09:22:22 +03:00
23rd
7aea200860 Fixed padding reset in top bar suggestion on suggestion changed. 2025-05-15 09:21:54 +03:00
Ilya Fedin
5d8ac95d07 Prepend PkgConfig variables with TDESKTOP_
To avoid clashes with cache variables set by third party cmake modules
2025-05-14 11:13:50 +04:00
Ilya Fedin
cd0ebb41aa Use CMAKE_COMPILE_WARNING_AS_ERROR in actions
Instead of specifying the compiler flag manually
2025-05-14 10:43:50 +04:00
Ilya Fedin
eb028b0dad Ensure clangd cache is out of build directory
It's annoying to rebuild index after cleaning the build directory
2025-05-13 10:41:42 +04:00
Ilya Fedin
61803f7516 Update submodules 2025-05-13 08:07:02 +04:00
Ilya Fedin
50bfed79be Update protobuf in snap 2025-05-13 07:48:03 +04:00
Ilya Fedin
1c77ae818e Update cmake_helpers 2025-05-12 09:41:26 +04:00
Ilya Fedin
66ede6037d Add t2e2e to snap 2025-05-12 09:41:26 +04:00
Ilya Fedin
01452b7309 Add tde2e to macOS Packaged action 2025-05-12 09:41:26 +04:00
Ilya Fedin
b5f2470b79 td -> tde2e 2025-05-12 09:41:26 +04:00
Ilya Fedin
49403e9fee Fix COPY order for libraries in Dockerfile 2025-05-12 09:41:26 +04:00
John Preston
66d512f26f Version 5.14.2.
- Buy Rare Gifts in the Marketplace.
- Sell Your Gifts for Stars.
- Set Your Channel to Auto-Translate.
2025-05-09 10:01:55 +04:00
John Preston
2ba0ebf3e8 Update cmake_helpers submodule. 2025-05-09 10:01:55 +04:00
John Preston
bbcd27d3c2 Fix possible crash in restrictions. 2025-05-09 10:01:55 +04:00
Ilya Fedin
837a3528cd Fix mozjpeg build with cmake 4 2025-05-08 03:41:54 -07:00
Ilya Fedin
f39662588f Revert "Cherry-pick mozjpeg cmake 4 compatibility"
This reverts commit 9fd1f95ab8.
2025-05-08 03:41:54 -07:00
Ilya Fedin
4b12f52029 Revert "Set CMAKE_MSVC_RUNTIME_LIBRARY for mozjpeg"
This reverts commit ce764c862f.
2025-05-08 03:41:54 -07:00
Ilya Fedin
f2920ddefb Use Docker's actions to build Docker image 2025-05-08 02:52:14 -07:00
Ilya Fedin
ce010653d5 Don't create unnecessary subfolder in Linux action
It results in a tdesktop/tdesktop/tdesktop path
2025-05-08 02:52:14 -07:00
Ilya Fedin
ce764c862f Set CMAKE_MSVC_RUNTIME_LIBRARY for mozjpeg
The cherry-pick made in 9fd1f95ab8 broke mozjpeg's own WITH_CRT_DLL variable so we have to use the cmake one
2025-05-08 02:38:45 -07:00
Ilya Fedin
60d821ae3e Use cmake --build in macOS action 2025-05-08 02:37:08 -07:00
Ilya Fedin
8f7f8fc0b5 Set CMAKE_CONFIGURATION_TYPES for actions 2025-05-08 02:37:08 -07:00
John Preston
ec45041a66 Fix empty query migrated group search. 2025-05-08 10:53:23 +04:00
Ilya Fedin
67a666b282 Return accidentally removed video formats 2025-05-07 23:19:39 -07:00
Ilya Fedin
d9404fc566 Raise minimum required cmake version to 3.25
Use policies up to 3.31
2025-05-07 23:13:01 -07:00
23rd
bcd899c641 Slightly improved phrases to admin log for channels. 2025-05-07 22:35:30 +03:00
John Preston
ec61ac29ea Fix forum showing when group not opened. 2025-05-07 22:17:49 +04:00
John Preston
180e663a43 Implement nice confcall bar text. 2025-05-07 22:10:44 +04:00
John Preston
ae1711a685 Use translated phrase for collectible upgrade. 2025-05-07 21:05:33 +04:00
John Preston
9c3b62574d Change some hard-coded phrases. 2025-05-07 20:35:01 +04:00
John Preston
a3637c12d6 Fix first message date with new peer info. 2025-05-07 18:53:21 +04:00
John Preston
cae192682b Improve notification Ctrl+Click to open a new window.
Fixes #29144.
2025-05-07 18:52:52 +04:00
23rd
6c68bacaef Added ability to open chat in window from Ctrl+click on notifications. 2025-05-07 18:09:34 +04:00
John Preston
ee7a2b564b Show "Join" button for pinned call links. 2025-05-07 18:03:59 +04:00
John Preston
fb25d90b48 Hide weird unread badge in new-window forum. 2025-05-07 18:03:46 +04:00
John Preston
9075a521f0 Correctly show global search with in-chat. 2025-05-07 18:03:18 +04:00
John Preston
00a0e595ff Don't add global posts search preview for in-chat start. 2025-05-07 17:12:00 +04:00
John Preston
694ff32b01 Always search hashtags in current chat. 2025-05-07 16:56:55 +04:00
John Preston
a74635ff56 Fix: Hide 'My gifts' tab when gifting to self 2025-05-07 16:52:57 +04:00
John Preston
8c6f3d66b5 Don't mask gift numbers in service notifications. 2025-05-07 16:44:41 +04:00
John Preston
a49cb06d77 Fix unread count update in folder strip. 2025-05-07 16:39:42 +04:00
John Preston
f96f478470 Rename linked-chat to discussion-link. 2025-05-07 14:58:47 +04:00
John Preston
1d2f713673 Fix Cursor rules files. 2025-05-07 14:50:01 +04:00
23rd
57d24d0fbf Fixed ability to dismiss of suggestion of 2+ birthdays of contacts. 2025-05-07 12:16:51 +03:00
23rd
584e55a89c Fixed crash on dismiss of birthday suggestion. 2025-05-07 12:15:50 +03:00
23rd
4560a83441 Fixed creation of new filter with selected dialog from menu. 2025-05-07 11:47:00 +03:00
23rd
f4658728e8 Fixed update of currency balance on error receiving. 2025-05-07 11:17:33 +03:00
23rd
54825dc66f Fixed button for currency withdrawal from bots. 2025-05-07 10:28:54 +03:00
23rd
d4056ac10a Slightly improved style of withdrawal widget in bot earn stats. 2025-05-07 10:04:26 +03:00
23rd
8f409a8fe2 Fixed swipe-back on strip of similar channels. 2025-05-07 10:04:26 +03:00
23rd
d369d988b0 Fixed possible crashed on local zoom of charts in stats. 2025-05-07 10:04:26 +03:00
23rd
2a74736761 Removed ability to set wallpaper to replies chat. 2025-05-07 10:04:26 +03:00
23rd
6bd0bf6e69 Made more rpl-friendly balance label in channel profile. 2025-05-07 10:04:26 +03:00
23rd
53cee177e8 Added timeout to earn requests for channels and bots. 2025-05-07 10:04:26 +03:00
23rd
a8afc62db7 Added ability to inspect earn balance from channel info. 2025-05-07 10:04:26 +03:00
23rd
14328eb601 Fixed right label for only paid reaction in edit peer info box. 2025-05-06 20:50:19 +03:00
23rd
2184755fdf Fixed ripple from top button in box about sponsored messages. 2025-05-06 20:50:19 +03:00
23rd
3a3cd1f856 Slightly improved icon position in PointDetailsWidget for stats. 2025-05-06 20:50:19 +03:00
23rd
24a3a41cd6 Slightly improved code style in PromoSuggestions. 2025-05-06 12:33:03 +03:00
23rd
197f6b05ae Added support of custom promo suggestions. 2025-05-06 12:21:42 +03:00
23rd
c2e887a86e Moved out top promo from api and suggestions from config to single file. 2025-05-06 12:21:06 +03:00
AlexeyZavar
12b16577ef feat: send with sound in menu 2025-05-05 20:51:41 +03:00
AlexeyZavar
409165dec6 chore: refactor settings 2025-05-05 20:36:16 +03:00
AlexeyZavar
4870d59a43 fix: check if a message is modified 2025-05-05 19:35:09 +03:00
AlexeyZavar
70c3bb3288 fix: allow deleting deleted messages 2025-05-05 19:06:58 +03:00
AlexeyZavar
36156997ee fix: make it build
Thanks to tdesktop team for publishing broken sources ^^
2025-05-05 18:45:40 +03:00
Ilya Fedin
2c2728448c Update cmake_helpers 2025-05-05 16:52:55 +03:00
Ilya Fedin
d1781a7c47 Fix tde2e include the way tdlib itself uses it 2025-05-05 16:51:48 +03:00
John Preston
dc1459438c Fix a crash in screen share window close. 2025-05-05 11:43:51 +04:00
John Preston
00e6da9d64 Fix build with Xcode. 2025-05-05 11:43:51 +04:00
John Preston
68b3d75705 Track and show "too early" gift transfer/resell. 2025-05-05 11:43:51 +04:00
John Preston
3e538b732a Update API scheme on layer 203. 2025-05-05 11:43:51 +04:00
John Preston
833341dea7 Show transfer price if transfer from resale. 2025-05-05 11:43:51 +04:00
John Preston
bc3efe2f4c Improve gift resale transaction entries. 2025-05-05 11:43:51 +04:00
John Preston
10e4c59f2e Correct implementation of auto-translation. 2025-05-05 11:43:51 +04:00
John Preston
d9016b7979 Update API scheme on layer 203. 2025-05-05 11:43:51 +04:00
John Preston
d975610ecd Update API scheme on layer 203. 2025-05-05 11:43:51 +04:00
John Preston
5d1251f6d8 Improve layout of resale gift counters. 2025-05-05 11:43:50 +04:00
John Preston
bdf802e64a Use TextWithEntities().append(style::IconEmoji). 2025-05-05 11:43:50 +04:00
John Preston
f2b888f9ae Use nice icons in resale gifts sorting. 2025-05-05 11:43:50 +04:00
John Preston
9583007769 Apply auto-translation from French? for test. 2025-05-05 11:43:50 +04:00
John Preston
eb81c33308 Allow saving "Autotranslation of Messages" in channels. 2025-05-05 11:43:50 +04:00
John Preston
8d734f5cc4 Update API scheme on layer 203. 2025-05-05 11:43:50 +04:00
John Preston
3375ff6152 Use correct phrases for the resold gifts. 2025-05-05 11:43:50 +04:00
John Preston
80fc58f83e Reorder privacy and security settings. 2025-05-05 11:43:50 +04:00
John Preston
17c0124747 Improve price layout in saved gifts. 2025-05-05 11:43:50 +04:00
John Preston
c220d4dd17 Handle STARGIFT_RESELL_TOO_EARLY error. 2025-05-05 11:43:50 +04:00
John Preston
15146725e3 Fix transfer of my gifts from Resale. 2025-05-05 11:43:50 +04:00
John Preston
ddfab824c3 Respect gift privacy for resell gifts. 2025-05-05 11:43:50 +04:00
John Preston
8b5a00ca27 Add separate "Change Price" context menu button. 2025-05-05 11:43:50 +04:00
John Preston
04a7f14c0e Add price tag in resale gift view. 2025-05-05 11:43:50 +04:00
John Preston
18f14b828c Allow buying resold gifts. 2025-05-05 11:43:50 +04:00
John Preston
0a92e12a62 Allow placing your gifts on sale. 2025-05-05 11:43:50 +04:00
John Preston
5b71281ec4 Update API scheme on layer 203. 2025-05-05 11:43:50 +04:00
John Preston
08fdc4f1fc Add "Resale" tab in gift selection. 2025-05-05 11:43:50 +04:00
John Preston
c726bef740 Allow buying reselling gifts. 2025-05-05 11:43:50 +04:00
John Preston
94e0ac3f54 Add resale gift sorting modes icons. 2025-05-05 11:43:50 +04:00
John Preston
284f7fc4f7 Improve resale unique gift display. 2025-05-05 11:43:50 +04:00
John Preston
e629460942 Implement filtering of resale gifts. 2025-05-05 11:43:50 +04:00
John Preston
904e531113 Show resell info in gifts choose box. 2025-05-05 11:43:49 +04:00
John Preston
ca2f2adc90 Use correct paths for the rules files. 2025-05-05 10:58:35 +04:00
Ilya Fedin
78a3e329f5 Use gperf from msys2 2025-05-03 04:46:45 -07:00
Ilya Fedin
5938e0f821 Use native versions of diffutils and pkg-config on Windows 2025-05-03 04:46:45 -07:00
Ilya Fedin
4a6ae3b46c Use ninja from Windows SDK 2025-05-03 04:46:45 -07:00
Ilya Fedin
2327d661b9 Update msys2 2025-05-03 04:46:45 -07:00
Ilya Fedin
9790e37154 Remove unused ThirdParty\cmake\bin from prepare.py 2025-05-03 04:46:45 -07:00
Ilya Fedin
f97d751343 Update tg_owt 2025-05-03 04:46:45 -07:00
Ilya Fedin
81c1f6bd8e Update rnnoise 2025-05-03 04:46:45 -07:00
Ilya Fedin
e3a5a4239b Don't override C(XX)FLAGS for static MSVC library in prepare.py
Rely solely on CMAKE_MSVC_RUNTIME_LIBRARY
2025-05-03 04:46:45 -07:00
Ilya Fedin
fcec85881f Update xz to 5.8.1 in Docker 2025-05-03 04:46:45 -07:00
Ilya Fedin
cfefb8b2e0 Update zlib to 1.3.1 2025-05-03 04:46:45 -07:00
Ilya Fedin
e81a2a5011 Update Opus to 1.5.2
This fixes compatibility with cmake 4
2025-05-03 04:46:45 -07:00
Ilya Fedin
d62b488459 Ensure ffmpeg can find static pkg-config deps 2025-05-03 04:46:45 -07:00
Ilya Fedin
932bd92b95 Cherry-pick libde265 cmake 4 compatibility 2025-05-03 04:46:45 -07:00
Ilya Fedin
9fd1f95ab8 Cherry-pick mozjpeg cmake 4 compatibility 2025-05-03 04:46:45 -07:00
Ilya Fedin
cf414cb9cb Update cmake_helpers 2025-05-03 03:09:40 -07:00
Ilya Fedin
f676d32f96 Fix tde2e include the way tdlib itself uses it 2025-05-03 03:09:40 -07:00
AlexeyZavar
939c9afeb4 Merge tag 'v5.14.1' into dev 2025-05-02 01:50:47 +03:00
John Preston
7d88c48c39 Version 5.14.1.
- Fix launching on Windows 7.
2025-05-01 19:01:11 +04:00
John Preston
26337a6bd4 Partially revert "Get rid of /DELAYLOAD"
This partially reverts commit 6586791655.
2025-05-01 18:57:35 +04:00
John Preston
1263a5bfc0 Fix build on MSVC. 2025-05-01 17:59:38 +04:00
John Preston
fe21ca5b95 Update lib_ui. 2025-05-01 17:57:46 +04:00
23rd
0fe9dad515 Added initial api support of bank card entity in messages. 2025-05-01 13:51:16 +03:00
John Preston
75b33c906d Version 5.14.
- Secure Group Calls Made Easy.
- Automated Business Accounts.
- New Gifts Settings.
2025-05-01 12:43:35 +04:00
23rd
835fa77964 Fixed unpaused custom emoji in top bar of sponsored messages. 2025-05-01 12:43:35 +04:00
John Preston
3e13186560 Fix right Open button in search results. 2025-05-01 12:11:03 +04:00
John Preston
01f191289d Update cmake_helpers. 2025-05-01 11:59:54 +04:00
Ilya Fedin
6586791655 Get rid of /DELAYLOAD 2025-05-01 00:59:24 -07:00
John Preston
b4f6774ca8 Update cmake_helpers. 2025-05-01 11:52:57 +04:00
John Preston
75d346fe69 Add support for tg://stars link. 2025-05-01 11:13:22 +04:00
John Preston
27780c7327 Add xml to ip-revealing extensions.
In case you put SVG content in an .xml file it shows it in the browser.
2025-05-01 11:13:22 +04:00
John Preston
100a8882f1 Add support for svg icons in style codegen. 2025-05-01 11:13:22 +04:00
John Preston
983bd1a57b Add some Cursor rules / ignore paths. 2025-05-01 11:13:22 +04:00
John Preston
810f7949f4 Fix crash in marking message contents read. 2025-05-01 11:13:22 +04:00
23rd
28c502bd85 Fixed display of plural phrase in moderate box. 2025-05-01 11:13:22 +04:00
23rd
b8c313965f Fixed display of negative views count in message preview from stats. 2025-05-01 11:13:22 +04:00
23rd
8a2dcbbcff Removed 'new' badge from entry for messages effect in premium summary. 2025-05-01 11:13:22 +04:00
John Preston
263b9fa611 Add avrt.dll to the list of delayload libs. 2025-05-01 11:13:22 +04:00
23rd
793e15f80c Added entry point to settings section for login email change. 2025-05-01 11:13:22 +04:00
23rd
23d1394fb2 Added settings section for input of code confirm for login email. 2025-05-01 11:13:22 +04:00
23rd
f97bb23c9d Added settings section for input of new login email replacement. 2025-05-01 11:13:22 +04:00
23rd
d557739a28 Added api support to change login email. 2025-05-01 11:13:22 +04:00
23rd
8d06243b57 Added login email pattern to cloud password data. 2025-05-01 11:13:22 +04:00
23rd
9a4b73b942 Added ability to provide marked text to right label of settings button. 2025-05-01 11:13:21 +04:00
23rd
d73e0dd13c Added phrases for login email settings. 2025-05-01 11:13:21 +04:00
23rd
2f3818fe4b Added assertion on looking up for controller from top bar suggestion. 2025-05-01 11:13:21 +04:00
John Preston
d3d773079c Closed alpha version 5.13.1.5. 2025-05-01 11:13:21 +04:00
23rd
0b2acec50c Ensured to clear all top bar suggestion states on each check. 2025-05-01 11:13:21 +04:00
23rd
3501e4f44d Slightly improved check of today birthdays suggestion. 2025-05-01 11:13:21 +04:00
23rd
384c540197 Added special status to peers in gifts list with tomorrow birthday. 2025-05-01 11:13:21 +04:00
John Preston
1b78ffc018 Fix crash in joining video chats. 2025-05-01 11:13:21 +04:00
John Preston
79f4f0adbf Closed alpha version 5.13.1.4. 2025-05-01 11:13:21 +04:00
John Preston
98d71308a8 Update tgcalls, don't link libtgvoip any more. 2025-05-01 11:13:21 +04:00
23rd
4f0fa66575 Added ability to open profile of user by click on userpic in gift box. 2025-05-01 11:13:21 +04:00
23rd
ecac3a0f16 Added context menu to list in ChooseStarGiftRecipient. 2025-05-01 11:13:21 +04:00
23rd
d1898b9a0b Excluded non-today birthdays from reminder in top bar from dialogs. 2025-05-01 11:13:21 +04:00
23rd
868c7b170e Set premium grace suggestion as top priority. 2025-05-01 11:13:21 +04:00
23rd
b1c5c53687 Fixed display of chat filters strip while search in peer. 2025-05-01 11:13:21 +04:00
23rd
6704886c6e Fixed display of top bar suggestion while search in peer. 2025-05-01 11:13:21 +04:00
23rd
7e45283ba2 Added privacy link to birthday box from top bar suggestion. 2025-05-01 11:13:21 +04:00
John Preston
ff67d876b2 Respect "call_requests_disabled" for confcalls. 2025-05-01 11:13:21 +04:00
John Preston
4975a0a8d8 Update tgcalls. 2025-05-01 11:13:21 +04:00
John Preston
e34a4338a1 Closed alpha version 5.13.1.3. 2025-05-01 11:13:21 +04:00
John Preston
0b4986b47a Fix build on Windows. 2025-05-01 11:13:21 +04:00
John Preston
937eab5f27 Update tde2e/tgcalls. 2025-05-01 11:13:20 +04:00
John Preston
70378bfac8 Improve emoji animation. 2025-05-01 11:13:20 +04:00
John Preston
29d87f692a Add carousel animation for emoji fingerprint. 2025-05-01 11:13:20 +04:00
John Preston
b1b2798be1 Update tde2e library. 2025-05-01 11:13:20 +04:00
John Preston
2b74ad8b5f Disable raised-hand state in confcalls. 2025-05-01 11:13:20 +04:00
John Preston
3098fa6855 Rejoin async on e2e error. 2025-05-01 11:13:20 +04:00
John Preston
53883a7f1f Improve confcall re-create keyboard navigation. 2025-05-01 11:13:20 +04:00
John Preston
2c048376d4 Add TDLib build phases for tde2e part. 2025-05-01 11:13:20 +04:00
John Preston
b583240d58 Put prioritized users on top of inactive confcall. 2025-05-01 11:13:20 +04:00
John Preston
844be11d43 Closed alpha version 5.13.1.2. 2025-05-01 11:13:20 +04:00
John Preston
53b739139b Suggest invite to empty/discarded joining call. 2025-05-01 11:13:20 +04:00
John Preston
d09d1d72e6 Improve "Open" bot button in suggestions. 2025-05-01 11:13:20 +04:00
John Preston
01d927aceb Improve confcall join. 2025-05-01 11:13:20 +04:00
John Preston
59abfcbd6d Support "Device Storage" web app feature. 2025-05-01 11:13:20 +04:00
John Preston
4c2ec15f70 Fix "Add People" button visibility update. 2025-05-01 11:13:20 +04:00
John Preston
2b6dfbf4eb Closed alpha version 5.13.1.1. 2025-05-01 11:13:18 +04:00
John Preston
eb8372eb91 Poll sub_chain_id:1 blocks after call_create. 2025-05-01 11:13:18 +04:00
John Preston
c6b2967da0 Implement "Create New Call" interface. 2025-05-01 11:13:18 +04:00
John Preston
042f51e58f Optimize confcall join process. 2025-05-01 11:13:18 +04:00
John Preston
c72cf46db7 Implement fast confcall migration. 2025-05-01 11:13:18 +04:00
John Preston
2a7aac76d9 Update API scheme on layer 202. 2025-05-01 11:13:18 +04:00
John Preston
a569495f5d Fix discarding group call invites. 2025-05-01 11:13:18 +04:00
John Preston
59e56600bc Reuse p2p call window for migrated confcall. 2025-05-01 11:13:18 +04:00
John Preston
915dec7ba5 Show right call top bar after migration. 2025-05-01 11:13:18 +04:00
John Preston
909bd3dd2d Allow kicking from confcall by creator. 2025-05-01 11:13:18 +04:00
John Preston
d50fad615f Check confcall size limit. 2025-05-01 11:13:18 +04:00
John Preston
b036bedbc3 Support distinct calling/invited states. 2025-05-01 11:13:18 +04:00
John Preston
55c05d1a6e Allow discard invite or cancel ringing. 2025-05-01 11:13:17 +04:00
John Preston
344c0f6427 Check phone access on join. 2025-05-01 11:13:17 +04:00
John Preston
8ab1a7268b Handle all types of confcall invite responses. 2025-05-01 11:13:17 +04:00
John Preston
e5f31dbe8e Remove unnecessary stale participant check. 2025-05-01 11:13:17 +04:00
John Preston
783c5c12e9 Improve couple of phrases. 2025-05-01 11:13:17 +04:00
John Preston
c972485555 Allow revoking confcall link. 2025-05-01 11:13:17 +04:00
John Preston
c507382d19 Keep window geometry on confcall migration. 2025-05-01 11:13:17 +04:00
John Preston
fbbcbc8753 Respect conference_supported flag. 2025-05-01 11:13:17 +04:00
John Preston
a5fa595627 Update API scheme on layer 202. 2025-05-01 11:13:17 +04:00
John Preston
502045f1fa Improve mute/video migration to confcall. 2025-05-01 11:13:17 +04:00
John Preston
e9280777fd Fix confcall video encryption. 2025-05-01 11:13:17 +04:00
John Preston
c36f402b88 Fix bug in OpenAL patches on Windows. 2025-05-01 11:13:17 +04:00
John Preston
3a68dd50ce Fix applying some Data::GroupCall updates. 2025-05-01 11:13:17 +04:00
John Preston
eb06c0da08 Try migrating mute/video state. 2025-05-01 11:13:17 +04:00
John Preston
6528567746 Log applying blocks and fix sub_chain_id:1. 2025-05-01 11:13:17 +04:00
John Preston
09229812f4 Show nice confcall invites. 2025-05-01 11:13:17 +04:00
John Preston
aaa37a3e0d Update API scheme on layer 202. 2025-05-01 11:13:17 +04:00
John Preston
c5531b1bd8 Implement audio/video confcall invitations. 2025-05-01 11:13:17 +04:00
John Preston
021115b463 Nice join confcall confirm box. 2025-05-01 11:13:17 +04:00
John Preston
698d9c208f Improve confcall invite management. 2025-05-01 11:13:17 +04:00
John Preston
01a6b432f3 Improve some confcall graphics. 2025-05-01 11:13:16 +04:00
John Preston
a5f44b3ed6 Fix incorrect naming userpic as public photo. 2025-05-01 11:13:16 +04:00
John Preston
a3ba99c682 Implement incoming confcall window. 2025-05-01 11:13:16 +04:00
John Preston
7c709fddba Allow editing confcall messages. 2025-05-01 11:13:16 +04:00
John Preston
8f313b4603 Update API scheme on layer 202. 2025-05-01 11:13:16 +04:00
John Preston
41c0a5ee3b Add "Join Call" button to confcall link previews. 2025-05-01 11:13:16 +04:00
John Preston
346f7aadd6 Render confcall messages as phone calls. 2025-05-01 11:13:16 +04:00
John Preston
be611c1920 Show confcall users that are only on blockchain. 2025-05-01 11:13:16 +04:00
John Preston
e33a866a63 Give some admin rights to confcall creator. 2025-05-01 11:13:16 +04:00
John Preston
c846eeed9d Fix cal buttons positioning. 2025-05-01 11:13:16 +04:00
John Preston
d052eac019 Initial call->confcall migration. 2025-05-01 11:13:16 +04:00
John Preston
9dbd134601 Implement multi-inviting to confcalls. 2025-05-01 11:13:16 +04:00
John Preston
6451e1cfe2 Remove debug logging in swipes. 2025-05-01 11:13:16 +04:00
John Preston
9f3f715527 Allow sharing link from confcall. 2025-05-01 11:13:16 +04:00
John Preston
0d8e5b139b Add some special phrases. 2025-05-01 11:13:16 +04:00
John Preston
5d5dda548a Implement nice call link box. 2025-05-01 11:13:16 +04:00
John Preston
1d32e5267c Fix incorrect waiting blocks applying. 2025-05-01 11:13:16 +04:00
John Preston
a300a25419 Fix complicated crash in async base::Timer destroying. 2025-05-01 11:13:16 +04:00
John Preston
4eaf03b922 Update API scheme on layer 202. 2025-05-01 11:13:15 +04:00
John Preston
4401ea388c PoC confcall invite, emoji. 2025-05-01 11:13:15 +04:00
John Preston
dfe6ad3a32 Update gift icon for input field. 2025-05-01 11:13:15 +04:00
John Preston
e3ef870b29 Remove stale confcall users from blockchain. 2025-05-01 11:13:15 +04:00
John Preston
7deb5bfdf2 Update API scheme, something works now. 2025-05-01 11:13:15 +04:00
John Preston
0e46a4402a Update API scheme on layer 202. 2025-05-01 11:13:15 +04:00
John Preston
33a15e69bb Move blocks order checking to tde2e_api module. 2025-05-01 11:13:15 +04:00
John Preston
ebe11fdb1e Pass encrypt/decrypt callback to tgcalls. 2025-05-01 11:13:15 +04:00
John Preston
f9a7c46868 Update tgcalls. 2025-05-01 11:13:15 +04:00
John Preston
c80c23e8e8 PoC conference call creation. 2025-05-01 11:13:15 +04:00
John Preston
5e6c81a98e Parse e2e participant keys. 2025-05-01 11:13:15 +04:00
John Preston
214cc83d4a Update API scheme to layer 202. 2025-05-01 11:13:15 +04:00
John Preston
8e643fbf87 Add tde2e dependency. 2025-05-01 11:13:11 +04:00
23rd
6008d9e12b Added birthday sublist to contact list in gift box. 2025-05-01 11:13:01 +04:00
23rd
81da453ec4 Added suggestion to top-up low credits balance for subscriptions. 2025-05-01 11:13:01 +04:00
23rd
f34835463d Added initial ability to create credit icon as non-session custom emoji. 2025-05-01 11:13:01 +04:00
23rd
eb3419f3fc Added ability to request credits subscriptions with missing balance. 2025-05-01 11:13:01 +04:00
23rd
5886a07300 Fixed ability to renew credits subscription. 2025-05-01 11:13:01 +04:00
23rd
69e7c27fd0 Added premium grace suggestion to top bar in dialogs. 2025-05-01 11:13:01 +04:00
23rd
165cf6809f Added experimental option to display date when you joined to channel. 2025-05-01 11:13:01 +04:00
23rd
9b2b8b6796 Fixed display of top bar suggestion while display filtered dialogs. 2025-05-01 11:13:01 +04:00
23rd
3ed6d1dec1 Added strike out cost without discount in premium options in settings. 2025-05-01 11:13:00 +04:00
23rd
9ad1d1c25d Fixed some unused-but-set-variable warnings. 2025-05-01 11:13:00 +04:00
23rd
667e614bf3 Simplified proper cleanup of allocated event filters for swipe handler. 2025-05-01 11:13:00 +04:00
23rd
d49da1fdd0 Added missed label for current balance in section of bot credits earn. 2025-05-01 11:13:00 +04:00
23rd
85b0733169 Improved guard of right edge iterator in linear chart view for stats. 2025-05-01 11:13:00 +04:00
23rd
7f2bba7c4a Fixed ttl phrase for 1 year. 2025-05-01 11:13:00 +04:00
23rd
664ec62396 Slightly improved style of text in top bar suggestion. 2025-05-01 11:13:00 +04:00
23rd
b4a9e45214 Improved display of top bar suggestion in non-main chats lists. 2025-05-01 11:13:00 +04:00
23rd
2eab7044ba Added ability to emplace top bar suggestion later. 2025-05-01 11:13:00 +04:00
23rd
8d449f91c6 Fixed phrases in list of active group calls from Calls box. 2025-05-01 11:13:00 +04:00
23rd
be8a836528 Fixed clearing of inactive quick dialog actions. 2025-05-01 11:13:00 +04:00
23rd
423782fd2b Improved birthday reminder of multiple contacts in top bar from dialogs. 2025-05-01 11:13:00 +04:00
23rd
dc1dc8dffa Added today birthdays to data session. 2025-05-01 11:13:00 +04:00
23rd
16a77e2975 Removed redundant buttons from profile of bot verification. 2025-05-01 11:13:00 +04:00
23rd
df69a70dd7 Removed ability to set wallpaper to chat with bot verification. 2025-05-01 11:13:00 +04:00
23rd
0638c86211 Removed ability to set TTL to chat with bot verification. 2025-05-01 11:13:00 +04:00
23rd
8c0de22c14 Added birthday reminder of multiple contacts to top bar in dialogs. 2025-05-01 11:13:00 +04:00
23rd
f83568c6c9 Added birthday reminder of single contact to top bar in dialogs. 2025-05-01 11:13:00 +04:00
23rd
10d472728c Added userpic suggestion to top bar in dialogs. 2025-05-01 11:13:00 +04:00
23rd
2c3cb3f5ce Added suggestion for restore premium to top bar in dialogs. 2025-05-01 11:12:59 +04:00
23rd
fbfe3fd5ed Added suggestion for upgrade to premium to top bar in dialogs. 2025-05-01 11:12:59 +04:00
23rd
b280a26317 Replaced management of top bar for suggestion in dialogs with rpl. 2025-05-01 11:12:59 +04:00
23rd
640db8af7d Added suggestion for annual premium to top bar in dialogs. 2025-05-01 11:12:59 +04:00
23rd
98d9357208 Added auto clean of top bar in dialogs on empty. 2025-05-01 11:12:59 +04:00
23rd
f3b6c7c09b Added birthday suggestion to top bar in dialogs. 2025-05-01 11:12:59 +04:00
23rd
3a622f111a Added initial dummy draft for top bar suggestions in dialogs. 2025-05-01 11:12:59 +04:00
23rd
e0b1ed87e8 Fixed ability to trigger quick dialog action with non-middle button. 2025-05-01 11:12:59 +04:00
23rd
63578affa4 Added toasts to quick dialog actions. 2025-05-01 11:12:59 +04:00
23rd
74b188fa46 Fixed ability to click on bot app button in narrowed chat list. 2025-05-01 11:12:59 +04:00
Ilya Fedin
fadaf852b7 Update lib_lottie 2025-04-30 23:43:46 -07:00
Ilya Fedin
ac6124951a Use C++/WinRT from SDK 2025-04-30 23:43:46 -07:00
Ilya Fedin
89e42af149 Update cmake_helpers 2025-04-30 23:42:10 -07:00
Ilya Fedin
cf5987b2b4 Update protobuf in Docker 2025-04-30 23:42:10 -07:00
Ilya Fedin
069d8d376c Unify libtgvoip options handling 2025-04-30 23:42:10 -07:00
Ilya Fedin
fe3d8ea2be Don't check non-MSVC options with MSVC for tgcalls 2025-04-30 23:42:10 -07:00
Ilya Fedin
3ac03b43e1 Add missing dependency on win_directx_helper 2025-04-30 23:42:10 -07:00
Ilya Fedin
eaf1a532f4 Remove workaround to find the right OpenAL in macOS packaged action 2025-04-30 23:42:10 -07:00
Ilya Fedin
f2b0116c1e Don't require PkgConfig for libtgvoip 2025-04-30 23:42:10 -07:00
Ilya Fedin
155b5fa831 Don't link openh264 to td_ui
It's not used directly
2025-04-30 23:42:10 -07:00
Ilya Fedin
130c77a305 Update disptach to 6.1 2025-04-30 23:32:45 -07:00
GitHub Action
2e168d152f Update User-Agent for DNS to Chrome 135.0.0.0. 2025-04-30 23:02:17 -07:00
AlexeyZavar
e0890541ea fix: update submodule 2025-04-25 02:29:17 +03:00
AlexeyZavar
1447b62999 Merge tag 'v5.13.1' into dev 2025-04-25 02:29:09 +03:00
AlexeyZavar
518ae8044d chore: update strings & move option 2025-04-25 01:18:24 +03:00
Grigory
314a90995a
feat: add option to show only added emojis & stickers 2025-04-25 00:54:29 +03:00
komaru.yml
8f29e32577
fix: grammar in ayu_SettingsWatermark 2025-04-25 00:53:30 +03:00
AlexeyZavar
b6e25a353d feat: speed-up ayudata queries 2025-04-25 00:42:53 +03:00
Yagiz Nizipli
635ed02198 update ada-url to v3.2.2 2025-04-24 00:06:56 -07:00
dependabot[bot]
cd81a54062 Bump jinja2 from 3.1.5 to 3.1.6 in /Telegram/build/docker/centos_env
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.5...3.1.6)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-version: 3.1.6
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-24 00:06:11 -07:00
GitHub Action
1035d787ab Update User-Agent for DNS to Chrome 134.0.0.0. 2025-04-24 00:05:39 -07:00
Ilya Fedin
29567df407 Re-enable ffmpeg optimizations on Linux
By disabling LTO
2025-04-23 23:59:30 -07:00
Ilya Fedin
79cb4668f1 Fix a crash on Linux without actions notification capability 2025-04-23 23:58:12 -07:00
Ilya Fedin
9bdc19e2fd Format markup-lacking Linux notifications using lng_dialogs_text_with_from 2025-04-11 09:51:19 -07:00
Ilya Fedin
25cd6106f5 Use Ui::ImageExtensions in PhotoVideoFilesFilter
This allows it to have all supported image extensions just like ImagesFilter
2025-04-11 09:51:08 -07:00
Ilya Fedin
13fbe59164 Free more space in Docker action 2025-04-05 06:56:47 +05:00
Ilya Fedin
c261c3367a Fix a PiP crash with Qt 6.9 2025-04-05 06:55:06 +05:00
Ilya Fedin
8b92ab25c7 Update Qt 6.8.2 -> 6.9.0 2025-04-04 15:53:51 +05:00
Ilya Fedin
0aa1031270 Use global c(xx)flags for breakpad in Docker, just not LTO 2025-04-04 15:18:55 +05:00
Ilya Fedin
dec8bdb39d Update breakpad in Docker to v2024.02.16 2025-04-04 15:18:55 +05:00
Ilya Fedin
f318aeb67c Don't base Docker libjxl stage on patches
There's nothing the stage uses in it
2025-04-04 13:13:31 +05:00
nyakze
8b791e77d6 Update mime_type.cpp
add m3u to ip revealing types
2025-04-01 18:22:09 +05:00
Ilya Fedin
260b72fec1 Check location picker support early 2025-03-31 00:17:18 +05:00
Ilya Fedin
7d0beafce0 Ensure currentImageBack isn't null 2025-03-28 23:07:55 +05:00
Ilya Fedin
3c2f8b65ce Let QIcon::fromTheme check whether the tray icon is valid
QIcon::fromTheme overload with a fallback does a smarter check whether the icon is valid, use it to prevent getting a half-valid QIcon.
2025-03-27 21:58:36 +05:00
John Preston
5f73e8b3bf Version 5.13.1.
- Fix crash in group/channel stories.
2025-03-26 23:25:46 +05:00
John Preston
74afeeb85f Fix crash in group/channel stories. 2025-03-26 23:22:14 +05:00
John Preston
f8920e5fef Version 5.13.
- Allow transferring my unique gifts from Send Gift section.
- Edit type of gifts you accept in Settings > Privacy and Security.
- Swipe navigation using swipe gesture on touchpads / touchscreens.
- Choose chat list quick action for swipe or middle click.
2025-03-26 13:23:36 +05:00
John Preston
dd76313084 Fix shell prepare running on macOS. 2025-03-26 13:23:36 +05:00
John Preston
627ff6f26e Fix build with GCC. 2025-03-26 11:51:26 +04:00
John Preston
705db0b9cf Fix build with Xcode. 2025-03-26 12:27:55 +05:00
John Preston
47a958d81d Update lib_ui. 2025-03-26 07:13:52 +04:00
John Preston
906fc9cc1d Show more frozen errors. 2025-03-26 07:13:16 +04:00
John Preston
44d9525476 Update send gift icon visibility. 2025-03-26 07:13:16 +04:00
John Preston
8b2a549fab Fix crash in gifts repaint. 2025-03-26 07:13:15 +04:00
John Preston
7312e34f46 Update icons for gifts privacy. 2025-03-26 07:13:15 +04:00
John Preston
696be858f6 Load my gifts while scrolling in Send Gift. 2025-03-26 07:13:15 +04:00
John Preston
e1f4fd0c7b Remove blue border from gifts. 2025-03-26 07:13:15 +04:00
John Preston
f51320d1bc Add some more frozen restrictions. 2025-03-26 07:13:15 +04:00
John Preston
a0764190f2 Support sponsored peers in search results. 2025-03-26 07:13:15 +04:00
John Preston
33c5b35444 Send sponsored peers click requests. 2025-03-26 07:13:15 +04:00
John Preston
04e10f81b5 Send sponsored peers view requests. 2025-03-26 07:13:15 +04:00
John Preston
7f2545a9ef Request sponsored peers in global search. 2025-03-26 07:13:15 +04:00
John Preston
a2a16f3f23 Implement new business bots permissions. 2025-03-26 07:13:15 +04:00
John Preston
ab2a947992 Move "Show Gift Button" block up. 2025-03-26 07:13:15 +04:00
John Preston
7d0a73a6b0 Show gift button in the message field. 2025-03-26 07:13:15 +04:00
John Preston
e3c3a68566 Update API scheme on layer 201. 2025-03-26 07:13:15 +04:00
John Preston
4fc026b13c Allow transferring unique gifts from Send Gift. 2025-03-26 07:13:15 +04:00
John Preston
c0fed4d2c3 Filter out allowed gift types. 2025-03-26 07:13:15 +04:00
John Preston
b656e14453 Edit additional privacy options for gifts. 2025-03-26 07:13:11 +04:00
John Preston
fbab3964e6 Handle some frozen cases. 2025-03-26 07:11:20 +04:00
John Preston
d9b270b477 Initial frozen accounts support. 2025-03-26 07:11:20 +04:00
John Preston
7f53a19647 Update API scheme to layer 201. 2025-03-26 07:11:20 +04:00
23rd
9f1e90d007 Updated Qt to 6.2.12 on macOS. 2025-03-25 17:55:54 +03:00
23rd
9a439e1941 Added ability to switch tabs in dialogs suggestions with swipe. 2025-03-24 22:58:04 +03:00
23rd
4e4c69993c Ensured proper cleanup of allocated event filters for swipe handler. 2025-03-24 22:58:04 +03:00
23rd
0d085d500f Added ability to provide custom swipe handler to Info::ContentWidget. 2025-03-24 22:58:04 +03:00
23rd
f734c0475b Replaced SetupSwipeHandler signature from arguments to struct. 2025-03-24 22:58:04 +03:00
23rd
a30951dc91 Fixed swipe handler for small chat lists. 2025-03-24 22:58:04 +03:00
23rd
c4b37950a9 Added filename as fallback for audio files while export chat history.
Fixed #28920.
2025-03-24 22:58:04 +03:00
23rd
7cf832a2f4 Replaced div tags with span for reactions in export chat history. 2025-03-24 22:58:04 +03:00
23rd
1f07e7978d Improved background buttons in box for share QR box on different scales. 2025-03-24 22:58:04 +03:00
23rd
5adab2739b Fixed icon scale in call panel when recipient has low level of battery. 2025-03-24 22:58:04 +03:00
23rd
2be76760de Slightly improved style of settings for quick dialog action. 2025-03-24 22:58:04 +03:00
23rd
28c125a3ec Added some special cases when quick dialog action can't be performed. 2025-03-21 17:59:26 +03:00
23rd
bdf8a37a8f Guarded repaint of special quick dialog actions that lead to de-listing. 2025-03-21 17:59:21 +03:00
23rd
838711e2ac Added maximum of lifetime to every deactivated quick dialog action. 2025-03-21 17:26:50 +03:00
23rd
c085691c54 Moved out active quick action from total list of quick dialog actions. 2025-03-21 16:47:55 +03:00
23rd
47506d70ed Simplified signature of ResolveQuickDialogLottieIconName. 2025-03-21 16:47:46 +03:00
23rd
efc7cc4980 Added convenient bool operator to SwipeContextData. 2025-03-21 16:44:50 +03:00
John Preston
f2016a8aa5 Don't ensure cursor visibility on modifier keys.
Fix #29108.
2025-03-21 09:35:00 +04:00
Yagiz Nizipli
d6bbc375c4 Update prepare.py 2025-03-21 09:26:42 +04:00
Yagiz Nizipli
885996c5cf update ada-url to v3.2.1 2025-03-21 09:26:42 +04:00
John Preston
4e4604e00a Beta version 5.12.6.
- Allow customizing chats list swipe left action.
- Fix custom emoji in poll results view.
- Fix crash in main menu swipe closing.
2025-03-20 18:37:30 +04:00
John Preston
b057d4fcb7 Allow folder switching by swipes in vertical mode. 2025-03-20 18:23:17 +04:00
John Preston
cdf27296e4 Fix deselecting dialog rows between them. 2025-03-20 18:04:14 +04:00
23rd
889f111300 Slightly improved saving of quick dialog action in settings. 2025-03-20 16:59:33 +03:00
23rd
520b4f92ab Improved phrases for quick dialog actions in settings. 2025-03-20 16:59:33 +03:00
23rd
feb1d4ebcc Fixed dialog dragging with pressed quick dialog action. 2025-03-20 16:59:33 +03:00
23rd
c11a7589e2 Added initial ability to trigger quick dialog action with middle click. 2025-03-20 16:59:33 +03:00
23rd
c332b7cb40 Added initial handler for middle mouse click on dialogs. 2025-03-20 16:59:33 +03:00
23rd
418dcedc4e Replaced single QuickActionContext in dialogs widget with flat map. 2025-03-20 16:59:33 +03:00
23rd
a21eb9d59e Moved out quick actions enum for dialog to separated module. 2025-03-20 16:59:33 +03:00
23rd
25ed8fe044 Renamed swipe dialog action to quick dialog action. 2025-03-20 16:59:33 +03:00
23rd
b079c79390 Added correspond colors for every swipe dialog action. 2025-03-20 16:59:33 +03:00
23rd
d7a89ef122 Added implementation for all swipe dialog actions. 2025-03-20 16:59:33 +03:00
23rd
b95035e7a2 Added initial ability to change swipe dialog action from chat settings. 2025-03-20 16:59:33 +03:00
23rd
e28d29f276 Added initial implementation of swipe action to dialogs. 2025-03-20 16:59:33 +03:00
23rd
c29d78ac0d Added ability to provide reach ratio speed to swipe. 2025-03-20 16:59:33 +03:00
23rd
ad9106b815 Added ability to request reach out ratio of swipe. 2025-03-20 16:59:33 +03:00
John Preston
f3ea24f9f9 Update lib_ui. 2025-03-20 17:47:21 +04:00
John Preston
96fdece478 Fix mini-thumbs in channel last message preview. 2025-03-20 17:46:27 +04:00
John Preston
c30a5782df Revert "Fixed blinking of message preview from user's personal channel."
This reverts commit 75e454f3fd.
2025-03-20 17:46:27 +04:00
John Preston
c924fcb91f Fix custom emoji in poll results view. 2025-03-20 17:46:27 +04:00
John Preston
46e7b6d6df Implement "Choose gift to unpin" box feature. 2025-03-20 17:46:27 +04:00
John Preston
bb8ecf2f84 Fix spoiler hiding of ellipse image preview. 2025-03-20 17:46:27 +04:00
John Preston
7123a6d647 Hide image preview of ttl rounds behind spoiler. 2025-03-20 17:46:27 +04:00
John Preston
eb4ef8b3d7 Replace Reply with Forward for specific bots. 2025-03-20 17:46:26 +04:00
23rd
0d346610a2 Fixed sort of received star gifts. 2025-03-20 10:36:41 +03:00
John Preston
fe0c1acd79 Fix crash in main menu swipes on macOS. 2025-03-17 10:45:23 +04:00
AlexeyZavar
b3552d8c2c fix: set deleted mark for service message 2025-03-15 00:10:52 +03:00
AlexeyZavar
206a15191f fix: repeated deleted text 2025-03-15 00:01:53 +03:00
Alexey
22de3980d1
chore: update bug report template 2025-03-14 22:19:10 +03:00
John Preston
af35beefc2 Beta version 5.12.5: Fix build with Qt 6. 2025-03-14 17:23:54 +04:00
John Preston
532258bea8 Beta version 5.12.5.
- Support swipe navigation on touchscreens.
- Close main menu by swipe navigation.
2025-03-14 17:06:42 +04:00
Ilya Fedin
5b257293eb Update patches on Linux 2025-03-14 16:50:58 +04:00
John Preston
8e6d23ddd6 Support tg://settings/phone_privacy links. 2025-03-14 16:40:50 +04:00
John Preston
6d5d61c842 Label 'Add users' for Remove Fee. 2025-03-14 16:40:50 +04:00
John Preston
9d2e2a1739 Fix processing of video qualities.
Regression was introduced in b618d1e56a.
2025-03-14 16:40:49 +04:00
John Preston
19e2642ec1 Improve paid messages in groups layout. 2025-03-14 16:40:49 +04:00
John Preston
f9df522b41 Show error not-found on comment link click. 2025-03-14 16:40:49 +04:00
John Preston
b3e5c4a4aa Fix send button size on chat switch. 2025-03-14 16:40:49 +04:00
John Preston
06ed6c81a7 Remove 'delete also for' in Deleted Accounts. 2025-03-14 16:40:44 +04:00
John Preston
d1e4dbb603 Fix animated emoji in folder name. 2025-03-14 16:40:44 +04:00
John Preston
abe8079296 Allow temp-set of wearable as a status. 2025-03-14 16:40:44 +04:00
John Preston
033cb2790c Remove debug widget in the info section. 2025-03-14 16:03:58 +04:00
John Preston
188edce258 Support swipe-back from main menu. 2025-03-14 15:03:27 +04:00
John Preston
34858b36c1 Fix swipe gestures on touchscreens. 2025-03-14 14:36:13 +04:00
Ilya Fedin
044ef3447c Add the missing 5.12.4 changelog part 2025-03-14 11:14:28 +04:00
Ilya Fedin
2660439160 Fix Platform::ApplicationIconName for snap
Looks like it broke through rebases
2025-03-14 10:22:24 +04:00
AlexeyZavar
9502120ee3 chore: update sqlite_orm 2025-03-13 13:26:43 +03:00
AlexeyZavar
7f1a3320dd chore: update sqlite3 2025-03-13 13:23:40 +03:00
AlexeyZavar
8a4fd7f182 fix: update submodule 2025-03-13 12:57:39 +03:00
AlexeyZavar
b0a4d15d64 Merge tag 'v5.12.3' into dev 2025-03-13 12:57:30 +03:00
John Preston
3f6f96cfb4 Fix typo in lcms2 build commands for Windows. 2025-03-12 21:15:30 +04:00
John Preston
99a1c98ae0 Beta version 5.12.4.
- Touchpad swipe back to go back in navigation history.
- Touchpad swipe between folders if they're horizontal.

Out-of-the-box monochrome tray icon on Linux
with GTK icon recolorization support.

Files telegram{,{,-attention,-mute}-panel} are renamed
to org.telegram.desktop{,{,-attention,-mute}-symbolic} for
unified icon lookup in multiple (sometimes sandboxed) builds
and GTK icon recolorization support.

Snap package got icon theming support,
the icon names are snap.telegram-desktop.{,{,-attention,-mute}-symbolic}
(notice the name ends with a dot in case of no suffix!)
2025-03-12 18:26:46 +04:00
John Preston
fd718dfd5c Allow more Info sections swipe-back. 2025-03-12 18:02:47 +04:00
Ilya Fedin
31cb2f1999 Switch tray to symbolic icons
This allows to rely on GTK recoloring rather than requiring the user to have an icon theme
2025-03-12 14:54:41 +04:00
Ilya Fedin
a6a8e32be7 Install app icon in a spec-compilant way 2025-03-12 14:54:41 +04:00
Ilya Fedin
594bb8a76b Support icon themes in snap 2025-03-12 14:54:41 +04:00
Ilya Fedin
228bbc1e8e Always use app ID based icon name
This allows to unify it between flatpak and non-flatpak builds and corresponds to what most other GUI apps on Linux do
2025-03-12 14:54:41 +04:00
Ilya Fedin
b14c2878b3 Revert "Move icon name getter to cross-platform header"
This reverts commit d9318c9935.
2025-03-12 14:54:41 +04:00
Ilya Fedin
57f10040e1 Get rid of XEmbed mentions
The code goes through Qt abstractions which not necessarily go through XEmbed
2025-03-12 14:53:43 +04:00
Ilya Fedin
0fb67c78a9 Add a method to calculate instance hash to Launcher 2025-03-12 14:53:21 +04:00
John Preston
ff0f7f49da Fix new swipes on Windows. 2025-03-12 14:02:04 +04:00
23rd
9682e37547 Added shortcut to open chat preview from dialogs. 2025-03-12 11:59:20 +04:00
23rd
7197d9480b Added ability to swipe between chats filters. 2025-03-12 11:59:20 +04:00
23rd
3315c9c7f4 Added ability to open main menu with swipe-to-back. 2025-03-12 11:59:20 +04:00
23rd
f57eff4195 Added ability to mirror icon from widget for swipe-to-back. 2025-03-12 11:59:20 +04:00
23rd
f0c8e48403 Added ability to keep ratio of swipe within range. 2025-03-12 11:59:20 +04:00
23rd
de87bed375 Moved out data for swipe handler from history view to ui controls. 2025-03-12 11:59:20 +04:00
23rd
5cdfaab2db Moved out swipe handler from history view to ui controls. 2025-03-12 11:59:20 +04:00
23rd
acb0b029b9 Added ability to switch tab in tabbed selector with swipe. 2025-03-12 11:59:20 +04:00
23rd
4c74cbbbe9 Added ability to set swipe back widget on opposite side. 2025-03-12 11:59:20 +04:00
23rd
ad64e068db Allowed swipe-to-back in side info section. 2025-03-12 11:59:20 +04:00
23rd
6bed3f3f09 Increased speed of swipe-to-back. 2025-03-12 11:59:20 +04:00
23rd
d02e55da06 Added ability to swipe-to-back to all info sections with narrow type. 2025-03-12 11:59:20 +04:00
23rd
d662a8f2b9 Added ability to swipe-to-back to other sections. 2025-03-12 11:59:20 +04:00
23rd
13a93102a5 Added ability to swipe-to-back to admin log section. 2025-03-12 11:59:20 +04:00
23rd
0d6a1e6610 Added ability to swipe-to-back to replies section. 2025-03-12 11:59:20 +04:00
23rd
05cd9eebb8 Added ability to swipe-to-back to dialogs widget. 2025-03-12 11:59:20 +04:00
23rd
d93d8ab1cc Added ability to provide ElasticScroll to SetupSwipeHandler. 2025-03-12 11:59:12 +04:00
23rd
540fa0e669 Added ability to swipe-to-back to history widget. 2025-03-12 04:36:34 +03:00
23rd
17a10cf6bb Added initial ability to handle history view swipe in both directions. 2025-03-12 04:36:24 +03:00
John Preston
11d0f9db03 Try fixing crashes on Linux. 2025-03-10 13:32:36 +04:00
John Preston
f024ceecdd Version 5.12.3.
- Fix a couple more crashes.
- Fix gift disappearing on unpin.
- Fix country emoji for Fragment numbers.
2025-03-10 11:58:20 +04:00
John Preston
08c07a0785 Don't remove last gift on unpin if all loaded. 2025-03-10 11:57:20 +04:00
John Preston
b843f91b3c Support 'FT' "country" flag emoji. 2025-03-10 11:52:42 +04:00
23rd
4b2c5b3321 Removed chat filters strip from folders and forums in separated windows. 2025-03-10 11:20:33 +04:00
23rd
2b43f2682a Fixed open of locked chats filter with shortcuts to open near filters. 2025-03-10 11:20:28 +04:00
23rd
7da0124286 Moved out lambda to jump to near chats filters to static function. 2025-03-10 11:18:43 +04:00
23rd
feaeef6482 Fixed repaint of send button when it has slowmode countdown. 2025-03-10 11:11:10 +04:00
23rd
15bcfeec1d Added pause to animation of custom emoji in status info. 2025-03-10 11:11:10 +04:00
23rd
5fb002ab4c Added ability to specify time when export data. 2025-03-10 11:11:10 +04:00
23rd
f56ddbb1e0 Added recursive animation to lock hint while recording voice. 2025-03-10 11:11:10 +04:00
John Preston
6bd2a7c962 Fix possible crash in MediaGenericTextPart. 2025-03-10 11:00:49 +04:00
John Preston
9d591ae806 Fix infinite recursion in channel reactions edit. 2025-03-10 10:59:39 +04:00
Ilya Fedin
7d30e3913c Add lcms2 dependency for Qt6 on Windows 2025-03-10 10:58:10 +04:00
Kaiyang Wu
19d7dd7aa3 fix(integration_linux): include core_settings.h with Qt version <= 6.5.0
Signed-off-by: Kaiyang Wu <self@origincode.me>
2025-03-09 20:33:20 +04:00
John Preston
45444253fd Version 5.12.2.
- Fix some crashes.
2025-03-09 09:44:47 +04:00
John Preston
308ade6a7e Fix crash in some custom emoji cases. 2025-03-09 06:55:25 +04:00
AlexeyZavar
66d54ccd54 feat: open channel in discussion group 2025-03-09 02:59:45 +03:00
AlexeyZavar
ccf8d91f01 feat: burn ttl message & display expired status 2025-03-09 02:33:22 +03:00
AlexeyZavar
7c940a0480 fix: ttl messages hint 2025-03-09 01:28:07 +03:00
AlexeyZavar
277a2edb57 fix: read stories crashes 2025-03-09 00:53:32 +03:00
AlexeyZavar
bd742689e9 fix: weird crash 2025-03-09 00:40:42 +03:00
AlexeyZavar
9ca0c3c41d fix: more checks for disposal 2025-03-09 00:30:18 +03:00
AlexeyZavar
ce8650b4de fix: create a copy of selected TTL messages 2025-03-08 23:58:27 +03:00
AlexeyZavar
4bce9d440e fix: make it build 2025-03-08 23:37:48 +03:00
AlexeyZavar
adc691f516 Merge tag 'v5.12.1' into dev 2025-03-08 23:02:34 +03:00
John Preston
fc67a801e3 Version 5.12.1: Fix build with Xcode. 2025-03-08 07:09:15 +04:00
John Preston
6a3657ca87 Version 5.12.1.
- Fix a crash in some chat switchings.
- Fix crashes in empty repaint callbacks.
2025-03-08 07:06:37 +04:00
John Preston
0537c5f273 Fix crashes in empty repaint callbacks. 2025-03-08 07:05:45 +04:00
John Preston
cc4a5f30b6 Fix a crash in some chat switchings. 2025-03-07 23:56:17 +04:00
John Preston
b0d7c3e9b1 Revert "Re-enable ffmpeg optimizations on Linux"
This reverts commit bd28ac6e1f.

It fails to link in Release mode with LTO.
2025-03-07 22:20:18 +04:00
John Preston
3bf7c44fc9 Version 5.12.
- Set a fee for incoming messages from unknown users.
- Set a fee for messages in groups or channel comments.
- Show some information about who's messaging you.
- Pin gifts on your profile.
2025-03-07 20:50:29 +04:00
John Preston
4ff4e63a11 Fix sending paid intro sticker. 2025-03-07 19:03:41 +04:00
John Preston
72a35ba58b Show new-peer-info photo/name change. 2025-03-07 19:03:41 +04:00
John Preston
b6a31979f2 Add the same enter/leave check to ListWidget. 2025-03-07 19:03:40 +04:00
John Preston
7c710e22cc Always process mouse input in active window.
Fixes #29008.
2025-03-07 19:03:40 +04:00
John Preston
ab58e7a225 Show common groups userpics in new-peer-info. 2025-03-07 19:03:40 +04:00
John Preston
c9fb97cd7c Simplify marked text context logic. 2025-03-07 19:03:40 +04:00
John Preston
789f3e1584 Add non-official account info icon. 2025-03-07 19:03:39 +04:00
John Preston
0fc8229be1 Initial new peer information display. 2025-03-07 19:03:39 +04:00
John Preston
a1e555267e Fix sending invite links to paid. 2025-03-07 19:03:39 +04:00
John Preston
0ac88c0cb5 Show special blank chat for paid messages. 2025-03-07 19:03:39 +04:00
John Preston
d43a6da62b Fix sending bot commands in paid chats. 2025-03-07 19:03:39 +04:00
John Preston
940455f786 Preload gifts for the gift to user layer. 2025-03-07 19:03:39 +04:00
John Preston
0f74456f30 Support gifts pinning. 2025-03-07 19:03:39 +04:00
John Preston
7840fa6d90 Add context menu for gifts in list. 2025-03-07 19:03:39 +04:00
John Preston
95ccc99fee Hide reply in notification for paid peers. 2025-03-07 19:03:39 +04:00
23rd
7b0a156bba Added lottie icon when have no enough info for earn stats. 2025-03-07 19:03:39 +04:00
23rd
0d8ae7bb37 Renamed creditsAmount in invoice for premium gift with represented name. 2025-03-07 19:03:39 +04:00
23rd
9491cff1df Fixed display credits in list of gift options. 2025-03-07 19:03:39 +04:00
23rd
51dc5d6e37 Fixed discount calculation for gifts options with different currencies. 2025-03-07 19:03:39 +04:00
John Preston
f4c739ab92 Improve transactions history for new stuff. 2025-03-07 19:03:39 +04:00
John Preston
0dd8ae3d77 Update submodules. 2025-03-07 19:03:39 +04:00
John Preston
7d2878d81c Support gifting premium for stars. 2025-03-07 19:03:39 +04:00
23rd
bd70a05861 Removed button to turn off sponsored messages in megagroups. 2025-03-07 19:03:39 +04:00
23rd
0605c7b2bc Added ability to display possible currency earn in megagroups in future. 2025-03-07 19:03:39 +04:00
23rd
8e83a55143 Added ability to request earn stats without currency earn in megagroups. 2025-03-07 19:03:39 +04:00
John Preston
4ab4eb8ef2 Pause voice in pay-to-send chats. 2025-03-07 19:03:39 +04:00
John Preston
d1e6150874 Don't suggest userpics to paid-restricted. 2025-03-07 19:03:38 +04:00
John Preston
4121c99f36 Allow folders submenu to have a scroll. 2025-03-07 19:03:38 +04:00
John Preston
827040f487 Use paid messages values from appConfig. 2025-03-07 19:03:38 +04:00
John Preston
9032489786 Add pays-me status bar in chat. 2025-03-07 19:03:38 +04:00
John Preston
8ea7bd4913 Simplify paid message button labeling. 2025-03-07 19:03:38 +04:00
John Preston
97b021efaf Star-count button in multi-Forward/CreatePoll. 2025-03-07 19:03:38 +04:00
John Preston
b3f9a77ba7 Star-count button in SendFilesBox/ShareBox. 2025-03-07 19:03:38 +04:00
John Preston
63fdc1f876 Update API scheme on layer 200. 2025-03-07 19:03:38 +04:00
John Preston
17cf354c58 Support custom send button for paid. 2025-03-07 19:03:38 +04:00
John Preston
c6fd8bcb99 Edit paid messages exceptions. 2025-03-07 19:03:38 +04:00
John Preston
1684465e04 Add sending paid stories replies. 2025-03-07 19:03:38 +04:00
John Preston
fe2df96953 Improve paid peer-box multi-send. 2025-03-07 19:03:38 +04:00
John Preston
ee9d0cfd99 Update API scheme, disable scheduled paid. 2025-03-07 19:03:38 +04:00
John Preston
7b7e18e752 Support paid sending in ShareBox. 2025-03-07 19:03:38 +04:00
John Preston
928be4151b Update API scheme, parse premium gifts for stars. 2025-03-07 19:03:38 +04:00
John Preston
37dd648686 Implement paid location sending. 2025-03-07 19:03:38 +04:00
John Preston
93a590774e Send paid stickers/gifs/inline-results. 2025-03-07 19:03:38 +04:00
John Preston
22b99b6d3e Send paid shared contacts. 2025-03-07 19:03:37 +04:00
John Preston
101d626d4f Support paid files-with-comment and polls. 2025-03-07 19:03:37 +04:00
John Preston
3633c19208 Update API scheme, improve service messages. 2025-03-07 19:03:37 +04:00
John Preston
e302f328f7 Don't cut confirming emoji status. 2025-03-07 19:03:37 +04:00
John Preston
f74ba95e95 Don't track caption in fullscreen video view.
Fixes #28981.
2025-03-07 19:03:37 +04:00
John Preston
c38982d286 Simplify paid stars check. 2025-03-07 19:03:37 +04:00
John Preston
fe9bac096b Refresh balance after paid message sending. 2025-03-07 19:03:37 +04:00
John Preston
5b809c4fc6 Show paid stars information above a message. 2025-03-07 19:03:37 +04:00
John Preston
4729e51e14 Improve phrases for paid messages. 2025-03-07 19:03:37 +04:00
John Preston
960cf7a34b Update API scheme, new paid. 2025-03-07 19:03:37 +04:00
John Preston
852ab19760 Update API scheme, track stars-per-message. 2025-03-07 19:03:37 +04:00
John Preston
2e45d9fc6b Allow replacing default shortcuts. 2025-03-07 19:03:37 +04:00
John Preston
74b71b92b6 Update API scheme on layer 200. 2025-03-07 19:03:37 +04:00
John Preston
bbc14ba74f Allow sending paid messages. 2025-03-07 19:03:37 +04:00
John Preston
45c7829cd8 Track stars-per-message for users and channels. 2025-03-07 19:03:37 +04:00
John Preston
f2aa3afbbb Allow editing charge-for-message privacy. 2025-03-07 19:03:37 +04:00
John Preston
909b01241b Update API scheme to layer 200. 2025-03-07 19:03:36 +04:00
Ilya Fedin
abb58c58a0 QPlatformKeyMapper -> QKeyMapper 2025-03-06 17:54:54 +04:00
Ilya Fedin
700e10d32c Use flat_map::remove in clearFrom{Topic,Item}
Now that notification closing happens in destructor, the iterator is no more needed
2025-03-06 17:30:26 +04:00
Ilya Fedin
4ac48d0e4a Fix clearFromTopic on Linux
Looks like it was broken since addition
2025-03-06 16:41:34 +04:00
Ilya Fedin
345b2cb835 Move notification closing to NotificationData destruction 2025-03-04 14:17:43 +04:00
Ilya Fedin
b962309498 Move hints.lookup_value() out of xdg_notifications_notifications_call_notify
Or it gets executed after hints.end() which clears hints
2025-03-04 12:28:37 +04:00
Eugene
e99cb9bfb8 Ensure policy check before creating Zone.Identifier for downloaded files on Windows 2025-03-04 10:47:31 +04:00
Ilya Fedin
9e12e18f90 Clean up unnecessary calls to Manager::Private::clearNotification
It was added to replicate NotificationData::close but lots of places call it after the notification is already cleared
2025-03-03 18:40:22 +04:00
Ilya Fedin
66fc9b38df Fix a race condition with asynchronous notification sending 2025-03-03 18:40:06 +04:00
Ilya Fedin
5dbe429e6b Fix NotificationData initialization 2025-03-03 18:39:55 +04:00
GitHub Action
b2481ea6c1 Update User-Agent for DNS to Chrome 133.0.0.0. 2025-03-03 18:37:13 +04:00
Ilya Fedin
86a294ce4b Subscribe to XdgNotifications signals on Manager initialization 2025-03-01 09:08:10 +04:00
Ilya Fedin
a8d1eadfbf Turn NotificationData into a struct 2025-02-28 13:20:53 +04:00
Ilya Fedin
b07d3c5403 Decouple GNotification from NotificationData 2025-02-28 12:05:09 +04:00
Ilya Fedin
892db55ae1 Get rid of NotificationData::init 2025-02-28 11:12:08 +04:00
Ilya Fedin
93615fef65 Revert "Check whether notification image has alpha channel"
This reverts commit cee593c423.

Avatars couldn't be opaque anyway while this simplifies porting out of NotificationData
2025-02-28 11:12:08 +04:00
Ilya Fedin
87452706ef Remove unused has_weak_ptr from Manager::Private 2025-02-28 11:12:08 +04:00
Ilya Fedin
3569615b21 Use gi::cstring for notification actions 2025-02-28 11:12:08 +04:00
Ilya Fedin
86f7d09d31 Pass notification icon name inline 2025-02-28 11:12:08 +04:00
Ilya Fedin
d5d1254393 Destroy NotificationData signal connections with rpl::lifetme 2025-02-28 11:12:08 +04:00
davidholio
4df90cfb9e Make sure caption items can only be interacted if not in video fullscreen. 2025-02-25 11:40:05 +04:00
Ilya Fedin
ec6862d31a Communicate PiP window margins to the OS 2025-02-25 10:15:33 +04:00
Ilya Fedin
6f23010382 Fix IconGraphic::counterSlice for Window::WithSmallCounter 2025-02-24 13:25:59 +04:00
Ilya Fedin
c672f105d3 IconGraphic::isCounterNeeded helper for Linux tray 2025-02-24 13:25:59 +04:00
Ilya Fedin
e60d501e4a Have a state struct in Linux tray 2025-02-24 13:25:59 +04:00
jovaska
0d7175058b Fix compilation with ffmpeg-4.x 2025-02-24 13:15:37 +04:00
Ilya Fedin
3b0bd9d1d1 Remove duplicate entry in qt snap part 2025-02-20 17:48:37 +04:00
Ilya Fedin
bd28ac6e1f Re-enable ffmpeg optimizations on Linux
They were disabled due to -Ofast but Dockerfile is switched to -O3 since a long time
2025-02-20 11:34:55 +04:00
Ilya Fedin
0c2d00c792 More clean up in qt snap part 2025-02-20 11:34:47 +04:00
Ilya Fedin
140ba653b9 More clean up in libjxl snap part 2025-02-20 11:34:33 +04:00
Ilya Fedin
f64f008f77 Remove fmt from snap
It's not really needed for a long time
2025-02-20 11:34:24 +04:00
Ilya Fedin
a6315bef05 Move GNotiftcation action handlers to Manager 2025-02-19 14:42:11 +04:00
Ilya Fedin
f810d7c82a Fix spaces on end of lines 2025-02-18 21:26:38 +04:00
Ilya Fedin
cf61dedc79 Simplify GNotification actions 2025-02-18 21:21:37 +04:00
Ilya Fedin
2ab9587f5f Don't wrap QByteArray into std::shared_ptr
This has no sense as QByteArray is CoW
2025-02-18 21:20:53 +04:00
Ilya Fedin
4950b52359 Don't set CMAKE_EXPORT_COMPILE_COMMANDS via cmake.configureSettings
It's controlled by cmake.exportCompileCommandsFile and defaults to true
2025-02-14 20:19:29 +04:00
Nikolai Nechaev
03af444735 Notifications: stop fading in before starting to fade out
When a notification is to start hiding (i.e., fade out), it is supposed
to start fading out from the maximum opacity, even if it was not fully
restored (which only happens if the cursor passed through the
notification too quickly). Thus, call `.stop()` for the previous
animation, if any, before `.start()`ing the next animation.
2025-02-14 20:17:02 +04:00
Nikolai Nechaev
7f6221b409 Manager::startAllHiding: don't treat fading in notifications specially
Previously, `Window::Notifications::Default::Manager` would not start
hiding notifications that are fading in when other notifications should
hide. This would lead to some notifications never hiding, e.g., when the
cursor passes through the notification too quickly and there was not
enough time for the notification to fade in completely.

Also renamed `Widget::isShowing` -> `Widget::isFadingIn` for clarity.

Fixes #28811.
2025-02-14 20:17:02 +04:00
630 changed files with 38043 additions and 14757 deletions

105
.cursor/rules/api_usage.mdc Normal file
View file

@ -0,0 +1,105 @@
---
description: For tasks requiring sending Telegram server API requests or working with generated API types.
globs:
alwaysApply: false
---
# Telegram Desktop API Usage
## API Schema
The API definitions are described using [TL Language]\(https:/core.telegram.org/mtproto/TL) in two main schema files:
1. **`Telegram/SourceFiles/mtproto/scheme/mtproto.tl`**
* Defines the core MTProto protocol types and methods used for basic communication, encryption, authorization, service messages, etc.
* Some fundamental types and methods from this schema (like basic types, RPC calls, containers) are often implemented directly in the C++ MTProto core (`SourceFiles/mtproto/`) and may be skipped during the C++ code generation phase.
* Other parts of `mtproto.tl` might still be processed by the code generator.
2. **`Telegram/SourceFiles/mtproto/scheme/api.tl`**
* Defines the higher-level Telegram API layer, including all the methods and types related to chat functionality, user profiles, messages, channels, stickers, etc.
* This is the primary schema used when making functional API requests within the application.
Both files use the same TL syntax to describe API methods (functions) and types (constructors).
## Code Generation
A custom code generation tool processes `api.tl` (and parts of `mtproto.tl`) to create corresponding C++ classes and types. These generated headers are typically included via the Precompiled Header (PCH) for the main `Telegram` project.
Generated types often follow the pattern `MTP[Type]` (e.g., `MTPUser`, `MTPMessage`) and methods correspond to functions within the `MTP` namespace or related classes (e.g., `MTPmessages_SendMessage`).
## Making API Requests
API requests are made using a standard pattern involving the `api()` object (providing access to the `MTP::Instance`), the generated `MTP...` request object, callback handlers for success (`.done()`) and failure (`.fail()`), and the `.send()` method.
Here's the general structure:
```cpp
// Include necessary headers if not already in PCH
// Obtain the API instance (usually via api() or MTP::Instance::Get())
api().request(MTPnamespace_MethodName(
// Constructor arguments based on the api.tl definition for the method
MTP_flags(flags_value), // Use MTP_flags if the method has flags
MTP_inputPeer(peer), // Use MTP_... types for parameters
MTP_string(messageText),
MTP_long(randomId),
// ... other arguments matching the TL definition
MTP_vector<MTPMessageEntity>() // Example for a vector argument
)).done([=]\(const MTPResponseType &result) {
// Handle the successful response (result).
// 'result' will be of the C++ type corresponding to the TL type
// specified after the '=' in the api.tl method definition.
// How to access data depends on whether the TL type has one or multiple constructors:
// 1. Multiple Constructors (e.g., User = User | UserEmpty):
// Use .match() with lambdas for each constructor:
result.match([&]\(const MTPDuser &data) {
/* use data.vfirst_name().v, etc. */
}, [&]\(const MTPDuserEmpty &data) {
/* handle empty user */
});
// Alternatively, check the type explicitly and use the constructor getter:
if (result.type() == mtpc_user) {
const auto &data = result.c_user(); // Asserts if type is not mtpc_user!
// use data.vfirst_name().v
} else if (result.type() == mtpc_userEmpty) {
const auto &data = result.c_userEmpty();
// handle empty user
}
// 2. Single Constructor (e.g., Messages = messages { msgs: vector<Message> }):
// Use .match() with a single lambda:
result.match([&]\(const MTPDmessages &data) { /* use data.vmessages().v */ });
// Or check the type explicitly and use the constructor getter:
if (result.type() == mtpc_messages) {
const auto &data = result.c_messages(); // Asserts if type is not mtpc_messages!
// use data.vmessages().v
}
// Or use the shortcut .data() for single-constructor types:
const auto &data = result.data(); // Only works for single-constructor types!
// use data.vmessages().v
}).fail([=]\(const MTP::Error &error) {
// Handle the API error (error).
// 'error' is an MTP::Error object containing the error code (error.type())
// and description (error.description()). Check for specific error strings.
if (error.type() == u"FLOOD_WAIT_X"_q) {
// Handle flood wait
} else {
Ui::show(Box<InformBox>(Lang::Hard::ServerError())); // Example generic error handling
}
}).handleFloodErrors().send(); // handleFloodErrors() is common, then send()
```
**Key Points:**
* Always refer to `Telegram/SourceFiles/mtproto/scheme/api.tl` for the correct method names, parameters (names and types), and response types.
* Use the generated `MTP...` types/classes for request parameters (e.g., `MTP_int`, `MTP_string`, `MTP_bool`, `MTP_vector`, `MTPInputUser`, etc.) and response handling.
* The `.done()` lambda receives the specific C++ `MTP...` type corresponding to the TL return type.
* For types with **multiple constructors** (e.g., `User = User | UserEmpty`), use `result.match([&]\(const MTPDuser &d){ ... }, [&]\(const MTPDuserEmpty &d){ ... })` to handle each case, or check `result.type() == mtpc_user` / `mtpc_userEmpty` and call the specific `result.c_user()` / `result.c_userEmpty()` getter (which asserts on type mismatch).
* For types with a **single constructor** (e.g., `Messages = messages{...}`), you can use `result.match([&]\(const MTPDmessages &d){ ... })` with one lambda, or check `type()` and call `c_messages()`, or use the shortcut `result.data()` to access the fields directly.
* The `.fail()` lambda receives an `MTP::Error` object. Check `error.type()` against known error strings (often defined as constants or using `u"..."_q` literals).
* Directly construct the `MTPnamespace_MethodName(...)` object inside `request()`.
* Include `.handleFloodErrors()` before `.send()` for standard flood wait handling.

View file

@ -0,0 +1,164 @@
---
description: For tasks requiring changing or adding user facing phrases and text parts.
globs:
alwaysApply: false
---
# Telegram Desktop Localization
## Coding Style Note
**Use `auto`:** In the actual codebase, variable types are almost always deduced using `auto` (or `const auto`, `const auto &`) rather than being written out explicitly. Examples in this guide may use explicit types for clarity, but prefer `auto` in practice.
```cpp
// Prefer this:
auto currentTitle = tr::lng_settings_title(tr::now);
auto nameProducer = GetNameProducer(); // Returns rpl::producer<...>
// Instead of this:
QString currentTitle = tr::lng_settings_title(tr::now);
rpl::producer<QString> nameProducer = GetNameProducer();
```
## String Resource File
Base user-facing English strings are defined in the `lang.strings` file:
`Telegram/Resources/langs/lang.strings`
This file uses a key-value format with named placeholders:
```
"lng_settings_title" = "Settings";
"lng_confirm_delete_item" = "Are you sure you want to delete {item_name}?";
"lng_files_selected" = "{count} files selected"; // Simple count example (see Pluralization)
```
Placeholders are enclosed in curly braces, e.g., `{name}`, `{user}`. A special placeholder `{count}` is used for pluralization rules.
### Pluralization
For keys that depend on a number (using the `{count}` placeholder), English typically requires two forms: singular and plural. These are defined in `lang.strings` using `#one` and `#other` suffixes:
```
"lng_files_selected#one" = "{count} file selected";
"lng_files_selected#other" = "{count} files selected";
```
While only `#one` and `#other` are defined in the base `lang.strings`, the code generation process creates C++ accessors for all six CLDR plural categories (`#zero`, `#one`, `#two`, `#few`, `#many`, `#other`) to support languages with more complex pluralization rules.
## Translation Process
While `lang.strings` provides the base English text and the keys, the actual translations are managed via Telegram's translations platform (translations.telegram.org) and loaded dynamically at runtime from the API. The keys from `lang.strings` (including the `#one`/`#other` variants) are used on the platform.
## Code Generation
A code generation tool processes `lang.strings` to create C++ structures and accessors within the `tr` namespace. These allow type-safe access to strings and handling of placeholders and pluralization. Generated keys typically follow the pattern `tr::lng_key_name`.
## String Usage in Code
Strings are accessed in C++ code using the generated objects within the `tr::` namespace. There are two main ways to use them: reactively (returning an `rpl::producer`) or immediately (returning the current value).
### 1. Reactive Usage (rpl::producer)
Calling a generated string function directly returns a reactive producer, typically `rpl::producer<QString>`. This producer automatically updates its value whenever the application language changes.
```cpp
// Key: "settings_title" = "Settings";
auto titleProducer = tr::lng_settings_title(); // Type: rpl::producer<QString>
// Key: "confirm_delete_item" = "Are you sure you want to delete {item_name}?";
auto itemNameProducer = /* ... */; // Type: rpl::producer<QString>
auto confirmationProducer = tr::lng_confirm_delete_item( // Type: rpl::producer<QString>
tr::now, // NOTE: tr::now is NOT passed here for reactive result
lt_item_name,
std::move(itemNameProducer)); // Placeholder producers should be moved
```
### 2. Immediate Usage (Current Value)
Passing `tr::now` as the first argument retrieves the string's current value in the active language (typically as a `QString`).
```cpp
// Key: "settings_title" = "Settings";
auto currentTitle = tr::lng_settings_title(tr::now); // Type: QString
// Key: "confirm_delete_item" = "Are you sure you want to delete {item_name}?";
const auto currentItemName = QString("My Document"); // Type: QString
auto currentConfirmation = tr::lng_confirm_delete_item( // Type: QString
tr::now, // Pass tr::now for immediate value
lt_item_name, currentItemName); // Placeholder value is a direct QString (or convertible)
```
### 3. Placeholders (`{tag}`)
Placeholders like `{item_name}` are replaced by providing arguments after `tr::now` (for immediate) or as the initial arguments (for reactive). A corresponding `lt_tag_name` constant is passed before the value.
* **Immediate:** Pass the direct value (e.g., `QString`, `int`).
* **Reactive:** Pass an `rpl::producer` of the corresponding type (e.g., `rpl::producer<QString>`). Remember to `std::move` the producer or use `rpl::duplicate` if you need to reuse the original producer afterwards.
### 4. Pluralization (`{count}`)
Keys using `{count}` require a numeric value for the `lt_count` placeholder. The correct plural form (`#zero`, `#one`, ..., `#other`) is automatically selected based on this value and the current language rules.
* **Immediate (`tr::now`):** Pass a `float64` or `int` (which is auto-converted to `float64`).
```cpp
int count = 1;
auto filesText = tr::lng_files_selected(tr::now, lt_count, count); // Type: QString
count = 5;
filesText = tr::lng_files_selected(tr::now, lt_count, count); // Uses "files_selected#other"
```
* **Reactive:** Pass an `rpl::producer<float64>`. Use the `tr::to_count()` helper to convert an `rpl::producer<int>` or wrap a single value.
```cpp
// From an existing int producer:
auto countProducer = /* ... */; // Type: rpl::producer<int>
auto filesTextProducer = tr::lng_files_selected( // Type: rpl::producer<QString>
lt_count,
countProducer | tr::to_count()); // Use tr::to_count() for conversion
// From a single int value wrapped reactively:
int currentCount = 5;
auto filesTextProducerSingle = tr::lng_files_selected( // Type: rpl::producer<QString>
lt_count,
rpl::single(currentCount) | tr::to_count());
// Alternative for single values (less common): rpl::single(currentCount * 1.)
```
### 5. Custom Projectors
An optional final argument can be a projector function (like `Ui::Text::Upper` or `Ui::Text::WithEntities`) to transform the output.
* If the projector returns `OutputType`, the string function returns `OutputType` (immediate) or `rpl::producer<OutputType>` (reactive).
* Placeholder values must match the projector's *input* requirements. For `Ui::Text::WithEntities`, placeholders expect `TextWithEntities` (immediate) or `rpl::producer<TextWithEntities>` (reactive).
```cpp
// Immediate with Ui::Text::WithEntities projector
// Key: "user_posted_photo" = "{user} posted a photo";
const auto userName = TextWithEntities{ /* ... */ }; // Type: TextWithEntities
auto message = tr::lng_user_posted_photo( // Type: TextWithEntities
tr::now,
lt_user,
userName, // Must be TextWithEntities
Ui::Text::WithEntities); // Projector
// Reactive with Ui::Text::WithEntities projector
auto userNameProducer = /* ... */; // Type: rpl::producer<TextWithEntities>
auto messageProducer = tr::lng_user_posted_photo( // Type: rpl::producer<TextWithEntities>
lt_user,
std::move(userNameProducer), // Move placeholder producers
Ui::Text::WithEntities); // Projector
```
## Key Summary
* Keys are defined in `Resources/langs/lang.strings` using `{tag}` placeholders.
* Plural keys use `{count}` and have `#one`/`#other` variants in `lang.strings`.
* Access keys via `tr::lng_key_name(...)` in C++.
* Call with `tr::now` as the first argument for the immediate `QString` (or projected type).
* Call without `tr::now` for the reactive `rpl::producer<QString>` (or projected type).
* Provide placeholder values (`lt_tag_name, value`) matching the usage (direct value for immediate, `rpl::producer` for reactive). Producers should typically be moved via `std::move`.
* For `{count}`:
* Immediate: Pass `int` or `float64`.
* Reactive: Pass `rpl::producer<float64>`, typically by converting an `int` producer using `| tr::to_count()`.
* Optional projector function as the last argument modifies the output type and required placeholder types.
* Actual translations are loaded at runtime from the API.

216
.cursor/rules/rpl_guide.mdc Normal file
View file

@ -0,0 +1,216 @@
---
description:
globs:
alwaysApply: true
---
# RPL (Reactive Programming Library) Guide
## Coding Style Note
**Use `auto`:** In the actual codebase, variable types are almost always deduced using `auto` (or `const auto`, `const auto &`) rather than being written out explicitly. Examples in this guide may use explicit types for clarity, but prefer `auto` in practice.
```cpp
// Prefer this:
auto intProducer = rpl::single(123);
const auto &lifetime = existingLifetime;
// Instead of this:
rpl::producer<int> intProducer = rpl::single(123);
const rpl::lifetime &lifetime = existingLifetime;
// Sometimes needed if deduction is ambiguous or needs help:
auto user = std::make_shared<UserData>();
auto data = QByteArray::fromHex("...");
```
## Introduction
RPL is the reactive programming library used in this project, residing in the `rpl::` namespace. It allows handling asynchronous streams of data over time.
The core concept is the `rpl::producer`, which represents a stream of values that can be generated over a certain lifetime.
## Producers: `rpl::producer<Type, Error = no_error>`
The fundamental building block is `rpl::producer<Type, Error>`. It produces values of `Type` and can optionally signal an error of type `Error`. By default, `Error` is `rpl::no_error`, indicating that the producer does not explicitly handle error signaling through this mechanism.
```cpp
// A producer that emits integers.
auto intProducer = /* ... */; // Type: rpl::producer<int>
// A producer that emits strings and can potentially emit a CustomError.
auto stringProducerWithError = /* ... */; // Type: rpl::producer<QString, CustomError>
```
Producers are typically lazy; they don't start emitting values until someone subscribes to them.
## Lifetime Management: `rpl::lifetime`
Reactive pipelines have a limited duration, managed by `rpl::lifetime`. An `rpl::lifetime` object essentially holds a collection of cleanup callbacks. When the lifetime ends (either explicitly destroyed or goes out of scope), these callbacks are executed, tearing down the associated pipeline and freeing resources.
```cpp
rpl::lifetime myLifetime;
// ... later ...
// myLifetime is destroyed, cleanup happens.
// Or, pass a lifetime instance to manage a pipeline's duration.
rpl::lifetime &parentLifetime = /* ... get lifetime from context ... */;
```
## Starting a Pipeline: `rpl::start_...`
To consume values from a producer, you start a pipeline using one of the `rpl::start_...` methods. These methods subscribe to the producer and execute callbacks for the events they handle.
The most common method is `rpl::start_with_next`:
```cpp
auto counter = /* ... */; // Type: rpl::producer<int>
rpl::lifetime lifetime;
// Counter is consumed here, use std::move if it's an l-value.
std::move(
counter
) | rpl::start_with_next([=]\(int nextValue) {
// Process the next integer value emitted by the producer.
qDebug() << "Received: " << nextValue;
}, lifetime); // Pass the lifetime to manage the subscription.
// Note: `counter` is now in a moved-from state and likely invalid.
// If you need to start the same producer multiple times, duplicate it:
// rpl::duplicate(counter) | rpl::start_with_next(...);
// If you DON'T pass a lifetime to a start_... method:
auto counter2 = /* ... */; // Type: rpl::producer<int>
rpl::lifetime subscriptionLifetime = std::move(
counter2
) | rpl::start_with_next([=]\(int nextValue) { /* ... */ });
// The returned lifetime MUST be stored. If it's discarded immediately,
// the subscription stops instantly.
// `counter2` is also moved-from here.
```
Other variants allow handling errors (`_error`) and completion (`_done`):
```cpp
auto dataStream = /* ... */; // Type: rpl::producer<QString, Error>
rpl::lifetime lifetime;
// Assuming dataStream might be used again, we duplicate it for the first start.
// If it's the only use, std::move(dataStream) would be preferred.
rpl::duplicate(
dataStream
) | rpl::start_with_error([=]\(Error &&error) {
// Handle the error signaled by the producer.
qDebug() << "Error: " << error.text();
}, lifetime);
// Using dataStream again, perhaps duplicated again or moved if last use.
rpl::duplicate(
dataStream
) | rpl::start_with_done([=] {
// Execute when the producer signals it's finished emitting values.
qDebug() << "Stream finished.";
}, lifetime);
// Last use of dataStream, so we move it.
std::move(
dataStream
) | rpl::start_with_next_error_done(
[=]\(QString &&value) { /* handle next value */ },
[=]\(Error &&error) { /* handle error */ },
[=] { /* handle done */ },
lifetime);
```
## Transforming Producers
RPL provides functions to create new producers by transforming existing ones:
* `rpl::map`: Transforms each value emitted by a producer.
```cpp
auto ints = /* ... */; // Type: rpl::producer<int>
// The pipe operator often handles the move implicitly for chained transformations.
auto strings = std::move(
ints // Explicit move is safer
) | rpl::map([](int value) {
return QString::number(value * 2);
}); // Emits strings like "0", "2", "4", ...
```
* `rpl::filter`: Emits only the values from a producer that satisfy a condition.
```cpp
auto ints = /* ... */; // Type: rpl::producer<int>
auto evenInts = std::move(
ints // Explicit move is safer
) | rpl::filter([](int value) {
return (value % 2 == 0);
}); // Emits only even numbers.
```
## Combining Producers
You can combine multiple producers into one:
* `rpl::combine`: Combines the latest values from multiple producers whenever *any* of them emits a new value. Requires all producers to have emitted at least one value initially.
While it produces a `std::tuple`, subsequent operators like `map`, `filter`, and `start_with_next` can automatically unpack this tuple into separate lambda arguments.
```cpp
auto countProducer = rpl::single(1); // Type: rpl::producer<int>
auto textProducer = rpl::single(u"hello"_q); // Type: rpl::producer<QString>
rpl::lifetime lifetime;
// rpl::combine takes producers by const-ref internally and duplicates,
// so move/duplicate is usually not strictly needed here unless you
// want to signal intent or manage the lifetime of p1/p2 explicitly.
auto combined = rpl::combine(
countProducer, // or rpl::duplicate(countProducer)
textProducer // or rpl::duplicate(textProducer)
);
// Starting the combined producer consumes it.
// The lambda receives unpacked arguments, not the tuple itself.
std::move(
combined
) | rpl::start_with_next([=]\(int count, const QString &text) {
// No need for std::get<0>(latest), etc.
qDebug() << "Combined: Count=" << count << ", Text=" << text;
}, lifetime);
// This also works with map, filter, etc.
std::move(
combined
) | rpl::filter([=]\(int count, const QString &text) {
return count > 0 && !text.isEmpty();
}) | rpl::map([=]\(int count, const QString &text) {
return text.repeated(count);
}) | rpl::start_with_next([=]\(const QString &result) {
qDebug() << "Mapped & Filtered: " << result;
}, lifetime);
```
* `rpl::merge`: Merges the output of multiple producers of the *same type* into a single producer. It emits a value whenever *any* of the source producers emits a value.
```cpp
auto sourceA = /* ... */; // Type: rpl::producer<QString>
auto sourceB = /* ... */; // Type: rpl::producer<QString>
// rpl::merge also duplicates internally.
auto merged = rpl::merge(sourceA, sourceB);
// Starting the merged producer consumes it.
std::move(
merged
) | rpl::start_with_next([=]\(QString &&value) {
// Receives values from either sourceA or sourceB as they arrive.
qDebug() << "Merged value: " << value;
}, lifetime);
```
## Key Concepts Summary
* Use `rpl::producer<Type, Error>` to represent streams of values.
* Manage subscription duration using `rpl::lifetime`.
* Pass `rpl::lifetime` to `rpl::start_...` methods.
* If `rpl::lifetime` is not passed, **store the returned lifetime** to keep the subscription active.
* Use operators like `| rpl::map`, `| rpl::filter` to transform streams.
* Use `rpl::combine` or `rpl::merge` to combine streams.
* When starting a chain (`std::move(producer) | rpl::map(...)`), explicitly move the initial producer.
* These functions typically duplicate their input producers internally.
* Starting a pipeline consumes the producer; use `

154
.cursor/rules/styling.mdc Normal file
View file

@ -0,0 +1,154 @@
---
description: For tasks requiring working with user facing UI components.
globs:
alwaysApply: false
---
# Telegram Desktop UI Styling
## Style Definition Files
UI element styles (colors, fonts, paddings, margins, icons, etc.) are defined in `.style` files using a custom syntax. These files are located alongside the C++ source files they correspond to within specific UI component directories (e.g., `Telegram/SourceFiles/ui/chat/chat.style`).
Definitions from other `.style` files can be included using the `using` directive at the top of the file:
```style
using "ui/basic.style";
using "ui/widgets/widgets.style";
```
The central definition of named colors happens in `Telegram/SourceFiles/ui/colors.palette`. This file allows for theme generation and loading colors from various sources.
### Syntax Overview
1. **Built-in Types:** The syntax recognizes several base types inferred from the value assigned:
* `int`: Integer numbers (e.g., `lineHeight: 20;`)
* `bool`: Boolean values (e.g., `useShadow: true;`)
* `pixels`: Pixel values, ending with `px` (e.g., `borderWidth: 1px;`). Generated as `int` in C++.
* `color`: Named colors defined in `colors.palette` (e.g., `background: windowBg;`)
* `icon`: Defined inline using a specific syntax (see below). Generates `style::icon`.
* `margins`: Four pixel values for margins or padding. Requires `margins(top, right, bottom, left)` syntax (e.g., `margin: margins(10px, 5px, 10px, 5px);` or `padding: margins(8px, 8px, 8px, 8px);`). Generates `style::margins` (an alias for `QMargins`).
* `size`: Two pixel values for width and height (e.g., `iconSize: size(16px, 16px);`). Generates `style::size`.
* `point`: Two pixel values for x and y coordinates (e.g., `textPos: point(5px, 2px);`). Generates `style::point`.
* `align`: Alignment keywords (e.g., `textAlign: align(center);` or `iconAlign: align(left);`). Generates `style::align`.
* `font`: Font definitions (e.g., `font: font(14px semibold);`). Generates `style::font`.
* `double`: Floating point numbers (e.g., `disabledOpacity: 0.5;`)
*Note on Borders:* Borders are typically defined using multiple fields like `border: pixels;` (for width) and `borderFg: color;` (for color), rather than a single CSS-like property.
2. **Structure Definition:** You can define complex data structures directly within the `.style` file:
```style
MyButtonStyle { // Defines a structure named 'MyButtonStyle'
textPadding: margins; // Field 'textPadding' expects margins type
icon: icon; // Field 'icon' of type icon
height: pixels; // Field 'height' of type pixels
}
```
This generates a `struct MyButtonStyle { ... };` inside the `namespace style`. Fields will have corresponding C++ types (`style::margins`, `style::icon`, `int`).
3. **Variable Definition & Inheritance:** Variables are defined using `name: value;` or `groupName { ... }`. They can be of built-in types or custom structures. Structures can be initialized inline or inherit from existing variables.
**Icon Definition Syntax:** Icons are defined inline using the `icon{...}` syntax. The generator probes for `.svg` files or `.png` files (including `@2x`, `@3x` variants) based on the provided path stem.
```style
// Single-part icon definition:
myIconSearch: icon{{ "gui/icons/search", iconColor }};
// Multi-part icon definition (layers drawn bottom-up):
myComplexIcon: icon{
{ "gui/icons/background", iconBgColor },
{ "gui/icons/foreground", iconFgColor }
};
// Icon with path modifiers (PNG only for flips, SVG only for size):
myFlippedIcon: icon{{ "gui/icons/arrow-flip_horizontal", arrowColor }};
myResizedIcon: icon{{ "gui/icons/logo-128x128", logoColor }}; // Forces 128x128 for SVG
```
**Other Variable Examples:**
```style
// Simple variables
buttonHeight: 30px;
activeButtonColor: buttonBgActive; // Named color from colors.palette
// Variable of a custom structure type, initialized inline
defaultButton: MyButtonStyle {
textPadding: margins(10px, 15px, 10px, 15px); // Use margins(...) syntax
icon: myIconSearch; // Assign the previously defined icon variable
height: buttonHeight; // Reference another variable
}
// Another variable inheriting from 'defaultButton' and overriding/adding fields
primaryButton: MyButtonStyle(defaultButton) {
icon: myComplexIcon; // Override icon with the multi-part one
backgroundColor: activeButtonColor; // Add a field not in MyButtonStyle definition
}
// Style group (often used for specific UI elements)
chatInput { // Example using separate border properties and explicit padding
border: 1px; // Border width
borderFg: defaultInputFieldBorder; // Border color (named color)
padding: margins(5px, 10px, 5px, 10px); // Use margins(...) syntax for padding field
backgroundColor: defaultChatBg; // Background color
}
```
## Code Generation
A code generation tool processes these `.style` files and `colors.palette` to create C++ objects.
- The `using` directives resolve dependencies between `.style` files.
- Custom structure definitions (like `MyButtonStyle`) generate corresponding `struct MyButtonStyle { ... };` within the `namespace style`.
- Style variables/groups (like `defaultButton`, `primaryButton`, `chatInput`) are generated as objects/structs within the `st` namespace (e.g., `st::defaultButton`, `st::primaryButton`, `st::chatInput`). These generated structs contain members corresponding to the fields defined in the `.style` file.
- Color objects are generated into the `st` namespace as well, based on their names in `colors.palette` (e.g., `st::windowBg`, `st::buttonBgActive`).
- The generated header files for styles are placed in the `Telegram/SourceFiles/styles/` directory with a `style_` prefix (e.g., `styles/style_widgets.h` for `ui/widgets/widgets.style`). You include them like `#include "styles/style_widgets.h"`.
Generated C++ types correspond to the `.style` types: `style::color`, `style::font`, `style::margins` (used for both `margin:` and `padding:` fields), `style::icon`, `style::size`, `style::point`, `style::align`, and `int` or `bool` for simple types.
## Style Usage in Code
Styles are applied in C++ code by referencing the generated `st::...` objects and their members.
```cpp
// Example: Including the generated style header
#include "styles/style_widgets.h" // For styles defined in ui/widgets/widgets.style
// ... inside some UI class code ...
// Accessing members of a generated style struct
int height = st::primaryButton.height; // Accessing the 'height' field (pixels -> int)
const style::icon &icon = st::primaryButton.icon; // Accessing the 'icon' field (st::myComplexIcon)
style::margins padding = st::primaryButton.textPadding; // Accessing 'textPadding'
style::color bgColor = st::primaryButton.backgroundColor; // Accessing the color (st::activeButtonColor)
// Applying styles (conceptual examples)
myButton->setIcon(st::primaryButton.icon);
myButton->setHeight(st::primaryButton.height);
myButton->setPadding(st::primaryButton.textPadding);
myButton->setBackgroundColor(st::primaryButton.backgroundColor);
// Using styles directly in painting
void MyWidget::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(rect(), st::chatInput.backgroundColor); // Use color from chatInput style
// Border painting requires width and color
int borderWidth = st::chatInput.border; // Access border width (pixels -> int)
style::color borderColor = st::chatInput.borderFg; // Access border color
if (borderWidth > 0) {
p.setPen(QPen(borderColor, borderWidth));
// Adjust rect for pen width if needed before drawing
p.drawRect(rect().adjusted(borderWidth / 2, borderWidth / 2, -borderWidth / 2, -borderWidth / 2));
}
// Access padding (style::margins)
style::margins inputPadding = st::chatInput.padding;
// ... use inputPadding.top(), inputPadding.left() etc. for content layout ...
}
```
**Key Points:**
* Styles are defined in `.style` files next to their corresponding C++ source files.
* `using "path/to/other.style";` includes definitions from other style files.
* Named colors are defined centrally in `ui/colors.palette`.
* `.style` syntax supports built-in types (like `pixels`, `color`, `margins`, `point`, `size`, `align`, `font`, `double`), custom structure definitions (`Name { field: type; ... }`), variable definitions (`name: value;`), and inheritance (`child: Name(parent) { ... }`).
* Values must match the expected type (e.g., fields declared as `margins` type, like `margin:` or `padding:`, require `margins(...)` syntax). Borders are typically set via separate `border: pixels;` and `borderFg: color;` fields.
* Icons are defined inline using `name: icon{{ "path_stem", color }};` or `name: icon{ { "path1", c1 }, ... };` syntax, with optional path modifiers.
* Code generation creates `struct` definitions in the `style` namespace for custom types and objects/structs in the `st` namespace for defined variables/groups.
* Generated headers are in `styles/` with a `style_` prefix and must be included.
* Access style properties via the generated `st::` objects (e.g., `st::primaryButton.height`, `st::chatInput.backgroundColor`).

2
.cursorignore Normal file
View file

@ -0,0 +1,2 @@
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
Telegram/ThirdParty/

View file

@ -5,14 +5,9 @@
"vscode": {
"settings": {
"C_Cpp.intelliSenseEngine": "disabled",
"clangd.arguments": [
"--compile-commands-dir=${workspaceFolder}/out"
],
"cmake.generator": "Ninja Multi-Config",
"cmake.buildDirectory": "${workspaceFolder}/out",
"cmake.configureSettings": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json"
},
"extensions": [
"ms-vscode.cpptools-extension-pack",

View file

@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thanks for reporting issues of Telegram Desktop!
Thanks for reporting issues of AyuGram Desktop!
To make it easier for us to help you please enter detailed information below.
- type: textarea
@ -39,12 +39,9 @@ body:
required: true
- type: input
attributes:
label: Version of Telegram Desktop
label: Version of AyuGram Desktop
description: >
Please note we don't support versions from Linux distro repositories.
If you need support for these versions, **please contact your distro maintainer**
or your distro bugtracker.
**Don't use 'latest'**, specify actual version, **that's a reason to close your issue**.
**Don't use 'latest'**, specify actual version.
validations:
required: true
- type: dropdown
@ -52,11 +49,7 @@ body:
label: Installation source
multiple: false
options:
- Static binary from official website
- Microsoft Store
- Mac App Store
- Flatpak
- Snap
- Binary from GitHub / official Telegram source
- Other (unofficial) source
validations:
required: true
@ -65,9 +58,7 @@ body:
label: Crash ID
description: >
If you're reporting a crash, please enter the crash ID from the crash reporter
opening on the next launch after crash. **You have to enable beta versions
installation in Settings -> Advanced for the reporter to appear.**
You don't have to wait for a beta version to arrive.
opening on the next launch after crash.
- type: textarea
attributes:
label: Logs

View file

@ -1,125 +0,0 @@
name: Linux.
on:
push:
paths-ignore:
- 'docs/**'
- '**.md'
- 'changelog.txt'
- 'LEGAL'
- 'LICENSE'
- '.github/**'
- '!.github/workflows/linux.yml'
- 'snap/**'
- 'Telegram/build/**'
- 'Telegram/Resources/uwp/**'
- 'Telegram/Resources/winrc/**'
- 'Telegram/SourceFiles/platform/win/**'
- 'Telegram/SourceFiles/platform/mac/**'
- 'Telegram/Telegram/**'
- 'Telegram/configure.bat'
- 'Telegram/Telegram.plist'
pull_request:
paths-ignore:
- 'docs/**'
- '**.md'
- 'changelog.txt'
- 'LEGAL'
- 'LICENSE'
- '.github/**'
- '!.github/workflows/linux.yml'
- 'snap/**'
- 'Telegram/build/**'
- 'Telegram/Resources/uwp/**'
- 'Telegram/Resources/winrc/**'
- 'Telegram/SourceFiles/platform/win/**'
- 'Telegram/SourceFiles/platform/mac/**'
- 'Telegram/Telegram/**'
- 'Telegram/configure.bat'
- 'Telegram/Telegram.plist'
jobs:
linux:
name: Rocky Linux 8
runs-on: ubuntu-latest
strategy:
matrix:
defines:
- ""
- "DESKTOP_APP_DISABLE_X11_INTEGRATION"
env:
UPLOAD_ARTIFACT: "true"
steps:
- name: Get repository name.
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- name: Clone.
uses: actions/checkout@v4
with:
submodules: recursive
path: ${{ env.REPO_NAME }}
- name: First set up.
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
docker pull ghcr.io/$GITHUB_REPOSITORY/centos_env
docker tag ghcr.io/$GITHUB_REPOSITORY/centos_env tdesktop:centos_env
- name: Telegram Desktop build.
run: |
cd $REPO_NAME
DEFINE=""
if [ -n "${{ matrix.defines }}" ]; then
DEFINE="-D ${{ matrix.defines }}=ON"
echo Define from matrix: $DEFINE
echo "ARTIFACT_NAME=Telegram_${{ matrix.defines }}" >> $GITHUB_ENV
else
echo "ARTIFACT_NAME=Telegram" >> $GITHUB_ENV
fi
docker run --rm \
-u $(id -u) \
-v $PWD:/usr/src/tdesktop \
-e CONFIG=Debug \
tdesktop:centos_env \
/usr/src/tdesktop/Telegram/build/docker/centos_env/build.sh \
-D CMAKE_C_FLAGS_DEBUG="" \
-D CMAKE_CXX_FLAGS_DEBUG="" \
-D CMAKE_C_FLAGS="-Werror" \
-D CMAKE_CXX_FLAGS="-Werror" \
-D CMAKE_EXE_LINKER_FLAGS="-s" \
-D TDESKTOP_API_TEST=ON \
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF \
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
$DEFINE
- name: Check.
run: |
filePath="$REPO_NAME/out/Debug/Telegram"
if test -f "$filePath"; then
echo "Build successfully done! :)"
size=$(stat -c %s "$filePath")
echo "File size of ${filePath}: ${size} Bytes."
else
echo "Build error, output file does not exist."
exit 1
fi
- name: Move artifact.
if: env.UPLOAD_ARTIFACT == 'true'
run: |
cd $REPO_NAME/out/Debug
mkdir artifact
mv {Telegram,Updater} artifact/
- uses: actions/upload-artifact@v4
if: env.UPLOAD_ARTIFACT == 'true'
name: Upload artifact.
with:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.REPO_NAME }}/out/Debug/artifact/

View file

@ -1,201 +0,0 @@
name: Windows.
on:
push:
paths-ignore:
- 'docs/**'
- '**.md'
- 'changelog.txt'
- 'LEGAL'
- 'LICENSE'
- '.github/**'
- '!.github/workflows/win.yml'
- 'lib/xdg/**'
- 'snap/**'
- 'Telegram/build/docker/**'
- 'Telegram/Resources/uwp/**'
- 'Telegram/SourceFiles/platform/linux/**'
- 'Telegram/SourceFiles/platform/mac/**'
- 'Telegram/Telegram/**'
- 'Telegram/configure.sh'
- 'Telegram/Telegram.plist'
pull_request:
paths-ignore:
- 'docs/**'
- '**.md'
- 'changelog.txt'
- 'LEGAL'
- 'LICENSE'
- '.github/**'
- '!.github/workflows/win.yml'
- 'lib/xdg/**'
- 'snap/**'
- 'Telegram/build/docker/**'
- 'Telegram/Resources/uwp/**'
- 'Telegram/SourceFiles/platform/linux/**'
- 'Telegram/SourceFiles/platform/mac/**'
- 'Telegram/Telegram/**'
- 'Telegram/configure.sh'
- 'Telegram/Telegram.plist'
jobs:
windows:
name: Windows
runs-on: windows-latest
strategy:
matrix:
arch: [Win32, x64]
generator: ["", "Ninja Multi-Config"]
env:
UPLOAD_ARTIFACT: "true"
ONLY_CACHE: "false"
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
defaults:
run:
shell: cmd
steps:
- name: Prepare directories.
run: |
mkdir %userprofile%\TBuild\Libraries
mklink /d %GITHUB_WORKSPACE%\TBuild %userprofile%\TBuild
echo TBUILD=%GITHUB_WORKSPACE%\TBuild>>%GITHUB_ENV%
- name: Get repository name.
shell: bash
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- uses: ilammy/msvc-dev-cmd@v1.13.0
name: Native Tools Command Prompt.
with:
arch: ${{ matrix.arch }}
- name: Clone.
uses: actions/checkout@v4
with:
submodules: recursive
path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}
- name: Set up environment paths.
shell: bash
run: |
echo "CACHE_KEY=$(sha256sum $TBUILD/$REPO_NAME/$PREPARE_PATH | awk '{ print $1 }')" >> $GITHUB_ENV
echo "Configurate git for cherry-picks."
git config --global user.email "you@example.com"
git config --global user.name "Sample"
- name: NuGet sources.
run: |
nuget sources Disable -Name "Microsoft Visual Studio Offline Packages"
nuget sources Add -Source https://api.nuget.org/v3/index.json & exit 0
- name: ThirdParty cache.
id: cache-third-party
uses: actions/cache@v4
with:
path: ${{ env.TBUILD }}\ThirdParty
key: ${{ runner.OS }}-${{ matrix.arch }}-third-party-${{ env.CACHE_KEY }}
restore-keys: ${{ runner.OS }}-${{ matrix.arch }}-third-party-
- name: Libraries cache.
id: cache-libs
uses: actions/cache@v4
with:
path: ${{ env.TBUILD }}\Libraries
key: ${{ runner.OS }}-${{ matrix.arch }}-libs-${{ env.CACHE_KEY }}
restore-keys: ${{ runner.OS }}-${{ matrix.arch }}-libs-
- name: Libraries.
env:
GYP_MSVS_OVERRIDE_PATH: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\'
GYP_MSVS_VERSION: 2022
run: |
cd %TBUILD%
%REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent
- name: Read configuration matrix.
shell: bash
run: |
ARTIFACT_NAME="Telegram"
ARCH=""
if [ -n "${{ matrix.arch }}" ]; then
case "${{ matrix.arch }}" in
Win32) ARCH="x86";;
*) ARCH="${{ matrix.arch }}";;
esac
echo "Architecture from matrix: $ARCH"
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.arch }}"
fi
GENERATOR=""
if [ -n "${{ matrix.generator }}" ]; then
GENERATOR="-G \"${{ matrix.generator }}\""
echo "Generator from matrix: $GENERATOR"
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.generator }}"
fi
echo "TDESKTOP_BUILD_GENERATOR=$GENERATOR" >> $GITHUB_ENV
[ -n "$GENERATOR" ] && ARCH=""
echo "TDESKTOP_BUILD_ARCH=$ARCH" >> $GITHUB_ENV
DEFINE=""
if [ -n "${{ matrix.defines }}" ]; then
DEFINE="-D ${{ matrix.defines }}=ON"
echo "Define from matrix: $DEFINE"
ARTIFACT_NAME="${ARTIFACT_NAME}_${{ matrix.defines }}"
fi
echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV
echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> $GITHUB_ENV
API="-D TDESKTOP_API_TEST=ON"
if [ $GITHUB_REF == 'refs/heads/nightly' ]; then
echo "Use the open credentials."
API="-D TDESKTOP_API_ID=611335 -D TDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c"
fi
echo "TDESKTOP_BUILD_API=$API" >> $GITHUB_ENV
- name: Free up some disk space.
run: |
cd %TBUILD%
del /S Libraries\*.pdb
del /S Libraries\*.pch
del /S Libraries\*.obj
- name: Telegram Desktop build.
if: env.ONLY_CACHE == 'false'
run: |
cd %TBUILD%\%REPO_NAME%\Telegram
call configure.bat ^
%TDESKTOP_BUILD_GENERATOR% ^
%TDESKTOP_BUILD_ARCH% ^
%TDESKTOP_BUILD_API% ^
-D CMAKE_C_FLAGS="/WX" ^
-D CMAKE_CXX_FLAGS="/WX" ^
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF ^
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^
-D DESKTOP_APP_NO_PDB=ON ^
%TDESKTOP_BUILD_DEFINE%
cmake --build ..\out --config Debug --parallel
- name: Move artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
run: |
set OUT=%TBUILD%\%REPO_NAME%\out\Debug
mkdir artifact
move %OUT%\Telegram.exe artifact/
move %OUT%\Updater.exe artifact/
- uses: actions/upload-artifact@v4
name: Upload artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
with:
name: ${{ env.ARTIFACT_NAME }}
path: artifact\

1
.gitignore vendored
View file

@ -20,6 +20,7 @@ ipch/
.vs/
.vscode/
.cache/
compile_commands.json
/Telegram/log.txt
/Telegram/data

View file

@ -4,15 +4,7 @@
# For license and copyright information please follow this link:
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
if (APPLE)
# target_precompile_headers with COMPILE_LANGUAGE restriction.
cmake_minimum_required(VERSION 3.23)
else()
cmake_minimum_required(VERSION 3.16)
endif()
if (POLICY CMP0149)
cmake_policy(SET CMP0149 NEW)
endif()
cmake_minimum_required(VERSION 3.25...3.31)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

View file

@ -30,10 +30,10 @@
### Windows
#### Официальный вариант
#### Официальная версия
Вы можете скачать готовый бинарный файл со вкладки [Releases](https://github.com/AyuGram/AyuGramDesktop/releases) или из
[Телеграм чата](https://t.me/ayugramchat/12788).
[Телеграм канала](https://t.me/AyuGramReleases).
#### Winget
@ -55,8 +55,16 @@ scoop install ayugram
### macOS
#### Официальная версия
Вы можете скачать подписанный пакет со вкладки [Releases](https://github.com/AyuGram/AyuGramDesktop/releases).
#### Homebrew
```bash
brew install --cask ayugram
```
### Arch Linux
Вы можете установить `ayugram-desktop` из [AUR](https://aur.archlinux.org/packages?O=0&K=ayugram).
@ -101,3 +109,8 @@ scoop install ayugram
### Иконки
- [Solar Icon Set](https://www.figma.com/community/file/1166831539721848736)
### Боты
- [TelegramDB](https://t.me/tgdatabase) для получения юзернейма по ID (до закрытия бесплатной версии 25 мая 2025)
- [usinfobot](https://t.me/usinfobot) для получения юзернейма по ID

View file

@ -34,7 +34,7 @@ And many more. Check out our [Documentation](https://docs.ayugram.one/desktop/).
#### Official
You can download prebuilt Windows binary from [Releases tab](https://github.com/AyuGram/AyuGramDesktop/releases) or from
the [Telegram topic](https://t.me/ayugramchat/12788).
the [Telegram channel](https://t.me/AyuGramReleases).
#### Winget
@ -56,8 +56,16 @@ build by yourself.
### macOS
#### Official
You can download prebuilt macOS package from [Releases tab](https://github.com/AyuGram/AyuGramDesktop/releases).
#### Homebrew
```bash
brew install --cask ayugram
```
### Arch Linux
You can install `ayugram-desktop` from [AUR](https://aur.archlinux.org/packages?O=0&K=ayugram).
@ -102,3 +110,8 @@ Enjoy using **AyuGram**? Consider sending us a tip!
### Icons
- [Solar Icon Set](https://www.figma.com/community/file/1166831539721848736)
### Bots
- [TelegramDB](https://t.me/tgdatabase) for username lookup by ID (until closing free inline mode at 25 May 2025)
- [usinfobot](https://t.me/usinfobot) for username lookup by ID

View file

@ -26,7 +26,6 @@ get_filename_component(res_loc Resources REALPATH)
include(cmake/telegram_options.cmake)
include(cmake/lib_ffmpeg.cmake)
include(cmake/lib_stripe.cmake)
include(cmake/lib_tgvoip.cmake)
include(cmake/lib_tgcalls.cmake)
include(cmake/lib_prisma.cmake)
include(cmake/td_export.cmake)
@ -34,6 +33,7 @@ include(cmake/td_iv.cmake)
include(cmake/td_lang.cmake)
include(cmake/td_mtproto.cmake)
include(cmake/td_scheme.cmake)
include(cmake/td_tde2e.cmake)
include(cmake/td_ui.cmake)
include(cmake/generate_appdata_changelog.cmake)
@ -47,17 +47,15 @@ if (WIN32)
platform/win/windows_quiethours.idl
platform/win/windows_toastactivator.idl
)
nuget_add_winrt(Telegram)
endif()
set_target_properties(Telegram PROPERTIES AUTOMOC ON)
target_link_libraries(Telegram
PRIVATE
tdesktop::lib_tgcalls_legacy
# tdesktop::lib_tgcalls_legacy
tdesktop::lib_tgcalls
tdesktop::lib_tgvoip
# tdesktop::lib_tgvoip
# Order in this list defines the order of include paths in command line.
# We need to place desktop-app::external_minizip this early to have its
@ -71,6 +69,7 @@ PRIVATE
tdesktop::td_lang
tdesktop::td_mtproto
tdesktop::td_scheme
tdesktop::td_tde2e
tdesktop::td_ui
desktop-app::lib_webrtc
desktop-app::lib_base
@ -231,6 +230,8 @@ PRIVATE
api/api_peer_colors.h
api/api_peer_photo.cpp
api/api_peer_photo.h
api/api_peer_search.cpp
api/api_peer_search.h
api/api_polls.cpp
api/api_polls.h
api/api_premium.cpp
@ -295,8 +296,8 @@ PRIVATE
boxes/peers/edit_contact_box.h
boxes/peers/edit_forum_topic_box.cpp
boxes/peers/edit_forum_topic_box.h
boxes/peers/edit_linked_chat_box.cpp
boxes/peers/edit_linked_chat_box.h
boxes/peers/edit_discussion_link_box.cpp
boxes/peers/edit_discussion_link_box.h
boxes/peers/edit_members_visible.cpp
boxes/peers/edit_members_visible.h
boxes/peers/edit_participant_box.cpp
@ -476,6 +477,8 @@ PRIVATE
calls/calls_video_bubble.h
calls/calls_video_incoming.cpp
calls/calls_video_incoming.h
calls/calls_window.cpp
calls/calls_window.h
chat_helpers/compose/compose_features.h
chat_helpers/compose/compose_show.cpp
chat_helpers/compose/compose_show.h
@ -525,6 +528,8 @@ PRIVATE
chat_helpers/ttl_media_layer_widget.h
core/application.cpp
core/application.h
core/bank_card_click_handler.cpp
core/bank_card_click_handler.h
core/base_integration.cpp
core/base_integration.h
core/changelogs.cpp
@ -578,6 +583,8 @@ PRIVATE
data/components/factchecks.h
data/components/location_pickers.cpp
data/components/location_pickers.h
data/components/promo_suggestions.cpp
data/components/promo_suggestions.h
data/components/recent_peers.cpp
data/components/recent_peers.h
data/components/scheduled_messages.cpp
@ -764,12 +771,16 @@ PRIVATE
dialogs/dialogs_main_list.h
dialogs/dialogs_pinned_list.cpp
dialogs/dialogs_pinned_list.h
dialogs/dialogs_quick_action.cpp
dialogs/dialogs_quick_action.h
dialogs/dialogs_row.cpp
dialogs/dialogs_row.h
dialogs/dialogs_search_from_controllers.cpp
dialogs/dialogs_search_from_controllers.h
dialogs/dialogs_search_tags.cpp
dialogs/dialogs_search_tags.h
dialogs/dialogs_top_bar_suggestion.cpp
dialogs/dialogs_top_bar_suggestion.h
dialogs/dialogs_widget.cpp
dialogs/dialogs_widget.h
editor/color_picker.cpp
@ -1001,6 +1012,8 @@ PRIVATE
history/history_unread_things.h
history/history_view_highlight_manager.cpp
history/history_view_highlight_manager.h
history/history_view_swipe_back_session.cpp
history/history_view_swipe_back_session.h
history/history_widget.cpp
history/history_widget.h
info/bot/earn/info_bot_earn_list.cpp
@ -1155,6 +1168,8 @@ PRIVATE
inline_bots/inline_bot_result.h
inline_bots/inline_bot_send_data.cpp
inline_bots/inline_bot_send_data.h
inline_bots/inline_bot_storage.cpp
inline_bots/inline_bot_storage.h
inline_bots/inline_results_inner.cpp
inline_bots/inline_results_inner.h
inline_bots/inline_results_widget.cpp
@ -1501,6 +1516,10 @@ PRIVATE
settings/cloud_password/settings_cloud_password_hint.h
settings/cloud_password/settings_cloud_password_input.cpp
settings/cloud_password/settings_cloud_password_input.h
settings/cloud_password/settings_cloud_password_login_email.cpp
settings/cloud_password/settings_cloud_password_login_email.h
settings/cloud_password/settings_cloud_password_login_email_confirm.cpp
settings/cloud_password/settings_cloud_password_login_email_confirm.h
settings/cloud_password/settings_cloud_password_manage.cpp
settings/cloud_password/settings_cloud_password_manage.h
settings/cloud_password/settings_cloud_password_start.cpp
@ -1612,6 +1631,8 @@ PRIVATE
support/support_preload.h
support/support_templates.cpp
support/support_templates.h
tde2e/tde2e_integration.cpp
tde2e/tde2e_integration.h
ui/boxes/edit_invite_link_session.cpp
ui/boxes/edit_invite_link_session.h
ui/boxes/peer_qr_box.cpp
@ -1808,6 +1829,10 @@ if (WIN32)
# COMMENT
# $<IF:${release},"Appending compatibility manifest.","Finalizing build.">
# )
if (QT_VERSION LESS 6)
target_link_libraries(Telegram PRIVATE desktop-app::win_directx_helper)
endif()
elseif (APPLE)
if (NOT DESKTOP_APP_USE_PACKAGED)
target_link_libraries(Telegram PRIVATE desktop-app::external_iconv)
@ -1985,66 +2010,8 @@ if (MSVC)
)
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:uxtheme.dll
/DELAYLOAD:crypt32.dll
/DELAYLOAD:bcrypt.dll
/DELAYLOAD:netapi32.dll
/DELAYLOAD:imm32.dll
/DELAYLOAD:userenv.dll
/DELAYLOAD:wtsapi32.dll
/DELAYLOAD:propsys.dll
)
if (QT_VERSION GREATER 6)
if (NOT build_winarm)
target_link_options(Telegram PRIVATE
/DELAYLOAD:API-MS-Win-EventLog-Legacy-l1-1-0.dll
)
endif()
target_link_options(Telegram
PRIVATE
/DELAYLOAD:API-MS-Win-Core-Console-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-Fibers-l2-1-0.dll
/DELAYLOAD:API-MS-Win-Core-Fibers-l2-1-1.dll
/DELAYLOAD:API-MS-Win-Core-File-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-LibraryLoader-l1-2-0.dll
/DELAYLOAD:API-MS-Win-Core-Localization-l1-2-0.dll
/DELAYLOAD:API-MS-Win-Core-Memory-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-Memory-l1-1-1.dll
/DELAYLOAD:API-MS-Win-Core-ProcessThreads-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-Synch-l1-2-0.dll # Synchronization.lib
/DELAYLOAD:API-MS-Win-Core-SysInfo-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-Timezone-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-WinRT-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-WinRT-Error-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Core-WinRT-String-l1-1-0.dll
/DELAYLOAD:API-MS-Win-Security-CryptoAPI-l1-1-0.dll
# /DELAYLOAD:API-MS-Win-Shcore-Scaling-l1-1-1.dll # We shadowed GetDpiForMonitor
/DELAYLOAD:authz.dll # Authz.lib
/DELAYLOAD:comdlg32.dll
/DELAYLOAD:dwrite.dll # DWrite.lib
/DELAYLOAD:dxgi.dll # DXGI.lib
/DELAYLOAD:d3d9.dll # D3D9.lib
/DELAYLOAD:d3d11.dll # D3D11.lib
/DELAYLOAD:d3d12.dll # D3D12.lib
/DELAYLOAD:setupapi.dll # SetupAPI.lib
/DELAYLOAD:winhttp.dll
)
endif()
endif()
target_prepare_qrc(Telegram)
@ -2075,22 +2042,6 @@ if (NOT DESKTOP_APP_DISABLE_AUTOUPDATE AND NOT build_macstore AND NOT build_wins
base/platform/win/base_windows_safe_library.h
)
target_include_directories(Updater PRIVATE ${lib_base_loc})
if (MSVC)
target_link_libraries(Updater
PRIVATE
delayimp
)
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()
elseif (APPLE)
add_custom_command(TARGET Updater
PRE_LINK
@ -2143,14 +2094,16 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED)
configure_file("../lib/xdg/com.ayugram.desktop.metainfo.xml" "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.metainfo.xml" @ONLY)
generate_appdata_changelog(Telegram "${CMAKE_SOURCE_DIR}/changelog.txt" "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.metainfo.xml")
install(TARGETS Telegram RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "ayugram.png")
install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "ayugram.png")
install(FILES "Resources/art/icon48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "ayugram.png")
install(FILES "Resources/art/icon64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "ayugram.png")
install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "ayugram.png")
install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "ayugram.png")
install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "ayugram.png")
install(FILES "Resources/icons/tray_monochrome.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "ayugram-symbolic.svg")
install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/art/icon48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/art/icon64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "com.ayugram.desktop.png")
install(FILES "Resources/icons/tray_monochrome.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "com.ayugram.desktop-symbolic.svg")
install(FILES "Resources/icons/tray_monochrome_attention.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "com.ayugram.desktop-attention-symbolic.svg")
install(FILES "Resources/icons/tray_monochrome_mute.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "com.ayugram.desktop-mute-symbolic.svg")
install(FILES "../lib/xdg/com.ayugram.desktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.service" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/com.ayugram.desktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Mini / mini_gift_sorting2</title>
<g id="Mini-/-mini_gift_sorting2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M39.7913043,28.3413043 C40.9234881,28.3413043 41.8413043,29.2591206 41.8413043,30.3913043 L41.8413043,45 C41.8413043,46.1321837 40.9234881,47.05 39.7913043,47.05 C38.6591206,47.05 37.7413043,46.1321837 37.7413043,45 L37.7413043,30.3913043 C37.7413043,29.2591206 38.6591206,28.3413043 39.7913043,28.3413043 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M32.1330398,38.0495689 C32.9336146,38.8501437 34.2316028,38.8501437 35.0321776,38.0495689 L39.7906087,33.291 L44.5504311,38.0495689 C45.3088704,38.8080082 46.5137416,38.847926 47.3191738,38.1693225 L47.4495689,38.0495689 C48.2501437,37.2489941 48.2501437,35.9510059 47.4495689,35.1504311 L41.7573686,29.4582308 C40.6715413,28.3724035 38.9110674,28.3724035 37.8252401,29.4582308 L32.1330398,35.1504311 C31.332465,35.9510059 31.332465,37.2489941 32.1330398,38.0495689 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M36.5217391,5.3326087 C40.4153466,5.3326087 43.5717391,8.48900121 43.5717391,12.3826087 L43.5717391,21.7217391 C43.5717391,22.8539229 42.6539229,23.7717391 41.5217391,23.7717391 C40.3895554,23.7717391 39.4717391,22.8539229 39.4717391,21.7217391 L39.4717391,12.3826087 C39.4717391,10.7533687 38.1509791,9.4326087 36.5217391,9.4326087 L10,9.4326087 C8.37075999,9.4326087 7.05,10.7533687 7.05,12.3826087 L7.05,35.9826087 C7.05,37.6118487 8.37075999,38.9326087 10,38.9326087 L27.373913,38.9326087 C28.5060968,38.9326087 29.423913,39.850425 29.423913,40.9826087 C29.423913,42.1147924 28.5060968,43.0326087 27.373913,43.0326087 L10,43.0326087 C6.10639251,43.0326087 2.95,39.8762162 2.95,35.9826087 L2.95,12.3826087 C2.95,8.48900121 6.10639251,5.3326087 10,5.3326087 L36.5217391,5.3326087 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<polygon id="Path" fill="#FFFFFF" fill-rule="nonzero" points="6.09565217 20.3891304 40.426087 20.3891304 40.426087 16.2891304 6.09565217 16.2891304"></polygon>
<path d="M11.8434783,0.95 C12.975662,0.95 13.8934783,1.86781626 13.8934783,3 L13.8934783,6.65217391 C13.8934783,7.78435765 12.975662,8.70217391 11.8434783,8.70217391 C10.7112945,8.70217391 9.79347826,7.78435765 9.79347826,6.65217391 L9.79347826,3 C9.79347826,1.86781626 10.7112945,0.95 11.8434783,0.95 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M34.6782609,0.95 C35.8104446,0.95 36.7282609,1.86781626 36.7282609,3 L36.7282609,6.65217391 C36.7282609,7.78435765 35.8104446,8.70217391 34.6782609,8.70217391 C33.5460771,8.70217391 32.6282609,7.78435765 32.6282609,6.65217391 L32.6282609,3 C32.6282609,1.86781626 33.5460771,0.95 34.6782609,0.95 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Mini / mini_gift_sorting3</title>
<g id="Mini-/-mini_gift_sorting3" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M34.4778761,13.749192 C35.6376741,13.749192 36.5778761,14.689394 36.5778761,15.849192 C36.5778761,17.00899 35.6376741,17.949192 34.4778761,17.949192 L7.57258674,17.949192 C6.41278876,17.949192 5.47258674,17.00899 5.47258674,15.849192 C5.47258674,14.689394 6.41278876,13.749192 7.57258674,13.749192 L34.4778761,13.749192 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M30.923367,27.509546 C32.083165,27.509546 33.023367,28.4497481 33.023367,29.609546 C33.023367,30.769344 32.083165,31.709546 30.923367,31.709546 L4,31.709546 C2.84020203,31.709546 1.9,30.769344 1.9,29.609546 C1.9,28.4497481 2.84020203,27.509546 4,27.509546 L30.923367,27.509546 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M14.7584617,4.53380965 C15.0159315,3.40295129 16.1413939,2.69492999 17.2722522,2.9523998 C18.4031106,3.20986962 19.1111319,4.33533198 18.8536621,5.46619035 L10.9056841,40.3752813 C10.6482143,41.5061396 9.52275197,42.2141609 8.39189361,41.9566911 C7.26103524,41.6992213 6.55301394,40.5737589 6.81048375,39.4429006 L14.7584617,4.53380965 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M28.1811642,4.55038432 C28.4294801,3.41748072 29.5491797,2.70038069 30.6820833,2.94869657 C31.8149869,3.19701246 32.532087,4.31671208 32.2837711,5.44961568 L24.6322095,40.3587066 C24.3838936,41.4916102 23.264194,42.2087102 22.1312904,41.9603943 C20.9983868,41.7120785 20.2812868,40.5923788 20.5296027,39.4594752 L28.1811642,4.55038432 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M39.7913043,28.3413043 C40.9234881,28.3413043 41.8413043,29.2591206 41.8413043,30.3913043 L41.8413043,45 C41.8413043,46.1321837 40.9234881,47.05 39.7913043,47.05 C38.6591206,47.05 37.7413043,46.1321837 37.7413043,45 L37.7413043,30.3913043 C37.7413043,29.2591206 38.6591206,28.3413043 39.7913043,28.3413043 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M32.1330398,38.0495689 C32.9336146,38.8501437 34.2316028,38.8501437 35.0321776,38.0495689 L39.7906087,33.291 L44.5504311,38.0495689 C45.3088704,38.8080082 46.5137416,38.847926 47.3191738,38.1693225 L47.4495689,38.0495689 C48.2501437,37.2489941 48.2501437,35.9510059 47.4495689,35.1504311 L41.7573686,29.4582308 C40.6715413,28.3724035 38.9110674,28.3724035 37.8252401,29.4582308 L32.1330398,35.1504311 C31.332465,35.9510059 31.332465,37.2489941 32.1330398,38.0495689 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Mini / mini_gift_sorting1</title>
<g id="Mini-/-mini_gift_sorting1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M23.4380165,1.95 C35.3025073,1.95 44.9260331,11.510317 44.9260331,23.3103448 C44.9260331,23.5919731 44.9205389,23.8730129 44.9095753,24.1533571 C44.8653322,25.2846761 43.9123508,26.1659251 42.7810319,26.121682 C41.6497129,26.0774389 40.7684638,25.1244576 40.812707,23.9931386 C40.8215831,23.7661706 40.8260331,23.5385471 40.8260331,23.3103448 C40.8260331,13.7807547 33.0441659,6.05 23.4380165,6.05 C13.8318671,6.05 6.05,13.7807547 6.05,23.3103448 C6.05,32.839935 13.8318671,40.5706897 23.4380165,40.5706897 C25.2657432,40.5706897 27.0529516,40.2914087 28.7555206,39.7492213 C29.8343232,39.4056738 30.9873658,40.0017158 31.3309133,41.0805185 C31.6744608,42.1593211 31.0784187,43.3123637 29.9996161,43.6559112 C27.8959061,44.3258431 25.6891219,44.6706897 23.4380165,44.6706897 C11.5735257,44.6706897 1.95,35.1103726 1.95,23.3103448 C1.95,11.510317 11.5735257,1.95 23.4380165,1.95 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M39.7913043,28.3413043 C40.9234881,28.3413043 41.8413043,29.2591206 41.8413043,30.3913043 L41.8413043,45 C41.8413043,46.1321837 40.9234881,47.05 39.7913043,47.05 C38.6591206,47.05 37.7413043,46.1321837 37.7413043,45 L37.7413043,30.3913043 C37.7413043,29.2591206 38.6591206,28.3413043 39.7913043,28.3413043 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M32.1330398,38.0495689 C32.9336146,38.8501437 34.2316028,38.8501437 35.0321776,38.0495689 L39.7906087,33.291 L44.5504311,38.0495689 C45.3088704,38.8080082 46.5137416,38.847926 47.3191738,38.1693225 L47.4495689,38.0495689 C48.2501437,37.2489941 48.2501437,35.9510059 47.4495689,35.1504311 L41.7573686,29.4582308 C40.6715413,28.3724035 38.9110674,28.3724035 37.8252401,29.4582308 L32.1330398,35.1504311 C31.332465,35.9510059 31.332465,37.2489941 32.1330398,38.0495689 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M23.8366211,35.9195313 C24.4958008,35.9195313 25.281738,35.5533203 25.281738,34.6744141 L25.281738,33.5025391 C29.2221677,33.0777344 31.4831055,30.7632813 31.4831055,27.3941406 C31.4831055,24.49375 29.7399414,22.7359375 26.1217773,21.9449219 L23.1481445,21.2710938 C21.287793,20.8609375 20.3795898,20.0113281 20.3795898,18.7662109 C20.3795898,17.2720703 21.6686523,16.1880859 23.6901367,16.1880859 C25.3307617,16.1880859 26.4733398,16.7447266 27.7477539,18.165625 C28.3922852,18.8394531 28.890332,19.0884766 29.5641602,19.0884766 C30.3844727,19.0884766 31.0143555,18.5171875 31.0143555,17.6675781 C31.0143555,16.8472656 30.530957,15.9537109 29.7106445,15.1480469 C28.6266602,14.1226563 27.2006837,13.4488281 25.369629,13.2144531 L25.369629,11.9986328 C25.369629,11.134375 24.5836914,10.7681641 23.9098633,10.7681641 C23.2506836,10.7681641 22.464746,11.1197266 22.464746,11.9986328 L22.464746,13.1705078 C18.6708007,13.5220703 16.4538086,15.7925781 16.4538086,19.0445313 C16.4538086,21.8863281 18.1969727,23.7759766 21.5368164,24.5230469 L24.5104492,25.2115234 C26.678418,25.7242188 27.5719727,26.4859375 27.5719727,27.775 C27.5719727,29.4449219 26.2682617,30.4996094 23.9391602,30.4996094 C22.1959961,30.4996094 20.7458008,29.8404297 19.4274414,28.4195313 C18.6803711,27.6724609 18.2702148,27.5113281 17.7135742,27.5113281 C16.8200195,27.5113281 16.1461914,28.0826172 16.1461914,29.0640625 C16.1461914,29.9283203 16.6442383,30.821875 17.537793,31.5982422 C18.709668,32.6675781 20.3407222,33.3267578 22.376855,33.5171875 L22.376855,34.6744141 C22.376855,35.5533203 23.162793,35.9195313 23.8366211,35.9195313 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="plane" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M1.3311718,6.36592184 C5.3576954,4.67244493 8.04267511,3.5560013 9.38611094,3.01659096 C13.2218932,1.47646481 14.0189359,1.2089284 14.5384372,1.2 C14.6526967,1.19815119 14.9081723,1.22548649 15.0736587,1.35511219 C15.2133922,1.4645656 15.2518384,1.61242159 15.2702362,1.71619544 C15.288634,1.81996929 15.3115436,2.05636876 15.2933322,2.24108442 C15.0854698,4.34939964 14.1860526,9.46572464 13.7284802,11.8270738 C13.5348641,12.8262491 13.1536281,13.1612675 12.7845475,13.1940535 C11.9824498,13.265305 11.3733733,12.6823476 10.5965026,12.190753 C9.3808532,11.4215044 8.69408865,10.9426448 7.51409044,10.1920004 C6.15039834,9.32450079 7.03442319,8.84770795 7.81158733,8.06849502 C8.01497489,7.86457129 11.5490353,4.7615061 11.6174372,4.48000946 C11.625992,4.44480359 11.6339313,4.31357282 11.5531696,4.24427815 C11.472408,4.17498349 11.3532107,4.19867957 11.2671947,4.21752527 C11.1452695,4.24423848 9.20325394,5.48334063 5.44114787,7.93483171 C4.88991321,8.30022994 4.39062196,8.47826423 3.94327414,8.46893456 C3.45010907,8.45864936 2.50145729,8.19975808 1.79623221,7.97846422 C0.931244952,7.70703829 0.243770289,7.56353344 0.303633888,7.10256824 C0.334814555,6.86246904 0.677327192,6.61692024 1.3311718,6.36592184 Z" id="Path-3" fill="#FFFFFF"></path>
</g>
<circle class="error" fill="#f23c34" cx="3.9" cy="12.7" r="2.2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="plane" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M1.3311718,6.36592184 C5.3576954,4.67244493 8.04267511,3.5560013 9.38611094,3.01659096 C13.2218932,1.47646481 14.0189359,1.2089284 14.5384372,1.2 C14.6526967,1.19815119 14.9081723,1.22548649 15.0736587,1.35511219 C15.2133922,1.4645656 15.2518384,1.61242159 15.2702362,1.71619544 C15.288634,1.81996929 15.3115436,2.05636876 15.2933322,2.24108442 C15.0854698,4.34939964 14.1860526,9.46572464 13.7284802,11.8270738 C13.5348641,12.8262491 13.1536281,13.1612675 12.7845475,13.1940535 C11.9824498,13.265305 11.3733733,12.6823476 10.5965026,12.190753 C9.3808532,11.4215044 8.69408865,10.9426448 7.51409044,10.1920004 C6.15039834,9.32450079 7.03442319,8.84770795 7.81158733,8.06849502 C8.01497489,7.86457129 11.5490353,4.7615061 11.6174372,4.48000946 C11.625992,4.44480359 11.6339313,4.31357282 11.5531696,4.24427815 C11.472408,4.17498349 11.3532107,4.19867957 11.2671947,4.21752527 C11.1452695,4.24423848 9.20325394,5.48334063 5.44114787,7.93483171 C4.88991321,8.30022994 4.39062196,8.47826423 3.94327414,8.46893456 C3.45010907,8.45864936 2.50145729,8.19975808 1.79623221,7.97846422 C0.931244952,7.70703829 0.243770289,7.56353344 0.303633888,7.10256824 C0.334814555,6.86246904 0.677327192,6.61692024 1.3311718,6.36592184 Z" id="Path-3" fill="#FFFFFF"></path>
</g>
<circle fill="#888888" cx="3.9" cy="12.7" r="2.2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"cloud_lng_passport_in_ar" = "Arabic";
"cloud_lng_passport_in_az" = "Azerbaijani";
"cloud_lng_passport_in_bg" = "Bulgarian";
"cloud_lng_passport_in_bn" = "Bangla";
"cloud_lng_passport_in_bn" = "Bengali";
"cloud_lng_passport_in_cs" = "Czech";
"cloud_lng_passport_in_da" = "Danish";
"cloud_lng_passport_in_de" = "German";
@ -64,7 +64,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"cloud_lng_translate_to_ar" = "Arabic";
"cloud_lng_translate_to_az" = "Azerbaijani";
"cloud_lng_translate_to_bg" = "Bulgarian";
// "cloud_lng_translate_to_bn" = "Bangla";
// "cloud_lng_translate_to_bn" = "Bengali";
"cloud_lng_translate_to_cs" = "Czech";
"cloud_lng_translate_to_da" = "Danish";
"cloud_lng_translate_to_de" = "German";
@ -109,50 +109,116 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"cloud_lng_translate_to_uz" = "Uzbek";
"cloud_lng_translate_to_vi" = "Vietnamese";
"cloud_lng_language_af" = "Afrikaans";
"cloud_lng_language_am" = "Amharic";
"cloud_lng_language_ar" = "Arabic";
"cloud_lng_language_az" = "Azerbaijani";
"cloud_lng_language_be" = "Belarusian";
"cloud_lng_language_bg" = "Bulgarian";
// "cloud_lng_language_bn" = "Bangla";
"cloud_lng_language_bn" = "Bengali";
"cloud_lng_language_bs" = "Bosnian";
"cloud_lng_language_ca" = "Catalan";
// "cloud_lng_language_ceb" = "Cebuano";
"cloud_lng_language_co" = "Corsican";
"cloud_lng_language_cs" = "Czech";
"cloud_lng_language_cy" = "Welsh";
"cloud_lng_language_da" = "Danish";
"cloud_lng_language_de" = "German";
// "cloud_lng_language_dv" = "Divehi";
// "cloud_lng_language_dz" = "Dzongkha";
"cloud_lng_language_dv" = "Divehi";
"cloud_lng_language_dz" = "Dzongkha";
"cloud_lng_language_el" = "Greek";
"cloud_lng_language_en" = "English";
"cloud_lng_language_eo" = "Esperanto";
"cloud_lng_language_es" = "Spanish";
"cloud_lng_language_et" = "Estonian";
"cloud_lng_language_eu" = "Basque";
"cloud_lng_language_fa" = "Persian";
"cloud_lng_language_fi" = "Finnish";
"cloud_lng_language_fr" = "French";
"cloud_lng_language_fy" = "Frisian";
"cloud_lng_language_ga" = "Irish";
"cloud_lng_language_gd" = "Scots Gaelic";
"cloud_lng_language_gl" = "Galician";
"cloud_lng_language_gu" = "Gujarati";
"cloud_lng_language_ha" = "Hausa";
"cloud_lng_language_haw" = "Hawaiian";
"cloud_lng_language_he" = "Hebrew";
"cloud_lng_language_hi" = "Hindi";
// "cloud_lng_language_hmn" = "Hmong";
"cloud_lng_language_hr" = "Croatian";
"cloud_lng_language_ht" = "Haitian Creole";
"cloud_lng_language_hu" = "Hungarian";
"cloud_lng_language_hy" = "Armenian";
"cloud_lng_language_id" = "Indonesian";
"cloud_lng_language_ig" = "Igbo";
"cloud_lng_language_is" = "Icelandic";
"cloud_lng_language_it" = "Italian";
"cloud_lng_language_iw" = "Hebrew (Obsolete code)";
"cloud_lng_language_ja" = "Japanese";
"cloud_lng_language_jv" = "Javanese";
"cloud_lng_language_ka" = "Georgian";
// "cloud_lng_language_km" = "Khmer";
"cloud_lng_language_kk" = "Kazakh";
"cloud_lng_language_km" = "Khmer";
"cloud_lng_language_kn" = "Kannada";
"cloud_lng_language_ko" = "Korean";
"cloud_lng_language_ku" = "Kurdish";
"cloud_lng_language_ky" = "Kyrgyz";
"cloud_lng_language_la" = "Latin";
"cloud_lng_language_lb" = "Luxembourgish";
"cloud_lng_language_lo" = "Lao";
"cloud_lng_language_lt" = "Lithuanian";
"cloud_lng_language_lv" = "Latvian";
"cloud_lng_language_mg" = "Malagasy";
"cloud_lng_language_mi" = "Maori";
"cloud_lng_language_mk" = "Macedonian";
"cloud_lng_language_ml" = "Malayalam";
"cloud_lng_language_mn" = "Mongolian";
"cloud_lng_language_mr" = "Marathi";
"cloud_lng_language_ms" = "Malay";
"cloud_lng_language_mt" = "Maltese";
"cloud_lng_language_my" = "Burmese";
"cloud_lng_language_ne" = "Nepali";
"cloud_lng_language_nl" = "Dutch";
"cloud_lng_language_no" = "Norwegian";
"cloud_lng_language_ny" = "Nyanja";
"cloud_lng_language_or" = "Odia (Oriya)";
"cloud_lng_language_pa" = "Punjabi";
"cloud_lng_language_pl" = "Polish";
"cloud_lng_language_ps" = "Pashto";
"cloud_lng_language_pt" = "Portuguese";
"cloud_lng_language_ro" = "Romanian";
"cloud_lng_language_ru" = "Russian";
"cloud_lng_language_rw" = "Kinyarwanda";
"cloud_lng_language_sd" = "Sindhi";
"cloud_lng_language_si" = "Sinhala";
"cloud_lng_language_sk" = "Slovak";
"cloud_lng_language_sl" = "Slovenian";
"cloud_lng_language_sm" = "Samoan";
"cloud_lng_language_sn" = "Shona";
"cloud_lng_language_so" = "Somali";
"cloud_lng_language_sq" = "Albanian";
"cloud_lng_language_sr" = "Serbian";
"cloud_lng_language_st" = "Sesotho";
"cloud_lng_language_su" = "Sundanese";
"cloud_lng_language_sv" = "Swedish";
"cloud_lng_language_sw" = "Swahili";
"cloud_lng_language_ta" = "Tamil";
"cloud_lng_language_te" = "Telugu";
"cloud_lng_language_tg" = "Tajik";
"cloud_lng_language_th" = "Thai";
"cloud_lng_language_tk" = "Turkmen";
"cloud_lng_language_tl" = "Tagalog";
"cloud_lng_language_tr" = "Turkish";
"cloud_lng_language_tt" = "Tatar";
"cloud_lng_language_ug" = "Uyghur";
"cloud_lng_language_uk" = "Ukrainian";
"cloud_lng_language_ur" = "Urdu";
"cloud_lng_language_uz" = "Uzbek";
"cloud_lng_language_vi" = "Vietnamese";
"cloud_lng_language_xh" = "Xhosa";
"cloud_lng_language_yi" = "Yiddish";
"cloud_lng_language_yo" = "Yoruba";
"cloud_lng_language_zh" = "Chinese";
// "cloud_lng_language_zh-CN" = "Chinese (Simplified)";
// "cloud_lng_language_zh-TW" = "Chinese (Traditional)";
"cloud_lng_language_zu" = "Zulu";

View file

@ -681,6 +681,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_shortcuts_archive_chat" = "Archive chat";
"lng_shortcuts_media_fullscreen" = "Toggle video fullscreen";
"lng_shortcuts_show_chat_menu" = "Show chat menu";
"lng_shortcuts_show_chat_preview" = "Show chat preview";
"lng_settings_chat_reactions_title" = "Quick Reaction";
"lng_settings_chat_reactions_subtitle" = "Choose your favorite reaction";
@ -835,6 +836,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_disconnect" = "Disconnect";
"lng_settings_connected_title" = "Connected websites";
"lng_settings_suggestion_phone_number_title" = "Is {phone} still your number?";
"lng_settings_suggestion_phone_number_about" = "Keep your number up to date to ensure you can always log into Telegram. {link}";
"lng_settings_suggestion_phone_number_about_link" = "https://telegram.org/faq#q-i-have-a-new-phone-number-what-do-i-do";
"lng_settings_suggestion_phone_number_change" = "Please change your phone number in the official Telegram app on your phone as soon as possible. {emoji}";
"lng_settings_power_menu" = "Battery and Animations";
"lng_settings_power_title" = "Power Usage";
"lng_settings_power_subtitle" = "Power saving options";
@ -881,6 +887,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_cloud_password_email_confirm" = "Confirm and Finish";
"lng_settings_cloud_password_reset_in" = "You can reset your password in {duration}.";
"lng_settings_cloud_login_email_section_title" = "Login Email";
"lng_settings_cloud_login_email_box_about" = "This email address will be used every time you log in to your Telegram account from a new device.";
"lng_settings_cloud_login_email_box_ok" = "Change email";
"lng_settings_cloud_login_email_title" = "Enter New Email";
"lng_settings_cloud_login_email_placeholder" = "Enter Login Email";
"lng_settings_cloud_login_email_about" = "You will receive Telegram login codes via email and not SMS. Please enter an email address to which you have access.";
"lng_settings_cloud_login_email_confirm" = "Confirm";
"lng_settings_cloud_login_email_code_title" = "Check Your New Email";
"lng_settings_cloud_login_email_code_about" = "Please enter the code we have sent to your new email {email}";
"lng_settings_cloud_login_email_success" = "Your email has been changed.";
"lng_settings_error_email_not_alowed" = "Sorry, this email is not allowed";
"lng_settings_ttl_title" = "Auto-Delete Messages";
"lng_settings_ttl_about" = "Automatically delete messages for everyone after a period of time in all new chats you start.";
"lng_settings_ttl_after" = "After {after_duration}";
@ -1179,6 +1197,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_restart_now" = "Restart";
"lng_settings_restart_later" = "Later";
"lng_settings_quick_dialog_action_title" = "Chat list quick action";
"lng_settings_quick_dialog_action_about" = "Choose the action you want to perform when you middle-click or swipe left in the chat list.";
"lng_settings_quick_dialog_action_both" = "Swipe left and Middle-click";
"lng_settings_quick_dialog_action_swipe" = "Swipe left";
"lng_settings_quick_dialog_action_mute" = "Mute";
"lng_settings_quick_dialog_action_unmute" = "Unmute";
"lng_settings_quick_dialog_action_pin" = "Pin";
"lng_settings_quick_dialog_action_unpin" = "Unpin";
"lng_settings_quick_dialog_action_read" = "Read";
"lng_settings_quick_dialog_action_unread" = "Unread";
"lng_settings_quick_dialog_action_archive" = "Archive";
"lng_settings_quick_dialog_action_unarchive" = "Unarchive";
"lng_settings_quick_dialog_action_delete" = "Delete";
"lng_settings_quick_dialog_action_disabled" = "Change folder";
"lng_quick_dialog_action_toast_mute_success" = "Notifications for this chat have been muted.";
"lng_quick_dialog_action_toast_unmute_success" = "Notifications enabled for this chat.";
"lng_quick_dialog_action_toast_pin_success" = "The chat has been pinned.";
"lng_quick_dialog_action_toast_unpin_success" = "The chat has been unpinned.";
"lng_quick_dialog_action_toast_read_success" = "The chat has been marked as read.";
"lng_quick_dialog_action_toast_unread_success" = "The chat has been marked as unread.";
"lng_quick_dialog_action_toast_archive_success" = "The chat has been archived.";
"lng_quick_dialog_action_toast_unarchive_success" = "The chat has been unarchived.";
"lng_settings_generic_subscribe" = "Subscribe to {link} to use this setting.";
"lng_settings_generic_subscribe_link" = "Telegram Premium";
"lng_sessions_header" = "This device";
"lng_sessions_other_header" = "Active Devices";
"lng_sessions_other_desc" = "You can log in to Telegram from other mobile, tablet and desktop devices, using the same phone number. All your data will be instantly synchronized.";
@ -1218,6 +1263,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_contacts" = "My contacts";
"lng_edit_privacy_close_friends" = "Close friends";
"lng_edit_privacy_contacts_and_premium" = "Contacts & Premium";
"lng_edit_privacy_paid" = "Paid";
"lng_edit_privacy_contacts_and_miniapps" = "Contacts & Mini Apps";
"lng_edit_privacy_nobody" = "Nobody";
"lng_edit_privacy_premium" = "Premium users";
@ -1293,6 +1339,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_gifts_always_title" = "Always allow";
"lng_edit_privacy_gifts_never_title" = "Never allow";
"lng_edit_privacy_gifts_types" = "Accepted Gift Types";
"lng_edit_privacy_gifts_premium" = "Premium Subscriptions";
"lng_edit_privacy_gifts_unlimited" = "Unlimited";
"lng_edit_privacy_gifts_limited" = "Limited-Edition";
"lng_edit_privacy_gifts_unique" = "Unique";
"lng_edit_privacy_gifts_types_about" = "Choose the types of gifts that you accept.";
"lng_edit_privacy_gifts_show_icon" = "Show Gift Icon in Chats";
"lng_edit_privacy_gifts_show_icon_about" = "Display the {emoji}Gift icon in the message input field for both participants in all chats.";
"lng_edit_privacy_gifts_restricted" = "This user doesn't accept gifts.";
"lng_edit_privacy_calls_title" = "Calls";
"lng_edit_privacy_calls_header" = "Who can call me";
"lng_edit_privacy_calls_always_empty" = "Always allow";
@ -1356,6 +1412,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_messages_privacy_premium_about" = "Subscribe now to change this setting and get access to other exclusive features of Telegram Premium.";
"lng_messages_privacy_premium" = "Only subscribers of {link} can select this option.";
"lng_messages_privacy_premium_link" = "Telegram Premium";
"lng_messages_privacy_charge" = "Charge for messages";
"lng_messages_privacy_charge_about" = "Charge a fee for messages from people outside your contacts or those you haven't messaged first.";
"lng_messages_privacy_price" = "Set your price per message";
"lng_messages_privacy_price_about" = "You will receive {percent} of the selected fee ({amount}) for each incoming message.";
"lng_messages_privacy_exceptions" = "Exceptions";
"lng_messages_privacy_remove_fee" = "Remove Fee";
"lng_messages_privacy_remove_about" = "Add users or entire groups who won't be charged for sending messages to you.";
"lng_self_destruct_title" = "Account self-destruction";
"lng_self_destruct_description" = "If you don't come online at least once within this period, your account will be deleted along with all groups, messages and contacts.";
@ -2158,6 +2221,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_boost_apply#other" = "{from} boosted the group {count} times";
"lng_action_set_chat_intro" = "{from} added the message below for all empty chats. How?";
"lng_action_payment_refunded" = "{peer} refunded {amount}";
"lng_action_paid_message_sent#one" = "You paid {count} Star to {action}";
"lng_action_paid_message_sent#other" = "You paid {count} Stars to {action}";
"lng_action_paid_message_one" = "send a message";
"lng_action_paid_message_some#one" = "send {count} message";
"lng_action_paid_message_some#other" = "send {count} messages";
"lng_action_paid_message_got#one" = "You received {count} Star from {name}";
"lng_action_paid_message_got#other" = "You received {count} Stars from {name}";
"lng_action_paid_message_refund#one" = "{from} refunded {count} Star to you";
"lng_action_paid_message_refund#other" = "{from} refunded {count} Stars to you";
"lng_action_paid_message_refund_self#one" = "You refunded {count} Star to {name}";
"lng_action_paid_message_refund_self#other" = "You refunded {count} Stars to {name}";
"lng_action_message_price_free" = "Messages are now free in this group.";
"lng_action_message_price_paid#one" = "Messages now cost {count} Star each in this group.";
"lng_action_message_price_paid#other" = "Messages now cost {count} Stars each in this group.";
"lng_you_paid_stars#one" = "You paid {count} Star.";
"lng_you_paid_stars#other" = "You paid {count} Stars.";
"lng_you_joined_group" = "You joined this group";
"lng_similar_channels_title" = "Similar channels";
"lng_similar_channels_view_all" = "View all";
@ -2175,6 +2256,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_peer_gifts_title" = "Gifts";
"lng_peer_gifts_about" = "These gifts were sent to {user} by other users.";
"lng_peer_gifts_about_mine" = "These gifts were sent to you by other users. Click on a gift to convert it to Stars or change its privacy settings.";
"lng_peer_gifts_empty_search" = "No matching gifts";
"lng_peer_gifts_view_all" = "View All Gifts";
"lng_peer_gifts_notify" = "Notify About New Gifts";
"lng_peer_gifts_notify_enabled" = "You will receive a message from Telegram when your channel receives a gift.";
"lng_peer_gifts_filter_by_value" = "Sort by Value";
@ -2664,6 +2747,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_summary_history_entry_inner_in" = "In-App Purchase";
"lng_credits_summary_balance" = "Balance";
"lng_credits_commission" = "{amount} commission";
"lng_credits_paid_messages_fee#one" = "Fee for {count} Message";
"lng_credits_paid_messages_fee#other" = "Fee for {count} Messages";
"lng_credits_paid_messages_fee_about" = "You receive {percent} of the price that you charge for each incoming message. {link}";
"lng_credits_paid_messages_fee_about_link" = "Change Fee {emoji}";
"lng_credits_paid_messages_full" = "Full Price";
"lng_credits_premium_gift_duration" = "Duration";
"lng_credits_more_options" = "More Options";
"lng_credits_balance_me" = "your balance";
"lng_credits_buy_button" = "Buy More Stars";
@ -2741,6 +2830,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_box_history_entry_reaction_name" = "Star Reaction";
"lng_credits_box_history_entry_subscription" = "Monthly subscription fee";
"lng_credits_box_history_entry_gift_upgrade" = "Collectible Upgrade";
"lng_credits_box_history_entry_gift_sold" = "Gift Sale";
"lng_credits_box_history_entry_gift_bought" = "Gift Purchase";
"lng_credits_box_history_entry_gift_sold_to" = "To";
"lng_credits_box_history_entry_gift_full_price" = "Full Price";
"lng_credits_box_history_entry_gift_bought_from" = "From";
"lng_credits_subscription_section" = "My subscriptions";
"lng_credits_box_subscription_title" = "Subscription";
@ -2777,6 +2871,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_small_balance_reaction" = "Buy **Stars** and send them to {channel} to support their posts.";
"lng_credits_small_balance_subscribe" = "Buy **Stars** and subscribe to **{channel}** and other channels.";
"lng_credits_small_balance_star_gift" = "Buy **Stars** to send gifts to {user} and other contacts.";
"lng_credits_small_balance_for_message" = "Buy **Stars** to send messages to {user}.";
"lng_credits_small_balance_for_messages" = "Buy **Stars** to send messages.";
"lng_credits_small_balance_fallback" = "Buy **Stars** to unlock content and services on Telegram.";
"lng_credits_purchase_blocked" = "Sorry, you can't purchase this item with Telegram Stars.";
"lng_credits_enough" = "You have enough stars at the moment. {link}";
@ -2881,8 +2977,34 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_chatbots_include_button" = "Select Chats";
"lng_chatbots_exclude_about" = "Select chats or entire chat categories which the bot will not have access to.";
"lng_chatbots_permissions_title" = "Bot permissions";
"lng_chatbots_warning_title" = "Warning";
"lng_chatbots_warning_both_text" = "The bot {bot} will be able to **manage your gifts and stars**, including giving them away to other users.";
"lng_chatbots_warning_gifts_text" = "The bot {bot} will be able to **manage your gifts**, including giving them away to other users.";
"lng_chatbots_warning_stars_text" = "The bot {bot} will be able to **transfer your stars**.";
"lng_chatbots_warning_username_text" = "The bot {bot} will be able to **set and remove usernames** for your account, which may result in the loss of your current username.";
"lng_chatbots_manage_messages" = "Manage Messages";
"lng_chatbots_read" = "Read Messages";
"lng_chatbots_reply" = "Reply to Messages";
"lng_chatbots_reply_about" = "The bot can only reply on your behalf in chats that were active during the last 24h.";
"lng_chatbots_mark_as_read" = "Mark Messages as Read";
"lng_chatbots_delete_sent" = "Delete Sent Messages";
"lng_chatbots_delete_received" = "Delete Received Messages";
"lng_chatbots_manage_profile" = "Manage Profile";
"lng_chatbots_edit_name" = "Edit Name";
"lng_chatbots_edit_bio" = "Edit Bio";
"lng_chatbots_edit_userpic" = "Edit Profile Picture";
"lng_chatbots_edit_username" = "Edit Username";
"lng_chatbots_manage_gifts" = "Manage Gifts and Stars";
"lng_chatbots_view_gifts" = "View Gifts";
"lng_chatbots_sell_gifts" = "Sell Gifts";
"lng_chatbots_gift_settings" = "Change Gift Settings";
"lng_chatbots_transfer_gifts" = "Transfer and Upgrade Gifts";
"lng_chatbots_transfer_stars" = "Transfer Stars";
"lng_chatbots_manage_stories" = "Manage Stories";
"lng_chatbots_remove" = "Remove Bot";
"lng_chatbots_not_found" = "Chatbot not found.";
"lng_chatbots_not_supported" = "This bot doesn't support Telegram Business yet.";
@ -3050,6 +3172,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boost_group_ask" = "Ask your **Premium** members to boost your group with this link:";
//"lng_boost_group_gifting" = "Boost your group by gifting your members Telegram Premium. {link}";
"lng_boost_channel_title_autotranslate" = "Autotranslation of Messages";
"lng_boost_channel_needs_level_autotranslate#one" = "Your channel needs to reach **Level {count}** to enable autotranslation of messages.";
"lng_boost_channel_needs_level_autotranslate#other" = "Your channel needs to reach **Level {count}** to enable autotranslation of messages.";
"lng_feature_stories#one" = "**{count}** Story Per Day";
"lng_feature_stories#other" = "**{count}** Stories Per Day";
"lng_feature_reactions#one" = "**{count}** Custom Reaction";
@ -3068,6 +3194,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_feature_custom_background_group" = "Custom Group Background";
"lng_feature_custom_emoji_pack" = "Custom Emoji Pack";
"lng_feature_transcribe" = "Voice-to-Text Conversion";
"lng_feature_autotranslate" = "Autotranslation of Messages";
"lng_giveaway_new_title" = "Boosts via Gifts";
"lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers.";
@ -3310,19 +3437,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_premium_about" = "Give {name} access to exclusive features with Telegram Premium. {features}";
"lng_gift_premium_features" = "See Features >";
"lng_gift_premium_label" = "Premium";
"lng_gift_premium_by_stars" = "or {amount}";
"lng_gift_stars_subtitle" = "Gift Stars";
"lng_gift_stars_about" = "Give {name} gifts that can be kept on your profile or converted to Stars. {link}";
"lng_gift_stars_link" = "What are Stars >";
"lng_gift_stars_limited" = "limited";
"lng_gift_stars_sold_out" = "sold out";
"lng_gift_stars_resale" = "resale";
"lng_gift_stars_on_sale" = "on sale";
"lng_gift_stars_tabs_all" = "All Gifts";
"lng_gift_stars_tabs_my" = "My Gifts";
"lng_gift_stars_tabs_limited" = "Limited";
"lng_gift_stars_tabs_in_stock" = "In Stock";
"lng_gift_stars_tabs_resale" = "Resale";
"lng_gift_send_title" = "Send a Gift";
"lng_gift_send_message" = "Enter Message";
"lng_gift_send_anonymous" = "Hide My Name";
"lng_gift_send_pay_with_stars" = "Pay with {amount}";
"lng_gift_send_stars_balance" = "Your balance is {amount}. {link}";
"lng_gift_send_stars_balance_link" = "Get More Stars >";
"lng_gift_send_anonymous_self" = "Hide my name and message from visitors to my profile.";
"lng_gift_send_anonymous_about" = "You can hide your name and message from visitors to {user}'s profile. {recipient} will still see your name and message.";
"lng_gift_send_anonymous_about_paid" = "You can hide your name from visitors to {user}'s profile. {recipient} will still see your name.";
"lng_gift_send_anonymous_about_channel" = "You can hide your name and message from all visitors of this channel except its admins.";
"lng_gift_send_unique" = "Make Unique for {price}";
"lng_gift_send_unique_about" = "Enable this to let {user} turn your gift into a unique collectible. {link}";
@ -3335,13 +3471,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_send_limited_left#other" = "{count} left";
"lng_gift_send_button" = "Send a Gift for {cost}";
"lng_gift_send_button_self" = "Buy a Gift for {cost}";
"lng_gift_buy_resale_title" = "Buy {name}";
"lng_gift_buy_resale_button" = "Buy for {cost}";
"lng_gift_buy_resale_confirm" = "Do you want to buy {name} for {price} and gift it to {user}?";
"lng_gift_buy_resale_confirm_self" = "Do you want to buy {name} for {price}?";
"lng_gift_buy_price_change_title" = "Price change!";
"lng_gift_buy_price_change_text" = "This gift price was changed and now is {price}. Do you still want to buy?";
"lng_gift_sent_title" = "Gift Sent!";
"lng_gift_sent_resale_done" = "{user} has been notified about your gift.";
"lng_gift_sent_resale_done_self" = "{gift} is now yours.";
"lng_gift_sent_about#one" = "You spent **{count}** Star from your balance.";
"lng_gift_sent_about#other" = "You spent **{count}** Stars from your balance.";
"lng_gift_limited_of_one" = "unique";
"lng_gift_limited_of_count" = "1 of {amount}";
"lng_gift_collectible_tag" = "gift";
"lng_gift_price_unique" = "Unique";
"lng_gift_view_unpack" = "Unpack";
"lng_gift_anonymous_hint" = "Only you can see the sender's name.";
"lng_gift_anonymous_hint_channel" = "Only admins of this channel can see the sender's name.";
@ -3357,6 +3500,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_show_on_channel" = "Display in channel's Gifts";
"lng_gift_availability" = "Availability";
"lng_gift_from_hidden" = "Hidden User";
"lng_gift_subtitle_birthdays" = "Birthdays";
"lng_gift_list_birthday_status_today" = "{emoji} Birthday today";
"lng_gift_list_birthday_status_yesterday" = "Birthday yesterday";
"lng_gift_list_birthday_status_tomorrow" = "Birthday tomorrow";
"lng_gift_self_status" = "buy yourself a gift";
"lng_gift_self_title" = "Buy a Gift";
"lng_gift_self_about" = "Buy yourself a gift to display on your page or reserve for later.\n\nLimited-edition gifts upgraded to collectibles can be gifted to others later.";
@ -3398,6 +3545,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_display_done_channel" = "The gift is now shown in channel's Gifts.";
"lng_gift_display_done_hide" = "The gift is now hidden from your profile page.";
"lng_gift_display_done_hide_channel" = "The gift is now hidden from channel's Gifts.";
"lng_gift_pinned_done_title" = "{gift} pinned";
"lng_gift_pinned_done" = "The gift will always be shown on top.";
"lng_gift_pinned_done_replaced" = "replacing {gift}";
"lng_gift_got_stars#one" = "You got **{count} Star** for this gift.";
"lng_gift_got_stars#other" = "You got **{count} Stars** for this gift.";
"lng_gift_channel_got#one" = "Channel got **{count} Star** for this gift.";
@ -3456,6 +3606,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_transfer_button_for" = "Transfer for {price}";
"lng_gift_transfer_wear" = "Wear";
"lng_gift_transfer_take_off" = "Take Off";
"lng_gift_transfer_sell" = "Sell";
"lng_gift_transfer_update" = "Change Price";
"lng_gift_transfer_unlist" = "Unlist";
"lng_gift_sell_unlist_title" = "Unlist {name}";
"lng_gift_sell_unlist_sure" = "Are you sure you want to unlist your gift?";
"lng_gift_sell_title" = "Price in Stars";
"lng_gift_sell_placeholder" = "Enter price in Stars";
"lng_gift_sell_about" = "You will receive {percent} of the selected amount.";
"lng_gift_sell_amount#one" = "You will receive **{count}** Star.";
"lng_gift_sell_amount#other" = "You will receive **{count}** Stars.";
"lng_gift_sell_min_price#one" = "Minimum price is {count} Star.";
"lng_gift_sell_min_price#other" = "Minimum price is {count} Stars.";
"lng_gift_sell_put" = "Put for Sale";
"lng_gift_sell_update" = "Update the Price";
"lng_gift_sell_toast" = "{name} is now for sale!";
"lng_gift_sell_updated" = "Sale price for {name} was updated.";
"lng_gift_sell_removed" = "{name} is removed from sale.";
"lng_gift_menu_show" = "Show";
"lng_gift_menu_hide" = "Hide";
"lng_gift_wear_title" = "Wear {name}";
"lng_gift_wear_about" = "and get these benefits:";
"lng_gift_wear_badge_title" = "Radiant Badge";
@ -3468,6 +3637,29 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_wear_subscribe" = "Subscribe to {link} to wear collectibles.";
"lng_gift_wear_start_toast" = "You put on {name}";
"lng_gift_wear_end_toast" = "You took off {name}";
"lng_gift_many_pinned_title" = "Too Many Pinned Gifts";
"lng_gift_many_pinned_choose" = "Select a gift to unpin below";
"lng_gift_resale_price" = "Price";
"lng_gift_resale_number" = "Number";
"lng_gift_resale_date" = "Date";
"lng_gift_resale_count#one" = "{count} gift in resale";
"lng_gift_resale_count#other" = "{count} gifts in resale";
"lng_gift_resale_sort_price" = "Sort by Price";
"lng_gift_resale_sort_date" = "Sort by Date";
"lng_gift_resale_sort_number" = "Sort by Number";
"lng_gift_resale_filter_all" = "Select All";
"lng_gift_resale_model" = "Model";
"lng_gift_resale_models#one" = "{count} Model";
"lng_gift_resale_models#other" = "{count} Models";
"lng_gift_resale_backdrop" = "Backdrop";
"lng_gift_resale_backdrops#one" = "{count} Backdrop";
"lng_gift_resale_backdrops#other" = "{count} Backdrops";
"lng_gift_resale_symbol" = "Symbol";
"lng_gift_resale_symbols#one" = "{count} Symbol";
"lng_gift_resale_symbols#other" = "{count} Symbols";
"lng_gift_resale_early" = "You will be able to resell this gift in {duration}.";
"lng_gift_transfer_early" = "You will be able to transfer this gift in {duration}.";
"lng_gift_resale_transfer_early_title" = "Try Later";
"lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";
@ -3583,6 +3775,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_restrict_users" = "Restrict users";
"lng_delete_all_from_user" = "Delete all from {user}";
"lng_delete_all_from_users" = "Delete all from users";
"lng_restrict_user#one" = "Restrict user";
"lng_restrict_user#other" = "Restrict users";
"lng_restrict_user_part" = "Partially restrict this user {emoji}";
"lng_restrict_users_part" = "Partially restrict users {emoji}";
"lng_restrict_user_full" = "Fully ban this user {emoji}";
@ -3609,6 +3803,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_new_contact_from_request_group" = "{user} is an admin of {name}, a group you requested to join.";
"lng_new_contact_about_status" = "This account uses {emoji} as a custom status next to its\nname. Such emoji statuses are available to all\nsubscribers of {link}.";
"lng_new_contact_about_status_link" = "Telegram Premium";
"lng_new_contact_not_contact" = "Not a contact";
"lng_new_contact_phone_number" = "Phone number";
"lng_new_contact_registration" = "Registration";
"lng_new_contact_common_groups" = "Common groups";
"lng_new_contact_groups#one" = "{count} group {emoji} {arrow}";
"lng_new_contact_groups#other" = "{count} groups {emoji} {arrow}";
"lng_new_contact_not_official" = "Not an official account";
"lng_new_contact_updated_name" = "User updated name {when}";
"lng_new_contact_updated_photo" = "User updated photo {when}";
"lng_new_contact_updated_now" = "less than an hour ago";
"lng_new_contact_updated_hours#one" = "{count} hour ago";
"lng_new_contact_updated_hours#other" = "{count} hours ago";
"lng_new_contact_updated_days#one" = "{count} day ago";
"lng_new_contact_updated_days#other" = "{count} days ago";
"lng_new_contact_updated_months#one" = "{count} month ago";
"lng_new_contact_updated_months#other" = "{count} months ago";
"lng_from_request_title_channel" = "Response to your join request";
"lng_from_request_title_group" = "Response to your join request";
"lng_from_request_body" = "You received this message because you requested to join {name} on {date}.";
@ -3637,6 +3847,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_send_anonymous_ph" = "Send anonymously...";
"lng_story_reply_ph" = "Reply privately...";
"lng_story_comment_ph" = "Comment story...";
"lng_message_paid_ph" = "Message for {amount}";
"lng_send_text_no" = "Text not allowed.";
"lng_send_text_no_about" = "The admins of this group only allow sending {types}.";
"lng_send_text_type_and_last" = "{types} and {last}";
@ -3743,6 +3954,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_dialogs_skip_archive_in_search" = "Skip results from archive";
"lng_dialogs_show_archive_in_search" = "With results from archive";
"lng_dialogs_suggestions_birthday_title" = "Add your birthday! 🎂";
"lng_dialogs_suggestions_birthday_about" = "Let your contacts know when youre celebrating.";
"lng_dialogs_suggestions_birthday_contact_title" = "Its {text}'s **birthday** today! 🎂";
"lng_dialogs_suggestions_birthday_contact_about" = "Send them a Gift.";
"lng_dialogs_suggestions_birthday_contacts_title#one" = "{count} contact have **birthdays** today! 🎂";
"lng_dialogs_suggestions_birthday_contacts_title#other" = "{count} contacts have **birthdays** today! 🎂";
"lng_dialogs_suggestions_birthday_contacts_about" = "Send them a Gift.";
"lng_dialogs_suggestions_birthday_contact_dismiss" = "You can send a Gift later in Settings";
"lng_dialogs_suggestions_premium_annual_title" = "Telegram Premium with a {text} discount";
"lng_dialogs_suggestions_premium_annual_about" = "Sign up for the annual payment plan for Telegram Premium now to get the discount.";
"lng_dialogs_suggestions_premium_upgrade_title" = "Telegram Premium with a {text} discount";
"lng_dialogs_suggestions_premium_upgrade_about" = "Upgrade to the annual payment plan for Telegram Premium now to get the discount.";
"lng_dialogs_suggestions_premium_restore_title" = "Get Premium back with up to {text} off";
"lng_dialogs_suggestions_premium_restore_about" = "Your Telegram Premium has recently expired. Tap here to extend it.";
"lng_dialogs_suggestions_premium_grace_title" = "⚠️ Your Premium subscription is expiring!";
"lng_dialogs_suggestions_premium_grace_about" = "Dont lose access to exclusive features.";
"lng_dialogs_suggestions_userpics_title" = "Add your photo! 📸";
"lng_dialogs_suggestions_userpics_about" = "Help your friends spot you easily.";
"lng_dialogs_suggestions_credits_sub_low_title#one" = "{emoji} {count} Star needed for {channels}";
"lng_dialogs_suggestions_credits_sub_low_title#other" = "{emoji} {count} Stars needed for {channels}";
"lng_dialogs_suggestions_credits_sub_low_about" = "Insufficient funds to cover your subscription.";
"lng_about_random" = "Send a {emoji} emoji to any chat to try your luck.";
"lng_about_random_send" = "Send";
@ -4080,6 +4313,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sensitive_toast" = "You can update the visibility of sensitive media in **Settings > Chat Settings > Sensitive content**";
"lng_translate_show_original" = "Show Original";
"lng_translate_return_original" = "View Original ({language})";
"lng_translate_bar_to" = "Translate to {name}";
"lng_translate_bar_to_other" = "Translate to {name}";
"lng_translate_menu_to" = "Translate To";
@ -4187,6 +4421,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_contact_title" = "Edit contact";
"lng_edit_channel_title" = "Edit channel";
"lng_edit_bot_title" = "Edit bot";
"lng_edit_autotranslate" = "Auto-translate messages";
"lng_edit_sign_messages" = "Sign messages";
"lng_edit_sign_messages_about" = "Add names of admins to the messages they post.";
"lng_edit_sign_profiles" = "Show authors' profiles";
@ -4281,6 +4516,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_search_filter_private" = "Private chats";
"lng_search_filter_group" = "Group chats";
"lng_search_filter_channel" = "Channels";
"lng_search_sponsored_button" = "Ad ⋮";
"lng_media_save_progress" = "{ready} of {total} {mb}";
"lng_mediaview_save_as" = "Save As...";
@ -4494,6 +4730,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_call_status_failed" = "failed to connect";
"lng_call_status_ringing" = "ringing...";
"lng_call_status_busy" = "line busy";
"lng_call_status_group_invite" = "Telegram Group Call";
"lng_call_status_sure" = "Click on the Camera icon if you want to start a video call.";
"lng_call_fingerprint_tooltip" = "If the emoji on {user}'s screen are the same, this call is 100% secure";
@ -4503,6 +4740,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_call_error_camera_not_started" = "You can switch to video call once you're connected.";
"lng_call_error_camera_outdated" = "{user}'s app does not support video calls. They need to update their app before you can call them.";
"lng_call_error_audio_io" = "There seems to be a problem with your sound card. Please make sure that your computer's speakers and microphone are working and try again.";
"lng_call_error_add_not_started" = "You can add more people once you're connected.";
"lng_call_bar_hangup" = "End call";
"lng_call_leave_to_other_sure" = "End your active call and join this video chat?";
@ -4521,16 +4759,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_call_outgoing" = "Outgoing call";
"lng_call_video_outgoing" = "Outgoing video call";
"lng_call_group_outgoing" = "Outgoing group call";
"lng_call_incoming" = "Incoming call";
"lng_call_video_incoming" = "Incoming video call";
"lng_call_group_incoming" = "Incoming group call";
"lng_call_missed" = "Missed call";
"lng_call_video_missed" = "Missed video call";
"lng_call_group_missed" = "Missed group call";
"lng_call_cancelled" = "Canceled call";
"lng_call_video_cancelled" = "Canceled video call";
"lng_call_declined" = "Declined call";
"lng_call_video_declined" = "Declined video call";
"lng_call_group_declined" = "Declined group call";
"lng_call_duration_info" = "{time}, {duration}";
"lng_call_type_and_duration" = "{type} ({duration})";
"lng_call_invitation" = "Group call invitation";
"lng_call_ongoing" = "Ongoing group call";
"lng_call_rate_label" = "Please rate the quality of your call";
"lng_call_rate_comment" = "Comment (optional)";
@ -4539,6 +4783,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_call_start_video" = "Start Video";
"lng_call_stop_video" = "Stop Video";
"lng_call_screencast" = "Screencast";
"lng_call_add_people" = "Add People";
"lng_call_end_call" = "End Call";
"lng_call_mute_audio" = "Mute";
"lng_call_unmute_audio" = "Unmute";
@ -4570,8 +4815,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_connecting" = "Connecting...";
"lng_group_call_leave" = "Leave";
"lng_group_call_leave_title" = "Leave video chat";
"lng_group_call_leave_title_call" = "Leave group call";
"lng_group_call_leave_title_channel" = "Leave live stream";
"lng_group_call_leave_sure" = "Do you want to leave this video chat?";
"lng_group_call_leave_sure_call" = "Do you want to leave this group call?";
"lng_group_call_leave_sure_channel" = "Are you sure you want to leave this live stream?";
"lng_group_call_close" = "Close";
"lng_group_call_close_sure" = "Video chat is scheduled. You can abort it or just close this panel.";
@ -4601,15 +4848,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_also_end_channel" = "End live stream";
"lng_group_call_settings_title" = "Settings";
"lng_group_call_invite" = "Invite Members";
"lng_group_call_invite_conf" = "Add People";
"lng_group_call_invited_status" = "invited";
"lng_group_call_calling_status" = "calling...";
"lng_group_call_blockchain_only_status" = "listening";
"lng_group_call_muted_by_me_status" = "muted for you";
"lng_group_call_invite_title" = "Invite members";
"lng_group_call_invite_button" = "Invite";
"lng_group_call_confcall_add" = "Call";
"lng_group_call_add_to_group_one" = "{user} isn't a member of «{group}». Add them to the group?";
"lng_group_call_add_to_group_some" = "Some of those users aren't members of «{group}». Add them to the group?";
"lng_group_call_add_to_group_all" = "Those users aren't members of «{group}». Add them to the group?";
"lng_group_call_invite_members" = "Group members";
"lng_group_call_invite_search_results" = "Search results";
"lng_group_call_invite_limit" = "This is currently the maximum allowed number of participants.";
"lng_group_call_new_muted" = "Mute new participants";
"lng_group_call_speakers" = "Speakers";
"lng_group_call_microphone" = "Microphone";
@ -4648,6 +4900,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_context_pin_screen" = "Pin screencast";
"lng_group_call_context_unpin_screen" = "Unpin screencast";
"lng_group_call_context_remove" = "Remove";
"lng_group_call_context_cancel_invite" = "Discard invite";
"lng_group_call_context_stop_ringing" = "Stop calling";
"lng_group_call_context_ban_from_call" = "Ban from call";
"lng_group_call_remove_channel" = "Remove {channel} from the video chat and ban them?";
"lng_group_call_remove_channel_from_channel" = "Remove {channel} from the live stream?";
"lng_group_call_mac_access" = "Telegram Desktop does not have access to system wide keyboard input required for Push to Talk.";
@ -4756,6 +5011,54 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_rtmp_viewers#one" = "{count} viewer";
"lng_group_call_rtmp_viewers#other" = "{count} viewers";
"lng_confcall_join_title" = "Group Call";
"lng_confcall_join_text" = "You are invited to join a Telegram Call.";
"lng_confcall_join_text_inviter" = "{user} is inviting you to join a Telegram Call.";
"lng_confcall_already_joined_one" = "{user} already joined this call.";
"lng_confcall_already_joined_two" = "{user} and {other} already joined this call.";
"lng_confcall_already_joined_three" = "{user}, {other} and {third} already joined this call.";
"lng_confcall_already_joined_many#one" = "{user}, {other} and **{count}** other person already joined this call.";
"lng_confcall_already_joined_many#other" = "{user}, {other} and **{count}** other people already joined this call.";
"lng_confcall_join_button" = "Join Group Call";
"lng_confcall_create_call" = "Start New Call";
"lng_confcall_create_call_description#one" = "You can add up to {count} participant to a call.";
"lng_confcall_create_call_description#other" = "You can add up to {count} participants to a call.";
"lng_confcall_create_title" = "New Call";
"lng_confcall_create_link" = "Create Call Link";
"lng_confcall_create_link_description" = "You can create a link that will allow your friends on Telegram to join the call.";
"lng_confcall_link_revoke" = "Revoke link";
"lng_confcall_link_revoked_title" = "Link Revoked";
"lng_confcall_link_inactive" = "This link is no longer active.";
"lng_confcall_link_revoked_text" = "A new link has been generated.";
"lng_confcall_link_title" = "Call Link";
"lng_confcall_link_about" = "Anyone on Telegram can join your call by following the link below.";
"lng_confcall_link_or" = "or";
"lng_confcall_link_join" = "Be the first to join the call and add people from there. {link}";
"lng_confcall_link_join_link" = "Open call {arrow}";
"lng_confcall_inactive_title" = "Start Group Call";
"lng_confcall_inactive_about" = "This call is no longer active.\nYou can start a new one.";
"lng_confcall_invite_done_user" = "You're calling {user} to join.";
"lng_confcall_invite_done_many#one" = "You're calling **{count} person** to join.";
"lng_confcall_invite_done_many#other" = "You're calling **{count} people** to join.";
"lng_confcall_invite_already_user" = "{user} is already in the call.";
"lng_confcall_invite_already_many#one" = "**{count} person** is already in the call.";
"lng_confcall_invite_already_many#other" = "**{count} people** are already in the call.";
"lng_confcall_invite_privacy_user" = "You cannot call {user} because of their privacy settings.";
"lng_confcall_invite_privacy_many#one" = "You cannot call **{count} person** because of their privacy settings.";
"lng_confcall_invite_privacy_many#other" = "You cannot call **{count} people** because of their privacy settings.";
"lng_confcall_invite_fail_user" = "Couldn't call {user} to join.";
"lng_confcall_invite_fail_many#one" = "Couldn't call **{count} person** to join.";
"lng_confcall_invite_fail_many#other" = "Couldn't call **{count} people** to join.";
"lng_confcall_invite_kicked_user" = "{user} was banned from the call.";
"lng_confcall_invite_kicked_many#one" = "**{count} person** was removed from the call.";
"lng_confcall_invite_kicked_many#other" = "**{count} people** were removed from the call.";
"lng_confcall_not_accessible" = "This call is no longer accessible.";
"lng_confcall_participants_limit" = "This call reached the participants limit.";
"lng_confcall_sure_remove" = "Remove {user} from the call?";
"lng_confcall_e2e_badge" = "End-to-End Encrypted";
"lng_confcall_e2e_badge_small" = "E2E Encrypted";
"lng_confcall_e2e_about" = "These four emoji represent the call's encryption key. They must match for all participants and change when someone joins or leaves.";
"lng_no_mic_permission" = "Telegram needs microphone access so that you can make calls and record voice messages.";
"lng_player_message_today" = "today at {time}";
@ -4798,6 +5101,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_rights_boosts_no_restrict" = "Do not restrict boosters";
"lng_rights_boosts_about" = "Turn this on to always allow users who boosted your group to send messages and media.";
"lng_rights_boosts_about_on" = "Choose how many boosts a user must give to the group to bypass restrictions on sending messages.";
"lng_rights_charge_stars" = "Charge Stars for Messages";
"lng_rights_charge_stars_about" = "If you turn this on, regular members of the group will have to pay Stars to send messages.";
"lng_rights_charge_price" = "Set price per message";
"lng_rights_charge_price_about" = "Your group will receive {percent} of the selected fee ({amount}) for each incoming message.";
"lng_slowmode_enabled" = "Slow Mode is active.\nYou can send your next message in {left}.";
"lng_slowmode_no_many" = "Slow mode is enabled. You can't send more than one message at a time.";
@ -4805,6 +5112,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_slowmode_seconds#one" = "{count} second";
"lng_slowmode_seconds#other" = "{count} seconds";
"lng_payment_confirm_title" = "Confirm payment";
"lng_payment_confirm_text#one" = "{name} charges **{count}** Star per message.";
"lng_payment_confirm_text#other" = "{name} charges **{count}** Stars per message.";
"lng_payment_confirm_amount#one" = "**{count}** Star";
"lng_payment_confirm_amount#other" = "**{count}** Stars";
"lng_payment_confirm_users#one" = "You selected **{count}** user who charge Stars for messages.";
"lng_payment_confirm_users#other" = "You selected **{count}** users who charge Stars for messages.";
"lng_payment_confirm_chats#one" = "You selected **{count}** chat where you pay Stars for messages.";
"lng_payment_confirm_chats#other" = "You selected **{count}** chats where you pay Stars for messages.";
"lng_payment_confirm_sure#one" = "Would you like to pay {amount} to send **{count}** message?";
"lng_payment_confirm_sure#other" = "Would you like to pay {amount} to send **{count}** messages?";
"lng_payment_confirm_dont_ask" = "Don't ask me again";
"lng_payment_confirm_button#one" = "Pay for {count} Message";
"lng_payment_confirm_button#other" = "Pay for {count} Messages";
"lng_payment_bar_text" = "{name} must pay {cost} for each message to you.";
"lng_payment_bar_button" = "Remove Fee";
"lng_payment_refund_title" = "Remove Fee";
"lng_payment_refund_text" = "Are you sure you want to allow {name} to message you for free?";
"lng_payment_refund_also#one" = "Refund already paid {count} Star";
"lng_payment_refund_also#other" = "Refund already paid {count} Stars";
"lng_payment_refund_confirm" = "Confirm";
"lng_rights_gigagroup_title" = "Broadcast group";
"lng_rights_gigagroup_convert" = "Convert to Broadcast Group";
"lng_rights_gigagroup_about" = "Broadcast groups can have over 200,000 members, but only admins can send messages in them.";
@ -4936,6 +5265,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_send_non_premium_message_toast" = "**{user}** only accepts messages from contacts and {link} subscribers.";
"lng_send_non_premium_message_toast_link" = "Telegram Premium";
"lng_send_charges_stars_text" = "{user} charges {amount} for each message.";
"lng_send_charges_stars_go" = "Buy Stars";
"lng_exceptions_list_title" = "Exceptions";
"lng_removed_list_title" = "Removed users";
@ -4946,10 +5278,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_filter_all_actions" = "All actions";
"lng_admin_log_filter_actions_type_subtitle" = "Filter actions by type";
"lng_admin_log_filter_actions_member_section" = "Members And Admins";
"lng_admin_log_filter_actions_subscriber_section" = "Subscribers And Admins";
"lng_admin_log_filter_restrictions" = "New restrictions";
"lng_admin_log_filter_admins_new" = "Admin rights";
"lng_admin_log_filter_members_new" = "New members";
"lng_admin_log_filter_subscribers_new" = "New subscribers";
"lng_admin_log_filter_actions_settings_section" = "Group Settings";
"lng_admin_log_filter_actions_channel_settings_section" = "Channel Settings";
"lng_admin_log_filter_info_group" = "Group info";
"lng_admin_log_filter_info_channel" = "Channel info";
"lng_admin_log_filter_actions_messages_section" = "Messages";
@ -4960,6 +5295,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_filter_voice_chats_channel" = "Live stream";
"lng_admin_log_filter_invite_links" = "Invite links";
"lng_admin_log_filter_members_removed" = "Members leaving";
"lng_admin_log_filter_subscribers_removed" = "Subscribers leaving";
"lng_admin_log_filter_topics" = "Topics";
"lng_admin_log_filter_sub_extend" = "Subscription Renewals";
"lng_admin_log_filter_all_admins" = "All users and admins";
@ -5070,6 +5406,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_participant_volume_channel" = "{from} changed live stream volume for {user} to {percent}";
"lng_admin_log_antispam_enabled" = "{from} enabled aggressive anti-spam";
"lng_admin_log_antispam_disabled" = "{from} disabled aggressive anti-spam";
"lng_admin_log_autotranslate_enabled" = "{from} enabled automatic translation";
"lng_admin_log_autotranslate_disabled" = "{from} disabled automatic translation";
"lng_admin_log_change_color" = "{from} changed channel color from {previous} to {color}";
"lng_admin_log_set_background_emoji" = "{from} set channel background emoji to {emoji}";
"lng_admin_log_change_background_emoji" = "{from} changed channel background emoji from {previous} to {emoji}";
@ -5653,6 +5991,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_view_button_stickerset" = "View stickers";
"lng_view_button_emojipack" = "View emoji";
"lng_view_button_collectible" = "View collectible";
"lng_view_button_call" = "Join call";
"lng_sponsored_hide_ads" = "Hide";
"lng_sponsored_title" = "What are sponsored messages?";
@ -5666,6 +6005,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sponsored_revenued_info1_title" = "Respect Your Privacy";
"lng_sponsored_revenued_info1_description" = "Ads on Telegram do not use your personal information and are based on the channel in which you see them.";
"lng_sponsored_revenued_info1_bot_description" = "Ads on Telegram do not use your personal information and are based on the mini app in which you see them.";
"lng_sponsored_revenued_info1_search_description" = "Ads on Telegram do not use your personal information and are based on the search query you entered.";
"lng_sponsored_revenued_info2_title" = "Help the Channel Creator";
"lng_sponsored_revenued_info2_bot_title" = "Help the Bot Developer";
"lng_sponsored_revenued_info2_description" = "50% of the revenue from Telegram Ads goes to the owner of the channel where they are displayed.";
@ -5674,9 +6014,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_sponsored_revenued_info3_description#one" = "You can turn off ads by subscribing to {link}, and Level {count} channels can remove them for their subscribers.";
"lng_sponsored_revenued_info3_description#other" = "You can turn off ads by subscribing to {link}, and Level {count} channels can remove them for their subscribers.";
"lng_sponsored_revenued_info3_bot_description" = "You can turn off ads in mini apps by subscribing to {link}.";
"lng_sponsored_revenued_info3_search_description" = "You can turn off ads by subscribing to Telegram Premium. {link}";
"lng_sponsored_revenued_info3_search_link" = "Subscribe {arrow}";
"lng_sponsored_revenued_footer_title" = "Can I Launch an Ad?";
"lng_sponsored_revenued_footer_description" = "Anyone can create an ad to display in this channel — with minimal budgets. Check out the **Telegram Ad Platform** for details. {link}";
"lng_sponsored_revenued_footer_bot_description" = "Anyone can create an ad to display in this bot — with minimal budgets. Check out the **Telegram Ad Platform** for details. {link}";
"lng_sponsored_revenued_footer_search_description" = "Anyone can create an ad to display in search results for any query. Check out the **Telegram Ad Platform** for details. {link}";
"lng_sponsored_top_bar_hide" = "remove";
"lng_telegram_features_url" = "https://t.me/TelegramTips";
@ -6040,6 +6383,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_bot_earn_chart_revenue" = "Revenue";
"lng_bot_earn_overview_title" = "Proceeds overview";
"lng_bot_earn_available" = "Available balance";
"lng_bot_earn_reward" = "Total balance";
"lng_bot_earn_total" = "Total lifetime proceeds";
"lng_bot_earn_balance_title" = "Available balance";
"lng_bot_earn_balance_about" = "Stars from your total balance can be used for ads or withdrawn as rewards 21 days after they are earned.";
@ -6162,6 +6506,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_qr_box_transparent_background" = "Transparent Background";
"lng_qr_box_font_size" = "Font size";
"lng_frozen_bar_title" = "Your account is frozen!";
"lng_frozen_bar_text" = "Click to view details {arrow}";
"lng_frozen_restrict_title" = "Your account is frozen";
"lng_frozen_restrict_text" = "Click to view details";
"lng_frozen_title" = "Your Account is Frozen";
"lng_frozen_subtitle1" = "Violation of Terms";
"lng_frozen_text1" = "Your account was frozen for breaking Telegram's Terms and Conditions.";
"lng_frozen_subtitle2" = "Read-Only Mode";
"lng_frozen_text2" = "You can access your account but can't send messages or take actions.";
"lng_frozen_subtitle3" = "Appeal Before Deactivation";
"lng_frozen_text3" = "Appeal via {link} before {date}, or your account will be deleted.";
"lng_frozen_appeal_button" = "Submit an Appeal";
"lng_context_bank_card_copy" = "Copy Card Number";
"lng_context_bank_card_copied" = "Card number copied to clipboard.";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose Default Program...";
@ -6243,38 +6603,41 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_DontSendOnlinePackets" = "Don't Send Online";
"ayu_DontSendUploadProgress" = "Don't Send Typing";
"ayu_SendOfflinePacketAfterOnline" = "Go Offline Automatically";
"ayu_GhostModeOptionLongTapDescription" = "Long tap on any option to prevent it from changing on toggling Ghost Mode.";
"ayu_GhostModeOptionLongTapDescription" = "Long-press any option to prevent it from changing when toggling Ghost Mode.";
"ayu_MarkReadAfterAction" = "Read on Interact";
"ayu_MarkReadAfterActionDescription" = "Automatically reads message when you send a new one or tap a reaction.";
"ayu_MarkReadAfterActionDescription" = "Automatically marks a message as read when you send a new one or tap a reaction.";
"ayu_MarkReadAfterSend" = "Send";
"ayu_MarkReadAfterReaction" = "Reaction";
"ayu_MarkReadAfterPoll" = "Poll";
"ayu_UseScheduledMessages" = "Schedule Messages";
"ayu_UseScheduledMessagesDescription" = "Automatically schedules outgoing messages for ~12 seconds, and more for media. Sending messages this way, you won't appear online.\nDon't use on bad networks.";
"ayu_UseScheduledMessagesDescription" = "Automatically schedules outgoing messages to send after ~12 seconds (longer for media). Using this feature, you won't appear online.\nAvoid using on unreliable networks.";
"ayu_SendWithoutSoundByDefault" = "Send without Sound";
"ayu_SendWithoutSoundByDefaultDescription" = "Automatically sends outgoing messages without sound.";
"ayu_SendWithoutSoundByDefaultDescription" = "Sends outgoing messages without sound by default.";
"ayu_SuggestGhostModeBeforeViewingStory" = "Story Ghost Mode Alert";
"ayu_SuggestGhostModeBeforeViewingStoryDescription" = "Shows an alert before opening the story, suggesting to turn on Ghost Mode.";
"ayu_SuggestGhostModeBeforeViewingStoryDescription" = "Displays an alert before opening a story, suggesting you enable Ghost Mode.";
"ayu_SpyEssentialsHeader" = "Spy essentials";
"ayu_SaveDeletedMessages" = "Save Deleted Messages";
"ayu_SaveMessagesHistory" = "Save Edits History";
"ayu_MessageSavingActionBarHeader" = "Message Saving Preferences";
"ayu_MessageSavingSaveMedia" = "Save Media";
"ayu_MessageSavingSaveMediaHint" = "Click for More";
"ayu_MessageSavingSaveMediaInPrivateChats" = "…in private chats";
"ayu_MessageSavingSaveMediaInPublicChannels" = "…in public channels";
"ayu_MessageSavingSaveMediaInPrivateChannels" = "…in private channels";
"ayu_MessageSavingSaveMediaInPublicGroups" = "…in public groups";
"ayu_MessageSavingSaveMediaInPrivateGroups" = "…in private groups";
"ayu_MessageSavingSaveMedia" = "Save Attachments";
"ayu_MessageSavingSaveMediaHint" = "Configure chats & limits";
"ayu_MessageSavingSaveMediaInPrivateChats" = "Private Chats";
"ayu_MessageSavingSaveMediaInPublicChannels" = "Public Channels";
"ayu_MessageSavingSaveMediaInPrivateChannels" = "Private Channels";
"ayu_MessageSavingSaveMediaInPublicGroups" = "Public Groups";
"ayu_MessageSavingSaveMediaInPrivateGroups" = "Private Groups";
"ayu_MessageSavingSaveMediaHintPopup" = "Make sure it's configured to your needs.";
"ayu_MaximumMediaSizeCellular" = "Media size limit (cellular data)";
"ayu_MaximumMediaSizeWiFi" = "Media size limit (WiFi)";
"ayu_MessageSavingOtherHeader" = "Other";
"ayu_MessageSavingSaveReactions" = "Save reactions";
"ayu_MessageSavingSaveForBots" = "Save in Bot Dialogs";
"ayu_MessageSavingSavePath" = "Attachments Folder";
"ayu_MessageSavingSavePathTitle" = "Choose folder";
"ayu_SpySaveReadMarks" = "Save Read Date";
"ayu_SpySaveReadMarksDescription" = "Locally saves data about reading messages. This will be shown if Telegram does not provide read date.";
"ayu_SpySaveReadMarksDescription" = "Locally saves data about reading messages. This will be shown if Telegram does not provide a read date.";
"ayu_SpySaveLocalOnline" = "Save Last Seen Date";
"ayu_SpySaveLocalOnlineDescription" = "Saves the last online date for users with hidden online status based on their actions. You'll be able to see **very approximately** when they were last online.";
"ayu_ExportDatabaseButton" = "Export Database";
"ayu_ImportDatabaseButton" = "Import Database";
"ayu_QoLTogglesHeader" = "Useful features";
"ayu_KeepAliveService" = "AyuGram Push Service";
"ayu_DisableAds" = "Disable Ads";
@ -6304,7 +6667,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_SettingsShowID_Hide" = "Hide";
"ayu_SettingsShowMessageShot" = "Show Message Shot";
"ayu_SettingsRecentStickersCount" = "Recent Stickers Count";
"ayu_SettingsCustomizationHint" = "After making changes to the \"Customization\" section, you must restart the application.";
"ayu_SettingsCustomizationHint" = "You must restart the application after making changes in the \"Customization\" section.";
"ayu_SettingsContextMenuTitle" = "Choose when to show the item";
"ayu_SettingsContextMenuDescription" = "Extended menu items will be displayed if you hold CTRL or SHIFT while right-clicking on the message.";
"ayu_SettingsContextMenuItemHidden" = "Hidden";
@ -6328,7 +6691,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_SettingsIncreaseWebviewHeight" = "Increase Content Height";
"ayu_SettingsIncreaseWebviewWidth" = "Increase Content Width";
"ayu_ExportDataTitle" = "Export AyuGram Database?";
"ayu_ExportDataDescription" = "It will be exported to the public folder, to Saved Attachments.";
"ayu_ExportDataDescription" = "It will be exported to the public folder under Saved Attachments.";
"ayu_ExportDataConfirm" = "Yes, export";
"ayu_ExportDataCancel" = "No, close window";
"ayu_ExportDataSuccess" = "Database exported successfully.";
@ -6406,11 +6769,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_IconYaPlus" = "Yandex Plus";
"ayu_WALMode" = "Enable WAL mode";
"ayu_PushNotificationCount" = "FCM notifications received";
"ayu_ClearAyuDatabase" = "Clear Messages Database";
"ayu_ClearAyuAttachmentsNotification" = "AyuGram attachments folder cleared";
"ayu_ClearTelegramDatabase" = "Clear Telegram Database";
"ayu_ClearAyuDatabaseNotification" = "AyuGram database cleared";
"ayu_ClearAyuAttachments" = "Clear Attachments Folder";
"ayu_AyuAttachments" = "AyuGram Attachments Folder";
"ayu_AyuDatabase" = "AyuGram Messages Database";
"ayu_TelegramCacheDatabase" = "Telegram Messages Database";
"ayu_ConfirmationsTitle" = "Confirmations";
"ayu_StickerConfirmation" = "For Stickers";
"ayu_GIFConfirmation" = "For GIFs";
@ -6478,13 +6839,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_SuggestGhostModeStoryText" = "Do you want to enable **Ghost Mode** before viewing the story?";
"ayu_SuggestGhostModeStoryActionTextYes" = "Yes";
"ayu_SuggestGhostModeStoryActionTextNo" = "No";
"ayu_ClearAttachmentsFolderWarning" = "Are you sure you want to clear the **attachments folder**? This action cannot be undone.";
"ayu_ClearMessagesDatabaseWarning" = "Are you sure you want to clear **all deleted & edited messages**? This action cannot be undone.";
"ayu_ClearTelegramDatabaseWarning" = "Are you sure you want to clear the **Telegram internal database**? This action cannot be undone.";
"ayu_FirstLaunchAlert" = "AyuGram is **free** software and should only be obtained from our **official sources**. You assume **full responsibility** for using this application with your account.";
"ayu_LocalPremiumAlert" = "With local Telegram Premium you won't have increased limits and won't be able to send animated emojis. Other users won't see your premium emoji and quote color.";
"ayu_LocalPremiumAlert" = "With local Telegram Premium, you won't get increased limits or be able to send animated emojis. Other users won't see your premium emoji and quote color.";
"ayu_ExteraChatsAlert" = "Don't ask questions related to **AyuGram** in **exteraGram** chats. If you need help, ask in the official **AyuGram** chat.";
"ayu_HideNextViewsDescriptionAyu" = "Hide my views forever, until Ghost Mode disabled.";
"ayu_HideNextViewsDescriptionAyu" = "Hide my views forever, until Ghost Mode is disabled.";
"ayu_EnableGhostModeStories" = "Enable Ghost Mode";
"ayu_GhostModeIsActive" = "Ghost Mode is Active";
"ayu_SimpleQuotesAndReplies" = "Disable Colorful Replies";
@ -6510,6 +6868,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_MessageShotShowReactions" = "Show reactions";
"ayu_MessageShotShowColorfulReplies" = "Show colorful replies";
"ayu_SendAsSticker" = "Send as Sticker";
"ayu_SendWithSound" = "Send With Sound";
"ayu_AyuForwardStatusPreparing" = "Forwarding messages";
"ayu_AyuForwardStatusLoadingMedia" = "Loading media";
"ayu_AyuForwardStatusForwarding" = "Forwarding messages";
@ -6528,19 +6887,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_LikelyOfflineStatus" = "offline ?";
"ayu_GhostModeShortcut" = "Enter with Ghost";
"ayu_SettingsShowMessageSeconds" = "Show Message Seconds";
"ayu_ShowOnlyAddedEmojisAndStickers" = "Show Only Added Emojis & Stickers";
"ayu_ContextCopyID" = "Copy ID";
"ayu_IDCopiedToast" = "ID copied to clipboard.";
"ayu_ContextHideMessage" = "Hide";
"ayu_ContextCopyCallbackData" = "Copy Callback Data";
"ayu_RegisterURLScheme" = "Register URL Scheme";
"ayu_SessionTerminated" = "Session **{item}** was terminated. You may still browse cached messages.";
"ayu_LocalPremiumNotice" = "You're using **local** Telegram Premium.\nIt **won't** give you any benefits.\n**Enjoy the star near your nickname!**";
"ayu_DeveloperPopup" = "**{item}** is a member of the **exteraGram** development team.";
"ayu_SupporterPopup" = "**{item}** supported the development of **exteraGram** or **AyuGram** and received an exclusive badge.";
"ayu_SettingsWatermark" = "AyuGram developed and maintained by Radolyn Labs.";
"ayu_SettingsWatermark" = "AyuGram is developed and maintained by Radolyn Labs.";
"ayu_ConfirmationSticker" = "Do you want to send this sticker?";
"ayu_ConfirmationGIF" = "Do you want to send this GIF?";
"ayu_ConfirmationVoice" = "Do you want to send this voice message?";
"ayu_IntroAbout" = "Welcome to the AyuGram Desktop.\nMake Telegram your own.";
"ayu_AboutText1" = "ToS breaking Telegram client based on {api_link}.";
"ayu_UpdateAyuGram" = "Update AyuGram";
"ayu_UtilityRestartRequired" = "App will close in 5 seconds.";
"ayu_UtilityRestartRequired" = "The app will close in 5 seconds.";

View file

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/animations">
<file alias="blocked_peers_empty.tgs">../../animations/blocked_peers_empty.tgs</file>
<file alias="change_number.tgs">../../animations/change_number.tgs</file>
<file alias="filters.tgs">../../animations/filters.tgs</file>
<file alias="cloud_filters.tgs">../../animations/cloud_filters.tgs</file>
<file alias="local_passcode_enter.tgs">../../animations/local_passcode_enter.tgs</file>
@ -30,6 +31,7 @@
<file alias="noresults.tgs">../../animations/noresults.tgs</file>
<file alias="hello_status.tgs">../../animations/hello_status.tgs</file>
<file alias="starref_link.tgs">../../animations/starref_link.tgs</file>
<file alias="media_forbidden.tgs">../../animations/media_forbidden.tgs</file>
<file alias="dice_idle.tgs">../../animations/dice/dice_idle.tgs</file>
<file alias="dart_idle.tgs">../../animations/dice/dart_idle.tgs</file>
@ -49,5 +51,16 @@
<file alias="star_reaction_effect1.tgs">../../animations/star_reaction/effect1.tgs</file>
<file alias="star_reaction_effect2.tgs">../../animations/star_reaction/effect2.tgs</file>
<file alias="star_reaction_effect3.tgs">../../animations/star_reaction/effect3.tgs</file>
<file alias="swipe_archive.tgs">../../animations/swipe_action/archive.tgs</file>
<file alias="swipe_unarchive.tgs">../../animations/swipe_action/unarchive.tgs</file>
<file alias="swipe_delete.tgs">../../animations/swipe_action/delete.tgs</file>
<file alias="swipe_disabled.tgs">../../animations/swipe_action/disabled.tgs</file>
<file alias="swipe_mute.tgs">../../animations/swipe_action/mute.tgs</file>
<file alias="swipe_unmute.tgs">../../animations/swipe_action/unmute.tgs</file>
<file alias="swipe_pin.tgs">../../animations/swipe_action/pin.tgs</file>
<file alias="swipe_unpin.tgs">../../animations/swipe_action/unpin.tgs</file>
<file alias="swipe_read.tgs">../../animations/swipe_action/read.tgs</file>
<file alias="swipe_unread.tgs">../../animations/swipe_action/unread.tgs</file>
</qresource>
</RCC>

View file

@ -24,6 +24,8 @@
<file alias="icons/settings/star.svg">../../icons/settings/star.svg</file>
<file alias="icons/settings/starmini.svg">../../icons/settings/starmini.svg</file>
<file alias="icons/tray/monochrome.svg">../../icons/tray_monochrome.svg</file>
<file alias="icons/tray/monochrome_attention.svg">../../icons/tray_monochrome_attention.svg</file>
<file alias="icons/tray/monochrome_mute.svg">../../icons/tray_monochrome_mute.svg</file>
<file alias="topic_icons/blue.svg">../../art/topic_icons/blue.svg</file>
<file alias="topic_icons/yellow.svg">../../art/topic_icons/yellow.svg</file>
<file alias="topic_icons/violet.svg">../../art/topic_icons/violet.svg</file>

View file

@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="5.11.1.0" />
Version="5.14.3.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 5,11,1,0
PRODUCTVERSION 5,11,1,0
FILEVERSION 5,14,3,0
PRODUCTVERSION 5,14,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "5.11.1.0"
VALUE "FileVersion", "5.14.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "5.11.1.0"
VALUE "ProductVersion", "5.14.3.0"
END
END
BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 5,11,1,0
PRODUCTVERSION 5,11,1,0
FILEVERSION 5,14,3,0
PRODUCTVERSION 5,14,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater"
VALUE "FileVersion", "5.11.1.0"
VALUE "FileVersion", "5.14.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "5.11.1.0"
VALUE "ProductVersion", "5.14.3.0"
END
END
BLOCK "VarFileInfo"

View file

@ -149,18 +149,14 @@ void InitFilterLinkHeader(
iconEmoji
).value_or(Ui::FilterIcon::Custom)).active;
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> repaint) {
return Core::MarkedTextContext{
.session = &box->peerListUiShow()->session(),
.customEmojiRepaint = std::move(repaint),
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
auto header = Ui::MakeFilterLinkHeader(box, {
.type = type,
.title = TitleText(type)(tr::now),
.about = AboutText(type, title.text),
.makeAboutContext = makeContext,
.aboutContext = Core::TextContext({
.session = &box->peerListUiShow()->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
.folderTitle = title.text,
.folderIcon = icon,
.badge = (type == Ui::FilterLinkHeaderType::AddingChats
@ -560,16 +556,12 @@ void ShowImportToast(
text.append('\n').append(phrase(tr::now, lt_count, added));
}
const auto isStatic = title.isStatic;
const auto makeContext = [=](not_null<QWidget*> widget) {
return Core::MarkedTextContext{
.session = &strong->session(),
.customEmojiRepaint = [=] { widget->update(); },
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
strong->showToast({
.text = std::move(text),
.textContext = makeContext,
.textContext = Core::TextContext({
.session = &strong->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
})
});
}
@ -640,18 +632,14 @@ void ProcessFilterInvite(
raw->setRealContentHeight(box->heightValue());
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &strong->session(),
.customEmojiRepaint = update,
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
auto owned = Ui::FilterLinkProcessButton(
box,
type,
title.text,
makeContext,
Core::TextContext({
.session = &strong->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
std::move(badge));
const auto button = owned.data();
@ -873,18 +861,14 @@ void ProcessFilterRemove(
}, type, title, iconEmoji, rpl::single(0), horizontalFilters);
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &strong->session(),
.customEmojiRepaint = update,
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
auto owned = Ui::FilterLinkProcessButton(
box,
type,
title.text,
makeContext,
Core::TextContext({
.session = &strong->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
std::move(badge));
const auto button = owned.data();

View file

@ -544,4 +544,38 @@ auto CloudPassword::checkRecoveryEmailAddressCode(const QString &code)
};
}
void RequestLoginEmailCode(
MTP::Sender &api,
const QString &sendToEmail,
Fn<void(int length, const QString &pattern)> done,
Fn<void(const QString &error)> fail) {
api.request(MTPaccount_SendVerifyEmailCode(
MTP_emailVerifyPurposeLoginChange(),
MTP_string(sendToEmail)
)).done([=](const MTPaccount_SentEmailCode &result) {
done(result.data().vlength().v, qs(result.data().vemail_pattern()));
}).fail([=](const MTP::Error &error) {
fail(error.type());
}).send();
}
void VerifyLoginEmail(
MTP::Sender &api,
const QString &code,
Fn<void()> done,
Fn<void(const QString &error)> fail) {
api.request(MTPaccount_VerifyEmail(
MTP_emailVerifyPurposeLoginChange(),
MTP_emailVerificationCode(MTP_string(code))
)).done([=](const MTPaccount_EmailVerified &result) {
result.match([=](const MTPDaccount_emailVerified &data) {
done();
}, [=](const MTPDaccount_emailVerifiedLogin &data) {
fail(QString());
});
}).fail([=](const MTP::Error &error) {
fail(error.type());
}).send();
}
} // namespace Api

View file

@ -70,4 +70,15 @@ private:
};
void RequestLoginEmailCode(
MTP::Sender &api,
const QString &sendToEmail,
Fn<void(int length, const QString &pattern)> done,
Fn<void(const QString &error)> fail);
void VerifyLoginEmail(
MTP::Sender &api,
const QString &code,
Fn<void()> done,
Fn<void(const QString &error)> fail);
} // namespace Api

View file

@ -25,6 +25,7 @@ struct SendOptions {
TimeId scheduled = 0;
BusinessShortcutId shortcutId = 0;
EffectId effectId = 0;
int starsApproved = 0;
bool silent = false;
bool handleSupportSwitch = false;
bool invertCaption = false;

View file

@ -150,6 +150,9 @@ void ConfirmPhone::resolve(
}, [](const MTPDauth_sentCodeSuccess &) {
LOG(("API Error: Unexpected auth.sentCodeSuccess "
"(Api::ConfirmPhone)."));
}, [](const MTPDauth_sentCodePaymentRequired &) {
LOG(("API Error: Unexpected auth.sentCodePaymentRequired "
"(Api::ConfirmPhone)."));
});
}).fail([=](const MTP::Error &error) {
_sendRequestId = 0;

View file

@ -90,7 +90,13 @@ constexpr auto kTransactionsLimit = 100;
? peerFromMTP(*tl.data().vstarref_peer()).value
: 0;
const auto incoming = (amount >= StarsAmount());
const auto saveActorId = (reaction || !extended.empty()) && incoming;
const auto paidMessagesCount
= tl.data().vpaid_messages().value_or_empty();
const auto premiumMonthsForStars
= tl.data().vpremium_gift_months().value_or_empty();
const auto saveActorId = (reaction
|| !extended.empty()
|| paidMessagesCount) && incoming;
const auto parsedGift = stargift
? FromTL(&peer->session(), *stargift)
: std::optional<Data::StarGift>();
@ -110,9 +116,9 @@ constexpr auto kTransactionsLimit = 100;
.bareGiftStickerId = giftStickerId,
.bareActorId = saveActorId ? barePeerId : uint64(0),
.uniqueGift = parsedGift ? parsedGift->unique : nullptr,
.starrefAmount = starrefAmount,
.starrefCommission = starrefCommission,
.starrefRecipientId = starrefBarePeerId,
.starrefAmount = paidMessagesCount ? StarsAmount() : starrefAmount,
.starrefCommission = paidMessagesCount ? 0 : starrefCommission,
.starrefRecipientId = paidMessagesCount ? 0 : starrefBarePeerId,
.peerType = tl.data().vpeer().match([](const HistoryPeerTL &) {
return Data::CreditsHistoryEntry::PeerType::Peer;
}, [](const MTPDstarsTransactionPeerPlayMarket &) {
@ -138,13 +144,20 @@ constexpr auto kTransactionsLimit = 100;
? base::unixtime::parse(tl.data().vtransaction_date()->v)
: QDateTime(),
.successLink = qs(tl.data().vtransaction_url().value_or_empty()),
.paidMessagesCount = paidMessagesCount,
.paidMessagesAmount = (paidMessagesCount
? starrefAmount
: StarsAmount()),
.paidMessagesCommission = paidMessagesCount ? starrefCommission : 0,
.starsConverted = int(nonUniqueGift
? nonUniqueGift->vconvert_stars().v
: 0),
.premiumMonthsForStars = premiumMonthsForStars,
.floodSkip = int(tl.data().vfloodskip_number().value_or(0)),
.converted = stargift && incoming,
.stargift = stargift.has_value(),
.giftUpgraded = tl.data().is_stargift_upgrade(),
.giftResale = tl.data().is_stargift_resale(),
.reaction = tl.data().is_reaction(),
.refunded = tl.data().is_refund(),
.pending = tl.data().is_pending(),
@ -336,12 +349,15 @@ void CreditsHistory::request(
void CreditsHistory::requestSubscriptions(
const Data::CreditsStatusSlice::OffsetToken &token,
Fn<void(Data::CreditsStatusSlice)> done) {
Fn<void(Data::CreditsStatusSlice)> done,
bool missingBalance) {
if (_requestId) {
return;
}
_requestId = _api.request(MTPpayments_GetStarsSubscriptions(
MTP_flags(0),
MTP_flags(missingBalance
? MTPpayments_getStarsSubscriptions::Flag::f_missing_balance
: MTPpayments_getStarsSubscriptions::Flags(0)),
_peer->isSelf() ? MTP_inputPeerSelf() : _peer->input,
MTP_string(token)
)).done([=](const MTPpayments_StarsStatus &result) {
@ -513,8 +529,12 @@ void EditCreditsSubscription(
)).done(done).fail([=](const MTP::Error &e) { fail(e.type()); }).send();
}
MTPInputSavedStarGift InputSavedStarGiftId(const Data::SavedStarGiftId &id) {
return id.isUser()
MTPInputSavedStarGift InputSavedStarGiftId(
const Data::SavedStarGiftId &id,
const std::shared_ptr<Data::UniqueGift> &unique) {
return (!id && unique)
? MTP_inputSavedStarGiftSlug(MTP_string(unique->slug))
: id.isUser()
? MTP_inputSavedStarGiftUser(MTP_int(id.userMessageId().bare))
: MTP_inputSavedStarGiftChat(
id.chat()->input,

View file

@ -82,7 +82,8 @@ public:
Fn<void(Data::CreditsStatusSlice)> done);
void requestSubscriptions(
const Data::CreditsStatusSlice::OffsetToken &token,
Fn<void(Data::CreditsStatusSlice)> done);
Fn<void(Data::CreditsStatusSlice)> done,
bool missingBalance = false);
private:
using HistoryTL = MTPpayments_GetStarsTransactions;
@ -121,6 +122,7 @@ void EditCreditsSubscription(
Fn<void(QString)> fail);
[[nodiscard]] MTPInputSavedStarGift InputSavedStarGiftId(
const Data::SavedStarGiftId &id);
const Data::SavedStarGiftId &id,
const std::shared_ptr<Data::UniqueGift> &unique = nullptr);
} // namespace Api

View file

@ -46,11 +46,15 @@ void HandleWithdrawalButton(
bool loading = false;
};
const auto channel = receiver.currencyReceiver;
const auto peer = receiver.creditsReceiver;
const auto currencyReceiver = receiver.currencyReceiver;
const auto creditsReceiver = receiver.creditsReceiver;
const auto isChannel = receiver.currencyReceiver
&& receiver.currencyReceiver->isChannel();
const auto state = button->lifetime().make_state<State>();
const auto session = (channel ? &channel->session() : &peer->session());
const auto session = (currencyReceiver
? &currencyReceiver->session()
: &creditsReceiver->session());
using ChannelOutUrl = MTPstats_BroadcastRevenueWithdrawalUrl;
using CreditsOutUrl = MTPpayments_StarsRevenueWithdrawalUrl;
@ -59,7 +63,7 @@ void HandleWithdrawalButton(
const auto processOut = [=] {
if (state->loading) {
return;
} else if (peer && !receiver.creditsAmount()) {
} else if (creditsReceiver && !receiver.creditsAmount()) {
return;
}
state->loading = true;
@ -70,10 +74,10 @@ void HandleWithdrawalButton(
state->loading = false;
auto fields = PasscodeBox::CloudFields::From(pass);
fields.customTitle = channel
fields.customTitle = isChannel
? tr::lng_channel_earn_balance_password_title()
: tr::lng_bot_earn_balance_password_title();
fields.customDescription = channel
fields.customDescription = isChannel
? tr::lng_channel_earn_balance_password_description(tr::now)
: tr::lng_bot_earn_balance_password_description(tr::now);
fields.customSubmitButton = tr::lng_passcode_submit();
@ -94,18 +98,18 @@ void HandleWithdrawalButton(
show->showToast(message);
}
};
if (channel) {
if (currencyReceiver) {
session->api().request(
MTPstats_GetBroadcastRevenueWithdrawalUrl(
channel->input,
currencyReceiver->input,
result.result
)).done([=](const ChannelOutUrl &r) {
done(qs(r.data().vurl()));
}).fail(fail).send();
} else if (peer) {
} else if (creditsReceiver) {
session->api().request(
MTPpayments_GetStarsRevenueWithdrawalUrl(
peer->input,
creditsReceiver->input,
MTP_long(receiver.creditsAmount()),
result.result
)).done([=](const CreditsOutUrl &r) {
@ -134,17 +138,17 @@ void HandleWithdrawalButton(
processOut();
}
};
if (channel) {
if (currencyReceiver) {
session->api().request(
MTPstats_GetBroadcastRevenueWithdrawalUrl(
channel->input,
currencyReceiver->input,
MTP_inputCheckPasswordEmpty()
)).fail(fail).send();
} else if (peer) {
} else if (creditsReceiver) {
session->api().request(
MTPpayments_GetStarsRevenueWithdrawalUrl(
peer->input,
MTP_long(std::numeric_limits<int64_t>::max()),
creditsReceiver->input,
MTP_long(receiver.creditsAmount()),
MTP_inputCheckPasswordEmpty()
)).fail(fail).send();
}

View file

@ -22,7 +22,7 @@ void RestrictSponsored(
Fn<void(QString)> failed);
struct RewardReceiver final {
ChannelData *currencyReceiver = nullptr;
PeerData *currencyReceiver = nullptr;
PeerData *creditsReceiver = nullptr;
Fn<uint64()> creditsAmount;
};

View file

@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_global_privacy.h"
#include "apiwrap.h"
#include "data/components/promo_suggestions.h"
#include "data/data_user.h"
#include "main/main_session.h"
#include "main/main_app_config.h"
@ -100,13 +102,11 @@ rpl::producer<bool> GlobalPrivacy::showArchiveAndMute() const {
}
rpl::producer<> GlobalPrivacy::suggestArchiveAndMute() const {
return _session->appConfig().suggestionRequested(
u"AUTOARCHIVE_POPULAR"_q);
return _session->promoSuggestions().requested(u"AUTOARCHIVE_POPULAR"_q);
}
void GlobalPrivacy::dismissArchiveAndMuteSuggestion() {
_session->appConfig().dismissSuggestion(
u"AUTOARCHIVE_POPULAR"_q);
_session->promoSuggestions().dismiss(u"AUTOARCHIVE_POPULAR"_q);
}
void GlobalPrivacy::updateHideReadTime(bool hide) {
@ -114,7 +114,9 @@ void GlobalPrivacy::updateHideReadTime(bool hide) {
archiveAndMuteCurrent(),
unarchiveOnNewMessageCurrent(),
hide,
newRequirePremiumCurrent());
newRequirePremiumCurrent(),
newChargeStarsCurrent(),
disallowedGiftTypesCurrent());
}
bool GlobalPrivacy::hideReadTimeCurrent() const {
@ -125,14 +127,6 @@ rpl::producer<bool> GlobalPrivacy::hideReadTime() const {
return _hideReadTime.value();
}
void GlobalPrivacy::updateNewRequirePremium(bool value) {
update(
archiveAndMuteCurrent(),
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
value);
}
bool GlobalPrivacy::newRequirePremiumCurrent() const {
return _newRequirePremium.current();
}
@ -141,6 +135,45 @@ rpl::producer<bool> GlobalPrivacy::newRequirePremium() const {
return _newRequirePremium.value();
}
int GlobalPrivacy::newChargeStarsCurrent() const {
return _newChargeStars.current();
}
rpl::producer<int> GlobalPrivacy::newChargeStars() const {
return _newChargeStars.value();
}
void GlobalPrivacy::updateMessagesPrivacy(
bool requirePremium,
int chargeStars) {
update(
archiveAndMuteCurrent(),
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
requirePremium,
chargeStars,
disallowedGiftTypesCurrent());
}
DisallowedGiftTypes GlobalPrivacy::disallowedGiftTypesCurrent() const {
return _disallowedGiftTypes.current();
}
auto GlobalPrivacy::disallowedGiftTypes() const
-> rpl::producer<DisallowedGiftTypes> {
return _disallowedGiftTypes.value();
}
void GlobalPrivacy::updateDisallowedGiftTypes(DisallowedGiftTypes types) {
update(
archiveAndMuteCurrent(),
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
newRequirePremiumCurrent(),
newChargeStarsCurrent(),
types);
}
void GlobalPrivacy::loadPaidReactionShownPeer() {
if (_paidReactionShownPeerLoaded) {
return;
@ -169,7 +202,9 @@ void GlobalPrivacy::updateArchiveAndMute(bool value) {
value,
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
newRequirePremiumCurrent());
newRequirePremiumCurrent(),
newChargeStarsCurrent(),
disallowedGiftTypesCurrent());
}
void GlobalPrivacy::updateUnarchiveOnNewMessage(
@ -178,19 +213,26 @@ void GlobalPrivacy::updateUnarchiveOnNewMessage(
archiveAndMuteCurrent(),
value,
hideReadTimeCurrent(),
newRequirePremiumCurrent());
newRequirePremiumCurrent(),
newChargeStarsCurrent(),
disallowedGiftTypesCurrent());
}
void GlobalPrivacy::update(
bool archiveAndMute,
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium) {
bool newRequirePremium,
int newChargeStars,
DisallowedGiftTypes disallowedGiftTypes) {
using Flag = MTPDglobalPrivacySettings::Flag;
using DisallowedFlag = MTPDdisallowedGiftsSettings::Flag;
_api.request(_requestId).cancel();
const auto newRequirePremiumAllowed = _session->premium()
|| _session->appConfig().newRequirePremiumFree();
const auto showGiftIcon
= (disallowedGiftTypes & DisallowedGiftType::SendHide);
const auto flags = Flag()
| (archiveAndMute
? Flag::f_archive_and_mute_new_noncontact_peers
@ -204,26 +246,58 @@ void GlobalPrivacy::update(
| (hideReadTime ? Flag::f_hide_read_marks : Flag())
| ((newRequirePremium && newRequirePremiumAllowed)
? Flag::f_new_noncontact_peers_require_premium
: Flag());
: Flag())
| Flag::f_noncontact_peers_paid_stars
| (showGiftIcon ? Flag::f_display_gifts_button : Flag())
| Flag::f_disallowed_gifts;
const auto disallowedFlags = DisallowedFlag()
| ((disallowedGiftTypes & DisallowedGiftType::Premium)
? DisallowedFlag::f_disallow_premium_gifts
: DisallowedFlag())
| ((disallowedGiftTypes & DisallowedGiftType::Unlimited)
? DisallowedFlag::f_disallow_unlimited_stargifts
: DisallowedFlag())
| ((disallowedGiftTypes & DisallowedGiftType::Limited)
? DisallowedFlag::f_disallow_limited_stargifts
: DisallowedFlag())
| ((disallowedGiftTypes & DisallowedGiftType::Unique)
? DisallowedFlag::f_disallow_unique_stargifts
: DisallowedFlag());
const auto typesWas = _disallowedGiftTypes.current();
const auto typesChanged = (typesWas != disallowedGiftTypes);
_requestId = _api.request(MTPaccount_SetGlobalPrivacySettings(
MTP_globalPrivacySettings(MTP_flags(flags))
MTP_globalPrivacySettings(
MTP_flags(flags),
MTP_long(newChargeStars),
MTP_disallowedGiftsSettings(MTP_flags(disallowedFlags)))
)).done([=](const MTPGlobalPrivacySettings &result) {
_requestId = 0;
apply(result);
if (typesChanged) {
_session->user()->updateFullForced();
}
}).fail([=](const MTP::Error &error) {
_requestId = 0;
if (error.type() == u"PREMIUM_ACCOUNT_REQUIRED"_q) {
update(archiveAndMute, unarchiveOnNewMessage, hideReadTime, {});
update(
archiveAndMute,
unarchiveOnNewMessage,
hideReadTime,
false,
0,
DisallowedGiftTypes());
}
}).send();
_archiveAndMute = archiveAndMute;
_unarchiveOnNewMessage = unarchiveOnNewMessage;
_hideReadTime = hideReadTime;
_newRequirePremium = newRequirePremium;
_newChargeStars = newChargeStars;
_disallowedGiftTypes = disallowedGiftTypes;
}
void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &data) {
data.match([&](const MTPDglobalPrivacySettings &data) {
void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) {
const auto &data = settings.data();
_archiveAndMute = data.is_archive_and_mute_new_noncontact_peers();
_unarchiveOnNewMessage = data.is_keep_archived_unmuted()
? UnarchiveOnNewMessage::None
@ -232,7 +306,30 @@ void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &data) {
: UnarchiveOnNewMessage::AnyUnmuted;
_hideReadTime = data.is_hide_read_marks();
_newRequirePremium = data.is_new_noncontact_peers_require_premium();
});
_newChargeStars = data.vnoncontact_peers_paid_stars().value_or_empty();
if (const auto gifts = data.vdisallowed_gifts()) {
const auto &disallow = gifts->data();
_disallowedGiftTypes = DisallowedGiftType()
| (disallow.is_disallow_unlimited_stargifts()
? DisallowedGiftType::Unlimited
: DisallowedGiftType())
| (disallow.is_disallow_limited_stargifts()
? DisallowedGiftType::Limited
: DisallowedGiftType())
| (disallow.is_disallow_unique_stargifts()
? DisallowedGiftType::Unique
: DisallowedGiftType())
| (disallow.is_disallow_premium_gifts()
? DisallowedGiftType::Premium
: DisallowedGiftType())
| (data.is_display_gifts_button()
? DisallowedGiftType::SendHide
: DisallowedGiftType());
} else {
_disallowedGiftTypes = data.is_display_gifts_button()
? DisallowedGiftType::SendHide
: DisallowedGiftType();
}
}
} // namespace Api

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/flags.h"
#include "mtproto/sender.h"
class ApiWrap;
@ -23,6 +24,17 @@ enum class UnarchiveOnNewMessage {
AnyUnmuted,
};
enum class DisallowedGiftType : uchar {
Limited = 0x01,
Unlimited = 0x02,
Unique = 0x04,
Premium = 0x08,
SendHide = 0x10,
};
inline constexpr bool is_flag_type(DisallowedGiftType) { return true; }
using DisallowedGiftTypes = base::flags<DisallowedGiftType>;
[[nodiscard]] PeerId ParsePaidReactionShownPeer(
not_null<Main::Session*> session,
const MTPPaidReactionPrivacy &value);
@ -49,23 +61,34 @@ public:
[[nodiscard]] bool hideReadTimeCurrent() const;
[[nodiscard]] rpl::producer<bool> hideReadTime() const;
void updateNewRequirePremium(bool value);
[[nodiscard]] bool newRequirePremiumCurrent() const;
[[nodiscard]] rpl::producer<bool> newRequirePremium() const;
[[nodiscard]] int newChargeStarsCurrent() const;
[[nodiscard]] rpl::producer<int> newChargeStars() const;
void updateMessagesPrivacy(bool requirePremium, int chargeStars);
[[nodiscard]] DisallowedGiftTypes disallowedGiftTypesCurrent() const;
[[nodiscard]] auto disallowedGiftTypes() const
-> rpl::producer<DisallowedGiftTypes>;
void updateDisallowedGiftTypes(DisallowedGiftTypes types);
void loadPaidReactionShownPeer();
void updatePaidReactionShownPeer(PeerId shownPeer);
[[nodiscard]] PeerId paidReactionShownPeerCurrent() const;
[[nodiscard]] rpl::producer<PeerId> paidReactionShownPeer() const;
private:
void apply(const MTPGlobalPrivacySettings &data);
void apply(const MTPGlobalPrivacySettings &settings);
void update(
bool archiveAndMute,
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium);
bool newRequirePremium,
int newChargeStars,
DisallowedGiftTypes disallowedGiftTypes);
const not_null<Main::Session*> _session;
MTP::Sender _api;
@ -76,6 +99,8 @@ private:
rpl::variable<bool> _showArchiveAndMute = false;
rpl::variable<bool> _hideReadTime = false;
rpl::variable<bool> _newRequirePremium = false;
rpl::variable<int> _newChargeStars = 0;
rpl::variable<DisallowedGiftTypes> _disallowedGiftTypes;
rpl::variable<PeerId> _paidReactionShownPeer = false;
std::vector<Fn<void()>> _callbacks;
bool _paidReactionShownPeerLoaded = false;

View file

@ -28,8 +28,8 @@ constexpr auto kSearchPerPage = 50;
auto result = MessageIdsList();
for (const auto &message : messages) {
const auto peerId = PeerFromMessage(message);
if (const auto peer = data->peerLoaded(peerId)) {
if (const auto lastDate = DateFromMessage(message)) {
if (data->peerLoaded(peerId)) {
if (DateFromMessage(message)) {
const auto item = data->addNewMessage(
message,
MessageFlags(),

View file

@ -0,0 +1,170 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "api/api_peer_search.h"
#include "api/api_single_message_search.h"
#include "apiwrap.h"
#include "data/data_session.h"
#include "dialogs/ui/chat_search_in.h" // IsHashOrCashtagSearchQuery
#include "main/main_session.h"
namespace Api {
namespace {
constexpr auto kMinSponsoredQueryLength = 4;
} // namespace
PeerSearch::PeerSearch(not_null<Main::Session*> session, Type type)
: _session(session)
, _type(type) {
}
PeerSearch::~PeerSearch() {
clear();
}
void PeerSearch::request(
const QString &query,
Fn<void(PeerSearchResult)> callback,
RequestType type) {
using namespace Dialogs;
_query = Api::ConvertPeerSearchQuery(query);
_callback = callback;
if (_query.isEmpty()
|| IsHashOrCashtagSearchQuery(_query) != HashOrCashtag::None) {
finish(PeerSearchResult{});
return;
}
auto &cache = _cache[_query];
if (cache.peersReady && cache.sponsoredReady) {
finish(cache.result);
return;
} else if (type == RequestType::CacheOnly) {
_callback = nullptr;
return;
} else if (cache.requested) {
return;
}
cache.requested = true;
cache.result.query = _query;
if (_query.size() < kMinSponsoredQueryLength) {
cache.sponsoredReady = true;
} else if (_type == Type::WithSponsored) {
requestSponsored();
}
requestPeers();
}
void PeerSearch::requestPeers() {
const auto requestId = _session->api().request(MTPcontacts_Search(
MTP_string(_query),
MTP_int(SearchPeopleLimit)
)).done([=](const MTPcontacts_Found &result, mtpRequestId requestId) {
const auto &data = result.data();
_session->data().processUsers(data.vusers());
_session->data().processChats(data.vchats());
auto parsed = PeerSearchResult();
parsed.my.reserve(data.vmy_results().v.size());
for (const auto &id : data.vmy_results().v) {
const auto peerId = peerFromMTP(id);
parsed.my.push_back(_session->data().peer(peerId));
}
parsed.peers.reserve(data.vresults().v.size());
for (const auto &id : data.vresults().v) {
const auto peerId = peerFromMTP(id);
parsed.peers.push_back(_session->data().peer(peerId));
}
finishPeers(requestId, std::move(parsed));
}).fail([=](const MTP::Error &error, mtpRequestId requestId) {
finishPeers(requestId, PeerSearchResult{});
}).send();
_peerRequests.emplace(requestId, _query);
}
void PeerSearch::requestSponsored() {
const auto requestId = _session->api().request(
MTPcontacts_GetSponsoredPeers(MTP_string(_query))
).done([=](
const MTPcontacts_SponsoredPeers &result,
mtpRequestId requestId) {
result.match([&](const MTPDcontacts_sponsoredPeersEmpty &) {
finishSponsored(requestId, PeerSearchResult{});
}, [&](const MTPDcontacts_sponsoredPeers &data) {
_session->data().processUsers(data.vusers());
_session->data().processChats(data.vchats());
auto parsed = PeerSearchResult();
parsed.sponsored.reserve(data.vpeers().v.size());
for (const auto &peer : data.vpeers().v) {
const auto &data = peer.data();
const auto peerId = peerFromMTP(data.vpeer());
parsed.sponsored.push_back({
.peer = _session->data().peer(peerId),
.randomId = data.vrandom_id().v,
.sponsorInfo = TextWithEntities::Simple(
qs(data.vsponsor_info().value_or_empty())),
.additionalInfo = TextWithEntities::Simple(
qs(data.vadditional_info().value_or_empty())),
});
}
finishSponsored(requestId, std::move(parsed));
});
}).fail([=](const MTP::Error &error, mtpRequestId requestId) {
finishSponsored(requestId, PeerSearchResult{});
}).send();
_sponsoredRequests.emplace(requestId, _query);
}
void PeerSearch::finishPeers(
mtpRequestId requestId,
PeerSearchResult result) {
const auto query = _peerRequests.take(requestId);
Assert(query.has_value());
auto &cache = _cache[*query];
cache.peersReady = true;
cache.result.my = std::move(result.my);
cache.result.peers = std::move(result.peers);
if (cache.sponsoredReady && _query == *query) {
finish(cache.result);
}
}
void PeerSearch::finishSponsored(
mtpRequestId requestId,
PeerSearchResult result) {
const auto query = _sponsoredRequests.take(requestId);
Assert(query.has_value());
auto &cache = _cache[*query];
cache.sponsoredReady = true;
cache.result.sponsored = std::move(result.sponsored);
if (cache.peersReady && _query == *query) {
finish(cache.result);
}
}
void PeerSearch::finish(PeerSearchResult result) {
if (const auto onstack = base::take(_callback)) {
onstack(std::move(result));
}
}
void PeerSearch::clear() {
_query = QString();
_callback = nullptr;
_cache.clear();
for (const auto &[requestId, query] : base::take(_peerRequests)) {
_session->api().request(requestId).cancel();
}
for (const auto &[requestId, query] : base::take(_sponsoredRequests)) {
_session->api().request(requestId).cancel();
}
}
} // namespace Api

View file

@ -0,0 +1,76 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Main {
class Session;
} // namespace Main
namespace Api {
struct SponsoredSearchResult {
not_null<PeerData*> peer;
QByteArray randomId;
TextWithEntities sponsorInfo;
TextWithEntities additionalInfo;
};
struct PeerSearchResult {
QString query;
std::vector<not_null<PeerData*>> my;
std::vector<not_null<PeerData*>> peers;
std::vector<SponsoredSearchResult> sponsored;
};
class PeerSearch final {
public:
enum class Type {
WithSponsored,
JustPeers,
};
PeerSearch(not_null<Main::Session*> session, Type type);
~PeerSearch();
enum class RequestType {
CacheOnly,
CacheOrRemote,
};
void request(
const QString &query,
Fn<void(PeerSearchResult)> callback,
RequestType type = RequestType::CacheOrRemote);
void clear();
private:
struct CacheEntry {
PeerSearchResult result;
bool requested = false;
bool peersReady = false;
bool sponsoredReady = false;
};
void requestPeers();
void requestSponsored();
void finish(PeerSearchResult result);
void finishPeers(mtpRequestId requestId, PeerSearchResult result);
void finishSponsored(mtpRequestId requestId, PeerSearchResult result);
const not_null<Main::Session*> _session;
const Type _type;
QString _query;
Fn<void(PeerSearchResult)> _callback;
base::flat_map<QString, CacheEntry> _cache;
base::flat_map<mtpRequestId, QString> _peerRequests;
base::flat_map<mtpRequestId, QString> _sponsoredRequests;
};
} // namespace Api

View file

@ -42,7 +42,7 @@ Polls::Polls(not_null<ApiWrap*> api)
void Polls::create(
const PollData &data,
const SendAction &action,
SendAction action,
Fn<void()> done,
Fn<void()> fail) {
_session->api().sendAction(action);
@ -64,6 +64,9 @@ void Polls::create(
history->startSavingCloudDraft(topicRootId);
}
const auto silentPost = ShouldSendSilent(peer, action.options);
const auto starsPaid = std::min(
peer->starsPerMessageChecked(),
action.options.starsApproved);
if (silentPost) {
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
@ -76,6 +79,10 @@ void Polls::create(
if (action.options.effectId) {
sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
}
if (starsPaid) {
action.options.starsApproved -= starsPaid;
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
}
const auto sendAs = action.options.sendAs;
if (sendAs) {
sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
@ -98,7 +105,8 @@ void Polls::create(
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
MTP_long(action.options.effectId)
MTP_long(action.options.effectId),
MTP_long(starsPaid)
), [=](const MTPUpdates &result, const MTP::Response &response) {
if (clearCloudDraft) {
history->finishSavingCloudDraft(
@ -163,8 +171,8 @@ void Polls::sendVotes(
hideSending();
_session->updates().applyUpdates(result);
const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages && settings->markReadAfterAction && item)
const auto& settings = AyuSettings::getInstance();
if (!settings.sendReadMessages && settings.markReadAfterAction && item)
{
readHistory(item);
}

View file

@ -27,7 +27,7 @@ public:
void create(
const PollData &data,
const SendAction &action,
SendAction action,
Fn<void()> done,
Fn<void()> fail);
void sendVotes(

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_text_entities.h"
#include "apiwrap.h"
#include "base/random.h"
#include "data/data_channel.h"
#include "data/data_document.h"
#include "data/data_peer.h"
#include "data/data_peer_values.h"
@ -377,15 +378,15 @@ const Data::PremiumSubscriptionOptions &Premium::subscriptionOptions() const {
return _subscriptionOptions;
}
rpl::producer<> Premium::somePremiumRequiredResolved() const {
return _somePremiumRequiredResolved.events();
rpl::producer<> Premium::someMessageMoneyRestrictionsResolved() const {
return _someMessageMoneyRestrictionsResolved.events();
}
void Premium::resolvePremiumRequired(not_null<UserData*> user) {
_resolvePremiumRequiredUsers.emplace(user);
if (!_premiumRequiredRequestScheduled
&& _resolvePremiumRequestedUsers.empty()) {
_premiumRequiredRequestScheduled = true;
void Premium::resolveMessageMoneyRestrictions(not_null<UserData*> user) {
_resolveMessageMoneyRequiredUsers.emplace(user);
if (!_messageMoneyRequestScheduled
&& _resolveMessageMoneyRequestedUsers.empty()) {
_messageMoneyRequestScheduled = true;
crl::on_main(_session, [=] {
requestPremiumRequiredSlice();
});
@ -393,50 +394,65 @@ void Premium::resolvePremiumRequired(not_null<UserData*> user) {
}
void Premium::requestPremiumRequiredSlice() {
_premiumRequiredRequestScheduled = false;
if (!_resolvePremiumRequestedUsers.empty()
|| _resolvePremiumRequiredUsers.empty()) {
_messageMoneyRequestScheduled = false;
if (!_resolveMessageMoneyRequestedUsers.empty()
|| _resolveMessageMoneyRequiredUsers.empty()) {
return;
}
constexpr auto kPerRequest = 100;
auto users = MTP_vector_from_range(_resolvePremiumRequiredUsers
auto users = MTP_vector_from_range(_resolveMessageMoneyRequiredUsers
| ranges::views::transform(&UserData::inputUser));
if (users.v.size() > kPerRequest) {
auto shortened = users.v;
shortened.resize(kPerRequest);
users = MTP_vector<MTPInputUser>(std::move(shortened));
const auto from = begin(_resolvePremiumRequiredUsers);
_resolvePremiumRequestedUsers = { from, from + kPerRequest };
_resolvePremiumRequiredUsers.erase(from, from + kPerRequest);
const auto from = begin(_resolveMessageMoneyRequiredUsers);
_resolveMessageMoneyRequestedUsers = { from, from + kPerRequest };
_resolveMessageMoneyRequiredUsers.erase(from, from + kPerRequest);
} else {
_resolvePremiumRequestedUsers
= base::take(_resolvePremiumRequiredUsers);
_resolveMessageMoneyRequestedUsers
= base::take(_resolveMessageMoneyRequiredUsers);
}
const auto finish = [=](const QVector<MTPBool> &list) {
constexpr auto me = UserDataFlag::MeRequiresPremiumToWrite;
constexpr auto known = UserDataFlag::RequirePremiumToWriteKnown;
constexpr auto mask = me | known;
const auto finish = [=](const QVector<MTPRequirementToContact> &list) {
auto index = 0;
for (const auto &user : base::take(_resolvePremiumRequestedUsers)) {
const auto require = (index < list.size())
&& mtpIsTrue(list[index++]);
user->setFlags((user->flags() & ~mask)
for (const auto &user : base::take(_resolveMessageMoneyRequestedUsers)) {
const auto set = [&](bool requirePremium, int stars) {
using Flag = UserDataFlag;
constexpr auto me = Flag::RequiresPremiumToWrite;
constexpr auto known = Flag::MessageMoneyRestrictionsKnown;
constexpr auto hasPrem = Flag::HasRequirePremiumToWrite;
constexpr auto hasStars = Flag::HasStarsPerMessage;
user->setStarsPerMessage(stars);
user->setFlags((user->flags() & ~(me | hasPrem | hasStars))
| known
| (require ? me : UserDataFlag()));
| (requirePremium ? (me | hasPrem) : Flag())
| (stars ? hasStars : Flag()));
};
if (index >= list.size()) {
set(false, 0);
continue;
}
if (!_premiumRequiredRequestScheduled
&& !_resolvePremiumRequiredUsers.empty()) {
_premiumRequiredRequestScheduled = true;
list[index++].match([&](const MTPDrequirementToContactEmpty &) {
set(false, 0);
}, [&](const MTPDrequirementToContactPremium &) {
set(true, 0);
}, [&](const MTPDrequirementToContactPaidMessages &data) {
set(false, data.vstars_amount().v);
});
}
if (!_messageMoneyRequestScheduled
&& !_resolveMessageMoneyRequiredUsers.empty()) {
_messageMoneyRequestScheduled = true;
crl::on_main(_session, [=] {
requestPremiumRequiredSlice();
});
}
_somePremiumRequiredResolved.fire({});
_someMessageMoneyRestrictionsResolved.fire({});
};
_session->api().request(
MTPusers_GetIsPremiumRequiredToContact(std::move(users))
).done([=](const MTPVector<MTPBool> &result) {
MTPusers_GetRequirementsToContact(std::move(users))
).done([=](const MTPVector<MTPRequirementToContact> &result) {
finish(result.v);
}).fail([=] {
finish({});
@ -463,10 +479,14 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
for (const auto &tlOption : result.v) {
const auto &data = tlOption.data();
tlMapOptions[data.vusers().v].push_back(tlOption);
if (qs(data.vcurrency()) == Ui::kCreditsCurrency) {
continue;
}
const auto token = Token{ data.vusers().v, data.vmonths().v };
_stores[token] = Store{
.amount = data.vamount().v,
.currency = qs(data.vcurrency()),
.product = qs(data.vstore_product().value_or_empty()),
.quantity = data.vstore_quantity().value_or_empty(),
};
@ -475,14 +495,14 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
}
}
for (const auto &[amount, tlOptions] : tlMapOptions) {
if (amount == 1 && _optionsForOnePerson.currency.isEmpty()) {
_optionsForOnePerson.currency = qs(
tlOptions.front().data().vcurrency());
if (amount == 1 && _optionsForOnePerson.currencies.empty()) {
for (const auto &option : tlOptions) {
_optionsForOnePerson.months.push_back(
option.data().vmonths().v);
_optionsForOnePerson.totalCosts.push_back(
option.data().vamount().v);
_optionsForOnePerson.currencies.push_back(
qs(option.data().vcurrency()));
}
}
_subscriptionOptions[amount] = GiftCodesFromTL(tlOptions);
@ -509,7 +529,7 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::applyPrepaid(
_api.request(MTPpayments_LaunchPrepaidGiveaway(
_peer->input,
MTP_long(prepaidId),
invoice.creditsAmount
invoice.giveawayCredits
? Payments::InvoiceCreditsGiveawayToTL(invoice)
: Payments::InvoicePremiumGiftCodeGiveawayToTL(invoice)
)).done([=](const MTPUpdates &result) {
@ -540,7 +560,7 @@ Payments::InvoicePremiumGiftCode PremiumGiftCodeOptions::invoice(
const auto token = Token{ users, months };
const auto &store = _stores[token];
return Payments::InvoicePremiumGiftCode{
.currency = _optionsForOnePerson.currency,
.currency = store.currency,
.storeProduct = store.product,
.randomId = randomId,
.amount = store.amount,
@ -553,14 +573,15 @@ Payments::InvoicePremiumGiftCode PremiumGiftCodeOptions::invoice(
std::vector<GiftOptionData> PremiumGiftCodeOptions::optionsForPeer() const {
auto result = std::vector<GiftOptionData>();
if (!_optionsForOnePerson.currency.isEmpty()) {
if (!_optionsForOnePerson.currencies.empty()) {
const auto count = int(_optionsForOnePerson.months.size());
result.reserve(count);
for (auto i = 0; i != count; ++i) {
Assert(i < _optionsForOnePerson.totalCosts.size());
Assert(i < _optionsForOnePerson.currencies.size());
result.push_back({
.cost = _optionsForOnePerson.totalCosts[i],
.currency = _optionsForOnePerson.currency,
.currency = _optionsForOnePerson.currencies[i],
.months = _optionsForOnePerson.months[i],
});
}
@ -581,7 +602,7 @@ Data::PremiumSubscriptionOptions PremiumGiftCodeOptions::options(int amount) {
MTP_int(_optionsForOnePerson.months[i]),
MTPstring(),
MTPint(),
MTP_string(_optionsForOnePerson.currency),
MTP_string(_optionsForOnePerson.currencies[i]),
MTP_long(_optionsForOnePerson.totalCosts[i] * amount)));
}
_subscriptionOptions[amount] = GiftCodesFromTL(tlOptions);
@ -694,28 +715,38 @@ rpl::producer<rpl::no_value, QString> SponsoredToggle::setToggled(bool v) {
};
}
RequirePremiumState ResolveRequiresPremiumToWrite(
MessageMoneyRestriction ResolveMessageMoneyRestrictions(
not_null<PeerData*> peer,
History *maybeHistory) {
const auto user = peer->asUser();
if (!user
|| !user->someRequirePremiumToWrite()
|| user->session().premium()) {
return RequirePremiumState::No;
} else if (user->requirePremiumToWriteKnown()) {
return user->meRequiresPremiumToWrite()
? RequirePremiumState::Yes
: RequirePremiumState::No;
} else if (user->flags() & UserDataFlag::MutualContact) {
return RequirePremiumState::No;
} else if (!maybeHistory) {
return RequirePremiumState::Unknown;
if (const auto channel = peer->asChannel()) {
return {
.starsPerMessage = channel->starsPerMessageChecked(),
.known = true,
};
}
const auto user = peer->asUser();
if (!user) {
return { .known = true };
} else if (user->messageMoneyRestrictionsKnown()) {
return {
.starsPerMessage = user->starsPerMessageChecked(),
.premiumRequired = (user->requiresPremiumToWrite()
&& !user->session().premium()),
.known = true,
};
} else if (user->hasStarsPerMessage()) {
return {};
} else if (!user->hasRequirePremiumToWrite()) {
return { .known = true };
} else if (user->flags() & UserDataFlag::MutualContact) {
return { .known = true };
} else if (!maybeHistory) {
return {};
}
const auto update = [&](bool require) {
using Flag = UserDataFlag;
constexpr auto known = Flag::RequirePremiumToWriteKnown;
constexpr auto me = Flag::MeRequiresPremiumToWrite;
constexpr auto known = Flag::MessageMoneyRestrictionsKnown;
constexpr auto me = Flag::RequiresPremiumToWrite;
user->setFlags((user->flags() & ~me)
| known
| (require ? me : Flag()));
@ -727,16 +758,19 @@ RequirePremiumState ResolveRequiresPremiumToWrite(
const auto item = view->data();
if (!item->out() && !item->isService()) {
update(false);
return RequirePremiumState::No;
return { .known = true };
}
}
}
if (user->isContact() // Here we know, that we're not in his contacts.
&& maybeHistory->loadedAtTop() // And no incoming messages.
&& maybeHistory->loadedAtBottom()) {
update(true);
return {
.premiumRequired = !user->session().premium(),
.known = true,
};
}
return RequirePremiumState::Unknown;
return {};
}
rpl::producer<DocumentData*> RandomHelloStickerValue(
@ -765,6 +799,7 @@ std::optional<Data::StarGift> FromTL(
return gift.match([&](const MTPDstarGift &data) {
const auto document = session->data().processDocument(
data.vsticker());
const auto resellPrice = data.vresell_min_stars().value_or_empty();
const auto remaining = data.vavailability_remains();
const auto total = data.vavailability_total();
if (!document->sticker()) {
@ -775,13 +810,17 @@ std::optional<Data::StarGift> FromTL(
.stars = int64(data.vstars().v),
.starsConverted = int64(data.vconvert_stars().v),
.starsToUpgrade = int64(data.vupgrade_stars().value_or_empty()),
.starsResellMin = int64(resellPrice),
.document = document,
.resellTitle = qs(data.vtitle().value_or_empty()),
.resellCount = int(data.vavailability_resale().value_or_empty()),
.limitedLeft = remaining.value_or_empty(),
.limitedCount = total.value_or_empty(),
.firstSaleDate = data.vfirst_sale_date().value_or_empty(),
.lastSaleDate = data.vlast_sale_date().value_or_empty(),
.upgradable = data.vupgrade_stars().has_value(),
.birthday = data.is_birthday(),
.soldOut = data.is_sold_out(),
});
}, [&](const MTPDstarGiftUnique &data) {
const auto total = data.vavailability_total().v;
@ -814,6 +853,7 @@ std::optional<Data::StarGift> FromTL(
? peerFromMTP(*data.vowner_id())
: PeerId()),
.number = data.vnum().v,
.starsForResale = int(data.vresell_stars().value_or_empty()),
.model = *model,
.pattern = *pattern,
}),
@ -846,8 +886,11 @@ std::optional<Data::SavedStarGift> FromTL(
} else if (const auto unique = parsed->unique.get()) {
unique->starsForTransfer = data.vtransfer_stars().value_or(-1);
unique->exportAt = data.vcan_export_at().value_or_empty();
unique->canTransferAt = data.vcan_transfer_at().value_or_empty();
unique->canResellAt = data.vcan_resell_at().value_or_empty();
}
using Id = Data::SavedStarGiftId;
const auto hasUnique = parsed->unique != nullptr;
return Data::SavedStarGift{
.info = std::move(*parsed),
.manageId = (to->isUser()
@ -870,6 +913,7 @@ std::optional<Data::SavedStarGift> FromTL(
.date = data.vdate().v,
.upgradable = data.is_can_upgrade(),
.anonymous = data.is_name_hidden(),
.pinned = data.is_pinned_to_top() && hasUnique,
.hidden = data.is_unsaved(),
.mine = to->isSelf(),
};
@ -899,7 +943,7 @@ Data::UniqueGiftPattern FromTL(
}
Data::UniqueGiftBackdrop FromTL(const MTPDstarGiftAttributeBackdrop &data) {
auto result = Data::UniqueGiftBackdrop();
auto result = Data::UniqueGiftBackdrop{ .id = data.vbackdrop_id().v };
result.name = qs(data.vname());
result.rarityPermille = data.vrarity_permille().v;
result.centerColor = Ui::ColorFromSerialized(

View file

@ -116,8 +116,9 @@ public:
[[nodiscard]] auto subscriptionOptions() const
-> const Data::PremiumSubscriptionOptions &;
[[nodiscard]] rpl::producer<> somePremiumRequiredResolved() const;
void resolvePremiumRequired(not_null<UserData*> user);
[[nodiscard]] auto someMessageMoneyRestrictionsResolved() const
-> rpl::producer<>;
void resolveMessageMoneyRestrictions(not_null<UserData*> user);
private:
void reloadPromo();
@ -166,10 +167,10 @@ private:
Data::PremiumSubscriptionOptions _subscriptionOptions;
rpl::event_stream<> _somePremiumRequiredResolved;
base::flat_set<not_null<UserData*>> _resolvePremiumRequiredUsers;
base::flat_set<not_null<UserData*>> _resolvePremiumRequestedUsers;
bool _premiumRequiredRequestScheduled = false;
rpl::event_stream<> _someMessageMoneyRestrictionsResolved;
base::flat_set<not_null<UserData*>> _resolveMessageMoneyRequiredUsers;
base::flat_set<not_null<UserData*>> _resolveMessageMoneyRequestedUsers;
bool _messageMoneyRequestScheduled = false;
};
@ -208,6 +209,7 @@ private:
};
struct Store final {
uint64 amount = 0;
QString currency;
QString product;
int quantity = 0;
};
@ -218,7 +220,7 @@ private:
struct {
std::vector<int> months;
std::vector<int64> totalCosts;
QString currency;
std::vector<QString> currencies;
} _optionsForOnePerson;
std::vector<int> _availablePresets;
@ -244,12 +246,20 @@ private:
};
enum class RequirePremiumState {
Unknown,
Yes,
No,
struct MessageMoneyRestriction {
int starsPerMessage = 0;
bool premiumRequired = false;
bool known = false;
explicit operator bool() const {
return starsPerMessage != 0 || premiumRequired;
}
friend inline bool operator==(
const MessageMoneyRestriction &,
const MessageMoneyRestriction &) = default;
};
[[nodiscard]] RequirePremiumState ResolveRequiresPremiumToWrite(
[[nodiscard]] MessageMoneyRestriction ResolveMessageMoneyRestrictions(
not_null<PeerData*> peer,
History *maybeHistory);

View file

@ -25,13 +25,17 @@ Data::PremiumSubscriptionOption CreateSubscriptionOption(
* kDiscountDivider;
}();
return {
.months = months,
.duration = Ui::FormatTTL(months * 86400 * 31),
.discount = discount
.discount = (discount > 0)
? QString::fromUtf8("\xe2\x88\x92%1%").arg(discount)
: QString(),
.costPerMonth = Ui::FillAmountAndCurrency(
amount / float64(months),
currency),
.costNoDiscount = Ui::FillAmountAndCurrency(
monthlyAmount * months,
currency),
.costTotal = Ui::FillAmountAndCurrency(amount, currency),
.botUrl = botUrl,
};

View file

@ -24,15 +24,26 @@ template<typename Option>
if (tlOpts.isEmpty()) {
return {};
}
auto monthlyAmountPerCurrency = base::flat_map<QString, int>();
auto result = Data::PremiumSubscriptionOptions();
const auto monthlyAmount = [&] {
const auto monthlyAmount = [&](const QString &currency) -> int {
const auto it = monthlyAmountPerCurrency.find(currency);
if (it != end(monthlyAmountPerCurrency)) {
return it->second;
}
const auto &min = ranges::min_element(
tlOpts,
ranges::less(),
[](const Option &o) { return o.data().vamount().v; }
[&](const Option &o) {
return currency == qs(o.data().vcurrency())
? o.data().vamount().v
: std::numeric_limits<int64_t>::max();
}
)->data();
return min.vamount().v / float64(min.vmonths().v);
}();
const auto monthly = min.vamount().v / float64(min.vmonths().v);
monthlyAmountPerCurrency.emplace(currency, monthly);
return monthly;
};
result.reserve(tlOpts.size());
for (const auto &tlOption : tlOpts) {
const auto &option = tlOption.data();
@ -45,7 +56,7 @@ template<typename Option>
const auto currency = qs(option.vcurrency());
result.push_back(CreateSubscriptionOption(
months,
monthlyAmount,
monthlyAmount(currency),
amount,
currency,
botUrl));

View file

@ -118,8 +118,8 @@ void SendProgressManager::send(const Key &key, int progress) {
}
// AyuGram sendUploadProgress
const auto settings = &AyuSettings::getInstance();
if (!settings->sendUploadProgress)
const auto& settings = AyuSettings::getInstance();
if (!settings.sendUploadProgress)
{
DEBUG_LOG(("[AyuGram] Don't send upload progress"));
return;

View file

@ -95,7 +95,9 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
const auto messagePostAuthor = peer->isBroadcast()
? session->user()->name()
: QString();
const auto starsPaid = std::min(
peer->starsPerMessageChecked(),
action.options.starsApproved);
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
@ -111,6 +113,10 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
flags |= MessageFlag::InvertMedia;
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
}
if (starsPaid) {
action.options.starsApproved -= starsPaid;
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
}
auto &histories = history->owner().histories();
histories.sendPreparedMessage(
@ -129,7 +135,8 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId)
MTP_long(action.options.effectId),
MTP_long(starsPaid)
), [=](const MTPUpdates &result, const MTP::Response &response) {
}, [=](const MTP::Error &error, const MTP::Response &response) {
api->sendMessageFail(error, peer, randomId);
@ -160,7 +167,7 @@ void SendExistingMedia(
? (*localMessageId)
: session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();
const auto &action = message.action;
auto &action = message.action;
auto flags = NewMessageFlags(peer);
auto sendFlags = MTPmessages_SendMedia::Flags(0);
@ -190,7 +197,9 @@ void SendExistingMedia(
sendFlags |= MTPmessages_SendMedia::Flag::f_entities;
}
const auto captionText = caption.text;
const auto starsPaid = std::min(
peer->starsPerMessageChecked(),
action.options.starsApproved);
if (action.options.scheduled) {
flags |= MessageFlag::IsOrWasScheduled;
sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
@ -206,6 +215,10 @@ void SendExistingMedia(
flags |= MessageFlag::InvertMedia;
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
}
if (starsPaid) {
action.options.starsApproved -= starsPaid;
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
}
session->data().registerMessageRandomId(randomId, newId);
@ -216,6 +229,7 @@ void SendExistingMedia(
.replyTo = action.replyTo,
.date = NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.starsPaid = starsPaid,
.postAuthor = NewMessagePostAuthor(action),
.effectId = action.options.effectId,
}, media, caption);
@ -240,7 +254,8 @@ void SendExistingMedia(
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId)
MTP_long(action.options.effectId),
MTP_long(starsPaid)
), [=](const MTPUpdates &result, const MTP::Response &response) {
}, [=](const MTP::Error &error, const MTP::Response &response) {
if (error.code() == 400
@ -341,7 +356,7 @@ bool SendDice(MessageToSend &message) {
message.action.generateLocal = true;
const auto &action = message.action;
auto &action = message.action;
api->sendAction(action);
const auto newId = FullMsgId(
@ -380,6 +395,13 @@ bool SendDice(MessageToSend &message) {
flags |= MessageFlag::InvertMedia;
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
}
const auto starsPaid = std::min(
peer->starsPerMessageChecked(),
action.options.starsApproved);
if (starsPaid) {
action.options.starsApproved -= starsPaid;
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
}
session->data().registerMessageRandomId(randomId, newId);
@ -390,6 +412,7 @@ bool SendDice(MessageToSend &message) {
.replyTo = action.replyTo,
.date = NewMessageDate(action.options),
.shortcutId = action.options.shortcutId,
.starsPaid = starsPaid,
.postAuthor = NewMessagePostAuthor(action),
.effectId = action.options.effectId,
}, TextWithEntities(), MTP_messageMediaDice(
@ -411,7 +434,8 @@ bool SendDice(MessageToSend &message) {
MTP_int(action.options.scheduled),
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
Data::ShortcutIdToMTP(session, action.options.shortcutId),
MTP_long(action.options.effectId)
MTP_long(action.options.effectId),
MTP_long(starsPaid)
), [=](const MTPUpdates &result, const MTP::Response &response) {
}, [=](const MTP::Error &error, const MTP::Response &response) {
api->sendMessageFail(error, peer, randomId, newId);
@ -610,6 +634,9 @@ void SendConfirmedFile(
.replyTo = file->to.replyTo,
.date = NewMessageDate(file->to.options),
.shortcutId = file->to.options.shortcutId,
.starsPaid = std::min(
history->peer->starsPerMessageChecked(),
file->to.options.starsApproved),
.postAuthor = NewMessagePostAuthor(action),
.groupedId = groupId,
.effectId = file->to.options.effectId,

View file

@ -313,7 +313,7 @@ void PublicForwards::request(
const auto msgId = IdFromMessage(message);
const auto peerId = PeerFromMessage(message);
const auto lastDate = DateFromMessage(message);
if (const auto peer = owner.peerLoaded(peerId)) {
if (owner.peerLoaded(peerId)) {
if (!lastDate) {
return;
}

View file

@ -202,7 +202,11 @@ EntitiesInText EntitiesFromMTP(
d.vlength().v,
});
}, [&](const MTPDmessageEntityBankCard &d) {
// Skipping cards. // #TODO entities
result.push_back({
EntityType::BankCard,
d.voffset().v,
d.vlength().v,
});
}, [&](const MTPDmessageEntitySpoiler &d) {
result.push_back({
EntityType::Spoiler,
@ -273,6 +277,9 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
case EntityType::Phone: {
v.push_back(MTP_messageEntityPhone(offset, length));
} break;
case EntityType::BankCard: {
v.push_back(MTP_messageEntityBankCard(offset, length));
} break;
case EntityType::Hashtag: {
v.push_back(MTP_messageEntityHashtag(offset, length));
} break;

View file

@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_dc_options.h"
#include "data/business/data_shortcut_messages.h"
#include "data/components/credits.h"
#include "data/components/promo_suggestions.h"
#include "data/components/scheduled_messages.h"
#include "data/components/top_peers.h"
#include "data/notify/data_notify_settings.h"
@ -307,14 +308,19 @@ void Updates::feedUpdateVector(
auto list = updates.v;
const auto hasGroupCallParticipantUpdates = ranges::contains(
list,
mtpc_updateGroupCallParticipants,
&MTPUpdate::type);
true,
[](const MTPUpdate &update) {
return update.type() == mtpc_updateGroupCallParticipants
|| update.type() == mtpc_updateGroupCallChainBlocks;
});
if (hasGroupCallParticipantUpdates) {
ranges::stable_sort(list, std::less<>(), [](const MTPUpdate &entry) {
if (entry.type() == mtpc_updateGroupCallParticipants) {
if (entry.type() == mtpc_updateGroupCallChainBlocks) {
return 0;
} else {
} else if (entry.type() == mtpc_updateGroupCallParticipants) {
return 1;
} else {
return 2;
}
});
} else if (policy == SkipUpdatePolicy::SkipExceptGroupCallParticipants) {
@ -328,7 +334,8 @@ void Updates::feedUpdateVector(
if ((policy == SkipUpdatePolicy::SkipMessageIds
&& type == mtpc_updateMessageID)
|| (policy == SkipUpdatePolicy::SkipExceptGroupCallParticipants
&& type != mtpc_updateGroupCallParticipants)) {
&& type != mtpc_updateGroupCallParticipants
&& type != mtpc_updateGroupCallChainBlocks)) {
continue;
}
feedUpdate(entry);
@ -958,7 +965,8 @@ void Updates::applyGroupCallParticipantUpdates(const MTPUpdates &updates) {
data.vupdates(),
SkipUpdatePolicy::SkipExceptGroupCallParticipants);
}, [&](const MTPDupdateShort &data) {
if (data.vupdate().type() == mtpc_updateGroupCallParticipants) {
if (data.vupdate().type() == mtpc_updateGroupCallParticipants
|| data.vupdate().type() == mtpc_updateGroupCallChainBlocks) {
feedUpdate(data.vupdate());
}
}, [](const auto &) {
@ -990,10 +998,10 @@ void Updates::updateOnline(crl::time lastNonIdleTime, bool gotOtherOffline) {
});
// AyuGram sendOnlinePackets
const auto settings = &AyuSettings::getInstance();
const auto& settings = AyuSettings::getInstance();
const auto& config = _session->serverConfig();
bool isOnlineOrig = Core::App().hasActiveWindow(&session());
bool isOnline = settings->sendOnlinePackets && isOnlineOrig;
bool isOnline = settings.sendOnlinePackets && isOnlineOrig;
int updateIn = config.onlineUpdatePeriod;
Assert(updateIn >= 0);
@ -1227,7 +1235,8 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
MTPint(), // quick_reply_shortcut_id
MTPlong(), // effect
MTPFactCheck(),
MTPint()), // report_delivery_until_date
MTPint(), // report_delivery_until_date
MTPlong()), // paid_message_stars
MessageFlags(),
NewMessageType::Unread);
} break;
@ -1265,7 +1274,8 @@ void Updates::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
MTPint(), // quick_reply_shortcut_id
MTPlong(), // effect
MTPFactCheck(),
MTPint()), // report_delivery_until_date
MTPint(), // report_delivery_until_date
MTPlong()), // paid_message_stars
MessageFlags(),
NewMessageType::Unread);
} break;
@ -1315,7 +1325,7 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
user->madeAction(base::unixtime::now());
}
}
ClearMediaAsExpired(item);
item->clearMediaAsExpired();
}
} else {
// Perhaps it was an unread mention!
@ -2067,6 +2077,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateConfig: {
session().mtp().requestConfig();
session().promoSuggestions().invalidate();
} break;
case mtpc_updateUserPhone: {
@ -2116,6 +2127,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updatePhoneCall:
case mtpc_updatePhoneCallSignalingData:
case mtpc_updateGroupCallParticipants:
case mtpc_updateGroupCallChainBlocks:
case mtpc_updateGroupCallConnection:
case mtpc_updateGroupCall: {
Core::App().calls().handleUpdate(&session(), update);

View file

@ -210,6 +210,7 @@ MTPInputPrivacyKey KeyToTL(UserPrivacy::Key key) {
case Key::About: return MTP_inputPrivacyKeyAbout();
case Key::Birthday: return MTP_inputPrivacyKeyBirthday();
case Key::GiftsAutoSave: return MTP_inputPrivacyKeyStarGiftsAutoSave();
case Key::NoPaidMessages: return MTP_inputPrivacyKeyNoPaidMessages();
}
Unexpected("Key in Api::UserPrivacy::KetToTL.");
}
@ -241,6 +242,8 @@ std::optional<UserPrivacy::Key> TLToKey(mtpTypeId type) {
case mtpc_inputPrivacyKeyBirthday: return Key::Birthday;
case mtpc_privacyKeyStarGiftsAutoSave:
case mtpc_inputPrivacyKeyStarGiftsAutoSave: return Key::GiftsAutoSave;
case mtpc_privacyKeyNoPaidMessages:
case mtpc_inputPrivacyKeyNoPaidMessages: return Key::NoPaidMessages;
}
return std::nullopt;
}

View file

@ -32,6 +32,7 @@ public:
About,
Birthday,
GiftsAutoSave,
NoPaidMessages,
};
enum class Option {
Everyone,

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