Compare commits

...

470 commits
v5.12.3 ... 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
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
493 changed files with 22332 additions and 4832 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,11 +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.buildDirectory": "${workspaceFolder}/out",
"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: 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: 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.";
@ -1294,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";
@ -2173,9 +2228,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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";
"lng_similar_channels_more" = "More Channels";
@ -2192,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";
@ -2764,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";
@ -2906,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.";
@ -3075,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";
@ -3093,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.";
@ -3341,9 +3443,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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";
@ -3365,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.";
@ -3387,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.";
@ -3428,7 +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.";
@ -3487,6 +3606,23 @@ 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}";
@ -3501,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.";
@ -3616,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}";
@ -3793,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";
@ -4130,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";
@ -4237,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";
@ -4331,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...";
@ -4544,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";
@ -4553,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?";
@ -4571,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)";
@ -4589,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";
@ -4620,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.";
@ -4651,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";
@ -4698,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.";
@ -4806,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}";
@ -5025,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";
@ -5039,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";
@ -5149,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}";
@ -5732,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?";
@ -5745,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.";
@ -5753,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";
@ -6119,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.";
@ -6241,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...";
@ -6322,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";
@ -6383,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";
@ -6407,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.";
@ -6485,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";
@ -6557,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";
@ -6589,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";
@ -6607,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.12.3.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,12,3,0
PRODUCTVERSION 5,12,3,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.12.3.0"
VALUE "FileVersion", "5.14.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "5.12.3.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,12,3,0
PRODUCTVERSION 5,12,3,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.12.3.0"
VALUE "FileVersion", "5.14.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "5.12.3.0"
VALUE "ProductVersion", "5.14.3.0"
END
END
BLOCK "VarFileInfo"

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

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

@ -157,6 +157,7 @@ constexpr auto kTransactionsLimit = 100;
.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(),
@ -348,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) {
@ -525,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) {
@ -115,7 +115,8 @@ void GlobalPrivacy::updateHideReadTime(bool hide) {
unarchiveOnNewMessageCurrent(),
hide,
newRequirePremiumCurrent(),
newChargeStarsCurrent());
newChargeStarsCurrent(),
disallowedGiftTypesCurrent());
}
bool GlobalPrivacy::hideReadTimeCurrent() const {
@ -150,7 +151,27 @@ void GlobalPrivacy::updateMessagesPrivacy(
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
requirePremium,
chargeStars);
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() {
@ -182,7 +203,8 @@ void GlobalPrivacy::updateArchiveAndMute(bool value) {
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
newRequirePremiumCurrent(),
newChargeStarsCurrent());
newChargeStarsCurrent(),
disallowedGiftTypesCurrent());
}
void GlobalPrivacy::updateUnarchiveOnNewMessage(
@ -192,7 +214,8 @@ void GlobalPrivacy::updateUnarchiveOnNewMessage(
value,
hideReadTimeCurrent(),
newRequirePremiumCurrent(),
newChargeStarsCurrent());
newChargeStarsCurrent(),
disallowedGiftTypesCurrent());
}
void GlobalPrivacy::update(
@ -200,12 +223,16 @@ void GlobalPrivacy::update(
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium,
int newChargeStars) {
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
@ -220,14 +247,35 @@ void GlobalPrivacy::update(
| ((newRequirePremium && newRequirePremiumAllowed)
? Flag::f_new_noncontact_peers_require_premium
: Flag())
| Flag::f_noncontact_peers_paid_stars;
| 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_long(newChargeStars))
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) {
@ -236,7 +284,8 @@ void GlobalPrivacy::update(
unarchiveOnNewMessage,
hideReadTime,
false,
0);
0,
DisallowedGiftTypes());
}
}).send();
_archiveAndMute = archiveAndMute;
@ -244,6 +293,7 @@ void GlobalPrivacy::update(
_hideReadTime = hideReadTime;
_newRequirePremium = newRequirePremium;
_newChargeStars = newChargeStars;
_disallowedGiftTypes = disallowedGiftTypes;
}
void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) {
@ -257,6 +307,29 @@ void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) {
_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);
@ -57,6 +69,11 @@ public:
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;
@ -70,7 +87,8 @@ private:
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium,
int newChargeStars);
int newChargeStars,
DisallowedGiftTypes disallowedGiftTypes);
const not_null<Main::Session*> _session;
MTP::Sender _api;
@ -82,6 +100,7 @@ private:
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

@ -171,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

@ -799,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()) {
@ -809,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;
@ -848,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,
}),
@ -880,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()
@ -904,7 +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(),
.pinned = data.is_pinned_to_top() && hasUnique,
.hidden = data.is_unsaved(),
.mine = to->isSelf(),
};
@ -934,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

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

@ -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);
@ -1317,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!
@ -2069,6 +2077,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateConfig: {
session().mtp().requestConfig();
session().promoSuggestions().invalidate();
} break;
case mtpc_updateUserPhone: {
@ -2118,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

@ -97,8 +97,6 @@ namespace {
// Save draft to the cloud with 1 sec extra delay.
constexpr auto kSaveCloudDraftTimeout = 1000;
constexpr auto kTopPromotionInterval = TimeId(60 * 60);
constexpr auto kTopPromotionMinDelay = TimeId(10);
constexpr auto kSmallDelayMs = 5;
constexpr auto kReadFeaturedSetsTimeout = crl::time(1000);
constexpr auto kFileLoaderQueueStopTimeout = crl::time(5000);
@ -169,7 +167,6 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
, _featuredSetsReadTimer([=] { readFeaturedSets(); })
, _dialogsLoadState(std::make_unique<DialogsLoadState>())
, _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout))
, _topPromotionTimer([=] { refreshTopPromotion(); })
, _updateNotifyTimer([=] { sendNotifySettingsUpdates(); })
, _statsSessionKillTimer([=] { checkStatsSessions(); })
, _authorizations(std::make_unique<Api::Authorizations>(this))
@ -205,11 +202,6 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
}, _session->lifetime());
setupSupportMode();
Core::App().settings().proxy().connectionTypeValue(
) | rpl::start_with_next([=] {
refreshTopPromotion();
}, _session->lifetime());
});
}
@ -249,79 +241,6 @@ void ApiWrap::requestChangelog(
//).send();
}
void ApiWrap::refreshTopPromotion() {
const auto now = base::unixtime::now();
const auto next = (_topPromotionNextRequestTime != 0)
? _topPromotionNextRequestTime
: now;
if (_topPromotionRequestId) {
getTopPromotionDelayed(now, next);
return;
}
const auto key = [&]() -> std::pair<QString, uint32> {
if (!Core::App().settings().proxy().isEnabled()) {
return {};
}
const auto &proxy = Core::App().settings().proxy().selected();
if (proxy.type != MTP::ProxyData::Type::Mtproto) {
return {};
}
return { proxy.host, proxy.port };
}();
if (_topPromotionKey == key && now < next) {
getTopPromotionDelayed(now, next);
return;
}
_topPromotionKey = key;
_topPromotionRequestId = request(MTPhelp_GetPromoData(
)).done([=](const MTPhelp_PromoData &result) {
_topPromotionRequestId = 0;
topPromotionDone(result);
}).fail([=] {
_topPromotionRequestId = 0;
const auto now = base::unixtime::now();
const auto next = _topPromotionNextRequestTime = now
+ kTopPromotionInterval;
if (!_topPromotionTimer.isActive()) {
getTopPromotionDelayed(now, next);
}
}).send();
}
void ApiWrap::getTopPromotionDelayed(TimeId now, TimeId next) {
_topPromotionTimer.callOnce(std::min(
std::max(next - now, kTopPromotionMinDelay),
kTopPromotionInterval) * crl::time(1000));
};
void ApiWrap::topPromotionDone(const MTPhelp_PromoData &proxy) {
_topPromotionNextRequestTime = proxy.match([&](const auto &data) {
return data.vexpires().v;
});
getTopPromotionDelayed(
base::unixtime::now(),
_topPromotionNextRequestTime);
const auto settings = &AyuSettings::getInstance();
if (settings->disableAds) {
_session->data().setTopPromoted(nullptr, QString(), QString());
return;
}
proxy.match([&](const MTPDhelp_promoDataEmpty &data) {
_session->data().setTopPromoted(nullptr, QString(), QString());
}, [&](const MTPDhelp_promoData &data) {
_session->data().processChats(data.vchats());
_session->data().processUsers(data.vusers());
const auto peerId = peerFromMTP(data.vpeer());
const auto history = _session->data().history(peerId);
_session->data().setTopPromoted(
history,
data.vpsa_type().value_or_empty(),
data.vpsa_message().value_or_empty());
});
}
void ApiWrap::requestDeepLinkInfo(
const QString &path,
Fn<void(TextWithEntities message, bool updateRequired)> callback) {
@ -507,8 +426,8 @@ void ApiWrap::toggleHistoryArchived(
if (archived) {
history->setFolder(_session->data().folder(archiveId));
} else {
const auto settings = &AyuSettings::getInstance();
if (settings->hideAllChatsFolder) {
const auto& settings = AyuSettings::getInstance();
if (settings.hideAllChatsFolder) {
if (const auto window = Core::App().activeWindow()) {
if (const auto controller = window->sessionController()) {
const auto filters = &_session->data().chatsFilters();
@ -1384,7 +1303,7 @@ void ApiWrap::migrateFail(not_null<PeerData*> peer, const QString &error) {
void ApiWrap::markContentsRead(
const base::flat_set<not_null<HistoryItem*>> &items) {
const auto settings = &AyuSettings::getInstance();
const auto& settings = AyuSettings::getInstance();
auto markedIds = QVector<MTPint>();
auto channelMarkedIds = base::flat_map<
@ -1398,7 +1317,7 @@ void ApiWrap::markContentsRead(
continue;
}
if (!settings->sendReadMessages && !passthrough) {
if (!settings.sendReadMessages && !passthrough) {
continue;
}
@ -1430,8 +1349,8 @@ void ApiWrap::markContentsRead(not_null<HistoryItem*> item) {
return;
}
const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages && !passthrough) {
const auto& settings = AyuSettings::getInstance();
if (!settings.sendReadMessages && !passthrough) {
return;
}
@ -1833,8 +1752,8 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
using Flag = ChannelDataFlag;
chatParticipants().loadSimilarPeers(channel);
const auto settings = &AyuSettings::getInstance();
if (!settings->collapseSimilarChannels) {
const auto& settings = AyuSettings::getInstance();
if (!settings.collapseSimilarChannels) {
channel->setFlags(channel->flags() | Flag::SimilarExpanded);
}
}
@ -3461,8 +3380,8 @@ void ApiWrap::forwardMessages(
shared->callback();
}
const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages && settings->markReadAfterAction && history->lastMessage())
const auto& settings = AyuSettings::getInstance();
if (!settings.sendReadMessages && settings.markReadAfterAction && history->lastMessage())
{
readHistory(history->lastMessage());
}

View file

@ -200,7 +200,6 @@ public:
void requestChangelog(
const QString &sinceVersion,
Fn<void(const MTPUpdates &result)> callback);
void refreshTopPromotion();
void requestDeepLinkInfo(
const QString &path,
Fn<void(TextWithEntities message, bool updateRequired)> callback);
@ -569,9 +568,6 @@ private:
not_null<SendingAlbum*> album,
Fn<void(bool)> done = nullptr);
void getTopPromotionDelayed(TimeId now, TimeId next);
void topPromotionDone(const MTPhelp_PromoData &proxy);
void sendNotifySettingsUpdates();
template <typename Request>
@ -709,11 +705,6 @@ private:
std::unique_ptr<TaskQueue> _fileLoader;
base::flat_map<uint64, std::shared_ptr<SendingAlbum>> _sendingAlbums;
mtpRequestId _topPromotionRequestId = 0;
std::pair<QString, uint32> _topPromotionKey;
TimeId _topPromotionNextRequestTime = TimeId(0);
base::Timer _topPromotionTimer;
base::flat_set<not_null<const Data::ForumTopic*>> _updateNotifyTopics;
base::flat_set<not_null<const PeerData*>> _updateNotifyPeers;
base::flat_set<Data::DefaultNotify> _updateNotifyDefaults;

View file

@ -28,10 +28,10 @@ void initLang() {
}
void initUiSettings() {
auto settings = &AyuSettings::getInstance();
const auto& settings = AyuSettings::getInstance();
AyuUiSettings::setMonoFont(settings->monoFont);
AyuUiSettings::setWideMultiplier(settings->wideMultiplier);
AyuUiSettings::setMonoFont(settings.monoFont);
AyuUiSettings::setWideMultiplier(settings.wideMultiplier);
}
void initDatabase() {

View file

@ -219,6 +219,7 @@ AyuGramSettings::AyuGramSettings() {
disableAds = true;
disableStories = false;
disableCustomBackgrounds = true;
showOnlyAddedEmojisAndStickers = false;
collapseSimilarChannels = true;
hideSimilarChannels = false;
@ -300,32 +301,32 @@ AyuGramSettings::AyuGramSettings() {
voiceConfirmation = false;
}
void AyuGramSettings::set_sendReadMessages(bool val) {
sendReadMessages = val;
void set_sendReadMessages(bool val) {
settings->sendReadMessages = val;
sendReadMessagesReactive = val;
}
void AyuGramSettings::set_sendReadStories(bool val) {
sendReadStories = val;
void set_sendReadStories(bool val) {
settings->sendReadStories = val;
sendReadStoriesReactive = val;
}
void AyuGramSettings::set_sendOnlinePackets(bool val) {
sendOnlinePackets = val;
void set_sendOnlinePackets(bool val) {
settings->sendOnlinePackets = val;
sendOnlinePacketsReactive = val;
}
void AyuGramSettings::set_sendUploadProgress(bool val) {
sendUploadProgress = val;
void set_sendUploadProgress(bool val) {
settings->sendUploadProgress = val;
sendUploadProgressReactive = val;
}
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val) {
sendOfflinePacketAfterOnline = val;
void set_sendOfflinePacketAfterOnline(bool val) {
settings->sendOfflinePacketAfterOnline = val;
sendOfflinePacketAfterOnlineReactive = val;
}
void AyuGramSettings::set_ghostModeEnabled(bool val) {
void set_ghostModeEnabled(bool val) {
set_sendReadMessages(!val);
set_sendReadStories(!val);
set_sendOnlinePackets(!val);
@ -339,231 +340,234 @@ void AyuGramSettings::set_ghostModeEnabled(bool val) {
}
}
void AyuGramSettings::set_markReadAfterAction(bool val) {
markReadAfterAction = val;
void set_markReadAfterAction(bool val) {
settings->markReadAfterAction = val;
}
void AyuGramSettings::set_useScheduledMessages(bool val) {
useScheduledMessages = val;
void set_useScheduledMessages(bool val) {
settings->useScheduledMessages = val;
}
void AyuGramSettings::set_sendWithoutSound(bool val) {
sendWithoutSound = val;
void set_sendWithoutSound(bool val) {
settings->sendWithoutSound = val;
}
void AyuGramSettings::set_saveDeletedMessages(bool val) {
saveDeletedMessages = val;
void set_saveDeletedMessages(bool val) {
settings->saveDeletedMessages = val;
}
void AyuGramSettings::set_saveMessagesHistory(bool val) {
saveMessagesHistory = val;
void set_saveMessagesHistory(bool val) {
settings->saveMessagesHistory = val;
}
void AyuGramSettings::set_saveForBots(bool val) {
saveForBots = val;
void set_saveForBots(bool val) {
settings->saveForBots = val;
}
void AyuGramSettings::set_hideFromBlocked(bool val) {
hideFromBlocked = val;
void set_hideFromBlocked(bool val) {
settings->hideFromBlocked = val;
hideFromBlockedReactive = val;
}
void AyuGramSettings::set_disableAds(bool val) {
disableAds = val;
void set_disableAds(bool val) {
settings->disableAds = val;
}
void AyuGramSettings::set_disableStories(bool val) {
disableStories = val;
void set_disableStories(bool val) {
settings->disableStories = val;
}
void AyuGramSettings::set_disableCustomBackgrounds(bool val) {
disableCustomBackgrounds = val;
void set_disableCustomBackgrounds(bool val) {
settings->disableCustomBackgrounds = val;
}
void AyuGramSettings::set_collapseSimilarChannels(bool val) {
collapseSimilarChannels = val;
void set_showOnlyAddedEmojisAndStickers(bool val) {
settings->showOnlyAddedEmojisAndStickers = val;
}
void AyuGramSettings::set_hideSimilarChannels(bool val) {
hideSimilarChannels = val;
void set_collapseSimilarChannels(bool val) {
settings->collapseSimilarChannels = val;
}
void AyuGramSettings::set_wideMultiplier(double val) {
wideMultiplier = val;
void set_hideSimilarChannels(bool val) {
settings->hideSimilarChannels = val;
}
void AyuGramSettings::set_spoofWebviewAsAndroid(bool val) {
spoofWebviewAsAndroid = val;
void set_wideMultiplier(double val) {
settings->wideMultiplier = val;
}
void AyuGramSettings::set_increaseWebviewHeight(bool val) {
increaseWebviewHeight = val;
void set_spoofWebviewAsAndroid(bool val) {
settings->spoofWebviewAsAndroid = val;
}
void AyuGramSettings::set_increaseWebviewWidth(bool val) {
increaseWebviewWidth = val;
void set_increaseWebviewHeight(bool val) {
settings->increaseWebviewHeight = val;
}
void AyuGramSettings::set_disableNotificationsDelay(bool val) {
disableNotificationsDelay = val;
void set_increaseWebviewWidth(bool val) {
settings->increaseWebviewWidth = val;
}
void AyuGramSettings::set_localPremium(bool val) {
localPremium = val;
void set_disableNotificationsDelay(bool val) {
settings->disableNotificationsDelay = val;
}
void AyuGramSettings::set_appIcon(QString val) {
appIcon = std::move(val);
void set_localPremium(bool val) {
settings->localPremium = val;
}
void AyuGramSettings::set_simpleQuotesAndReplies(bool val) {
simpleQuotesAndReplies = val;
void set_appIcon(QString val) {
settings->appIcon = std::move(val);
}
void AyuGramSettings::set_replaceBottomInfoWithIcons(bool val) {
replaceBottomInfoWithIcons = val;
void set_simpleQuotesAndReplies(bool val) {
settings->simpleQuotesAndReplies = val;
}
void AyuGramSettings::set_deletedMark(QString val) {
deletedMark = std::move(val);
deletedMarkReactive = deletedMark;
void set_replaceBottomInfoWithIcons(bool val) {
settings->replaceBottomInfoWithIcons = val;
}
void AyuGramSettings::set_editedMark(QString val) {
editedMark = std::move(val);
editedMarkReactive = editedMark;
void set_deletedMark(QString val) {
settings->deletedMark = std::move(val);
deletedMarkReactive = settings->deletedMark;
}
void AyuGramSettings::set_recentStickersCount(int val) {
recentStickersCount = val;
void set_editedMark(QString val) {
settings->editedMark = std::move(val);
editedMarkReactive = settings->editedMark;
}
void AyuGramSettings::set_showReactionsPanelInContextMenu(int val) {
showReactionsPanelInContextMenu = val;
void set_recentStickersCount(int val) {
settings->recentStickersCount = val;
}
void AyuGramSettings::set_showViewsPanelInContextMenu(int val) {
showViewsPanelInContextMenu = val;
void set_showReactionsPanelInContextMenu(int val) {
settings->showReactionsPanelInContextMenu = val;
}
void AyuGramSettings::set_showHideMessageInContextMenu(int val) {
showHideMessageInContextMenu = val;
void set_showViewsPanelInContextMenu(int val) {
settings->showViewsPanelInContextMenu = val;
}
void AyuGramSettings::set_showUserMessagesInContextMenu(int val) {
showUserMessagesInContextMenu = val;
void set_showHideMessageInContextMenu(int val) {
settings->showHideMessageInContextMenu = val;
}
void AyuGramSettings::set_showMessageDetailsInContextMenu(int val) {
showMessageDetailsInContextMenu = val;
void set_showUserMessagesInContextMenu(int val) {
settings->showUserMessagesInContextMenu = val;
}
void AyuGramSettings::set_showAttachButtonInMessageField(bool val) {
showAttachButtonInMessageField = val;
void set_showMessageDetailsInContextMenu(int val) {
settings->showMessageDetailsInContextMenu = val;
}
void set_showAttachButtonInMessageField(bool val) {
settings->showAttachButtonInMessageField = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showCommandsButtonInMessageField(bool val) {
showCommandsButtonInMessageField = val;
void set_showCommandsButtonInMessageField(bool val) {
settings->showCommandsButtonInMessageField = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showEmojiButtonInMessageField(bool val) {
showEmojiButtonInMessageField = val;
void set_showEmojiButtonInMessageField(bool val) {
settings->showEmojiButtonInMessageField = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showMicrophoneButtonInMessageField(bool val) {
showMicrophoneButtonInMessageField = val;
void set_showMicrophoneButtonInMessageField(bool val) {
settings->showMicrophoneButtonInMessageField = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showAutoDeleteButtonInMessageField(bool val) {
showAutoDeleteButtonInMessageField = val;
void set_showAutoDeleteButtonInMessageField(bool val) {
settings->showAutoDeleteButtonInMessageField = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showAttachPopup(bool val) {
showAttachPopup = val;
void set_showAttachPopup(bool val) {
settings->showAttachPopup = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showEmojiPopup(bool val) {
showEmojiPopup = val;
void set_showEmojiPopup(bool val) {
settings->showEmojiPopup = val;
triggerHistoryUpdate();
}
void AyuGramSettings::set_showLReadToggleInDrawer(bool val) {
showLReadToggleInDrawer = val;
void set_showLReadToggleInDrawer(bool val) {
settings->showLReadToggleInDrawer = val;
}
void AyuGramSettings::set_showSReadToggleInDrawer(bool val) {
showSReadToggleInDrawer = val;
void set_showSReadToggleInDrawer(bool val) {
settings->showSReadToggleInDrawer = val;
}
void AyuGramSettings::set_showGhostToggleInDrawer(bool val) {
showGhostToggleInDrawer = val;
void set_showGhostToggleInDrawer(bool val) {
settings->showGhostToggleInDrawer = val;
}
void AyuGramSettings::set_showStreamerToggleInDrawer(bool val) {
showStreamerToggleInDrawer = val;
void set_showStreamerToggleInDrawer(bool val) {
settings->showStreamerToggleInDrawer = val;
}
void AyuGramSettings::set_showGhostToggleInTray(bool val) {
showGhostToggleInTray = val;
void set_showGhostToggleInTray(bool val) {
settings->showGhostToggleInTray = val;
}
void AyuGramSettings::set_showStreamerToggleInTray(bool val) {
showStreamerToggleInTray = val;
void set_showStreamerToggleInTray(bool val) {
settings->showStreamerToggleInTray = val;
}
void AyuGramSettings::set_monoFont(QString val) {
monoFont = val;
void set_monoFont(QString val) {
settings->monoFont = val;
}
void AyuGramSettings::set_showPeerId(int val) {
showPeerId = val;
void set_showPeerId(int val) {
settings->showPeerId = val;
showPeerIdReactive = val;
}
void AyuGramSettings::set_hideNotificationCounters(bool val) {
hideNotificationCounters = val;
void set_hideNotificationCounters(bool val) {
settings->hideNotificationCounters = val;
}
void AyuGramSettings::set_hideNotificationBadge(bool val) {
hideNotificationBadge = val;
void set_hideNotificationBadge(bool val) {
settings->hideNotificationBadge = val;
}
void AyuGramSettings::set_hideAllChatsFolder(bool val) {
hideAllChatsFolder = val;
void set_hideAllChatsFolder(bool val) {
settings->hideAllChatsFolder = val;
}
void AyuGramSettings::set_channelBottomButton(int val) {
channelBottomButton = val;
void set_channelBottomButton(int val) {
settings->channelBottomButton = val;
}
void AyuGramSettings::set_showMessageSeconds(bool val) {
showMessageSeconds = val;
void set_showMessageSeconds(bool val) {
settings->showMessageSeconds = val;
}
void AyuGramSettings::set_showMessageShot(bool val) {
showMessageShot = val;
void set_showMessageShot(bool val) {
settings->showMessageShot = val;
}
void AyuGramSettings::set_stickerConfirmation(bool val) {
stickerConfirmation = val;
void set_stickerConfirmation(bool val) {
settings->stickerConfirmation = val;
}
void AyuGramSettings::set_gifConfirmation(bool val) {
gifConfirmation = val;
void set_gifConfirmation(bool val) {
settings->gifConfirmation = val;
}
void AyuGramSettings::set_voiceConfirmation(bool val) {
voiceConfirmation = val;
void set_voiceConfirmation(bool val) {
settings->voiceConfirmation = val;
}
bool isUseScheduledMessages() {
const auto settings = &getInstance();
return isGhostModeActive() && settings->useScheduledMessages;
}

View file

@ -37,6 +37,7 @@ public:
bool disableAds;
bool disableStories;
bool disableCustomBackgrounds;
bool showOnlyAddedEmojisAndStickers;
bool collapseSimilarChannels;
bool hideSimilarChannels;
@ -94,88 +95,89 @@ public:
bool stickerConfirmation;
bool gifConfirmation;
bool voiceConfirmation;
void set_sendReadMessages(bool val);
void set_sendReadStories(bool val);
void set_sendOnlinePackets(bool val);
void set_sendUploadProgress(bool val);
void set_sendOfflinePacketAfterOnline(bool val);
void set_ghostModeEnabled(bool val);
void set_markReadAfterAction(bool val);
void set_useScheduledMessages(bool val);
void set_sendWithoutSound(bool val);
void set_saveDeletedMessages(bool val);
void set_saveMessagesHistory(bool val);
void set_saveForBots(bool val);
void set_hideFromBlocked(bool val);
void set_disableAds(bool val);
void set_disableStories(bool val);
void set_disableCustomBackgrounds(bool val);
void set_collapseSimilarChannels(bool val);
void set_hideSimilarChannels(bool val);
void set_wideMultiplier(double val);
void set_spoofWebviewAsAndroid(bool val);
void set_increaseWebviewHeight(bool val);
void set_increaseWebviewWidth(bool val);
void set_disableNotificationsDelay(bool val);
void set_localPremium(bool val);
void set_appIcon(QString val);
void set_simpleQuotesAndReplies(bool val);
void set_replaceBottomInfoWithIcons(bool val);
void set_deletedMark(QString val);
void set_editedMark(QString val);
void set_recentStickersCount(int val);
void set_showReactionsPanelInContextMenu(int val);
void set_showViewsPanelInContextMenu(int val);
void set_showHideMessageInContextMenu(int val);
void set_showUserMessagesInContextMenu(int val);
void set_showMessageDetailsInContextMenu(int val);
void set_showAttachButtonInMessageField(bool val);
void set_showCommandsButtonInMessageField(bool val);
void set_showEmojiButtonInMessageField(bool val);
void set_showMicrophoneButtonInMessageField(bool val);
void set_showAutoDeleteButtonInMessageField(bool val);
void set_showAttachPopup(bool val);
void set_showEmojiPopup(bool val);
void set_showLReadToggleInDrawer(bool val);
void set_showSReadToggleInDrawer(bool val);
void set_showGhostToggleInDrawer(bool val);
void set_showStreamerToggleInDrawer(bool val);
void set_showGhostToggleInTray(bool val);
void set_showStreamerToggleInTray(bool val);
void set_monoFont(QString val);
void set_hideNotificationCounters(bool val);
void set_hideNotificationBadge(bool val);
void set_hideAllChatsFolder(bool val);
void set_channelBottomButton(int val);
void set_showPeerId(int val);
void set_showMessageSeconds(bool val);
void set_showMessageShot(bool val);
void set_stickerConfirmation(bool val);
void set_gifConfirmation(bool val);
void set_voiceConfirmation(bool val);
};
void set_sendReadMessages(bool val);
void set_sendReadStories(bool val);
void set_sendOnlinePackets(bool val);
void set_sendUploadProgress(bool val);
void set_sendOfflinePacketAfterOnline(bool val);
void set_ghostModeEnabled(bool val);
void set_markReadAfterAction(bool val);
void set_useScheduledMessages(bool val);
void set_sendWithoutSound(bool val);
void set_saveDeletedMessages(bool val);
void set_saveMessagesHistory(bool val);
void set_saveForBots(bool val);
void set_hideFromBlocked(bool val);
void set_disableAds(bool val);
void set_disableStories(bool val);
void set_disableCustomBackgrounds(bool val);
void set_showOnlyAddedEmojisAndStickers(bool val);
void set_collapseSimilarChannels(bool val);
void set_hideSimilarChannels(bool val);
void set_wideMultiplier(double val);
void set_spoofWebviewAsAndroid(bool val);
void set_increaseWebviewHeight(bool val);
void set_increaseWebviewWidth(bool val);
void set_disableNotificationsDelay(bool val);
void set_localPremium(bool val);
void set_appIcon(QString val);
void set_simpleQuotesAndReplies(bool val);
void set_replaceBottomInfoWithIcons(bool val);
void set_deletedMark(QString val);
void set_editedMark(QString val);
void set_recentStickersCount(int val);
void set_showReactionsPanelInContextMenu(int val);
void set_showViewsPanelInContextMenu(int val);
void set_showHideMessageInContextMenu(int val);
void set_showUserMessagesInContextMenu(int val);
void set_showMessageDetailsInContextMenu(int val);
void set_showAttachButtonInMessageField(bool val);
void set_showCommandsButtonInMessageField(bool val);
void set_showEmojiButtonInMessageField(bool val);
void set_showMicrophoneButtonInMessageField(bool val);
void set_showAutoDeleteButtonInMessageField(bool val);
void set_showAttachPopup(bool val);
void set_showEmojiPopup(bool val);
void set_showLReadToggleInDrawer(bool val);
void set_showSReadToggleInDrawer(bool val);
void set_showGhostToggleInDrawer(bool val);
void set_showStreamerToggleInDrawer(bool val);
void set_showGhostToggleInTray(bool val);
void set_showStreamerToggleInTray(bool val);
void set_monoFont(QString val);
void set_hideNotificationCounters(bool val);
void set_hideNotificationBadge(bool val);
void set_hideAllChatsFolder(bool val);
void set_channelBottomButton(int val);
void set_showPeerId(int val);
void set_showMessageSeconds(bool val);
void set_showMessageShot(bool val);
void set_stickerConfirmation(bool val);
void set_gifConfirmation(bool val);
void set_voiceConfirmation(bool val);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
AyuGramSettings,
sendReadMessages,
@ -193,6 +195,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
disableAds,
disableStories,
disableCustomBackgrounds,
showOnlyAddedEmojisAndStickers,
collapseSimilarChannels,
hideSimilarChannels,
wideMultiplier,

View file

@ -42,8 +42,8 @@ void runOnce() {
lateInit();
}
const auto settings = &AyuSettings::getInstance();
if (!settings->sendOfflinePacketAfterOnline) {
const auto& settings = AyuSettings::getInstance();
if (!settings.sendOfflinePacketAfterOnline) {
return;
}

View file

@ -16,6 +16,15 @@
using namespace sqlite_orm;
auto storage = make_storage(
"./tdata/ayudata.db",
make_index("idx_deleted_message_userId_dialogId_topicId_messageId",
column<DeletedMessage>(&DeletedMessage::userId),
column<DeletedMessage>(&DeletedMessage::dialogId),
column<DeletedMessage>(&DeletedMessage::topicId),
column<DeletedMessage>(&DeletedMessage::messageId)),
make_index("idx_edited_message_userId_dialogId_messageId",
column<EditedMessage>(&EditedMessage::userId),
column<EditedMessage>(&EditedMessage::dialogId),
column<EditedMessage>(&EditedMessage::messageId)),
make_table<DeletedMessage>(
"DeletedMessage",
make_column("fakeId", &DeletedMessage::fakeId, primary_key().autoincrement()),
@ -212,13 +221,15 @@ std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageI
bool hasRevisions(ID userId, ID dialogId, ID messageId) {
try {
return storage.count<EditedMessage>(
return !storage.select(
columns(column<EditedMessage>(&EditedMessage::messageId)),
where(
column<EditedMessage>(&EditedMessage::userId) == userId and
column<EditedMessage>(&EditedMessage::dialogId) == dialogId and
column<EditedMessage>(&EditedMessage::messageId) == messageId
)
) > 0;
),
limit(1)
).empty();
} catch (std::exception &ex) {
LOG(("Failed to check if message has revisions: %1").arg(ex.what()));
return false;
@ -251,13 +262,15 @@ std::vector<DeletedMessage> getDeletedMessages(ID userId, ID dialogId, ID topicI
bool hasDeletedMessages(ID userId, ID dialogId, ID topicId) {
try {
return storage.count<DeletedMessage>(
return !storage.select(
columns(column<DeletedMessage>(&DeletedMessage::dialogId)),
where(
column<DeletedMessage>(&DeletedMessage::userId) == userId and
column<DeletedMessage>(&DeletedMessage::dialogId) == dialogId and
(column<DeletedMessage>(&DeletedMessage::topicId) == topicId or topicId == 0)
)
) > 0;
),
limit(1)
).empty();
} catch (std::exception &ex) {
LOG(("Failed to check if dialog has deleted message: %1").arg(ex.what()));
return false;

View file

@ -14,7 +14,7 @@ static QImage LAST_LOADED_NO_MARGIN;
namespace AyuAssets {
void loadAppIco() {
auto settings = &AyuSettings::getInstance();
const auto& settings = AyuSettings::getInstance();
QString appDataPath = QDir::fromNativeSeparators(qgetenv("APPDATA"));
QString tempIconPath = appDataPath + "/AyuGram.ico";
@ -26,20 +26,20 @@ void loadAppIco() {
f.remove();
}
f.close();
QFile::copy(qsl(":/gui/art/ayu/%1/app_icon.ico").arg(settings->appIcon), tempIconPath);
QFile::copy(qsl(":/gui/art/ayu/%1/app_icon.ico").arg(settings.appIcon), tempIconPath);
}
void loadIcons() {
auto settings = &AyuSettings::getInstance();
if (LAST_LOADED_NAME != settings->appIcon) {
LAST_LOADED_NAME = settings->appIcon;
const auto& settings = AyuSettings::getInstance();
if (LAST_LOADED_NAME != settings.appIcon) {
LAST_LOADED_NAME = settings.appIcon;
#ifdef Q_OS_MAC
LAST_LOADED = QImage(qsl(":/gui/art/ayu/%1/app_macos.png").arg(settings->appIcon));
LAST_LOADED = QImage(qsl(":/gui/art/ayu/%1/app_macos.png").arg(settings.appIcon));
#else
LAST_LOADED = QImage(qsl(":/gui/art/ayu/%1/app.png").arg(settings->appIcon));
LAST_LOADED = QImage(qsl(":/gui/art/ayu/%1/app.png").arg(settings.appIcon));
#endif
LAST_LOADED_NO_MARGIN = QImage(qsl(":/gui/art/ayu/%1/app_preview.png").arg(settings->appIcon));
LAST_LOADED_NO_MARGIN = QImage(qsl(":/gui/art/ayu/%1/app_preview.png").arg(settings.appIcon));
}
}

View file

@ -87,8 +87,7 @@ void EditDeletedMarkBox::resizeEvent(QResizeEvent *e) {
}
void EditDeletedMarkBox::save() {
const auto settings = &AyuSettings::getInstance();
settings->set_deletedMark(_text->getLastText());
AyuSettings::set_deletedMark(_text->getLastText());
AyuSettings::save();
closeBox();

View file

@ -86,8 +86,7 @@ void EditEditedMarkBox::resizeEvent(QResizeEvent *e) {
}
void EditEditedMarkBox::save() {
const auto settings = &AyuSettings::getInstance();
settings->set_editedMark(_text->getLastText());
AyuSettings::set_editedMark(_text->getLastText());
AyuSettings::save();
closeBox();

View file

@ -38,8 +38,8 @@ void MessageShotBox::prepare() {
void MessageShotBox::setupContent() {
_selectedPalette = std::make_shared<style::palette>();
const auto settings = &AyuSettings::getInstance();
const auto savedShowColorfulReplies = !settings->simpleQuotesAndReplies;
const auto& settings = AyuSettings::getInstance();
const auto savedShowColorfulReplies = !settings.simpleQuotesAndReplies;
using namespace Settings;
@ -164,8 +164,7 @@ void MessageShotBox::setupContent() {
) | start_with_next(
[=](bool enabled)
{
const auto settings = &AyuSettings::getInstance();
settings->set_simpleQuotesAndReplies(!enabled);
AyuSettings::set_simpleQuotesAndReplies(!enabled);
_config.st = std::make_shared<Ui::ChatStyle>(_config.st.get());
updatePreview();
@ -209,8 +208,7 @@ void MessageShotBox::setupContent() {
AyuFeatures::MessageShot::resetDefaultSelected();
AyuFeatures::MessageShot::resetShotConfig();
const auto settings = &AyuSettings::getInstance();
settings->set_simpleQuotesAndReplies(!savedShowColorfulReplies);
AyuSettings::set_simpleQuotesAndReplies(!savedShowColorfulReplies);
},
content->lifetime());

View file

@ -54,10 +54,10 @@ void AddDeletedMessagesActions(PeerData *peerData,
const auto topic = peerData->isForum() ? thread->asTopic() : nullptr;
const auto topicId = topic ? topic->rootId().bare : 0;
const auto has = AyuMessages::hasDeletedMessages(peerData, topicId);
if (!has) {
return;
}
// const auto has = AyuMessages::hasDeletedMessages(peerData, topicId);
// if (!has) {
// return;
// }
addCallback(
tr::ayu_ViewDeletedMenuText(tr::now),
@ -156,7 +156,7 @@ void AddOpenChannelAction(PeerData *peerData,
return;
}
const auto chat = peerData->asMegagroup()->linkedChat();
const auto chat = peerData->asMegagroup()->discussionLink();
if (!chat) {
return;
}
@ -171,7 +171,20 @@ void AddOpenChannelAction(PeerData *peerData,
}
void AddHistoryAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
if (AyuMessages::hasRevisions(item)) {
if (item->hideEditedBadge()) {
return;
}
const auto edited = item->Get<HistoryMessageEdited>();
if (!edited) {
return;
}
const auto has = AyuMessages::hasRevisions(item);
if (!has) {
return;
}
menu->addAction(
tr::ayu_EditsHistoryMenuText(tr::now),
[=]
@ -181,12 +194,11 @@ void AddHistoryAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
std::make_shared<MessageHistory::SectionMemento>(item->history()->peer, item, 0));
},
&st::ayuEditsHistoryIcon);
}
}
void AddHideMessageAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
const auto settings = &AyuSettings::getInstance();
if (!needToShowItem(settings->showHideMessageInContextMenu)) {
const auto& settings = AyuSettings::getInstance();
if (!needToShowItem(settings.showHideMessageInContextMenu)) {
return;
}
@ -208,8 +220,8 @@ void AddHideMessageAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
}
void AddUserMessagesAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
const auto settings = &AyuSettings::getInstance();
if (!needToShowItem(settings->showUserMessagesInContextMenu)) {
const auto& settings = AyuSettings::getInstance();
if (!needToShowItem(settings.showUserMessagesInContextMenu)) {
return;
}
@ -233,8 +245,8 @@ void AddUserMessagesAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
}
void AddMessageDetailsAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
const auto settings = &AyuSettings::getInstance();
if (!needToShowItem(settings->showMessageDetailsInContextMenu)) {
const auto& settings = AyuSettings::getInstance();
if (!needToShowItem(settings.showMessageDetailsInContextMenu)) {
return;
}
@ -452,8 +464,8 @@ void AddReadUntilAction(not_null<Ui::PopupMenu*> menu, HistoryItem *item) {
return;
}
const auto settings = &AyuSettings::getInstance();
if (settings->sendReadMessages) {
const auto& settings = AyuSettings::getInstance();
if (settings.sendReadMessages) {
return;
}

View file

@ -121,7 +121,7 @@ void IconPicker::paintEvent(QPaintEvent *e) {
}
void IconPicker::mousePressEvent(QMouseEvent *e) {
auto settings = &AyuSettings::getInstance();
const auto& settings = AyuSettings::getInstance();
auto changed = false;
auto x = e->pos().x();
@ -139,8 +139,8 @@ void IconPicker::mousePressEvent(QMouseEvent *e) {
break;
}
if (settings->appIcon != iconName) {
wasSelected = settings->appIcon;
if (settings.appIcon != iconName) {
wasSelected = settings.appIcon;
animation.start(
[=]
{
@ -152,7 +152,7 @@ void IconPicker::mousePressEvent(QMouseEvent *e) {
anim::easeOutCubic
);
settings->set_appIcon(iconName);
AyuSettings::set_appIcon(iconName);
changed = true;
break;
}

File diff suppressed because it is too large Load diff

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