Compare commits

..

231 Commits

Author SHA1 Message Date
ZavaruKitsu e4e6fb14c7 feat: User Messages
Co-authored-by: RadRussianRus <radrussianrus@gmail.com>
2023-12-27 17:32:10 +03:00
ZavaruKitsu dc94f02345 fix: don't save empty messages 2023-12-27 17:32:10 +03:00
ZavaruKitsu 2482da3c3f fix: go back on escape 2023-12-27 17:32:10 +03:00
ZavaruKitsu 2c6439eeb6 fix: reactions and mentions not being read locally 2023-12-27 17:32:10 +03:00
ZavaruKitsu 0eab40b22f fix: simpleQuotesAndReplies 2023-12-27 17:32:10 +03:00
ZavaruKitsu 1a279c4409 feat: show service message time 2023-12-27 17:32:10 +03:00
ZavaruKitsu f1adebb23e feat: show DC
https://github.com/TDesktop-x64/tdesktop/pull/64/commits/9ea6c7dc52e6b69283bf065a851cbc0ef0bc5f9c

Co-authored-by: arm64v8a <48624112+arm64v8a@users.noreply.github.com>
2023-12-27 17:32:10 +03:00
ZavaruKitsu 032de55103 feat: better UI 2023-12-27 17:32:10 +03:00
ZavaruKitsu e079a69d7e fix: update submodules 2023-12-24 21:11:59 +03:00
ZavaruKitsu 421aa31d59 Merge 4.13.1 2023-12-24 17:32:28 +03:00
ZavaruKitsu 9cc0ca5d81 fix: use custom icon for edits history action
fix: remove buggy Hide
2023-12-24 17:18:28 +03:00
ZavaruKitsu 6fab4e1dc3 fix: noforwards 2023-12-24 16:26:28 +03:00
Ilya Fedin d63ebbe62c Handle webview crash 2023-12-23 19:12:17 +00:00
John Preston cb4fce251e Version 4.13.1: Fix build with GCC. 2023-12-23 14:18:12 -04:00
John Preston 4aa8a41119 Version 4.13.1.
- Fix crash in chat history right click.
- Fix user emoji status display in main menu, profile and settings.
2023-12-23 14:15:29 -04:00
John Preston 13cba72945 Fix emoji status display for users.
Regression was introduced in 805a5d73b6.
2023-12-23 14:14:03 -04:00
John Preston cf63b0138e Fix crash in context menu.
Regression was introduced in 4e3c1460f6.

Fixes #27254.
2023-12-23 14:12:50 -04:00
John Preston 3cbe0aae4a Version 4.13.
- Support setting channel wallpaper.
- Support setting channel emoji status.
- Allow gifting premium to several recipients at once.
2023-12-22 20:55:24 -04:00
John Preston 5ab8e68366 Fix possible crash in colorizeImage. 2023-12-22 20:52:11 -04:00
John Preston 1d345299f5 Allow smartglocal to customize tokenize url. 2023-12-22 20:52:11 -04:00
23rd fc50d5c30f Improved code style in HistoryView::WebPage. 2023-12-23 03:16:58 +03:00
23rd 4e3c1460f6 Fixed display of menu items from sponsored message with selected text. 2023-12-23 01:50:12 +03:00
23rd 5bc954396c Fixed display of long title or long description in sponsored messages. 2023-12-23 01:50:12 +03:00
John Preston b24290b019 Fix text-colored emoji in long-press preview. 2023-12-22 13:46:17 -04:00
John Preston 23cce64d00 Channel message reposts to stories like reposts. 2023-12-22 13:16:14 -04:00
John Preston 73690d14f7 Allow clipboard access for attach menu bots. 2023-12-22 12:42:23 -04:00
John Preston 2a5698cf34 Admin log events about channel emoji status. 2023-12-22 07:35:02 -04:00
John Preston fd64718502 Allow setting channel wallpaper. 2023-12-22 07:35:02 -04:00
John Preston 941126ad69 Allow setting channel emoji status. 2023-12-22 07:35:02 -04:00
John Preston 0e8058adb1 Update tg_owt to support custom reflectors. 2023-12-22 07:35:02 -04:00
23rd 01906c1161 Fixed display of archiving toasts on wrong window. 2023-12-22 07:35:02 -04:00
John Preston 9201cf24f1 Respect correct min-level for colors. 2023-12-22 07:35:02 -04:00
John Preston d5a1c354d0 Support by-emoji background resolve in preview. 2023-12-22 07:35:02 -04:00
John Preston 41ae1f56ed Update API scheme to layer 169. Multigifts. 2023-12-22 07:35:02 -04:00
23rd ed7212f864 Added mini icon of boosts to description in gifts box from settings. 2023-12-19 04:06:54 +03:00
23rd 8bcb784f12 Moved out child centering within widget to single function. 2023-12-19 01:52:33 +03:00
23rd 431549c81a Improved processing of successful payment in gift box from settings. 2023-12-19 01:43:58 +03:00
23rd 12110e17a2 Slightly improved style of userpics from top in gift box from settings. 2023-12-18 05:50:14 +03:00
23rd db8338156a Slightly improved style of terms label in gift box from settings. 2023-12-18 05:50:14 +03:00
John Preston de8b09d7fc Use correct phrases for outgoing giftcodes. 2023-12-17 21:20:21 +00:00
ZavaruKitsu f06747f2a1 fix: don't mark contents read
fix: crash if config is not a valid json
2023-12-17 22:52:00 +03:00
ZavaruKitsu d940dc193e fix: custom language improvements 2023-12-17 22:42:22 +03:00
23rd fddbce5dce Added premium summary to gift box from settings. 2023-12-17 13:05:21 +03:00
23rd 081817f62a Moved out making of premium summary to separated function. 2023-12-17 13:01:36 +03:00
23rd 8efbd7a1cb Added ability to hide subscription button in preview premium boxes. 2023-12-17 13:01:36 +03:00
23rd bce310d5c8 Added complex description to top of gift box from settings. 2023-12-17 13:01:36 +03:00
23rd ed9ecbd235 Added circle badge to userpics in gift box from settings. 2023-12-17 13:01:17 +03:00
23rd 1e756dd380 Added userpics to top of gift box from settings. 2023-12-17 13:00:40 +03:00
23rd b9b6226692 Added initial ability to gift premium to contacts from settings. 2023-12-17 09:50:50 +03:00
23rd 82d73e2396 Moved out making of "new" badges to single place. 2023-12-17 09:50:50 +03:00
John Preston cd5a6025f6 Support pre-defined channel wallpapers resolving. 2023-12-16 23:52:55 +00:00
John Preston b6c679449e Support custom channel backgrounds display. 2023-12-16 23:23:24 +00:00
John Preston ac744b957a Show emoji pattern also on link preview bubbles. 2023-12-16 22:52:30 +00:00
John Preston 805a5d73b6 Show emoji statuses in channels. 2023-12-16 22:43:35 +00:00
John Preston 6aaf841a73 Ignore Cmd+Up/Down if field isn't empty. 2023-12-16 22:00:41 +00:00
John Preston 60e72768e1 Update API scheme. Shared posts in stories. 2023-12-16 21:26:40 +00:00
John Preston 94e8f2a791 Update API scheme. Anonymous gift links. 2023-12-16 20:25:02 +00:00
John Preston 1fb4a2f4ba Update API scheme. Show interactions in channel stories. 2023-12-16 20:25:02 +00:00
John Preston 28d68acfe6 Use forward declaration for ripple animation. 2023-12-16 20:25:02 +00:00
John Preston d87a0a2d25 Show reposts / forwards in story viewers. 2023-12-16 20:25:02 +00:00
23rd 8e92778b62 Fixed API support of public forwards in statistics info. 2023-12-16 20:25:02 +00:00
John Preston f7e2c7977b Update API scheme. TODO public forwards stats. 2023-12-16 20:25:02 +00:00
John Preston 4337f0b509 Fix "Keep Disabled" in OpenGL crash check. 2023-12-16 20:25:02 +00:00
John Preston 2b960a1f21 Update API scheme. 2023-12-16 20:25:02 +00:00
John Preston 4b9648d8d9 Update API scheme. Giveaway winners. 2023-12-16 20:25:02 +00:00
John Preston 62f9f3c94b Update API scheme. HistoryView::Giveaway->MediaInBubble. 2023-12-16 20:25:02 +00:00
John Preston e854f0b60c Show additional prize in giveaway message. 2023-12-16 20:25:02 +00:00
John Preston 19f38f3c6f Optimize empty->non-empty userpics repainting. 2023-12-16 20:25:02 +00:00
John Preston d56724f290 Add additional prize info to giveaway details. 2023-12-16 20:25:02 +00:00
John Preston 8abc35ca86 Make giveaway end message clickable. 2023-12-16 20:25:02 +00:00
John Preston e135f8954f Update API scheme to layer 168. Giveaways. 2023-12-16 20:25:02 +00:00
John Preston f5b59c9456 Remove old test code giveaway creation. 2023-12-16 20:25:02 +00:00
23rd 6471d43c71 Added mini preview for some types of webpages. 2023-12-16 20:25:02 +00:00
23rd 563b8d1468 Added support of inline markup reply to JSON export. 2023-12-16 20:25:01 +00:00
23rd f41a3fe01f Fixed display of non-stack bar chart view with empty values in chart. 2023-12-16 20:25:01 +00:00
23rd 29c9266ef5 Fixed display of bottom solid line in chart view for some scroll states. 2023-12-16 20:25:01 +00:00
23rd 1a856e359f Fixed display of bottom captions in chart view with long date strings. 2023-12-16 20:25:01 +00:00
23rd 59099a8d46 Added ability to open profile info through menu from public forwards. 2023-12-16 20:25:01 +00:00
23rd 98c6a3ff79 Added support of stories in list of public forwards in statistics info. 2023-12-16 20:25:01 +00:00
23rd cccc2ce0f1 Improved processing of access to boosts info. 2023-12-16 20:25:01 +00:00
23rd 88b20f6700 Fixed indents in some files. 2023-12-16 20:25:01 +00:00
Ilya Fedin 3adbfb1fb5 Update GCC to 13 in Docker 2023-12-16 09:32:50 +04:00
Ilya Fedin 0ee0ffa7f1 Update breakpad in Docker 2023-12-16 09:32:50 +04:00
Ilya Fedin 4c82620677 Disable building libstdc++ tests 2023-12-16 09:32:50 +04:00
Ilya Fedin 73294bfabf Make Linux action to use the pre-set entrypoint 2023-12-16 09:32:50 +04:00
Ilya Fedin 6c42095108 Move the GHCR authentication to the first set up step 2023-12-16 09:32:50 +04:00
John Preston fbe93b0afc Fix webpage layouts with thumbnails. 2023-12-15 14:15:35 +00:00
ZavaruKitsu a98e92639c fix: crash in server read 2023-12-12 15:26:33 +03:00
Ilya Fedin e173c727f7 Fix remaining known xdg-output fractional scaling issues on Wayland
And enable it by default
2023-12-07 10:24:19 +04:00
ZavaruKitsu 084967354b feat: rework sendReadMessages
fix: send read packet manually
fix: send read packet after sending media
2023-12-01 20:58:00 +03:00
ZavaruKitsu bde3caded7 fix: mark as β 2023-12-01 19:49:42 +03:00
ZavaruKitsu 29dd896c83 feat: disable similar channels 2023-12-01 19:21:03 +03:00
ZavaruKitsu d6457ebcc7 fix: add β note to anti-recall and disable by default 2023-12-01 17:35:30 +03:00
ZavaruKitsu c9fa0166e6 fix: prettify settings a bit 2023-12-01 17:23:29 +03:00
ZavaruKitsu 66b1fe7beb fix: make it build 2023-12-01 16:34:32 +03:00
Ilya Fedin 85f56217a8 Fix docker & snap build 2023-12-01 17:20:46 +04:00
ZavaruKitsu 0f8187fa36 Merge tag 'v4.12.2' into dev
# Conflicts:
#	.github/workflows/win.yml
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/SourceFiles/settings/settings_advanced.cpp
#	Telegram/SourceFiles/settings/settings_main.cpp
#	Telegram/lib_ui
#	snap/snapcraft.yaml
2023-12-01 15:38:13 +03:00
Ilya Fedin 06564efe0e Build GLib manually in Docker and Snap 2023-12-01 15:39:42 +04:00
Ilya Fedin 664ebe4ed0 Use xdg-output for Wayland fractional scaling
That's way more stable
2023-12-01 15:39:14 +04:00
John Preston cb3dece478 Version 4.12.2.
- Fix choosing custom reactions in channels.

Also fix a crash on start with old hardware by rebuilding using
the 17.7.7 VS Build Tools, because 17.8.* has a regression
with emitting a SSE 4.2 instruction, see:

https://developercommunity.visualstudio.com/t/Illegal-Instruction-SSE-42-POPCNT-exc/10520578
2023-12-01 13:07:42 +04:00
John Preston c86ca6a61a Check custom reactions in channels better. 2023-12-01 13:05:06 +04:00
John Preston 8e2240d9d9 Fix custom reactions in channels. 2023-12-01 13:00:52 +04:00
John Preston 28acaf06ad Version 4.12.1.
- Fix assertion violation in imported messages rendering.
2023-12-01 09:44:38 +04:00
John Preston fe12c3639b Revert "Removed unused code of hidden sender userpics for sponsored messages."
This reverts commit 3f19dc0486.
2023-12-01 09:18:22 +04:00
John Preston 0e2131e6eb Version 4.12: Fix build with GCC. 2023-11-30 20:59:58 +04:00
John Preston 98be0a69df Version 4.12.
- Similar channels.
- Wallpapers for both sides.
- Voice-to-Text for everyone.
- Story statistics for channels.
- Custom Reactions for channels.
- Automatic code highlighting in messages.
2023-11-30 20:23:19 +04:00
Ilya Fedin d6aecdfe4b Update cmake_helpers and patches in Docker 2023-11-30 17:57:34 +04:00
John Preston fa63a220fa Fix build with Xcode. 2023-11-30 17:56:57 +04:00
John Preston 2611899448 Set custom reactions hard limit to max level. 2023-11-30 17:56:57 +04:00
John Preston 514ced1d8e Respect wallpaper_overriden flag. 2023-11-30 17:56:57 +04:00
23rd 1a69975131 Replaced Qt format of dates in statistics with internal format. 2023-11-29 09:09:36 +03:00
23rd 27b284ef5b Added initial support of trial voice transcribes. 2023-11-29 07:32:20 +03:00
23rd a546b3a9b6 Replaced display of premium layer with short box for sponsored messages. 2023-11-29 01:45:41 +03:00
John Preston 28d9330969 Add premium promo section about wallpapers. 2023-11-28 21:55:27 +04:00
John Preston 8c3fa14a75 Allow setting background for both sides. 2023-11-28 21:55:27 +04:00
John Preston e58940a876 Look for highlight language case-insensitive. 2023-11-28 21:55:27 +04:00
John Preston ae1da5baf4 Implement premium lock of similar channels. 2023-11-28 21:55:27 +04:00
23rd 2542ec5d93 Added list of public forwards for story statistics. 2023-11-28 21:55:27 +04:00
23rd dfe55b26a2 Added statistical values for stories to overview in statistics info. 2023-11-28 21:55:27 +04:00
23rd 6de95fc4ed Fixed display of recent posts with some types documents in statistics. 2023-11-28 21:55:27 +04:00
23rd 1e57563349 Improved style of icons in recent posts from list from statistics info. 2023-11-28 21:55:27 +04:00
23rd 9f0b4bc799 Added ability to paste login code from clipboard to new code input. 2023-11-28 21:55:27 +04:00
23rd ac8117a6d8 Improved style of input field for login code. 2023-11-28 21:55:27 +04:00
23rd 9ef0e5cf83 Moved animation callback for shake effect to single place. 2023-11-28 21:55:27 +04:00
23rd f433d6fbc9 Fixed button label in sponsored messages with external links. 2023-11-28 21:55:27 +04:00
23rd e24b86d460 Fixed restriction label when topic is closed.
Fixed #26344.
2023-11-28 21:55:27 +04:00
John Preston bfebb1339a Show "more similar channels" premium promo. 2023-11-28 21:55:27 +04:00
John Preston 49b59d73be Fix comments loading. Fixes #25889. 2023-11-28 21:55:27 +04:00
John Preston d41961945d Fix first time webpage preview customization. 2023-11-28 21:55:27 +04:00
John Preston aa29d1c619 Allow select single album part under spoiler. 2023-11-28 21:55:27 +04:00
John Preston d6d76c8477 Show repost-from-name in story header. 2023-11-28 21:55:27 +04:00
John Preston 6057bb2b37 Handle repost info clicks in expanded mode. 2023-11-28 21:55:27 +04:00
John Preston 5aaf119b36 Handle repost preview clicks. 2023-11-28 21:55:26 +04:00
John Preston 8f9123bb96 Display story repost nicely. 2023-11-28 21:55:26 +04:00
23rd 77b2076e0f Added build date info to version label as tooltip. 2023-11-28 21:55:26 +04:00
23rd 7681f14a3c Added icons to recent posts in list from statistics info. 2023-11-28 21:55:26 +04:00
23rd 4ad51ffb42 Removed some include directives. 2023-11-28 21:55:26 +04:00
23rd 0f3faf59ca Added support of bot apps to sponsored messages.
Added api support of custom button text in sponsored messages.
2023-11-28 21:55:26 +04:00
23rd d28ba4fad9 Moved out PeerByLinkInfo from SessionNavigation to separate file. 2023-11-28 21:55:26 +04:00
23rd 3f19dc0486 Removed unused code of hidden sender userpics for sponsored messages. 2023-11-28 21:55:26 +04:00
23rd fc86bb7a5f Removed redundant code for old sponsored messages. 2023-11-28 21:55:26 +04:00
23rd 0da515abc5 Added fast right action to sponsored messages. 2023-11-28 21:55:26 +04:00
23rd 4c5c2aadc4 Replaced style of sponsored messages with fake webpage. 2023-11-28 21:55:26 +04:00
23rd 17f89ba1f9 Added ability to get sponsored details from constructor of HistoryItem. 2023-11-28 21:55:26 +04:00
23rd a8de145e01 Moved out click handler for sponsored messages to separate module. 2023-11-28 21:55:26 +04:00
23rd c1d20d16fd Added small preview to story statistics. 2023-11-28 21:55:25 +04:00
23rd dc04a1afdb Removed display of selected index with incorrect value on bar chart. 2023-11-28 21:55:25 +04:00
23rd 856f39c123 Fixed search of indices on tiny charts in statistics. 2023-11-28 21:55:25 +04:00
23rd 909f3bf011 Added "new-windows-size-as-first" option. 2023-11-28 21:55:25 +04:00
23rd 19ab740da2 Added channel photo to recent posts in list from statistics info. 2023-11-28 21:55:25 +04:00
John Preston 11ea5e61cf Show repost header in stories. 2023-11-28 21:55:25 +04:00
John Preston 78897dd143 Show repost info on story view. 2023-11-28 21:55:25 +04:00
John Preston 23a0413113 Update API scheme on layer 167. 2023-11-28 21:55:25 +04:00
John Preston b5b5c28ac5 Request possible peer colors from API. 2023-11-28 21:55:25 +04:00
John Preston 5652abfd49 Update syntax-highlighting grammars. 2023-11-28 21:55:25 +04:00
John Preston 324f2f68ba Handle for_both chat wallpaper change. 2023-11-28 21:55:25 +04:00
John Preston f8825e8135 Update API scheme on layer 167. 2023-11-28 21:55:25 +04:00
John Preston 4dbe5c0a0f Load similar channels correctly. 2023-11-28 21:55:25 +04:00
John Preston 2df6729f2d Improve similar channels pseudo-widget. 2023-11-28 21:55:25 +04:00
John Preston 30d72f1d1d Try fixing media viewer on some Linux versions. 2023-11-28 21:55:24 +04:00
John Preston db0a31b87e Fix crash in scale preview reparenting. 2023-11-28 21:55:24 +04:00
John Preston 4b5e2582d9 Update API scheme on layer 167. 2023-11-28 21:55:24 +04:00
23rd 6a87fef851 Added reactions count to recent posts in list from statistics info. 2023-11-28 21:55:24 +04:00
23rd 1fbcec1d24 Added display of stories to list of recent posts in statistics info. 2023-11-28 21:55:24 +04:00
23rd 25d0123b9f Added more universal RecentPostId for saved state of statistics info. 2023-11-28 21:55:24 +04:00
23rd 69b9d404c0 Added api support of reactions count for recent posts in statistics. 2023-11-28 21:55:24 +04:00
23rd 0865776d9a Simplified FileOriginStory. 2023-11-28 21:55:24 +04:00
23rd 32008161a0 Fixed duration after changing of winners count in create giveaway box. 2023-11-28 21:55:24 +04:00
John Preston 36a8c49213 Show similar channels under join message. 2023-11-28 21:55:24 +04:00
John Preston 91fba41e2c Update API scheme on layer 167. 2023-11-28 21:55:24 +04:00
23rd 7d2d0bdfa2 Added initial entry point to statistics info for stories. 2023-11-28 21:55:24 +04:00
23rd 2bb8850e69 Added charts of story statistics to statistics info. 2023-11-28 21:55:24 +04:00
23rd 1056a5cc8e Added API support to resolve story statistics. 2023-11-28 21:55:24 +04:00
23rd 34d0dac351 Added ability to create statistics info layer with story id. 2023-11-28 21:55:24 +04:00
23rd f88eee8047 Added reactions count to overview in statistics info. 2023-11-28 21:55:24 +04:00
23rd 173a5046e8 Added new charts to channel and message statistics. 2023-11-28 21:55:24 +04:00
23rd 44f6280d0a Added ability to use BarChartView as non-stack as well. 2023-11-28 21:55:24 +04:00
23rd b7346c203a Renamed StackChartView to BarChartView. 2023-11-28 21:55:24 +04:00
23rd c3254a53bc Moved out calculation of height limits for linear chart to single place. 2023-11-28 21:55:24 +04:00
23rd 5ea066e6a7 Moved class of line ratio for double linear chart from private space. 2023-11-28 21:55:24 +04:00
23rd bc6556ebc4 Moved out class for cached selected points on chart from private space. 2023-11-28 21:55:23 +04:00
John Preston 4c6d33fd54 Allow sending to General in "View as Messages". 2023-11-28 21:55:23 +04:00
John Preston 96b651c29b Update "View as (Messages,Topics)" menu icons. 2023-11-28 21:55:23 +04:00
John Preston 0ffda016da Support cloud view_as_messages forum setting. 2023-11-28 21:55:23 +04:00
John Preston 43a8733fc7 Implement rich reactions selector. 2023-11-28 21:55:23 +04:00
John Preston 1e26c33b3d Implement choose-reactions input field. 2023-11-28 21:55:23 +04:00
John Preston 4ad70965e9 Don't check quote entities now that we have quote_offset. 2023-11-28 21:55:23 +04:00
John Preston 3a67e4f1f4 Support highlighting correct quoted part. 2023-11-28 21:55:23 +04:00
John Preston dcc326e17f Update API scheme to layer 167.
Support quote offset passing to API.
Support simple phrases in giveaway results message.
2023-11-28 21:55:23 +04:00
John Preston f442d69cb6 Fix possible crash on MTProto instance shutdown. 2023-11-28 21:23:27 +04:00
Ilya Fedin 17fa50bdff Update patches commit in Dockerfile 2023-11-28 13:18:43 +04:00
Ilya Fedin a04145d981 Update xkbcommon in Docker 2023-11-27 20:09:37 +04:00
Ilya Fedin e8c9cb7d2a Update Qt to 6.6.1 on Linux 2023-11-27 20:09:20 +04:00
Ilya Fedin 467a6c25a8 Fix upload artifact condition in Windows action 2023-11-27 20:09:04 +04:00
Ilya Fedin 1852386ace Add Windows Ninja CI 2023-11-27 18:02:59 +04:00
Ilya Fedin a93340c2e4 Try to restore session manager connection on Linux 2023-11-27 12:02:19 +04:00
Ilya Fedin 4a0ee22670 Shorten setting QSessionManager restart hint 2023-11-27 12:02:19 +04:00
John Preston 87a042b029 Fix build on Linux 2023-11-25 12:59:47 +04:00
Ilya Fedin 960761ef37 Replace jemalloc with scudo
This should provide a wider support for ARM hardware
2023-11-24 20:04:28 +04:00
John Preston b60e50df10 Try using hide media viewer workaround on Linux. 2023-11-22 12:18:45 +04:00
Ilya Fedin 4696f731da Force enable fractional-scale-v1 experimental option 2023-11-21 21:20:50 +04:00
Ilya Fedin 0f9d83f34b Use setFixedSize instead of set{Minimum,Maximum}Size combo 2023-11-21 21:20:50 +04:00
Ilya Fedin cfc254bd90 Switch Qt to GitHub 2023-11-21 21:20:50 +04:00
23rd bdee6e0155 Removed ability to add to contacts inaccessible users. 2023-11-20 21:03:36 +03:00
23rd ac6765ebdb Replaced default toast text for shared messages with complex phrases. 2023-11-20 16:25:28 +03:00
23rd df3ae2c5f8 Added ability to open boosts info without statistics info access. 2023-11-20 02:53:46 +03:00
23rd 1af4af6ff3 Removed display of unwrapped media in sponsored messages. 2023-11-20 02:53:46 +03:00
Ilya Fedin a92e9f7162 Try to update qtwayland to 6.6.0 again 2023-11-19 07:46:32 +04:00
John Preston 27d9fa6acb Fix CI build on Linux. 2023-11-17 13:07:18 +04:00
John Preston 7d4362267a Fix compare helpers on macOS. 2023-11-17 13:06:04 +04:00
John Preston 1ba52402b5 Fix build with new MSVC, workaround compiler bug. 2023-11-17 12:01:25 +04:00
John Preston 5d0a36e456 Fix edit photo button area. 2023-11-17 12:01:25 +04:00
John Preston af6e15ed59 Fix title alignment in AskBoostBox. 2023-11-16 14:31:15 +04:00
John Preston 25216a140e Fix build on Windows. 2023-11-16 14:31:15 +04:00
John Preston 65fc7d2b10 Update lib_ui submodule. 2023-11-16 14:29:45 +04:00
John Preston 99da95880e Fix lang keys access on startup. 2023-11-15 18:20:59 +03:00
23rd 12272a450f Slightly optimized include directives in some headers. 2023-11-15 04:20:20 +03:00
23rd 819020e515 Moved out common default style entries from settings. 2023-11-15 04:20:20 +03:00
23rd acb1a7ccf2 Spread some style entries from basic style. 2023-11-15 04:19:51 +03:00
23rd 596460172f Optimized include directives of core_settings header. 2023-11-15 03:30:04 +03:00
23rd baa99be6a5 Removed some unwanted include directives of lang_keys in header files. 2023-11-15 03:30:04 +03:00
23rd f748de9dc4 Removed redundant include directives of settings_common headers. 2023-11-15 03:30:04 +03:00
23rd 85e2d54a05 Split out settings_common module into td_ui and non-td_ui variants. 2023-11-15 03:30:04 +03:00
23rd f629bf76ff Removed AddButton and CreateButton without icon from Settings. 2023-11-15 03:30:04 +03:00
23rd f6cb9072d2 Moved AddSkip and AddDivier from Settings namespace to separate module. 2023-11-15 03:30:04 +03:00
23rd 497aa6dbc8 Added ability to see admins who promoted or restricted participants. 2023-11-14 21:48:34 +03:00
John Preston 830e9a5953 Version 4.11.8. (macOS only)
- Fix phrases on macOS by doing a clean rebuild.
2023-11-14 21:28:24 +04:00
John Preston 5cabfb56e0 Fix "small" undef in Windows includes. 2023-11-14 09:27:48 +04:00
Ilya Fedin 8a19fab19c Update macOS to 13 on macOS packaged action 2023-11-13 16:10:37 +04:00
Ilya Fedin c592b66f5b Ignore brew upgrade failure in macOS packaged action 2023-11-13 13:54:36 +04:00
Ilya Fedin 8ce9a92898 Update brew packages in macOS packaged action
This ensures the same versions of packages between GitHub runners at a point in time
2023-11-13 13:34:14 +04:00
649 changed files with 33451 additions and 5630 deletions
+2 -3
View File
@@ -28,6 +28,7 @@ jobs:
run: |
sudo apt update
curl -sSL https://install.python-poetry.org | python3 -
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
- name: Free up some disk space.
uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8
@@ -40,6 +41,4 @@ jobs:
- name: Push the Docker image.
if: ${{ github.ref_name == github.event.repository.default_branch }}
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
docker push $IMAGE_TAG
run: docker push $IMAGE_TAG
+9 -15
View File
@@ -43,15 +43,6 @@ jobs:
linux:
name: Rocky Linux 8
runs-on: ubuntu-latest
container:
image: ghcr.io/${{ github.repository }}/centos_env
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
defaults:
run:
shell: scl enable gcc-toolset-12 -- bash --noprofile --norc -eo pipefail {0}
strategy:
matrix:
@@ -75,12 +66,13 @@ jobs:
- name: First set up.
run: |
gcc --version
ln -s /usr/src/Libraries
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/Telegram
cd $REPO_NAME
DEFINE=""
if [ -n "${{ matrix.defines }}" ]; then
@@ -91,7 +83,11 @@ jobs:
echo "ARTIFACT_NAME=Telegram" >> $GITHUB_ENV
fi
./configure.sh \
docker run --rm \
-v $PWD:/usr/src/tdesktop \
-e DEBUG=1 \
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" \
@@ -101,8 +97,6 @@ jobs:
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
$DEFINE
cmake --build ../out --config Debug --parallel
- name: Check.
run: |
filePath="$REPO_NAME/out/Debug/Telegram"
+3 -1
View File
@@ -40,7 +40,7 @@ jobs:
macos:
name: MacOS
runs-on: macos-latest
runs-on: macos-13
strategy:
matrix:
@@ -67,6 +67,8 @@ jobs:
- name: First set up.
run: |
brew update
brew upgrade || true
brew install autoconf automake boost cmake ffmpeg openal-soft openssl opus ninja pkg-config python qt yasm xz
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
+37 -41
View File
@@ -1,7 +1,6 @@
name: Windows.
on:
workflow_dispatch:
push:
paths-ignore:
- 'docs/**'
@@ -47,10 +46,11 @@ jobs:
strategy:
matrix:
arch: [Win32]
arch: [Win32, x64]
generator: ["", "Ninja Multi-Config"]
env:
UPLOAD_ARTIFACT: "true"
UPLOAD_ARTIFACT: "false"
ONLY_CACHE: "false"
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
@@ -110,19 +110,42 @@ jobs:
cd %TBUILD%
%REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent
- name: Read defines.
- 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"
echo "ARTIFACT_NAME=Telegram_${{ matrix.arch }}_${{ matrix.defines }}" >> $GITHUB_ENV
else
echo "ARTIFACT_NAME=Telegram_${{ matrix.arch }}" >> $GITHUB_ENV
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."
@@ -143,50 +166,23 @@ jobs:
cd %TBUILD%\%REPO_NAME%\Telegram
call configure.bat ^
${{ matrix.arch }} ^
%TDESKTOP_BUILD_GENERATOR% ^
%TDESKTOP_BUILD_ARCH% ^
%TDESKTOP_BUILD_API% ^
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^
-D DESKTOP_APP_NO_PDB=ON ^
%TDESKTOP_BUILD_DEFINE% ^
-DCMAKE_SYSTEM_VERSION=%SDK%
%TDESKTOP_BUILD_DEFINE%
cd ..\out
msbuild -m Telegram.sln /p:Configuration=Debug,Platform=${{ matrix.arch }},DebugSymbols=false,DebugType=none
cmake --build ..\out --config Debug --parallel
- name: Move artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || ${{ github.ref == 'refs/heads/nightly' }}
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
run: |
mkdir artifact
move %TBUILD%\%REPO_NAME%\out\Debug\AyuGram.exe artifact/
move %TBUILD%\%REPO_NAME%\out\Debug\Telegram.exe artifact/
- uses: actions/upload-artifact@master
name: Upload artifact.
if: (env.UPLOAD_ARTIFACT == 'true') || ${{ github.ref == 'refs/heads/nightly' }}
if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly')
with:
name: ${{ env.ARTIFACT_NAME }}
path: artifact\
release:
name: Release
needs: [windows]
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- uses: actions/checkout@v2
- name: Merge Releases
uses: actions/download-artifact@v2
with:
name: Telegram_Win32
path: artifact
- name: Upload release
uses: Hs1r1us/Release-AIO@v1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# The name of the tag
tag_name: prelease-${{ github.run_number }}
prerelease: true
release_name: Ayugram CI
asset_files: './artifact'
-3
View File
@@ -76,9 +76,6 @@
[submodule "Telegram/lib_webview"]
path = Telegram/lib_webview
url = https://github.com/desktop-app/lib_webview.git
[submodule "Telegram/ThirdParty/jemalloc"]
path = Telegram/ThirdParty/jemalloc
url = https://github.com/jemalloc/jemalloc
[submodule "Telegram/ThirdParty/dispatch"]
path = Telegram/ThirdParty/dispatch
url = https://github.com/apple/swift-corelibs-libdispatch
+3 -2
View File
@@ -10,8 +10,9 @@ if (APPLE)
else()
cmake_minimum_required(VERSION 3.16)
endif()
cmake_policy(SET CMP0076 NEW)
cmake_policy(SET CMP0091 NEW)
if (POLICY CMP0149)
cmake_policy(SET CMP0149 NEW)
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+25 -4
View File
@@ -197,6 +197,8 @@ PRIVATE
api/api_messages_search.h
api/api_messages_search_merged.cpp
api/api_messages_search_merged.h
api/api_peer_colors.cpp
api/api_peer_colors.h
api/api_peer_photo.cpp
api/api_peer_photo.h
api/api_polls.cpp
@@ -447,16 +449,18 @@ PRIVATE
chat_helpers/gifs_list_widget.h
chat_helpers/message_field.cpp
chat_helpers/message_field.h
chat_helpers/share_message_phrase_factory.cpp
chat_helpers/share_message_phrase_factory.h
chat_helpers/spellchecker_common.cpp
chat_helpers/spellchecker_common.h
chat_helpers/stickers_dice_pack.cpp
chat_helpers/stickers_dice_pack.h
chat_helpers/stickers_emoji_image_loader.cpp
chat_helpers/stickers_emoji_image_loader.h
chat_helpers/stickers_emoji_pack.cpp
chat_helpers/stickers_emoji_pack.h
chat_helpers/stickers_gift_box_pack.cpp
chat_helpers/stickers_gift_box_pack.h
chat_helpers/stickers_dice_pack.cpp
chat_helpers/stickers_dice_pack.h
chat_helpers/stickers_list_footer.cpp
chat_helpers/stickers_list_footer.h
chat_helpers/stickers_list_widget.cpp
@@ -778,6 +782,8 @@ PRIVATE
history/view/media/history_view_premium_gift.h
history/view/media/history_view_service_box.cpp
history/view/media/history_view_service_box.h
history/view/media/history_view_similar_channels.cpp
history/view/media/history_view_similar_channels.h
history/view/media/history_view_slot_machine.cpp
history/view/media/history_view_slot_machine.h
history/view/media/history_view_sticker.cpp
@@ -853,6 +859,8 @@ PRIVATE
history/view/history_view_service_message.h
history/view/history_view_spoiler_click_handler.cpp
history/view/history_view_spoiler_click_handler.h
history/view/history_view_sponsored_click_handler.cpp
history/view/history_view_sponsored_click_handler.h
history/view/history_view_sticker_toast.cpp
history/view/history_view_sticker_toast.h
history/view/history_view_transcribe_button.cpp
@@ -958,6 +966,8 @@ PRIVATE
info/profile/info_profile_widget.h
info/settings/info_settings_widget.cpp
info/settings/info_settings_widget.h
info/similar_channels/info_similar_channels_widget.cpp
info/similar_channels/info_similar_channels_widget.h
info/statistics/info_statistics_common.h
info/statistics/info_statistics_inner_widget.cpp
info/statistics/info_statistics_inner_widget.h
@@ -1095,6 +1105,8 @@ PRIVATE
media/stories/media_stories_recent_views.h
media/stories/media_stories_reply.cpp
media/stories/media_stories_reply.h
media/stories/media_stories_repost_view.cpp
media/stories/media_stories_repost_view.h
media/stories/media_stories_share.cpp
media/stories/media_stories_share.h
media/stories/media_stories_sibling.cpp
@@ -1345,8 +1357,8 @@ PRIVATE
settings/settings_calls.h
settings/settings_codes.cpp
settings/settings_codes.h
settings/settings_common.cpp
settings/settings_common.h
settings/settings_common_session.cpp
settings/settings_common_session.h
settings/settings_experimental.cpp
settings/settings_experimental.h
settings/settings_folders.cpp
@@ -1506,6 +1518,7 @@ PRIVATE
window/window_section_common.h
window/window_session_controller.cpp
window/window_session_controller.h
window/window_session_controller_link_info.h
window/window_slide_animation.cpp
window/window_slide_animation.h
window/window_top_bar_wrap.h
@@ -1798,6 +1811,10 @@ endif()
set_target_properties(Telegram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
if (WIN32)
target_link_libraries(Telegram
PRIVATE
delayimp
)
target_link_options(Telegram
PRIVATE
/DELAYLOAD:secur32.dll
@@ -1854,6 +1871,10 @@ if (NOT DESKTOP_APP_DISABLE_AUTOUPDATE AND NOT build_macstore AND NOT build_wins
)
target_include_directories(Updater PRIVATE ${lib_base_loc})
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_link_libraries(Updater
PRIVATE
delayimp
)
target_link_options(Updater
PRIVATE
/DELAYLOAD:user32.dll
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+156 -10
View File
@@ -591,6 +591,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_section_background" = "Chat background";
"lng_settings_bg_from_gallery" = "Choose from gallery";
"lng_settings_bg_from_file" = "Choose from file";
"lng_settings_bg_remove" = "Remove wallpaper";
"lng_settings_bg_theme_edit" = "Edit theme";
"lng_settings_bg_theme_create" = "Create new theme";
"lng_settings_bg_cloud_themes" = "Custom themes";
@@ -813,6 +814,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_manage_enabled_dictionary" = "Dictionary is enabled";
"lng_settings_manage_remove_dictionary" = "Remove Dictionary";
"lng_settings_gift_premium" = "Premium Gifting";
"lng_settings_gift_premium_users_confirm" = "Proceed";
"lng_settings_gift_premium_users_error#one" = "You can select maximum {count} user.";
"lng_settings_gift_premium_users_error#other" = "You can select maximum {count} users.";
"lng_backgrounds_header" = "Choose Wallpaper";
"lng_theme_sure_keep" = "Keep this theme?";
"lng_theme_reverting#one" = "Reverting to the old theme in {count} second.";
@@ -833,12 +839,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_background_blur" = "Blurred";
"lng_background_sure_delete" = "Are you sure you want to delete this background?";
"lng_background_other_info" = "{user} will be able to apply this wallpaper";
"lng_background_other_channel" = "All subscribers will see this wallpaper";
"lng_background_apply1" = "Apply the wallpaper in this chat.";
"lng_background_apply2" = "Enjoy the view.";
"lng_background_apply_button" = "Apply For This Chat";
"lng_background_dimming" = "Background dimming";
"lng_background_sure_reset_default" = "Are you sure you want to reset the wallpaper?";
"lng_background_reset_default" = "Reset";
"lng_background_apply_me" = "Apply for me";
"lng_background_apply_both" = "Apply for me and {user}";
"lng_background_apply_channel" = "Apply For Channel";
"lng_download_path_ask" = "Ask download path for each file";
"lng_download_path" = "Download path";
@@ -1175,6 +1185,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_bot_privacy" = "Bot Privacy Policy";
"lng_profile_common_groups#one" = "{count} group in common";
"lng_profile_common_groups#other" = "{count} groups in common";
"lng_profile_similar_channels#one" = "{count} similar channel";
"lng_profile_similar_channels#other" = "{count} similar channels";
"lng_profile_participants_section" = "Members";
"lng_profile_subscribers_section" = "Subscribers";
"lng_profile_add_contact" = "Add Contact";
@@ -1347,6 +1359,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_peer_reactions_none_about" = "Members of the group can't add any reactions to messages.";
"lng_manage_peer_reactions_some_title" = "Only allow these reactions";
"lng_manage_peer_reactions_available" = "Available reactions";
"lng_manage_peer_reactions_own" = "You can also {link} emoji packs and use them as reactions.";
"lng_manage_peer_reactions_own_link" = "create your own";
"lng_manage_peer_reactions_level#one" = "Your channel needs to reach level **{count}** to use **{same_count}** custom reaction.";
"lng_manage_peer_reactions_level#other" = "Your channel needs to reach level **{count}** to use **{same_count}** custom reactions.";
"lng_manage_peer_reactions_boost" = "Boost your channel {link}.";
"lng_manage_peer_reactions_boost_link" = "here";
"lng_manage_peer_reactions_limit" = "Channels can't have more custom reactions.";
"lng_manage_peer_antispam" = "Aggressive Anti-Spam";
"lng_manage_peer_antispam_about" = "Telegram will filter more spam but may occasionally affect ordinary messages. You can report False Positives in Recent Actions.";
@@ -1641,11 +1660,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_suggested_video_button" = "View Video";
"lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu.";
"lng_action_webapp_bot_allowed" = "You allowed this bot to message you in his web-app.";
"lng_action_set_wallpaper_me" = "You set a new wallpaper for this chat";
"lng_action_set_wallpaper" = "{user} set a new wallpaper for this chat";
"lng_action_set_wallpaper_me" = "You set a new wallpaper for this chat.";
"lng_action_set_wallpaper" = "{user} set a new wallpaper for this chat.";
"lng_action_set_wallpaper_both_me" = "You set a new wallpaper for {user} and you.";
"lng_action_set_wallpaper_button" = "View Wallpaper";
"lng_action_set_same_wallpaper_me" = "You set the same wallpaper for this chat";
"lng_action_set_same_wallpaper" = "{user} set the same wallpaper for this chat";
"lng_action_set_wallpaper_remove" = "Remove";
"lng_action_set_same_wallpaper_me" = "You set the same wallpaper for this chat.";
"lng_action_set_same_wallpaper" = "{user} set the same wallpaper for this chat.";
"lng_action_topic_created_inside" = "Topic created";
"lng_action_topic_closed_inside" = "Topic closed";
"lng_action_topic_reopened_inside" = "Topic reopened";
@@ -1667,6 +1688,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available.";
"lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available.";
"lng_action_giveaway_started" = "{from} just started a giveaway of Telegram Premium subscriptions to its followers.";
"lng_action_giveaway_results#one" = "{count} winner of the giveaway was randomly selected by Telegram and received private messages with giftcodes.";
"lng_action_giveaway_results#other" = "{count} winners of the giveaway were randomly selected by Telegram and received private messages with giftcodes.";
"lng_action_giveaway_results_some" = "Some winners of the giveaway were randomly selected by Telegram and received private messages with giftcodes.";
"lng_action_giveaway_results_none" = "No winners of the giveaway could be selected.";
"lng_similar_channels_title" = "Similar channels";
"lng_similar_channels_view_all" = "View all";
"lng_similar_channels_more" = "More Channels";
"lng_similar_channels_premium_all#one" = "Subscribe to {link} to unlock up to **{count}** similar channel.";
"lng_similar_channels_premium_all#other" = "Subscribe to {link} to unlock up to **{count}** similar channels.";
"lng_similar_channels_premium_all_link" = "Telegram Premium";
"lng_similar_channels_show_more" = "Show more channels";
"lng_premium_gift_duration_months#one" = "for {count} month";
"lng_premium_gift_duration_months#other" = "for {count} months";
@@ -1808,9 +1841,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_forwarded_hidden" = "The account was hidden by the user.";
"lng_forwarded_imported" = "This message was imported from another app. It may not be real.";
"lng_signed_author" = "Author: {user}";
"lng_sponsored" = "sponsored";
"lng_recommended" = "recommended";
"lng_sponsored_message_title" = "Sponsored";
"lng_recommended_message_title" = "Recommended";
"lng_edited" = "edited";
"lng_commented" = "commented";
"lng_edited_date" = "Edited: {date}";
"lng_sent_date" = "Sent: {date}";
"lng_views_tooltip#one" = "Views: {count}";
@@ -1921,6 +1955,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_summary_subtitle_gift#other" = "{user} has gifted you a {count}-months subscription for Telegram Premium.";
"lng_premium_summary_subtitle_gift_me#one" = "You gifted {user} a {count}-month subscription for Telegram Premium.";
"lng_premium_summary_subtitle_gift_me#other" = "You gifted {user} a {count}-months subscription for Telegram Premium.";
"lng_premium_summary_subtitle_wallpapers" = "Wallpapers for Both Sides";
"lng_premium_summary_about_wallpapers" = "Set custom wallpapers for you and your chat partner.";
"lng_premium_summary_subtitle_stories" = "Upgraded Stories";
"lng_premium_summary_about_stories" = "Priority order, stealth mode, permanent views history and more.";
"lng_premium_summary_subtitle_double_limits" = "Doubled Limits";
@@ -2028,6 +2064,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_gift_per" = "{cost} / month";
"lng_premium_gift_terms" = "You can review the list of features and terms of use for Telegram Premium {link}.";
"lng_premium_gift_terms_link" = "here";
"lng_premium_gifts_about_user1" = "Give **{user}** access to exclusive features.";
"lng_premium_gifts_about_user2" = "Give **{user}** and **{second_user}** access to exclusive features.";
"lng_premium_gifts_about_user3" = "Give **{user}**, **{second_user}** and **{name}** access to exclusive features.";
"lng_premium_gifts_about_user_more#one" = "Give **{user}**, **{second_user}**, **{name}** and **{count}** more friend access to exclusive features.";
"lng_premium_gifts_about_user_more#other" = "Give **{user}**, **{second_user}**, **{name}** and **{count}** more friends access to exclusive features.";
"lng_premium_gifts_about_reward#one" = "You will receive {emoji}**{count}** boost.";
"lng_premium_gifts_about_reward#other" = "You will receive {emoji}**{count}** boosts.";
"lng_premium_gifts_about_paid_title" = "Gifts Sent!";
"lng_premium_gifts_about_paid1" = "**{user}** has been notified about the gifts you purchased.";
"lng_premium_gifts_about_paid2" = "**{user}** and **{second_user}** have been notified about the gifts you purchased.";
"lng_premium_gifts_about_paid3" = "**{user}**, **{second_user}** and **{name}** have been notified about the gifts you purchased.";
"lng_premium_gifts_about_paid_more#one" = "**{user}**, **{second_user}**, **{name}** and **{count}** other have been notified about the gifts you purchased.";
"lng_premium_gifts_about_paid_more#other" = "**{user}**, **{second_user}**, **{name}** and **{count}** others have been notified about the gifts you purchased.";
"lng_premium_gifts_about_paid_below#one" = "They now have access to additional features.";
"lng_premium_gifts_about_paid_below#other" = "They now have access to additional features.";
"lng_premium_gifts_summary_subtitle" = "What's Included";
"lng_boost_channel_button" = "Boost Channel";
"lng_boost_again_button" = "Boost Again";
@@ -2083,6 +2135,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boost_channel_title_color" = "Enable colors";
"lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color.";
"lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color.";
"lng_boost_channel_title_wallpaper" = "Enable wallpapers";
"lng_boost_channel_needs_level_wallpaper#one" = "Your channel needs to reach **Level {count}** to change channel wallpaper.";
"lng_boost_channel_needs_level_wallpaper#other" = "Your channel needs to reach **Level {count}** to change channel wallpaper.";
"lng_boost_channel_title_status" = "Enable emoji status";
"lng_boost_channel_needs_level_status#one" = "Your channel needs to reach **Level {count}** to set emoji status.";
"lng_boost_channel_needs_level_status#other" = "Your channel needs to reach **Level {count}** to set emoji status.";
"lng_boost_channel_title_reactions" = "Custom reactions";
"lng_boost_channel_needs_level_reactions#one" = "Your channel needs to reach **Level {count}** to add **{same_count}** custom emoji as a reaction.";
"lng_boost_channel_needs_level_reactions#other" = "Your channel needs to reach **Level {count}** to add **{same_count}** custom emoji as reactions.";
"lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:";
"lng_boost_channel_ask_button" = "Copy Link";
"lng_boost_channel_or" = "or";
@@ -2138,6 +2203,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_giveaway_maximum_users_error#other" = "You can select maximum {count} users.";
"lng_giveaway_channels_confirm_title" = "Channel is Private";
"lng_giveaway_channels_confirm_about" = "Are you sure you want to add a private channel? Users won't be able to join it without an invite link.";
"lng_giveaway_additional_prizes" = "Additional prizes";
"lng_giveaway_additional_about" = "Turn this on if you want to give the winners your own prizes in addition to Premium subscriptions.";
"lng_giveaway_additional_prizes_ph" = "Enter your prize";
"lng_giveaway_prizes_just_premium#one" = "All prizes: **{count}** Telegram Premium subscription {duration}.";
"lng_giveaway_prizes_just_premium#other" = "All prizes: **{count}** Telegram Premium subscriptions {duration}.";
"lng_giveaway_prizes_additional#one" = "All prizes: **{count}** {prize} with Telegram Premium subscription {duration}.";
"lng_giveaway_prizes_additional#other" = "All prizes: **{count}** {prize} with Telegram Premium subscriptions {duration}.";
"lng_giveaway_show_winners" = "Show winners";
"lng_giveaway_show_winners_about" = "Choose whether to make the list of winners public when the giveaway ends.";
"lng_giveaway_created_title" = "Giveaway created";
"lng_giveaway_created_body" = "Check your channels' {link} to see how this giveaway boosted your channel.";
@@ -2157,6 +2231,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_prizes_title#one" = "Giveaway Prize";
"lng_prizes_title#other" = "Giveaway Prizes";
"lng_prizes_additional#one" = "**{count}** {prize}";
"lng_prizes_additional#other" = "**{count}** {prize}";
"lng_prizes_additional_with" = "with";
"lng_prizes_about#one" = "**{count}** Telegram Premium Subscription {duration}.";
"lng_prizes_about#other" = "**{count}** Telegram Premium Subscriptions {duration}.";
"lng_prizes_participants" = "Participants";
@@ -2175,6 +2252,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_prizes_end_text" = "This giveaway was sponsored by {admins}.";
"lng_prizes_admins#one" = "the admins of {channel}, who aquired **{count} Telegram Premium** subscription {duration} for its followers";
"lng_prizes_admins#other" = "the admins of {channel}, who aquired **{count} Telegram Premium** subscriptions {duration} for its followers.";
"lng_prizes_additional_added#one" = "{channel} also included **{count} {prize}** in the prize. Admins of the channel are responsible for delivering this prize.";
"lng_prizes_additional_added#other" = "{channel} also included **{count} {prize}** in the prizes. Admins of the channel are responsible for delivering these prizes.";
"lng_prizes_how_when_finish" = "On {date}, Telegram will automatically select {winners}.";
"lng_prizes_end_when_finish" = "On {date}, Telegram automatically selected {winners}.";
"lng_prizes_end_activated#one" = "**{count}** of the winners already used their gift link.";
@@ -2200,6 +2279,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_prizes_cancelled" = "The channel cancelled the prizes by reversing the payment for them.";
"lng_prizes_badge" = "x{amount}";
"lng_prizes_results_title" = "Winners Selected!";
"lng_prizes_results_about#one" = "**{count}** winner of the {link} was randomly selected by Telegram.";
"lng_prizes_results_about#other" = "**{count}** winners of the {link} were randomly selected by Telegram.";
"lng_prizes_results_link" = "Giveaway";
"lng_prizes_results_winners" = "Winners";
"lng_prizes_results_more#one" = "and {count} more!";
"lng_prizes_results_more#other" = "and {count} more!";
"lng_prizes_results_all" = "All winners received gift links in private messages.";
"lng_prizes_results_some" = "Some winners couldn't be selected.";
"lng_gift_link_title" = "Gift Link";
"lng_gift_link_about" = "This link allows you to activate\na **Telegram Premium** subscription.";
"lng_gift_link_label_from" = "From";
@@ -2746,6 +2835,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_share_wrong_user" = "This game was opened from a different user.";
"lng_share_game_link_copied" = "Game link copied to clipboard.";
"lng_share_done" = "Done!";
"lng_share_message_to_saved_messages" = "Message forwarded to **Saved Messages**.";
"lng_share_messages_to_saved_messages" = "Messages forwarded to **Saved Messages**.";
"lng_share_message_to_chat" = "Message forwarded to **{chat}**.";
"lng_share_messages_to_chat" = "Messages forwarded to **{chat}**.";
"lng_share_message_to_two_chats" = "Message forwarded to **{user}** and **{chat}**.";
"lng_share_messages_to_two_chats" = "Messages forwarded to **{user}** and **{chat}**.";
"lng_share_message_to_many_chats#one" = "Message forwarded to **{count} chat**.";
"lng_share_message_to_many_chats#other" = "Message forwarded to **{count} chats**.";
"lng_share_messages_to_many_chats#one" = "Messages forwarded to **{count} chat**.";
"lng_share_messages_to_many_chats#other" = "Messages forwarded to **{count} chats**.";
"lng_contact_phone" = "Phone Number";
"lng_enter_contact_data" = "New Contact";
@@ -2759,6 +2858,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_sign_messages" = "Sign messages";
"lng_edit_group" = "Edit group";
"lng_edit_channel_color" = "Change name color";
"lng_edit_channel_level_min" = "Level 1+";
"lng_edit_channel_wallpaper" = "Channel wallpaper";
"lng_edit_channel_wallpaper_about" = "Set a wallpaper that will be visible for everyone reading your channel.";
"lng_edit_channel_status" = "Channel emoji status";
"lng_edit_channel_status_about" = "Choose a status that will be shown next to the channel's name.";
"lng_edit_self_title" = "Edit your name";
"lng_confirm_contact_data" = "New Contact";
"lng_add_contact" = "Create";
@@ -3294,6 +3398,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_audio_player_reverse" = "Reverse order";
"lng_audio_player_shuffle" = "Shuffle";
"lng_audio_transcribe_long" = "This voice message is too long.";
"lng_audio_transcribe_trials_left#one" = "You have {count} free transcription left until {date}.";
"lng_audio_transcribe_trials_left#other" = "You have {count} free transcriptions left until {date}.";
"lng_audio_transcribe_trials_over" = "You have used all your free transcriptions this week. Wait until {date} to use it again or subscribe to {link} now.";
"lng_rights_edit_admin" = "Manage permissions";
"lng_rights_edit_admin_header" = "What can this admin do?";
@@ -3570,6 +3677,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"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}";
"lng_admin_log_removed_background_emoji" = "{from} removed channel background emoji {emoji}";
"lng_admin_log_change_profile_color" = "{from} changed channel profile color from {previous} to {color}";
"lng_admin_log_set_profile_background_emoji" = "{from} set channel profile background emoji to {emoji}";
"lng_admin_log_change_profile_background_emoji" = "{from} changed channel profile background emoji from {previous} to {emoji}";
"lng_admin_log_removed_profile_background_emoji" = "{from} removed channel profile background emoji {emoji}";
"lng_admin_log_change_wallpaper" = "{from} changed channel wallpaper";
"lng_admin_log_set_status" = "{from} set channel emoji status to {emoji}";
"lng_admin_log_change_status" = "{from} changed channel emoji status from {previous} to {emoji}";
"lng_admin_log_removed_status" = "{from} removed channel emoji status {emoji}";
"lng_admin_log_set_status_until" = "{from} set channel emoji status to {emoji} until {date}";
"lng_admin_log_change_status_until" = "{from} changed channel emoji status from {previous} to {emoji} until {date}";
"lng_admin_log_user_with_username" = "{name} ({mention})";
"lng_admin_log_messages_ttl_set" = "{from} enabled messages auto-delete after {duration}";
"lng_admin_log_messages_ttl_changed" = "{from} changed messages auto-delete period from {previous} to {duration}";
@@ -4096,6 +4213,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_view_button_request_join" = "Request to Join";
"lng_view_button_external_link" = "Open link";
"lng_view_button_boost" = "Boost";
"lng_view_button_giftcode" = "Open";
"lng_sponsored_hide_ads" = "Hide";
"lng_sponsored_title" = "What are sponsored messages?";
@@ -4141,10 +4259,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_forum_topics_no_discussion" = "Topics can't be enabled in discussion groups at the moment.";
"lng_forum_choose_title_and_icon" = "Choose title and icon for your topic";
"lng_forum_replies_only" = "You can reply to messages in topics.";
"lng_forum_message_in" = "Message in {topic}";
"lng_forum_reply_in" = "Reply in {topic}";
"lng_forum_no_topics" = "No topics currently created in this forum.";
"lng_forum_create_topic" = "Create topic";
"lng_forum_discard_sure" = "Are you sure you want to discard this topic?";
"lng_forum_view_as_messages" = "View as Messages";
"lng_forum_view_as_topics" = "View as Topics";
"lng_forum_no_messages" = "No messages";
"lng_forum_messages#one" = "{count} message";
"lng_forum_messages#other" = "{count} messages";
@@ -4158,6 +4279,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_request_peer_confirm_rights" = "This will also add {bot} to {chat} with the following rights: {rights}.";
"lng_request_peer_confirm_send" = "Send";
"lng_request_user_title" = "Choose User";
"lng_request_users_title" = "Choose Users";
"lng_request_user_premium_yes" = "The user should have a Premium subscription.";
"lng_request_user_premium_no" = "The user shouldn't have a Premium subscription.";
"lng_request_user_no" = "No such users";
@@ -4286,12 +4408,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stats_title" = "Statistics";
"lng_stats_message_title" = "Message Statistic";
"lng_stats_story_title" = "Story Statistic";
"lng_stats_zoom_out" = "Zoom Out";
"lng_stats_day_month_year" = "{days_count} {month} {year}";
"lng_stats_day_month" = "{days_count} {month}";
"lng_stats_weekday_day_month_year" = "{day}, {days_count} {month} {year}";
"lng_stats_weekday_day_month_time" = "{day}, {days_count} {month} {time}";
"lng_stats_overview_title" = "Overview";
"lng_stats_overview_member_count" = "Followers";
"lng_stats_overview_mean_view_count" = "Views Per Post";
"lng_stats_overview_mean_share_count" = "Shared Per Post";
"lng_stats_overview_mean_reactions_count" = "Reactions Per Post";
"lng_stats_overview_mean_story_view_count" = "Views Per Story";
"lng_stats_overview_mean_story_share_count" = "Shared Per Story";
"lng_stats_overview_mean_story_reactions_count" = "Reactions Per Story";
"lng_stats_overview_enabled_notifications" = "Enabled Notifications";
"lng_stats_overview_messages" = "Messages";
"lng_stats_overview_group_mean_view_count" = "Viewing Members";
@@ -4321,8 +4453,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_stats_recent_messages_title" = "Recent posts";
"lng_stats_recent_messages_views#one" = "{count} view";
"lng_stats_recent_messages_views#other" = "{count} views";
"lng_stats_recent_messages_shares#one" = "{count} share";
"lng_stats_recent_messages_shares#other" = "{count} shares";
"lng_stats_loading" = "Loading stats...";
"lng_stats_loading_subtext" = "Please wait a few moments while we generate your stats.";
@@ -4336,6 +4466,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_chart_title_language" = "Languages";
"lng_chart_title_message_interaction" = "Interactions";
"lng_chart_title_instant_view_interaction" = "IV Interactions";
"lng_chart_title_reactions_by_emotion" = "Reactions";
"lng_chart_title_story_interactions" = "Story Interactions";
"lng_chart_title_story_reactions_by_emotion" = "Story reactions";
"lng_chart_title_group_join" = "Group members";
"lng_chart_title_group_join_by_source" = "New members by source";
@@ -4463,7 +4596,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_SpyEssentialsHeader" = "Spy essentials";
"ayu_SaveDeletedMessages" = "Save deleted messages";
"ayu_SaveMessagesHistory" = "Save edits history";
"ayu_MessageSavingBtn" = "Message Saving Preferences";
"ayu_MessageSavingActionBarHeader" = "Message Saving Preferences";
"ayu_MessageSavingBtn" = "Preferences";
"ayu_MessageSavingSubTitle" = "Configure media & per dialog saving";
"ayu_MessageSavingMediaHeader" = "Media";
"ayu_MessageSavingSaveMedia" = "Save media";
"ayu_MessageSavingSaveMediaHint" = "Click for more";
@@ -4478,6 +4613,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_MessageSavingSaveFormatting" = "Save formatting";
"ayu_MessageSavingSaveReactions" = "Save reactions";
"ayu_MessageSavingSaveForBots" = "Save in bot dialogs";
"ayu_SpyAllToggle" = "Spy on people";
"ayu_SpySaveReadMarks" = "Save read date";
"ayu_SpySaveLastActivity" = "Save last activity";
"ayu_QoLTogglesHeader" = "Useful features";
"ayu_KeepAliveService" = "AyuGram Push Service";
"ayu_DisableAds" = "Disable ads";
@@ -4511,6 +4649,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_CaseInsensitiveExpression" = "Case insensitive expression";
"ayu_RegexFiltersAddError" = "Regex syntax error";
"ayu_RegexFilterQuickAdd" = "Add filter";
"ayu_RegexFilterBulletinText" = "Filter added to the **Shared filters**.";
"ayu_RegexFilterBulletinAction" = "Move to current chat";
"ayu_AyuSyncHeader" = "AyuSync";
"ayu_AyuSyncStatusTitle" = "Sync status";
"ayu_AyuSyncStatusOk" = "connected";
@@ -4570,6 +4710,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_ViewFiltersMenuText" = "View Filters";
"ayu_PeekOnlineSuccess" = "Peeked via";
"ayu_OneViewTTL" = "one view";
"ayu_UserMessagesMenuText" = "User Messages";
"ayu_ReadUntilMenuText" = "Read Message";
"ayu_DeleteKeepLocally" = "Keep locally";
"ayu_BoxActionReset" = "Reset";
@@ -4585,7 +4726,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_HideNextViewsDescriptionAyu" = "Hide my views forever, until Ghost Mode disabled.";
"ayu_EnableGhostModeStories" = "Enable Ghost Mode";
"ayu_GhostModeIsActive" = "Ghost Mode Is Active";
"ayu_SimpleQuotesAndReplies" = "Simple quotes & replies";
"ayu_SimpleQuotesAndReplies" = "Disable colorful replies";
"ayu_DisableSimilarChannels" = "Disable similar channels";
"ayu_CollapseSimilarChannels" = "Collapse similar channels";
"ayu_HideSimilarChannelsTab" = "Hide similar channels tab";
"ayu_MainFont" = "Application font";
"ayu_MonospaceFont" = "Monospace font";
"ayu_FontDefault" = "Default";
@@ -4595,6 +4739,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ayu_AyuForwardForwardingDescription" = "Please keep this window open while AyuGram is forwarding your messages.";
"ayu_AyuForwardLoadingMediaDescription" = "Please keep this window open while AyuGram is downloading media from your messages.";
"ayu_DeleteDateMenuText" = "Delete Date";
"ayu_ReadDateMenuText" = "Read Date";
"ayu_ContentsReadDateMenuText" = "Contents Read Date";
"ayu_ForwardableMenuText" = "Forwardable";
"ayu_ForwardableMenuTextNo" = "No";
"ayu_LikelyOfflineStatus" = "offline ?";
@@ -15,6 +15,7 @@
<file alias="art/slot_2_idle.tgs">../../art/slot_2_idle.tgs</file>
<file alias="art/slot_back.tgs">../../art/slot_back.tgs</file>
<file alias="art/slot_pull.tgs">../../art/slot_pull.tgs</file>
<file alias="art/winners.tgs">../../art/winners.tgs</file>
<file alias="day-blue.tdesktop-theme">../../day-blue.tdesktop-theme</file>
<file alias="night.tdesktop-theme">../../night.tdesktop-theme</file>
<file alias="night-green.tdesktop-theme">../../night-green.tdesktop-theme</file>
+1 -1
View File
@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.11.7.0" />
Version="4.13.1.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
+4 -4
View File
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,11,7,0
PRODUCTVERSION 4,11,7,0
FILEVERSION 4,13,1,0
PRODUCTVERSION 4,13,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "4.11.7.0"
VALUE "FileVersion", "4.13.1.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.11.7.0"
VALUE "ProductVersion", "4.13.1.0"
END
END
BLOCK "VarFileInfo"
+4 -4
View File
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,11,7,0
PRODUCTVERSION 4,11,7,0
FILEVERSION 4,13,1,0
PRODUCTVERSION 4,13,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater"
VALUE "FileVersion", "4.11.7.0"
VALUE "FileVersion", "4.13.1.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.11.7.0"
VALUE "ProductVersion", "4.13.1.0"
END
END
BLOCK "VarFileInfo"
+7 -6
View File
@@ -537,11 +537,12 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
GetLocalTime(&stLocalTime);
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szExeName, updaterVersionStr,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
wsprintf(
szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szExeName, updaterVersionStr,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
}
@@ -562,7 +563,7 @@ void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
DWORD len = GetModuleFileName(GetModuleHandle(0), szPath, maxFileLen);
if (!len) return;
WCHAR *pathEnd = szPath + len;
WCHAR *pathEnd = szPath + len;
if (!_wcsicmp(pathEnd - wcslen(_exeName), _exeName)) {
wsprintf(pathEnd - wcslen(_exeName), L"");
+6 -2
View File
@@ -415,12 +415,16 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
const auto peer = item->history()->peer;
const auto itemId = item->id;
const auto id = int32(button->buttonId);
const auto chosen = [=](not_null<PeerData*> result) {
const auto chosen = [=](std::vector<not_null<PeerData*>> result) {
peer->session().api().request(MTPmessages_SendBotRequestedPeer(
peer->input,
MTP_int(itemId),
MTP_int(id),
result->input
MTP_vector_from_range(
result
| ranges::views::transform([](
not_null<PeerData*> peer) {
return MTPInputPeer(peer->input); }))
)).done([=](const MTPUpdates &result) {
peer->session().api().applyUpdates(result);
}).send();
@@ -20,12 +20,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h"
#include "ui/controls/filter_link_header.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/buttons.h"
#include "ui/filter_icons.h"
#include "ui/vertical_list.h"
#include "window/window_session_controller.h"
#include "styles/style_filter_icons.h"
#include "styles/style_layers.h"
@@ -341,7 +341,7 @@ void ToggleChatsController::setupAboveWidget() {
_addedTopWidget = container->add(object_ptr<Ui::RpWidget>(container));
const auto realAbove = container->add(
object_ptr<Ui::VerticalLayout>(container));
AddDivider(realAbove);
Ui::AddDivider(realAbove);
const auto totalCount = [&] {
if (_chats.empty()) {
return _additional.size();
@@ -422,7 +422,7 @@ void ToggleChatsController::setupBelowWidget() {
auto widget = object_ptr<Ui::DividerLabel>(
(QWidget*)nullptr,
std::move(layout),
st::settingsDividerLabelPadding);
st::defaultBoxDividerLabelPadding);
raw->add(object_ptr<Ui::FlatLabel>(
raw,
(_action == ToggleAction::Removing
@@ -211,6 +211,29 @@ void ApplyBotsList(
Data::PeerUpdate::Flag::FullInfo);
}
[[nodiscard]] ChatParticipants::Channels ParseSimilar(
not_null<ChannelData*> channel,
const MTPmessages_Chats &chats) {
auto result = ChatParticipants::Channels();
std::vector<not_null<ChannelData*>>();
chats.match([&](const auto &data) {
const auto &list = data.vchats().v;
result.list.reserve(list.size());
for (const auto &chat : list) {
const auto peer = channel->owner().processChat(chat);
if (const auto channel = peer->asChannel()) {
result.list.push_back(channel);
}
}
if constexpr (MTPDmessages_chatsSlice::Is<decltype(data)>()) {
if (channel->session().premiumPossible()) {
result.more = data.vcount().v - data.vchats().v.size();
}
}
});
return result;
}
} // namespace
ChatParticipant::ChatParticipant(
@@ -685,4 +708,50 @@ void ChatParticipants::unblock(
_kickRequests.emplace(kick, requestId);
}
void ChatParticipants::loadSimilarChannels(not_null<ChannelData*> channel) {
if (!channel->isBroadcast()) {
return;
} else if (const auto i = _similar.find(channel); i != end(_similar)) {
if (i->second.requestId
|| !i->second.channels.more
|| !channel->session().premium()) {
return;
}
}
_similar[channel].requestId = _api.request(
MTPchannels_GetChannelRecommendations(channel->inputChannel)
).done([=](const MTPmessages_Chats &result) {
auto &similar = _similar[channel];
similar.requestId = 0;
auto parsed = ParseSimilar(channel, result);
if (similar.channels == parsed) {
return;
}
similar.channels = std::move(parsed);
if (const auto history = channel->owner().historyLoaded(channel)) {
if (const auto item = history->joinedMessageInstance()) {
history->owner().requestItemResize(item);
}
}
_similarLoaded.fire_copy(channel);
}).send();
}
auto ChatParticipants::similar(not_null<ChannelData*> channel)
-> const Channels & {
const auto i = channel->isBroadcast()
? _similar.find(channel)
: end(_similar);
if (i != end(_similar)) {
return i->second.channels;
}
static const auto empty = Channels();
return empty;
}
auto ChatParticipants::similarLoaded() const
-> rpl::producer<not_null<ChannelData*>> {
return _similarLoaded.events();
}
} // namespace Api
@@ -120,7 +120,26 @@ public:
not_null<ChannelData*> channel,
not_null<PeerData*> participant);
void loadSimilarChannels(not_null<ChannelData*> channel);
struct Channels {
std::vector<not_null<ChannelData*>> list;
int more = 0;
friend inline bool operator==(
const Channels &,
const Channels &) = default;
};
[[nodiscard]] const Channels &similar(not_null<ChannelData*> channel);
[[nodiscard]] auto similarLoaded() const
-> rpl::producer<not_null<ChannelData*>>;
private:
struct SimilarChannels {
Channels channels;
mtpRequestId requestId = 0;
};
MTP::Sender _api;
using PeerRequests = base::flat_map<PeerData*, mtpRequestId>;
@@ -143,6 +162,9 @@ private:
not_null<PeerData*>>;
base::flat_map<KickRequest, mtpRequestId> _kickRequests;
base::flat_map<not_null<ChannelData*>, SimilarChannels> _similar;
rpl::event_stream<not_null<ChannelData*>> _similarLoaded;
};
} // namespace Api
@@ -0,0 +1,141 @@
/*
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_colors.h"
#include "apiwrap.h"
#include "data/data_peer.h"
#include "ui/chat/chat_style.h"
namespace Api {
namespace {
constexpr auto kRequestEach = 3600 * crl::time(1000);
} // namespace
PeerColors::PeerColors(not_null<ApiWrap*> api)
: _api(&api->instance())
, _timer([=] { request(); }) {
request();
_timer.callEach(kRequestEach);
}
PeerColors::~PeerColors() = default;
void PeerColors::request() {
if (_requestId) {
return;
}
_requestId = _api.request(MTPhelp_GetPeerColors(
MTP_int(_hash)
)).done([=](const MTPhelp_PeerColors &result) {
_requestId = 0;
result.match([&](const MTPDhelp_peerColors &data) {
_hash = data.vhash().v;
apply(data);
}, [](const MTPDhelp_peerColorsNotModified &) {
});
}).fail([=] {
_requestId = 0;
}).send();
}
std::vector<uint8> PeerColors::suggested() const {
return _suggested.current();
}
rpl::producer<std::vector<uint8>> PeerColors::suggestedValue() const {
return _suggested.value();
}
auto PeerColors::indicesValue() const
-> rpl::producer<Ui::ColorIndicesCompressed> {
return rpl::single(_colorIndicesCurrent
? *_colorIndicesCurrent
: Ui::ColorIndicesCompressed()
) | rpl::then(_colorIndicesChanged.events() | rpl::map([=] {
return *_colorIndicesCurrent;
}));
}
int PeerColors::requiredLevelFor(PeerId channel, uint8 index) const {
if (Data::DecideColorIndex(channel) == index) {
return 0;
} else if (const auto i = _requiredLevels.find(index)
; i != end(_requiredLevels)) {
return i->second;
}
return 1;
}
void PeerColors::apply(const MTPDhelp_peerColors &data) {
auto suggested = std::vector<uint8>();
auto colors = std::make_shared<
std::array<Ui::ColorIndexData, Ui::kColorIndexCount>>();
using ParsedColor = std::array<uint32, Ui::kColorPatternsCount>;
const auto parseColors = [](const MTPhelp_PeerColorSet &set) {
return set.match([&](const MTPDhelp_peerColorSet &data) {
auto result = ParsedColor();
const auto &list = data.vcolors().v;
if (list.empty() || list.size() > Ui::kColorPatternsCount) {
LOG(("API Error: Bad count for PeerColorSet.colors: %1"
).arg(list.size()));
return ParsedColor();
}
auto fill = result.data();
for (const auto &color : list) {
*fill++ = (uint32(1) << 24) | uint32(color.v);
}
return result;
}, [](const MTPDhelp_peerColorProfileSet &) {
LOG(("API Error: peerColorProfileSet in colors result!"));
return ParsedColor();
});
};
const auto &list = data.vcolors().v;
_requiredLevels.clear();
suggested.reserve(list.size());
for (const auto &color : list) {
const auto &data = color.data();
const auto colorIndexBare = data.vcolor_id().v;
if (colorIndexBare < 0 || colorIndexBare >= Ui::kColorIndexCount) {
LOG(("API Error: Bad color index: %1").arg(colorIndexBare));
continue;
}
const auto colorIndex = uint8(colorIndexBare);
if (const auto min = data.vchannel_min_level()) {
_requiredLevels[colorIndex] = min->v;
}
if (!data.is_hidden()) {
suggested.push_back(colorIndex);
}
if (const auto light = data.vcolors()) {
auto &fields = (*colors)[colorIndex];
fields.light = parseColors(*light);
if (const auto dark = data.vdark_colors()) {
fields.dark = parseColors(*dark);
} else {
fields.dark = fields.light;
}
}
}
if (!_colorIndicesCurrent) {
_colorIndicesCurrent = std::make_unique<Ui::ColorIndicesCompressed>(
Ui::ColorIndicesCompressed{ std::move(colors) });
_colorIndicesChanged.fire({});
} else if (*_colorIndicesCurrent->colors != *colors) {
_colorIndicesCurrent->colors = std::move(colors);
_colorIndicesChanged.fire({});
}
_suggested = std::move(suggested);
}
} // namespace Api
@@ -0,0 +1,51 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/timer.h"
#include "mtproto/sender.h"
class ApiWrap;
namespace Ui {
struct ColorIndicesCompressed;
} // namespace Ui
namespace Api {
class PeerColors final {
public:
explicit PeerColors(not_null<ApiWrap*> api);
~PeerColors();
[[nodiscard]] std::vector<uint8> suggested() const;
[[nodiscard]] rpl::producer<std::vector<uint8>> suggestedValue() const;
[[nodiscard]] auto indicesValue() const
-> rpl::producer<Ui::ColorIndicesCompressed>;
[[nodiscard]] int requiredLevelFor(
PeerId channel,
uint8 index) const;
private:
void request();
void apply(const MTPDhelp_peerColors &data);
MTP::Sender _api;
int32 _hash = 0;
mtpRequestId _requestId = 0;
base::Timer _timer;
rpl::variable<std::vector<uint8>> _suggested;
base::flat_map<uint8, int> _requiredLevels;
rpl::event_stream<> _colorIndicesChanged;
std::unique_ptr<Ui::ColorIndicesCompressed> _colorIndicesCurrent;
};
} // namespace Api
@@ -515,6 +515,7 @@ auto PeerPhoto::emojiList(EmojiListType type) -> EmojiListData & {
case EmojiListType::Profile: return _profileEmojiList;
case EmojiListType::Group: return _groupEmojiList;
case EmojiListType::Background: return _backgroundEmojiList;
case EmojiListType::NoChannelStatus: return _noChannelStatusEmojiList;
}
Unexpected("Type in PeerPhoto::emojiList.");
}
@@ -551,6 +552,8 @@ void PeerPhoto::requestEmojiList(EmojiListType type) {
? send(MTPaccount_GetDefaultProfilePhotoEmojis())
: (type == EmojiListType::Group)
? send(MTPaccount_GetDefaultGroupPhotoEmojis())
: (type == EmojiListType::NoChannelStatus)
? send(MTPaccount_GetChannelRestrictedStatusEmojis())
: send(MTPaccount_GetDefaultBackgroundEmojis());
}
@@ -32,6 +32,7 @@ public:
Profile,
Group,
Background,
NoChannelStatus,
};
struct UserPhoto {
@@ -112,6 +113,7 @@ private:
EmojiListData _profileEmojiList;
EmojiListData _groupEmojiList;
EmojiListData _backgroundEmojiList;
EmojiListData _noChannelStatusEmojiList;
};
+3 -3
View File
@@ -21,7 +21,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
// AyuGram includes
#include "ayu/ayu_state.h"
#include "ayu/ayu_settings.h"
#include "ayu/utils/telegram_helpers.h"
namespace Api {
@@ -156,8 +157,7 @@ void Polls::sendVotes(
const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages && settings->markReadAfterPoll && item)
{
AyuState::setAllowSendReadPacket(true);
item->history()->session().data().histories().readInboxOnNewMessage(item);
readHistory(item);
}
}).fail([=] {
_pollVotesRequestIds.erase(itemId);
+6 -7
View File
@@ -26,7 +26,7 @@ namespace {
[[nodiscard]] GiftCode Parse(const MTPDpayments_checkedGiftCode &data) {
return {
.from = peerFromMTP(data.vfrom_id()),
.from = data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(),
.to = data.vto_id() ? peerFromUser(*data.vto_id()) : PeerId(),
.giveawayId = data.vgiveaway_msg_id().value_or_empty(),
.date = data.vdate().v,
@@ -342,15 +342,12 @@ PremiumGiftCodeOptions::PremiumGiftCodeOptions(not_null<PeerData*> peer)
rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
return [=](auto consumer) {
auto lifetime = rpl::lifetime();
const auto channel = _peer->asChannel();
if (!channel) {
return lifetime;
}
using TLOption = MTPPremiumGiftCodeOption;
_api.request(MTPpayments_GetPremiumGiftCodeOptions(
MTP_flags(
MTPpayments_GetPremiumGiftCodeOptions::Flag::f_boost_peer),
MTP_flags(_peer->isChannel()
? MTPpayments_GetPremiumGiftCodeOptions::Flag::f_boost_peer
: MTPpayments_GetPremiumGiftCodeOptions::Flag(0)),
_peer->input
)).done([=](const MTPVector<TLOption> &result) {
auto tlMapOptions = base::flat_map<Amount, QVector<TLOption>>();
@@ -420,6 +417,8 @@ const std::vector<int> &PremiumGiftCodeOptions::availablePresets() const {
}
[[nodiscard]] int PremiumGiftCodeOptions::monthsFromPreset(int monthsIndex) {
Expects(monthsIndex >= 0 && monthsIndex < _availablePresets.size());
return _optionsForOnePerson.months[monthsIndex];
}
+183 -93
View File
@@ -9,8 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "data/data_channel.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/data_stories.h"
#include "data/data_story.h"
#include "history/history.h"
#include "main/main_session.h"
#include "statistics/statistics_data_deserialize.h"
@@ -62,15 +63,25 @@ constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
tlUnmuted.vpart().v / tlUnmuted.vtotal().v * 100.,
0.,
100.);
using Recent = MTPMessageInteractionCounters;
using Recent = MTPPostInteractionCounters;
auto recentMessages = ranges::views::all(
data.vrecent_message_interactions().v
data.vrecent_posts_interactions().v
) | ranges::views::transform([&](const Recent &tl) {
return Data::StatisticsMessageInteractionInfo{
.messageId = tl.data().vmsg_id().v,
.viewsCount = tl.data().vviews().v,
.forwardsCount = tl.data().vforwards().v,
};
return tl.match([&](const MTPDpostInteractionCountersStory &data) {
return Data::StatisticsMessageInteractionInfo{
.storyId = data.vstory_id().v,
.viewsCount = data.vviews().v,
.forwardsCount = data.vforwards().v,
.reactionsCount = data.vreactions().v,
};
}, [&](const MTPDpostInteractionCountersMessage &data) {
return Data::StatisticsMessageInteractionInfo{
.messageId = data.vmsg_id().v,
.viewsCount = data.vviews().v,
.forwardsCount = data.vforwards().v,
.reactionsCount = data.vreactions().v,
};
});
}) | ranges::to_vector;
return {
@@ -80,6 +91,15 @@ constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
.memberCount = StatisticalValueFromTL(data.vfollowers()),
.meanViewCount = StatisticalValueFromTL(data.vviews_per_post()),
.meanShareCount = StatisticalValueFromTL(data.vshares_per_post()),
.meanReactionCount = StatisticalValueFromTL(
data.vreactions_per_post()),
.meanStoryViewCount = StatisticalValueFromTL(
data.vviews_per_story()),
.meanStoryShareCount = StatisticalValueFromTL(
data.vshares_per_story()),
.meanStoryReactionCount = StatisticalValueFromTL(
data.vreactions_per_story()),
.enabledNotificationsPercentage = unmuted,
@@ -110,6 +130,15 @@ constexpr auto kCheckRequestsTimer = 10 * crl::time(1000);
.instantViewInteractionGraph = StatisticalGraphFromTL(
data.viv_interactions_graph()),
.reactionsByEmotionGraph = StatisticalGraphFromTL(
data.vreactions_by_emotion_graph()),
.storyInteractionsGraph = StatisticalGraphFromTL(
data.vstory_interactions_graph()),
.storyReactionsByEmotionGraph = StatisticalGraphFromTL(
data.vstory_reactions_by_emotion_graph()),
.recentMessageInteractions = std::move(recentMessages),
};
}
@@ -324,7 +353,7 @@ Data::SupergroupStatistics Statistics::supergroupStats() const {
PublicForwards::PublicForwards(
not_null<ChannelData*> channel,
FullMsgId fullId)
Data::RecentPostId fullId)
: StatisticsRequestSender(channel)
, _fullId(fullId) {
}
@@ -335,99 +364,94 @@ void PublicForwards::request(
if (_requestId) {
return;
}
const auto offsetPeer = channel()->owner().peer(token.fullId.peer);
const auto tlOffsetPeer = offsetPeer
? offsetPeer->input
: MTP_inputPeerEmpty();
constexpr auto kLimit = tl::make_int(100);
_requestId = makeRequest(MTPstats_GetMessagePublicForwards(
channel()->inputChannel,
MTP_int(_fullId.msg),
MTP_int(token.rate),
tlOffsetPeer,
MTP_int(token.fullId.msg),
kLimit
)).done([=, channel = channel()](const MTPmessages_Messages &result) {
using Messages = QVector<FullMsgId>;
const auto channel = StatisticsRequestSender::channel();
const auto processResult = [=](const MTPstats_PublicForwards &tl) {
using Messages = QVector<Data::RecentPostId>;
_requestId = 0;
auto nextToken = Data::PublicForwardsSlice::OffsetToken();
const auto process = [&](const MTPVector<MTPMessage> &messages) {
auto result = Messages();
for (const auto &message : messages.v) {
const auto &data = tl.data();
auto &owner = channel->owner();
owner.processUsers(data.vusers());
owner.processChats(data.vchats());
const auto nextToken = data.vnext_offset()
? qs(*data.vnext_offset())
: Data::PublicForwardsSlice::OffsetToken();
const auto fullCount = data.vcount().v;
auto recentList = Messages(data.vforwards().v.size());
for (const auto &tlForward : data.vforwards().v) {
tlForward.match([&](const MTPDpublicForwardMessage &data) {
const auto &message = data.vmessage();
const auto msgId = IdFromMessage(message);
const auto peerId = PeerFromMessage(message);
const auto lastDate = DateFromMessage(message);
if (const auto peer = channel->owner().peerLoaded(peerId)) {
if (lastDate) {
channel->owner().addNewMessage(
message,
MessageFlags(),
NewMessageType::Existing);
nextToken.fullId = { peerId, msgId };
result.push_back(nextToken.fullId);
if (const auto peer = owner.peerLoaded(peerId)) {
if (!lastDate) {
return;
}
owner.addNewMessage(
message,
MessageFlags(),
NewMessageType::Existing);
recentList.push_back({ .messageId = { peerId, msgId } });
}
}
return result;
};
auto allLoaded = false;
auto fullCount = 0;
auto messages = result.match([&](const MTPDmessages_messages &data) {
channel->owner().processUsers(data.vusers());
channel->owner().processChats(data.vchats());
auto list = process(data.vmessages());
allLoaded = true;
fullCount = list.size();
return list;
}, [&](const MTPDmessages_messagesSlice &data) {
channel->owner().processUsers(data.vusers());
channel->owner().processChats(data.vchats());
auto list = process(data.vmessages());
if (const auto nextRate = data.vnext_rate()) {
const auto rateUpdated = (nextRate->v != token.rate);
if (rateUpdated) {
nextToken.rate = nextRate->v;
} else {
allLoaded = true;
}, [&](const MTPDpublicForwardStory &data) {
const auto story = owner.stories().applySingle(
peerFromMTP(data.vpeer()),
data.vstory());
if (story) {
recentList.push_back({ .storyId = story->fullId() });
}
}
fullCount = data.vcount().v;
return list;
}, [&](const MTPDmessages_channelMessages &data) {
channel->owner().processUsers(data.vusers());
channel->owner().processChats(data.vchats());
auto list = process(data.vmessages());
allLoaded = true;
fullCount = data.vcount().v;
return list;
}, [&](const MTPDmessages_messagesNotModified &) {
allLoaded = true;
return Messages();
});
});
}
const auto allLoaded = nextToken.isEmpty() || (nextToken == token);
_lastTotal = std::max(_lastTotal, fullCount);
done({
.list = std::move(messages),
.list = std::move(recentList),
.total = _lastTotal,
.allLoaded = allLoaded,
.token = nextToken,
});
}).fail([=] {
_requestId = 0;
}).send();
};
constexpr auto kLimit = tl::make_int(100);
if (_fullId.messageId) {
_requestId = makeRequest(MTPstats_GetMessagePublicForwards(
channel->inputChannel,
MTP_int(_fullId.messageId.msg),
MTP_string(token),
kLimit
)).done(processResult).fail([=] { _requestId = 0; }).send();
} else if (_fullId.storyId) {
_requestId = makeRequest(MTPstats_GetStoryPublicForwards(
channel->input,
MTP_int(_fullId.storyId.story),
MTP_string(token),
kLimit
)).done(processResult).fail([=] { _requestId = 0; }).send();
}
}
MessageStatistics::MessageStatistics(
not_null<ChannelData*> channel,
FullMsgId fullId)
: StatisticsRequestSender(channel)
, _publicForwards(channel, fullId)
, _publicForwards(channel, { .messageId = fullId })
, _fullId(fullId) {
}
MessageStatistics::MessageStatistics(
not_null<ChannelData*> channel,
FullStoryId storyId)
: StatisticsRequestSender(channel)
, _publicForwards(channel, { .storyId = storyId })
, _storyId(storyId) {
}
Data::PublicForwardsSlice MessageStatistics::firstSlice() const {
return _firstSlice;
}
@@ -438,21 +462,26 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
}
const auto requestFirstPublicForwards = [=](
const Data::StatisticalGraph &messageGraph,
const Data::StatisticalGraph &reactionsGraph,
const Data::StatisticsMessageInteractionInfo &info) {
_publicForwards.request({}, [=](Data::PublicForwardsSlice slice) {
const auto callback = [=](Data::PublicForwardsSlice slice) {
const auto total = slice.total;
_firstSlice = std::move(slice);
done({
.messageInteractionGraph = messageGraph,
.reactionsByEmotionGraph = reactionsGraph,
.publicForwards = total,
.privateForwards = info.forwardsCount - total,
.views = info.viewsCount,
.reactions = info.reactionsCount,
});
});
};
_publicForwards.request({}, callback);
};
const auto requestPrivateForwards = [=](
const Data::StatisticalGraph &messageGraph) {
const Data::StatisticalGraph &messageGraph,
const Data::StatisticalGraph &reactionsGraph) {
api().request(MTPchannels_GetMessages(
channel()->inputChannel,
MTP_vector<MTPInputMessage>(
@@ -462,6 +491,13 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
const auto process = [&](const MTPVector<MTPMessage> &messages) {
const auto &message = messages.v.front();
return message.match([&](const MTPDmessage &data) {
auto reactionsCount = 0;
if (const auto tlReactions = data.vreactions()) {
const auto &tlCounts = tlReactions->data().vresults();
for (const auto &tlCount : tlCounts.v) {
reactionsCount += tlCount.data().vcount().v;
}
}
return Data::StatisticsMessageInteractionInfo{
.messageId = IdFromMessage(message),
.viewsCount = data.vviews()
@@ -470,6 +506,7 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
.forwardsCount = data.vforwards()
? data.vforwards()->v
: 0,
.reactionsCount = reactionsCount,
};
}, [](const MTPDmessageEmpty &) {
return Data::StatisticsMessageInteractionInfo();
@@ -488,22 +525,74 @@ void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
return Data::StatisticsMessageInteractionInfo();
});
requestFirstPublicForwards(messageGraph, std::move(info));
requestFirstPublicForwards(
messageGraph,
reactionsGraph,
std::move(info));
}).fail([=](const MTP::Error &error) {
requestFirstPublicForwards(messageGraph, {});
requestFirstPublicForwards(messageGraph, reactionsGraph, {});
}).send();
};
makeRequest(MTPstats_GetMessageStats(
MTP_flags(MTPstats_GetMessageStats::Flags(0)),
channel()->inputChannel,
MTP_int(_fullId.msg.bare)
)).done([=](const MTPstats_MessageStats &result) {
requestPrivateForwards(
StatisticalGraphFromTL(result.data().vviews_graph()));
}).fail([=](const MTP::Error &error) {
requestPrivateForwards({});
}).send();
const auto requestStoryPrivateForwards = [=](
const Data::StatisticalGraph &messageGraph,
const Data::StatisticalGraph &reactionsGraph) {
api().request(MTPstories_GetStoriesByID(
channel()->input,
MTP_vector<MTPint>(1, MTP_int(_storyId.story)))
).done([=](const MTPstories_Stories &result) {
const auto &storyItem = result.data().vstories().v.front();
auto info = storyItem.match([&](const MTPDstoryItem &data) {
if (!data.vviews()) {
return Data::StatisticsMessageInteractionInfo();
}
const auto &tlViews = data.vviews()->data();
return Data::StatisticsMessageInteractionInfo{
.storyId = data.vid().v,
.viewsCount = tlViews.vviews_count().v,
.forwardsCount = tlViews.vforwards_count().value_or(0),
.reactionsCount = tlViews.vreactions_count().value_or(0),
};
}, [](const auto &) {
return Data::StatisticsMessageInteractionInfo();
});
requestFirstPublicForwards(
messageGraph,
reactionsGraph,
std::move(info));
}).fail([=](const MTP::Error &error) {
requestFirstPublicForwards(messageGraph, reactionsGraph, {});
}).send();
};
if (_storyId) {
makeRequest(MTPstats_GetStoryStats(
MTP_flags(MTPstats_GetStoryStats::Flags(0)),
channel()->input,
MTP_int(_storyId.story)
)).done([=](const MTPstats_StoryStats &result) {
const auto &data = result.data();
requestStoryPrivateForwards(
StatisticalGraphFromTL(data.vviews_graph()),
StatisticalGraphFromTL(data.vreactions_by_emotion_graph()));
}).fail([=](const MTP::Error &error) {
requestStoryPrivateForwards({}, {});
}).send();
} else {
makeRequest(MTPstats_GetMessageStats(
MTP_flags(MTPstats_GetMessageStats::Flags(0)),
channel()->inputChannel,
MTP_int(_fullId.msg.bare)
)).done([=](const MTPstats_MessageStats &result) {
const auto &data = result.data();
requestPrivateForwards(
StatisticalGraphFromTL(data.vviews_graph()),
StatisticalGraphFromTL(data.vreactions_by_emotion_graph()));
}).fail([=](const MTP::Error &error) {
requestPrivateForwards({}, {});
}).send();
}
}
Boosts::Boosts(not_null<PeerData*> peer)
@@ -523,6 +612,7 @@ rpl::producer<rpl::no_value, QString> Boosts::request() {
_peer->input
)).done([=](const MTPpremium_BoostsStatus &result) {
const auto &data = result.data();
channel->updateLevelHint(data.vlevel().v);
const auto hasPremium = !!data.vpremium_audience();
const auto premiumMemberCount = hasPremium
? std::max(0, int(data.vpremium_audience()->data().vpart().v))
+8 -2
View File
@@ -68,14 +68,16 @@ private:
class PublicForwards final : public StatisticsRequestSender {
public:
PublicForwards(not_null<ChannelData*> channel, FullMsgId fullId);
PublicForwards(
not_null<ChannelData*> channel,
Data::RecentPostId fullId);
void request(
const Data::PublicForwardsSlice::OffsetToken &token,
Fn<void(Data::PublicForwardsSlice)> done);
private:
const FullMsgId _fullId;
const Data::RecentPostId _fullId;
mtpRequestId _requestId = 0;
int _lastTotal = 0;
@@ -86,6 +88,9 @@ public:
explicit MessageStatistics(
not_null<ChannelData*> channel,
FullMsgId fullId);
explicit MessageStatistics(
not_null<ChannelData*> channel,
FullStoryId storyId);
void request(Fn<void(Data::MessageStatistics)> done);
@@ -94,6 +99,7 @@ public:
private:
PublicForwards _publicForwards;
const FullMsgId _fullId;
const FullStoryId _storyId;
Data::PublicForwardsSlice _firstSlice;
+64 -6
View File
@@ -7,13 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "api/api_transcribes.h"
#include "history/history_item.h"
#include "history/history.h"
#include "main/main_session.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_peer.h"
#include "apiwrap.h"
#include "data/data_document.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
namespace Api {
@@ -22,6 +25,44 @@ Transcribes::Transcribes(not_null<ApiWrap*> api)
, _api(&api->instance()) {
}
bool Transcribes::trialsSupport() {
if (!_trialsSupport) {
const auto count = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_weekly_number"_q,
0);
const auto until = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_cooldown_until"_q,
0);
_trialsSupport = (count > 0) || (until > 0);
}
return *_trialsSupport;
}
TimeId Transcribes::trialsRefreshAt() {
if (_trialsRefreshAt < 0) {
_trialsRefreshAt = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_cooldown_until"_q,
0);
}
return _trialsRefreshAt;
}
int Transcribes::trialsCount() {
if (_trialsCount < 0) {
_trialsCount = _session->account().appConfig().get<int>(
u"transcribe_audio_trial_weekly_number"_q,
-1);
return std::max(_trialsCount, 0);
}
return _trialsCount;
}
crl::time Transcribes::trialsMaxLengthMs() const {
return 1000 * _session->account().appConfig().get<int>(
u"transcribe_audio_trial_duration_max"_q,
300);
}
void Transcribes::toggle(not_null<HistoryItem*> item) {
const auto id = item->fullId();
auto i = _map.find(id);
@@ -86,6 +127,23 @@ void Transcribes::load(not_null<HistoryItem*> item) {
MTP_int(item->id)
)).done([=](const MTPmessages_TranscribedAudio &result) {
const auto &data = result.data();
{
const auto trialsCountChanged = data.vtrial_remains_num()
&& (_trialsCount != data.vtrial_remains_num()->v);
if (trialsCountChanged) {
_trialsCount = data.vtrial_remains_num()->v;
}
const auto refreshAtChanged = data.vtrial_remains_until_date()
&& (_trialsRefreshAt != data.vtrial_remains_until_date()->v);
if (refreshAtChanged) {
_trialsRefreshAt = data.vtrial_remains_until_date()->v;
}
if (trialsCountChanged) {
ShowTrialTranscribesToast(_trialsCount, _trialsRefreshAt);
}
}
auto &entry = _map[id];
entry.requestId = 0;
entry.pending = data.is_pending();
@@ -36,12 +36,21 @@ public:
void apply(const MTPDupdateTranscribedAudio &update);
[[nodiscard]] bool trialsSupport();
[[nodiscard]] TimeId trialsRefreshAt();
[[nodiscard]] int trialsCount();
[[nodiscard]] crl::time trialsMaxLengthMs() const;
private:
void load(not_null<HistoryItem*> item);
const not_null<Main::Session*> _session;
MTP::Sender _api;
int _trialsCount = -1;
std::optional<bool> _trialsSupport;
TimeId _trialsRefreshAt = -1;
base::flat_map<FullMsgId, Entry> _map;
base::flat_map<uint64, FullMsgId> _ids;
+21
View File
@@ -2023,6 +2023,19 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
} break;
case mtpc_updatePeerWallpaper: {
const auto &d = update.c_updatePeerWallpaper();
if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) {
if (const auto paper = d.vwallpaper()) {
peer->setWallPaper(
Data::WallPaper::Create(&session(), *paper),
d.is_wallpaper_overridden());
} else {
peer->setWallPaper({});
}
}
} break;
case mtpc_updateBotCommands: {
const auto &d = update.c_updateBotCommands();
if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) {
@@ -2358,6 +2371,14 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
} break;
case mtpc_updateChannelViewForumAsMessages: {
const auto &d = update.c_updateChannelViewForumAsMessages();
const auto id = ChannelId(d.vchannel_id());
if (const auto channel = session().data().channelLoaded(id)) {
channel->setViewAsMessagesFlag(mtpIsTrue(d.venabled()));
}
} break;
// Pinned message.
case mtpc_updatePinnedMessages: {
const auto &d = update.c_updatePinnedMessages();
+50 -43
View File
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_hash.h"
#include "api/api_invite_links.h"
#include "api/api_media.h"
#include "api/api_peer_colors.h"
#include "api/api_peer_photo.h"
#include "api/api_polls.h"
#include "api/api_sending.h"
@@ -33,50 +34,35 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_user_names.h"
#include "api/api_websites.h"
#include "data/notify/data_notify_settings.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h"
#include "data/data_changes.h"
#include "data/data_photo.h"
#include "data/data_web_page.h"
#include "data/data_folder.h"
#include "data/data_forum_topic.h"
#include "data/data_forum.h"
#include "data/data_media_types.h"
#include "data/data_sparse_ids.h"
#include "data/data_search_controller.h"
#include "data/data_scheduled_messages.h"
#include "data/data_channel_admins.h"
#include "data/data_session.h"
#include "data/data_stories.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_cloud_themes.h"
#include "data/data_chat_filters.h"
#include "data/data_histories.h"
#include "data/data_wall_paper.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/dialogs_key.h"
#include "core/core_cloud_password.h"
#include "core/application.h"
#include "base/unixtime.h"
#include "base/random.h"
#include "base/qt/qt_common_adapters.h"
#include "base/call_delayed.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "mainwidget.h"
#include "boxes/add_contact_box.h"
#include "mtproto/mtproto_config.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_components.h"
#include "history/history_item_helpers.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "main/main_account.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/stickers_box.h"
#include "boxes/sticker_set_box.h"
#include "boxes/premium_limits_box.h"
#include "window/notifications_manager.h"
@@ -87,7 +73,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/message_field.h"
#include "ui/item_text_options.h"
#include "ui/text/text_utilities.h"
#include "ui/emoji_config.h"
#include "ui/chat/attach/attach_prepare.h"
#include "ui/toast/toast.h"
#include "support/support_helper.h"
@@ -95,9 +80,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localimageloader.h"
#include "storage/download_manager_mtproto.h"
#include "storage/file_upload.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "storage/storage_media_prepare.h"
#include "storage/storage_account.h"
// AyuGram includes
@@ -151,6 +133,15 @@ void ShowChannelsLimitBox(not_null<PeerData*> peer) {
}
}
[[nodiscard]] FileLoadTo FileLoadTaskOptions(const Api::SendAction &action) {
const auto peer = action.history->peer;
return FileLoadTo(
peer->id,
action.options,
action.replyTo,
action.replaceMediaOf);
}
} // namespace
ApiWrap::ApiWrap(not_null<Main::Session*> session)
@@ -184,7 +175,8 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
, _transcribes(std::make_unique<Api::Transcribes>(this))
, _premium(std::make_unique<Api::Premium>(this))
, _usernames(std::make_unique<Api::Usernames>(this))
, _websites(std::make_unique<Api::Websites>(this)) {
, _websites(std::make_unique<Api::Websites>(this))
, _peerColors(std::make_unique<Api::PeerColors>(this)) {
crl::on_main(session, [=] {
// You can't use _session->lifetime() in the constructor,
// only queued, because it is not constructed yet.
@@ -233,11 +225,11 @@ void ApiWrap::setupSupportMode() {
void ApiWrap::requestChangelog(
const QString &sinceVersion,
Fn<void(const MTPUpdates &result)> callback) {
request(MTPhelp_GetAppChangelog(
MTP_string(sinceVersion)
)).done(
callback
).send();
//request(MTPhelp_GetAppChangelog(
// MTP_string(sinceVersion)
//)).done(
// callback
//).send();
}
void ApiWrap::refreshTopPromotion() {
@@ -1341,6 +1333,12 @@ void ApiWrap::markContentsRead(
markedIds.push_back(MTP_int(item->id));
}
}
const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages) {
return;
}
if (!markedIds.isEmpty()) {
request(MTPmessages_ReadMessageContents(
MTP_vector<MTPint>(markedIds)
@@ -1360,6 +1358,12 @@ void ApiWrap::markContentsRead(not_null<HistoryItem*> item) {
if (!item->markContentsRead(true) || !item->isRegular()) {
return;
}
const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages) {
return;
}
const auto ids = MTP_vector<MTPint>(1, MTP_int(item->id));
if (const auto channel = item->history()->peer->asChannel()) {
request(MTPchannels_ReadMessageContents(
@@ -1754,6 +1758,14 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
}).send();
_channelAmInRequests.emplace(channel, requestId);
using Flag = ChannelDataFlag;
chatParticipants().loadSimilarChannels(channel);
const auto settings = &AyuSettings::getInstance();
if (!settings->collapseSimilarChannels) {
channel->setFlags(channel->flags() | Flag::SimilarExpanded);
}
}
}
@@ -2070,13 +2082,13 @@ void ApiWrap::deleteHistory(
void ApiWrap::applyUpdates(
const MTPUpdates &updates,
uint64 sentMessageRandomId) {
uint64 sentMessageRandomId) const {
this->updates().applyUpdates(updates, sentMessageRandomId);
}
int ApiWrap::applyAffectedHistory(
PeerData *peer,
const MTPmessages_AffectedHistory &result) {
const MTPmessages_AffectedHistory &result) const {
const auto &data = result.c_messages_affectedHistory();
if (const auto channel = peer ? peer->asChannel() : nullptr) {
channel->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v);
@@ -2098,7 +2110,7 @@ void ApiWrap::applyAffectedMessages(
}
void ApiWrap::applyAffectedMessages(
const MTPmessages_AffectedMessages &result) {
const MTPmessages_AffectedMessages &result) const {
const auto &data = result.c_messages_affectedMessages();
updates().updateAndApply(data.vpts().v, data.vpts_count().v);
}
@@ -2557,8 +2569,8 @@ void ApiWrap::refreshFileReference(
request(MTPhelp_GetPremiumPromo());
}, [&](Data::FileOriginStory data) {
request(MTPstories_GetStoriesByID(
_session->data().peer(data.peerId)->input,
MTP_vector<MTPint>(1, MTP_int(data.storyId))));
_session->data().peer(data.peer)->input,
MTP_vector<MTPint>(1, MTP_int(data.story))));
}, [&](v::null_t) {
fail();
});
@@ -3444,7 +3456,7 @@ void ApiWrap::sendVoiceMessage(
crl::time duration,
const SendAction &action) {
const auto caption = TextWithTags();
const auto to = fileLoadTaskOptions(action);
const auto to = FileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>(
&session(),
result,
@@ -3462,7 +3474,7 @@ void ApiWrap::editMedia(
if (list.files.empty()) return;
auto &file = list.files.front();
const auto to = fileLoadTaskOptions(action);
const auto to = FileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>(
&session(),
file.path,
@@ -3491,7 +3503,7 @@ void ApiWrap::sendFiles(
sendMessage(std::move(message));
}
const auto to = fileLoadTaskOptions(action);
const auto to = FileLoadTaskOptions(action);
if (album) {
album->options = to.options;
}
@@ -3530,7 +3542,7 @@ void ApiWrap::sendFile(
const QByteArray &fileContent,
SendMediaType type,
const SendAction &action) {
const auto to = fileLoadTaskOptions(action);
const auto to = FileLoadTaskOptions(action);
auto caption = TextWithTags();
const auto spoiler = false;
const auto information = nullptr;
@@ -4227,15 +4239,6 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
});
}
FileLoadTo ApiWrap::fileLoadTaskOptions(const SendAction &action) const {
const auto peer = action.history->peer;
return FileLoadTo(
peer->id,
action.options,
action.replyTo,
action.replaceMediaOf);
}
void ApiWrap::reloadContactSignupSilent() {
if (_contactSignupSilentRequestId) {
return;
@@ -4451,3 +4454,7 @@ Api::Usernames &ApiWrap::usernames() {
Api::Websites &ApiWrap::websites() {
return *_websites;
}
Api::PeerColors &ApiWrap::peerColors() {
return *_peerColors;
}
+6 -6
View File
@@ -9,8 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_common.h"
#include "base/timer.h"
#include "base/flat_map.h"
#include "base/flat_set.h"
#include "mtproto/sender.h"
#include "data/stickers/data_stickers_set.h"
#include "data/data_messages.h"
@@ -73,6 +71,7 @@ class InviteLinks;
class ViewsManager;
class ConfirmPhone;
class PeerPhoto;
class PeerColors;
class Polls;
class ChatParticipants;
class UnreadThings;
@@ -141,10 +140,10 @@ public:
void applyUpdates(
const MTPUpdates &updates,
uint64 sentMessageRandomId = 0);
uint64 sentMessageRandomId = 0) const;
int applyAffectedHistory(
PeerData *peer, // May be nullptr, like for deletePhoneCallHistory.
const MTPmessages_AffectedHistory &result);
const MTPmessages_AffectedHistory &result) const;
void registerModifyRequest(const QString &key, mtpRequestId requestId);
void clearModifyRequest(const QString &key);
@@ -392,6 +391,7 @@ public:
[[nodiscard]] Api::Premium &premium();
[[nodiscard]] Api::Usernames &usernames();
[[nodiscard]] Api::Websites &websites();
[[nodiscard]] Api::PeerColors &peerColors();
void updatePrivacyLastSeens();
@@ -503,7 +503,7 @@ private:
not_null<PeerData*> peer,
bool justClear,
bool revoke);
void applyAffectedMessages(const MTPmessages_AffectedMessages &result);
void applyAffectedMessages(const MTPmessages_AffectedMessages &result) const;
void deleteAllFromParticipantSend(
not_null<ChannelData*> channel,
@@ -532,7 +532,6 @@ private:
Api::SendOptions options,
uint64 randomId,
Fn<void(bool)> done = nullptr);
FileLoadTo fileLoadTaskOptions(const SendAction &action) const;
void getTopPromotionDelayed(TimeId now, TimeId next);
void topPromotionDone(const MTPhelp_PromoData &proxy);
@@ -711,6 +710,7 @@ private:
const std::unique_ptr<Api::Premium> _premium;
const std::unique_ptr<Api::Usernames> _usernames;
const std::unique_ptr<Api::Websites> _websites;
const std::unique_ptr<Api::PeerColors> _peerColors;
mtpRequestId _wallPaperRequestId = 0;
QString _wallPaperSlug;
+14 -7
View File
@@ -11,6 +11,15 @@
#include "core/core_settings.h"
#include "lang/lang_instance.h"
// hard-coded languages
std::map<QString, QString> langMapping = {
{"pt-br", "pt"},
{"zh-hans-beta", "zh-hans"},
{"zh-hant-beta", "zh-hant"},
{"zh-hans-raw", "zh-hans"},
{"zh-hant-raw", "zh-hant"},
};
CustomLangPack *CustomLangPack::instance = nullptr;
CustomLangPack::CustomLangPack() = default;
@@ -30,11 +39,7 @@ void CustomLangPack::fetchCustomLangPack(const QString &langPackId, const QStrin
{
LOG(("Current Language pack ID: %1, Base ID: %2").arg(langPackId, langPackBaseId));
auto finalLangPackId = langPackId;
if (finalLangPackId == qsl("pt-br")) {
// meh
finalLangPackId = qsl("pt");
}
auto finalLangPackId = langMapping.contains(langPackId) ? langMapping[langPackId] : langPackId;
const auto proxy = Core::App().settings().proxy().isEnabled()
? Core::App().settings().proxy().selected()
@@ -44,13 +49,15 @@ void CustomLangPack::fetchCustomLangPack(const QString &langPackId, const QStrin
networkManager.setProxy(LocaleProxy);
}
// using `jsdelivr` since China (...and maybe other?) users have some problems with GitHub
// https://crowdin.com/project/ayugram/discussions/6
QUrl url;
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
url.setUrl(qsl("https://cdn.jsdelivr.net/gh/AyuGram/Languages@l10n_main/values/langs/%1/Shared.json").arg(
finalLangPackId));
}
else {
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
url.setUrl(qsl("https://cdn.jsdelivr.net/gh/AyuGram/Languages@l10n_main/values/langs/%1/Shared.json").arg(
needFallback ? langPackBaseId : finalLangPackId));
}
_chkReply = networkManager.get(QNetworkRequest(url));
+24 -10
View File
@@ -139,15 +139,19 @@ void load()
initialize();
json p;
file >> p;
file.close();
try {
settings = p.get<AyuGramSettings>();
}
catch (...) {
LOG(("AyuGramSettings: failed to parse settings file"));
json p;
file >> p;
file.close();
try {
settings = p.get<AyuGramSettings>();
}
catch (...) {
LOG(("AyuGramSettings: failed to parse settings file"));
}
} catch (...) {
LOG(("AyuGramSettings: failed to read settings file (not json-like)"));
}
postinitialize();
}
@@ -225,12 +229,12 @@ void AyuGramSettings::set_useScheduledMessages(bool val)
useScheduledMessages = val;
}
void AyuGramSettings::set_keepDeletedMessages(bool val)
void AyuGramSettings::set_saveDeletedMessages(bool val)
{
saveDeletedMessages = val;
}
void AyuGramSettings::set_keepMessagesHistory(bool val)
void AyuGramSettings::set_saveMessagesHistory(bool val)
{
saveMessagesHistory = val;
}
@@ -245,6 +249,16 @@ void AyuGramSettings::set_disableStories(bool val)
disableStories = val;
}
void AyuGramSettings::set_collapseSimilarChannels(bool val)
{
collapseSimilarChannels = val;
}
void AyuGramSettings::set_hideSimilarChannels(bool val)
{
hideSimilarChannels = val;
}
void AyuGramSettings::set_disableNotificationsDelay(bool val)
{
disableNotificationsDelay = val;
+13 -3
View File
@@ -48,12 +48,14 @@ public:
useScheduledMessages = false;
// ~ Message edits & deletion history
saveDeletedMessages = true;
saveDeletedMessages = false;
saveMessagesHistory = true;
// ~ QoL toggles
disableAds = true;
disableStories = false;
collapseSimilarChannels = true;
hideSimilarChannels = false;
disableNotificationsDelay = false;
localPremium = false;
copyUsernameAsLink = true;
@@ -105,6 +107,8 @@ public:
bool saveMessagesHistory;
bool disableAds;
bool disableStories;
bool collapseSimilarChannels;
bool hideSimilarChannels;
bool disableNotificationsDelay;
bool localPremium;
bool copyUsernameAsLink;
@@ -149,14 +153,18 @@ public:
void set_useScheduledMessages(bool val);
void set_keepDeletedMessages(bool val);
void set_saveDeletedMessages(bool val);
void set_keepMessagesHistory(bool val);
void set_saveMessagesHistory(bool val);
void set_disableAds(bool val);
void set_disableStories(bool val);
void set_collapseSimilarChannels(bool val);
void set_hideSimilarChannels(bool val);
void set_disableNotificationsDelay(bool val);
void set_localPremium(bool val);
@@ -217,6 +225,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
saveMessagesHistory,
disableAds,
disableStories,
collapseSimilarChannels,
hideSimilarChannels,
disableNotificationsDelay,
localPremium,
copyUsernameAsLink,
-13
View File
@@ -8,17 +8,4 @@
namespace AyuState
{
void setAllowSendReadPacket(bool val, int resetAfter)
{
allowSendReadPacket.val = val;
allowSendReadPacket.resetAfter = resetAfter;
}
bool getAllowSendPacket()
{
auto settings = &AyuSettings::getInstance();
return settings->sendReadMessages || processVariable(allowSendReadPacket);
}
}
-4
View File
@@ -41,8 +41,4 @@ bool processVariable(AyuStateVariable &variable)
}
void setAllowSendReadPacket(bool val, int resetAfter = 1);
bool getAllowSendPacket();
}
@@ -12,6 +12,7 @@ using "ui/widgets/widgets.style";
ayuGhostIcon: icon {{ "ayu/ghost", menuIconColor }};
ayuMenuIcon: icon {{ "ayu/ayu_menu", menuIconColor }};
ayuEditsHistoryIcon: icon {{ "ayu/edits_history", menuIconColor }};
ayuLReadMenuIcon: icon {{ "ayu/lread", menuIconColor }};
ayuSReadMenuIcon: icon {{ "ayu/sread", menuIconColor }};
ayuStreamerModeMenuIcon: icon {{ "ayu/streamer", menuIconColor }};
@@ -21,3 +21,5 @@ cpImagePadding: 4px;
cpSpacingX: 16px;
cpSpacingY: 8px;
cpIconSize: 64px;
recentStickersLimitPadding: margins(22px, 4px, 22px, 8px);
@@ -18,7 +18,7 @@
namespace AyuUi
{
ConfirmationBox::ConfirmationBox(
ServerReadConfirmationBox::ServerReadConfirmationBox(
QWidget *,
not_null<Window::SessionController *> controller)
: _controller(controller)
@@ -26,7 +26,7 @@ ConfirmationBox::ConfirmationBox(
//
}
void ConfirmationBox::prepare()
void ServerReadConfirmationBox::prepare()
{
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
@@ -45,7 +45,7 @@ void ConfirmationBox::prepare()
{ closeBox(); });
}
void ConfirmationBox::resizeEvent(QResizeEvent *e)
void ServerReadConfirmationBox::resizeEvent(QResizeEvent *e)
{
BoxContent::resizeEvent(e);
@@ -53,7 +53,7 @@ void ConfirmationBox::resizeEvent(QResizeEvent *e)
_text->moveToLeft(padding.left(), padding.top());
}
void ConfirmationBox::ReadAllPeers()
void ServerReadConfirmationBox::ReadAllPeers()
{
auto settings = &AyuSettings::getInstance();
auto prev = settings->sendReadMessages;
@@ -12,10 +12,10 @@
namespace AyuUi
{
class ConfirmationBox : public Ui::BoxContent
class ServerReadConfirmationBox : public Ui::BoxContent
{
public:
ConfirmationBox(QWidget *, not_null<Window::SessionController *> controller);
ServerReadConfirmationBox(QWidget *, not_null<Window::SessionController *> controller);
protected:
void prepare() override;
@@ -14,6 +14,7 @@
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "ui/effects/scroll_content_shadow.h"
#include "ui/vertical_list.h"
using namespace Settings;
@@ -10,12 +10,12 @@
#include "ayu/messages/ayu_messages_controller.h"
#include "ayu/ui/boxes/message_history_box.h"
#include "history/history_inner_widget.h"
#include "settings/settings_common.h"
#include "styles/style_chat.h"
#include "mainwidget.h"
#include "styles/style_ayu_icons.h"
#include "ui/widgets/popup_menu.h"
#include "ayu/ui/sections/edited/edited_log_section.h"
#include "ayu/utils/telegram_helpers.h"
namespace AyuUi
@@ -28,22 +28,43 @@ void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
{
item->history()->session().tryResolveWindow()
->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item));
}, &st::menuIconInfo);
}, &st::ayuEditsHistoryIcon);
}
}
void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
{
const auto settings = &AyuSettings::getInstance();
const auto history = item->history();
menu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]()
{
const auto initSaveDeleted = settings->saveDeletedMessages;
// todo: rework
// const auto settings = &AyuSettings::getInstance();
// const auto history = item->history();
// menu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]()
// {
// const auto initSaveDeleted = settings->saveDeletedMessages;
//
// settings->set_saveDeletedMessages(false);
// history->destroyMessage(item);
// settings->set_saveDeletedMessages(initSaveDeleted);
// }, &st::menuIconClear);
}
settings->set_keepDeletedMessages(false);
history->destroyMessage(item);
settings->set_keepDeletedMessages(initSaveDeleted);
}, &st::menuIconClear);
void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
{
if (item->history()->peer->isChat() || item->history()->peer->isMegagroup()) {
menu->addAction(tr::ayu_UserMessagesMenuText(tr::now), [=]
{
if (const auto window = item->history()->session().tryResolveWindow()) {
if (const auto mainWidget = window->widget()->sessionController()) {
const auto peer = item->history()->peer;
const auto key = (peer && !peer->isUser())
? item->topic()
? Dialogs::Key{item->topic()}
: Dialogs::Key{item->history()}
: Dialogs::Key();
mainWidget->content()->searchMessages("", key, item->from()->asUser());
}
}
}, &st::menuIconInfo);
}
}
void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
@@ -53,11 +74,9 @@ void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
return;
}
const auto history = item->history();
menu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]()
{
AyuState::setAllowSendReadPacket(true);
history->session().data().histories().readInboxOnNewMessage(item);
readHistory(item);
}, &st::menuIconShowInChat);
}
@@ -87,6 +87,8 @@ void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
}
@@ -938,7 +938,10 @@ TextForMimeData InnerWidget::getSelectedText() const
void InnerWidget::keyPressEvent(QKeyEvent *e)
{
if (e == QKeySequence::Copy && _selectedItem != nullptr) {
if (e->key() == Qt::Key_Escape) {
_controller->showBackFromStack();
}
else if (e == QKeySequence::Copy && _selectedItem != nullptr) {
copySelectedText();
#ifdef Q_OS_MAC
} else if (e->key() == Qt::Key_E && e->modifiers().testFlag(Qt::ControlModifier)) {
@@ -16,8 +16,6 @@
#include "mainwindow.h"
#include "api/api_blocked_peers.h"
#include "ayu/features/streamer_mode/streamer_mode.h"
#include "boxes/connection_box.h"
#include "core/application.h"
#include "data/data_session.h"
@@ -30,13 +28,12 @@
#include "styles/style_basic.h"
#include "styles/style_boxes.h"
#include "styles/style_info.h"
#include "styles/style_menu_icons.h"
#include "styles/style_settings.h"
#include "styles/style_widgets.h"
#include "styles/style_ayu_styles.h"
#include "icon_picker.h"
#include "ui/painter.h"
#include "ui/boxes/confirm_box.h"
#include "ui/boxes/single_choice_box.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
@@ -47,6 +44,7 @@
#include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h"
#include "styles/style_ayu_icons.h"
#include "ui/vertical_list.h"
class PainterHighQualityEnabler;
@@ -247,95 +245,18 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
return button;
}
namespace Settings
struct NestedEntry
{
QString checkboxLabel;
bool initial;
std::function<void(bool)> callback;
};
rpl::producer<QString> Ayu::title()
void AddCollapsibleToggle(not_null<Ui::VerticalLayout *> container,
rpl::producer<QString> title,
std::vector<NestedEntry> checkboxes,
bool toggledWhenAll)
{
return tr::ayu_AyuPreferences();
}
Ayu::Ayu(
QWidget *parent,
not_null<Window::SessionController *> controller)
: Section(parent)
{
setupContent(controller);
}
void Ayu::AddPlatformOption(
not_null<Window::SessionController *> window,
not_null<Ui::VerticalLayout *> container,
base::options::option<bool> &option,
rpl::producer<> resetClicks)
{
auto &lifetime = container->lifetime();
const auto name = option.name().isEmpty() ? option.id() : option.name();
const auto toggles = lifetime.make_state<rpl::event_stream<bool>>();
std::move(
resetClicks
) | rpl::map_to(
option.defaultValue()
) | start_to_stream(*toggles, lifetime);
const auto button = AddButton(
container,
rpl::single(name),
(option.relevant()
? st::settingsButtonNoIcon
: st::settingsOptionDisabled)
)->toggleOn(toggles->events_starting_with(option.value()));
const auto restarter = (option.relevant() && option.restartRequired())
? button->lifetime().make_state<base::Timer>()
: nullptr;
if (restarter) {
restarter->setCallback([=]
{
window->show(Ui::MakeConfirmBox({
.text = tr::lng_settings_need_restart(),
.confirmed = []
{ Core::Restart(); },
.confirmText = tr::lng_settings_restart_now(),
.cancelText = tr::lng_settings_restart_later(),
}));
});
}
button->toggledChanges(
) | start_with_next([=, &option](bool toggled)
{
if (!option.relevant() && toggled != option.defaultValue()) {
toggles->fire_copy(option.defaultValue());
window->showToast(
tr::lng_settings_experimental_irrelevant(tr::now));
return;
}
option.set(toggled);
if (restarter) {
restarter->callOnce(st::settingsButtonNoIcon.toggle.duration);
}
}, container->lifetime());
const auto &description = option.description();
if (!description.isEmpty()) {
AddSkip(container);
AddDividerText(container, rpl::single(description));
}
}
void Ayu::SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container)
{
auto settings = &AyuSettings::getInstance();
const auto widget = object_ptr<Ui::VerticalLayout>(this);
widget->add(
object_ptr<Ui::FlatLabel>(
container,
tr::ayu_GhostEssentialsHeader(),
st::rightsHeaderLabel),
st::rightsHeaderMargin);
const auto addCheckbox = [&](
not_null<Ui::VerticalLayout *> verticalLayout,
const QString &label,
@@ -380,12 +301,59 @@ void Ayu::SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container)
return checkView;
};
struct NestedEntry
{
QString checkboxLabel;
bool initial;
std::function<void(bool)> callback;
};
auto wrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container));
const auto verticalLayout = wrap->entity();
auto innerChecks = std::vector<not_null<Ui::AbstractCheckView *>>();
for (const auto &entry : checkboxes) {
const auto c = addCheckbox(verticalLayout, entry.checkboxLabel, entry.initial);
c->checkedValue(
) | start_with_next([=](bool enabled)
{
entry.callback(enabled);
}, container->lifetime());
innerChecks.push_back(c);
}
const auto raw = wrap.data();
raw->hide(anim::type::instant);
AddInnerToggle(
container,
st::powerSavingButtonNoIcon,
innerChecks,
raw,
std::move(title),
toggledWhenAll);
container->add(std::move(wrap));
container->widthValue(
) | start_with_next([=](int w)
{
raw->resizeToWidth(w);
}, raw->lifetime());
}
namespace Settings
{
rpl::producer<QString> Ayu::title()
{
return tr::ayu_AyuPreferences();
}
Ayu::Ayu(
QWidget *parent,
not_null<Window::SessionController *> controller)
: Section(parent)
{
setupContent(controller);
}
void Ayu::SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container)
{
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader());
std::vector checkboxes{
NestedEntry{
@@ -425,102 +393,13 @@ void Ayu::SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container)
},
};
auto wrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container));
const auto verticalLayout = wrap->entity();
auto innerChecks = std::vector<not_null<Ui::AbstractCheckView *>>();
for (const auto &entry : checkboxes) {
const auto c = addCheckbox(verticalLayout, entry.checkboxLabel, entry.initial);
c->checkedValue(
) | start_with_next([=](bool enabled)
{
entry.callback(enabled);
}, container->lifetime());
innerChecks.push_back(c);
}
const auto raw = wrap.data();
raw->hide(anim::type::instant);
AddInnerToggle(
container,
st::powerSavingButtonNoIcon,
innerChecks,
raw,
tr::ayu_GhostModeToggle(),
true);
container->add(std::move(wrap));
container->widthValue(
) | start_with_next([=](int w)
{
raw->resizeToWidth(w);
}, raw->lifetime());
AddCollapsibleToggle(container, tr::ayu_GhostEssentialsHeader(), checkboxes, true);
}
void Ayu::SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container)
{
auto settings = &AyuSettings::getInstance();
const auto widget = object_ptr<Ui::VerticalLayout>(this);
widget->add(
object_ptr<Ui::FlatLabel>(
container,
tr::ayu_MarkReadAfterAction(),
st::rightsHeaderLabel),
st::rightsHeaderMargin);
const auto addCheckbox = [&](
not_null<Ui::VerticalLayout *> verticalLayout,
const QString &label,
const bool isCheckedOrig)
{
const auto checkView = [&]() -> not_null<Ui::AbstractCheckView *>
{
const auto checkbox = verticalLayout->add(
object_ptr<Ui::Checkbox>(
verticalLayout,
label,
isCheckedOrig,
st::settingsCheckbox),
st::powerSavingButton.padding);
const auto button = Ui::CreateChild<Ui::RippleButton>(
verticalLayout.get(),
st::defaultRippleAnimation);
button->stackUnder(checkbox);
combine(
verticalLayout->widthValue(),
checkbox->geometryValue()
) | start_with_next([=](int w, const QRect &r)
{
button->setGeometry(0, r.y(), w, r.height());
}, button->lifetime());
checkbox->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto checkView = checkbox->checkView();
button->setClickedCallback([=]
{
checkView->setChecked(
!checkView->checked(),
anim::type::normal);
});
return checkView;
}();
checkView->checkedChanges(
) | start_with_next([=](bool checked)
{
}, verticalLayout->lifetime());
return checkView;
};
struct NestedEntry
{
QString checkboxLabel;
bool initial;
std::function<void(bool)> callback;
};
std::vector checkboxes{
NestedEntry{
tr::ayu_MarkReadAfterSend(tr::now), settings->markReadAfterSend, [=](bool enabled)
@@ -545,50 +424,22 @@ void Ayu::SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container)
},
};
auto wrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container));
const auto verticalLayout = wrap->entity();
auto innerChecks = std::vector<not_null<Ui::AbstractCheckView *>>();
for (const auto &entry : checkboxes) {
const auto c = addCheckbox(verticalLayout, entry.checkboxLabel, entry.initial);
c->checkedValue(
) | start_with_next([=](bool enabled)
{
entry.callback(enabled);
}, container->lifetime());
innerChecks.push_back(c);
}
const auto raw = wrap.data();
raw->hide(anim::type::instant);
AddInnerToggle(
container,
st::powerSavingButtonNoIcon,
innerChecks,
raw,
tr::ayu_MarkReadAfterAction(),
false);
container->add(std::move(wrap));
container->widthValue(
) | start_with_next([=](int w)
{
raw->resizeToWidth(w);
}, raw->lifetime());
AddCollapsibleToggle(container, tr::ayu_MarkReadAfterAction(), checkboxes, false);
}
void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
{
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader());
SetupGhostModeToggle(container);
SetupReadAfterActionToggle(container);
AddButton(
AddButtonWithIcon(
container,
tr::ayu_UseScheduledMessages(),
tr::ayu_UseScheduledMessages() | rpl::map([=](QString val)
{
return val + " β";
}),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->useScheduledMessages)
@@ -609,9 +460,12 @@ void Ayu::SetupSpyEssentials(not_null<Ui::VerticalLayout *> container)
AddSubsectionTitle(container, tr::ayu_SpyEssentialsHeader());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_SaveDeletedMessages(),
tr::ayu_SaveDeletedMessages() | rpl::map([=](QString val)
{
return val + " β";
}),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->saveDeletedMessages)
@@ -621,11 +475,11 @@ void Ayu::SetupSpyEssentials(not_null<Ui::VerticalLayout *> container)
return (enabled != settings->saveDeletedMessages);
}) | start_with_next([=](bool enabled)
{
settings->set_keepDeletedMessages(enabled);
settings->set_saveDeletedMessages(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_SaveMessagesHistory(),
st::settingsButtonNoIcon
@@ -637,7 +491,7 @@ void Ayu::SetupSpyEssentials(not_null<Ui::VerticalLayout *> container)
return (enabled != settings->saveMessagesHistory);
}) | start_with_next([=](bool enabled)
{
settings->set_keepMessagesHistory(enabled);
settings->set_saveMessagesHistory(enabled);
AyuSettings::save();
}, container->lifetime());
}
@@ -648,7 +502,7 @@ void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
AddSubsectionTitle(container, tr::ayu_QoLTogglesHeader());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_DisableAds(),
st::settingsButtonNoIcon
@@ -664,7 +518,7 @@ void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_DisableStories(),
st::settingsButtonNoIcon
@@ -680,7 +534,46 @@ void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_SimpleQuotesAndReplies(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->simpleQuotesAndReplies)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->simpleQuotesAndReplies);
}) | start_with_next([=](bool enabled)
{
settings->set_simpleQuotesAndReplies(enabled);
AyuSettings::save();
}, container->lifetime());
std::vector checkboxes = {
NestedEntry{
tr::ayu_CollapseSimilarChannels(tr::now), settings->collapseSimilarChannels, [=](bool enabled)
{
settings->set_collapseSimilarChannels(enabled);
AyuSettings::save();
}
},
NestedEntry{
tr::ayu_HideSimilarChannelsTab(tr::now), settings->hideSimilarChannels, [=](bool enabled)
{
settings->set_hideSimilarChannels(enabled);
AyuSettings::save();
}
}
};
AddCollapsibleToggle(container, tr::ayu_DisableSimilarChannels(), checkboxes, true);
AddSkip(container);
AddDivider(container);
AddSkip(container);
AddButtonWithIcon(
container,
tr::ayu_DisableNotificationsDelay(),
st::settingsButtonNoIcon
@@ -696,7 +589,7 @@ void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_LocalPremium(),
st::settingsButtonNoIcon
@@ -712,7 +605,7 @@ void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_CopyUsernameAsLink(),
st::settingsButtonNoIcon
@@ -733,7 +626,7 @@ void Ayu::SetupAppIcon(not_null<Ui::VerticalLayout *> container)
{
container->add(
object_ptr<IconPicker>(container),
st::settingsSubsectionTitlePadding);
st::settingsCheckboxPadding);
}
void Ayu::SetupCustomization(not_null<Ui::VerticalLayout *> container,
@@ -745,6 +638,9 @@ void Ayu::SetupCustomization(not_null<Ui::VerticalLayout *> container,
SetupAppIcon(container);
AddDivider(container);
AddSkip(container);
auto btn = AddButtonWithLabel(
container,
tr::ayu_DeletedMarkText(),
@@ -769,11 +665,19 @@ void Ayu::SetupCustomization(not_null<Ui::VerticalLayout *> container,
Ui::show(std::move(box));
});
AddSkip(container);
AddDivider(container);
AddSkip(container);
SetupRecentStickersLimitSlider(container);
AddSkip(container);
AddDivider(container);
AddSkip(container);
SetupShowPeerId(container, controller);
AddButton(
AddButtonWithIcon(
container,
tr::ayu_HideAllChats(),
st::settingsButtonNoIcon
@@ -789,23 +693,7 @@ void Ayu::SetupCustomization(not_null<Ui::VerticalLayout *> container,
AyuSettings::save();
}, container->lifetime());
AddButton(
container,
tr::ayu_SimpleQuotesAndReplies(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->simpleQuotesAndReplies)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->simpleQuotesAndReplies);
}) | start_with_next([=](bool enabled)
{
settings->set_simpleQuotesAndReplies(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_SettingsShowMessageSeconds(),
st::settingsButtonNoIcon
@@ -840,7 +728,7 @@ void Ayu::SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
AddSkip(container);
AddSubsectionTitle(container, tr::ayu_DrawerElementsHeader());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_LReadMessages(),
st::settingsButton,
@@ -857,7 +745,7 @@ void Ayu::SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_SReadMessages(),
st::settingsButton,
@@ -874,7 +762,7 @@ void Ayu::SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_GhostModeToggle(),
st::settingsButton,
@@ -891,7 +779,7 @@ void Ayu::SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_StreamerModeToggle(),
st::settingsButton,
@@ -916,7 +804,7 @@ void Ayu::SetupTrayElements(not_null<Ui::VerticalLayout *> container)
AddSkip(container);
AddSubsectionTitle(container, tr::ayu_TrayElementsHeader());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_EnableGhostModeTray(),
st::settingsButtonNoIcon
@@ -932,7 +820,7 @@ void Ayu::SetupTrayElements(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_EnableStreamerModeTray(),
st::settingsButtonNoIcon
@@ -994,21 +882,18 @@ void Ayu::SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> containe
auto settings = &AyuSettings::getInstance();
container->add(
CreateButton(
container,
tr::ayu_SettingsRecentStickersCount(),
st::settingsButtonNoIcon)
);
object_ptr<Button>(container,
tr::ayu_SettingsRecentStickersCount(),
st::settingsButtonNoIcon)
)->setAttribute(Qt::WA_TransparentForMouseEvents);
auto recentStickersLimitSlider = MakeSliderWithLabel(
container,
st::settingsScale,
st::autoDownloadLimitSlider,
st::settingsScaleLabel,
st::normalFont->spacew * 2,
st::settingsScaleLabel.style.font->width("300%"));
container->add(
std::move(recentStickersLimitSlider.widget),
st::settingsScalePadding);
0,
st::settingsScaleLabel.style.font->width("30%"));
container->add(std::move(recentStickersLimitSlider.widget), st::recentStickersLimitPadding);
const auto slider = recentStickersLimitSlider.slider;
const auto label = recentStickersLimitSlider.label;
@@ -1086,7 +971,7 @@ void Ayu::SetupAyuSync(not_null<Ui::VerticalLayout *> container)
auto text = AyuSync::isAgentDownloaded() ? tr::ayu_AyuSyncOpenPreferences() : tr::ayu_AyuSyncDownloadAgent();
AddButton(
AddButtonWithIcon(
container,
text,
st::settingsButtonNoIcon
@@ -1103,7 +988,7 @@ void Ayu::SetupSendConfirmations(not_null<Ui::VerticalLayout *> container)
AddSubsectionTitle(container, tr::ayu_ConfirmationsTitle());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_StickerConfirmation(),
st::settingsButtonNoIcon
@@ -1119,7 +1004,7 @@ void Ayu::SetupSendConfirmations(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_GIFConfirmation(),
st::settingsButtonNoIcon
@@ -1135,7 +1020,7 @@ void Ayu::SetupSendConfirmations(not_null<Ui::VerticalLayout *> container)
AyuSettings::save();
}, container->lifetime());
AddButton(
AddButtonWithIcon(
container,
tr::ayu_VoiceConfirmation(),
st::settingsButtonNoIcon
@@ -7,6 +7,7 @@
#pragma once
#include "base/options.h"
#include "settings/settings_common_session.h"
#include "settings/settings_common.h"
class BoxContent;
@@ -28,12 +29,6 @@ public:
[[nodiscard]] rpl::producer<QString> title() override;
private:
void AddPlatformOption(
not_null<Window::SessionController *> window,
not_null<Ui::VerticalLayout *> container,
base::options::option<bool> &option,
rpl::producer<> resetClicks);
void SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container);
void SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container);
@@ -10,6 +10,7 @@
#include "api/api_text_entities.h"
#include "data/data_channel.h"
#include "lang_auto.h"
#include "apiwrap.h"
#include "data/data_forum.h"
@@ -23,6 +24,7 @@
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_unread_things.h"
#include "data/data_histories.h"
// https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java
std::unordered_set<ID> ayugram_channels = {
@@ -32,6 +34,7 @@ std::unordered_set<ID> ayugram_channels = {
1947958814, // @ayugramfun
1815864846, // @ayugramfcm
};
std::unordered_set<ID> ayugram_devs = {
139303278, // @alexeyzavar
778327202, // @sharapagorg
@@ -53,6 +56,7 @@ std::unordered_set<ID> extera_channels = {
1516526055, // @moexci
1622008530, // @moe_chat
};
std::unordered_set<ID> extera_devs = {
963080346,
1282540315,
@@ -86,7 +90,7 @@ bool accountExists(ID userId)
return userId == 0 || getSession(userId) != nullptr;
}
void dispatchToMainThread(std::function<void()> callback)
void dispatchToMainThread(std::function<void()> callback, int delay)
{
auto timer = new QTimer();
timer->moveToThread(qApp->thread());
@@ -96,7 +100,7 @@ void dispatchToMainThread(std::function<void()> callback)
callback();
timer->deleteLater();
});
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, delay));
}
not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session)
@@ -153,7 +157,8 @@ std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryIt
return std::make_pair(text, std::string(reinterpret_cast<char *>(buff.data()), buff.size()));
}
ID getBareID(not_null<PeerData *> peer) {
ID getBareID(not_null<PeerData *> peer)
{
return peerIsUser(peer->id)
? peerToUser(peer->id).bare
: peerIsChat(peer->id)
@@ -288,7 +293,36 @@ void MarkAsReadThread(not_null<Data::Thread *> thread)
}
}
QString formatTTL(int time) {
void readHistory(not_null<HistoryItem *> message)
{
const auto history = message->history();
const auto tillId = message->id;
history->session().data().histories()
.sendRequest(history, Data::Histories::RequestType::ReadInbox, [=](Fn<void()> finish)
{
if (const auto channel = history->peer->asChannel()) {
return history->session().api().request(MTPchannels_ReadHistory(
channel->inputChannel,
MTP_int(tillId)
)).send();
}
else {
return history->session().api().request(MTPmessages_ReadHistory(
history->peer->input,
MTP_int(tillId)
)).done([=](const MTPmessages_AffectedMessages &result)
{
history->session().api().applyAffectedMessages(history->peer, result);
}).fail([=]
{
}).send();
}
});
}
QString formatTTL(int time)
{
if (time == 0x7FFFFFFF) {
return QString("👀 %1").arg(tr::ayu_OneViewTTL(tr::now));
}
@@ -16,7 +16,7 @@
Main::Session *getSession(ID userId);
bool accountExists(ID userId);
void dispatchToMainThread(std::function<void()> callback);
void dispatchToMainThread(std::function<void()> callback, int delay = 0);
not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session);
ID getDialogIdFromPeer(not_null<PeerData *> peer);
std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem *> item);
@@ -29,4 +29,6 @@ bool isExteraRelated(ID peerId);
void MarkAsReadChatList(not_null<Dialogs::MainList *> list);
void MarkAsReadThread(not_null<Data::Thread *> thread);
void readHistory(not_null<HistoryItem *> message);
QString formatTTL(int time);
+1 -1
View File
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
namespace Ui {
class LinkButton;
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/call_delayed.h"
#include "base/random.h"
#include "ui/boxes/confirm_box.h"
#include "boxes/abstract_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h"
#include "boxes/peers/add_participants_box.h"
+1 -1
View File
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
#include "base/timer.h"
#include "mtproto/sender.h"
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h"
#include "data/data_session.h"
#include "data/data_auto_download.h"
#include "ui/vertical_list.h"
#include "ui/widgets/continuous_sliders.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
@@ -35,7 +36,6 @@ not_null<int64*> AddSizeLimitSlider(
not_null<Ui::VerticalLayout*> container,
const base::flat_map<Type, int64> &values,
int64 defaultValue) {
using namespace Settings;
using Pair = base::flat_map<Type, int64>::value_type;
const auto limits = Ui::CreateChild<rpl::event_stream<int64>>(
@@ -46,7 +46,7 @@ not_null<int64*> AddSizeLimitSlider(
[](Pair pair) { return pair.second; })->second;
const auto startLimit = currentLimit ? currentLimit : defaultValue;
const auto result = Ui::CreateChild<int64>(container.get(), startLimit);
AddButtonWithLabel(
Settings::AddButtonWithLabel(
container,
tr::lng_media_size_limit(),
limits->events_starting_with_copy(
@@ -109,11 +109,11 @@ void AutoDownloadBox::setupContent() {
Type type,
rpl::producer<QString> label) {
const auto value = settings->bytesLimit(_source, type);
AddButton(
content->add(object_ptr<Ui::SettingsButton>(
content,
std::move(label),
st::settingsButtonNoIcon
)->toggleOn(
))->toggleOn(
rpl::single(value > 0)
)->toggledChanges(
) | rpl::start_with_next([=](bool enabled) {
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
namespace Main {
class Session;
+1 -1
View File
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
namespace Ui {
class Radiobutton;
+137 -35
View File
@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/attach/attach_extensions.h"
#include "ui/chat/chat_theme.h"
#include "ui/ui_utility.h"
#include "ui/vertical_list.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "mtproto/sender.h"
@@ -24,7 +25,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h"
#include "boxes/background_preview_box.h"
#include "info/profile/info_profile_icon.h"
#include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h"
#include "ui/widgets/buttons.h"
#include "window/window_session_controller.h"
@@ -129,6 +129,8 @@ private:
int row) const;
void validatePaperThumbnail(const Paper &paper) const;
[[nodiscard]] bool forChannel() const;
const not_null<Main::Session*> _session;
PeerData * const _forPeer = nullptr;
@@ -165,9 +167,9 @@ void BackgroundBox::prepare() {
auto wrap = object_ptr<Ui::VerticalLayout>(this);
const auto container = wrap.data();
Settings::AddSkip(container);
Ui::AddSkip(container);
const auto button = container->add(Settings::CreateButton(
const auto button = container->add(object_ptr<Ui::SettingsButton>(
container,
tr::lng_settings_bg_from_file(),
st::infoProfileButton));
@@ -176,12 +178,29 @@ void BackgroundBox::prepare() {
st::infoIconMediaPhoto,
st::infoSharedMediaButtonIconPosition);
if (forChannel() && _forPeer->wallPaper()) {
const auto remove = container->add(object_ptr<Ui::SettingsButton>(
container,
tr::lng_settings_bg_remove(),
st::infoBlockButton));
object_ptr<Info::Profile::FloatingIcon>(
remove,
st::infoIconDeleteRed,
st::infoSharedMediaButtonIconPosition);
remove->setClickedCallback([=] {
if (const auto resolved = _inner->resolveResetCustomPaper()) {
chosen(*resolved);
}
});
}
button->setClickedCallback([=] {
chooseFromFile();
});
Settings::AddSkip(container);
Settings::AddDivider(container);
Ui::AddSkip(container);
Ui::AddDivider(container);
_inner = container->add(
object_ptr<Inner>(this, &_controller->session(), _forPeer));
@@ -290,6 +309,23 @@ void BackgroundBox::chosen(const Data::WallPaper &paper) {
closeBox();
}
return;
} else if (forChannel()) {
if (_forPeer->wallPaper() && _forPeer->wallPaper()->equals(paper)) {
closeBox();
return;
}
const auto &themes = _forPeer->owner().cloudThemes();
for (const auto &theme : themes.chatThemes()) {
for (const auto &[type, themed] : theme.settings) {
if (themed.paper && themed.paper->equals(paper)) {
_controller->show(Box<BackgroundPreviewBox>(
_controller,
Data::WallPaper::FromEmojiId(theme.emoticon),
BackgroundPreviewArgs{ _forPeer }));
return;
}
}
}
}
_controller->show(Box<BackgroundPreviewBox>(
_controller,
@@ -310,12 +346,16 @@ void BackgroundBox::resetForPeer() {
}).send();
const auto weak = Ui::MakeWeak(this);
_forPeer->setWallPaper(std::nullopt);
_forPeer->setWallPaper({});
if (weak) {
_controller->finishChatThemeEdit(_forPeer);
}
}
bool BackgroundBox::forChannel() const {
return _forPeer && _forPeer->isChannel();
}
void BackgroundBox::removePaper(const Data::WallPaper &paper) {
const auto session = &_controller->session();
const auto remove = [=, weak = Ui::MakeWeak(this)](Fn<void()> &&close) {
@@ -345,9 +385,16 @@ BackgroundBox::Inner::Inner(
, _session(session)
, _forPeer(forPeer)
, _api(&_session->mtp())
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [=] { update(); })) {
, _check(
std::make_unique<Ui::RoundCheckbox>(
st::overviewCheck,
[=] { update(); })) {
_check->setChecked(true, anim::type::instant);
resize(st::boxWideWidth, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
resize(
st::boxWideWidth,
(2 * (st::backgroundSize.height() + st::backgroundPadding)
+ st::backgroundPadding));
Window::Theme::IsNightModeValue(
) | rpl::start_with_next([=] {
updatePapers();
@@ -364,21 +411,31 @@ BackgroundBox::Inner::Inner(
_check->invalidateCache();
}, lifetime());
using Update = Window::Theme::BackgroundUpdate;
Window::Theme::Background()->updates(
) | rpl::start_with_next([=](const Update &update) {
if (update.type == Update::Type::New) {
sortPapers();
requestPapers();
this->update();
}
}, lifetime());
if (forChannel()) {
_session->data().cloudThemes().chatThemesUpdated(
) | rpl::start_with_next([=] {
updatePapers();
}, lifetime());
} else {
using Update = Window::Theme::BackgroundUpdate;
Window::Theme::Background()->updates(
) | rpl::start_with_next([=](const Update &update) {
if (update.type == Update::Type::New) {
sortPapers();
requestPapers();
this->update();
}
}, lifetime());
}
setMouseTracking(true);
}
void BackgroundBox::Inner::requestPapers() {
if (forChannel()) {
_session->data().cloudThemes().refreshChatThemes();
return;
}
_api.request(MTPaccount_GetWallPapers(
MTP_long(_session->data().wallpapersHash())
)).done([=](const MTPaccount_WallPapers &result) {
@@ -395,7 +452,7 @@ auto BackgroundBox::Inner::resolveResetCustomPaper() const
}
const auto nonCustom = Window::Theme::Background()->paper();
const auto themeEmoji = _forPeer->themeEmoji();
if (themeEmoji.isEmpty()) {
if (forChannel() || themeEmoji.isEmpty()) {
return nonCustom;
}
const auto &themes = _forPeer->owner().cloudThemes();
@@ -443,6 +500,8 @@ void BackgroundBox::Inner::pushCustomPapers() {
}
void BackgroundBox::Inner::sortPapers() {
Expects(!forChannel());
const auto currentCustom = _forPeer ? _forPeer->wallPaper() : nullptr;
_currentId = currentCustom
? currentCustom->id()
@@ -472,23 +531,60 @@ void BackgroundBox::Inner::sortPapers() {
}
void BackgroundBox::Inner::updatePapers() {
if (_session->data().wallpapers().empty()) {
return;
if (forChannel()) {
if (_session->data().cloudThemes().chatThemes().empty()) {
return;
}
} else {
if (_session->data().wallpapers().empty()) {
return;
}
}
_over = _overDown = Selection();
_papers = _session->data().wallpapers(
) | ranges::views::filter([&](const Data::WallPaper &paper) {
return (!paper.isPattern() || !paper.backgroundColors().empty())
&& (!_forPeer
|| (!Data::IsDefaultWallPaper(paper)
&& (Data::IsCloudWallPaper(paper)
|| Data::IsCustomWallPaper(paper))));
}) | ranges::views::transform([](const Data::WallPaper &paper) {
return Paper{ paper };
}) | ranges::to_vector;
pushCustomPapers();
sortPapers();
const auto was = base::take(_papers);
if (forChannel()) {
const auto now = _forPeer->wallPaper();
const auto &list = _session->data().cloudThemes().chatThemes();
if (list.empty()) {
return;
}
using Type = Data::CloudThemeType;
const auto type = Window::Theme::IsNightMode()
? Type::Dark
: Type::Light;
_papers.reserve(list.size() + 1);
const auto nowEmojiId = now ? now->emojiId() : QString();
if (!now || !now->emojiId().isEmpty()) {
_papers.push_back({ Window::Theme::Background()->paper() });
_currentId = _papers.back().data.id();
} else {
_papers.push_back({ *now });
_currentId = now->id();
}
for (const auto &theme : list) {
const auto i = theme.settings.find(type);
if (i != end(theme.settings) && i->second.paper) {
_papers.push_back({ *i->second.paper });
if (nowEmojiId == theme.emoticon) {
_currentId = _papers.back().data.id();
}
}
}
} else {
_papers = _session->data().wallpapers(
) | ranges::views::filter([&](const Data::WallPaper &paper) {
return (!paper.isPattern() || !paper.backgroundColors().empty())
&& (!_forPeer
|| (!Data::IsDefaultWallPaper(paper)
&& (Data::IsCloudWallPaper(paper)
|| Data::IsCustomWallPaper(paper))));
}) | ranges::views::transform([](const Data::WallPaper &paper) {
return Paper{ paper };
}) | ranges::to_vector;
pushCustomPapers();
sortPapers();
}
resizeToContentAndPreload();
}
@@ -587,6 +683,10 @@ void BackgroundBox::Inner::validatePaperThumbnail(
paper.thumbnail.setDevicePixelRatio(cRetinaFactor());
}
bool BackgroundBox::Inner::forChannel() const {
return _forPeer && _forPeer->isChannel();
}
void BackgroundBox::Inner::paintPaper(
QPainter &p,
const Paper &paper,
@@ -604,7 +704,8 @@ void BackgroundBox::Inner::paintPaper(
const auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size;
const auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size;
_check->paint(p, checkLeft, checkTop, width());
} else if (Data::IsCloudWallPaper(paper.data)
} else if (!forChannel()
&& Data::IsCloudWallPaper(paper.data)
&& !Data::IsDefaultWallPaper(paper.data)
&& !Data::IsLegacy2DefaultWallPaper(paper.data)
&& !Data::IsLegacy3DefaultWallPaper(paper.data)
@@ -642,7 +743,8 @@ void BackgroundBox::Inner::mouseMoveEvent(QMouseEvent *e) {
- st::stickerPanDeleteIconBg.width();
const auto deleteBottom = row * (height + skip) + skip
+ st::stickerPanDeleteIconBg.height();
const auto inDelete = (x >= deleteLeft)
const auto inDelete = !forChannel()
&& (x >= deleteLeft)
&& (y < deleteBottom)
&& Data::IsCloudWallPaper(data)
&& !Data::IsDefaultWallPaper(data)
+2 -1
View File
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
class PeerData;
@@ -38,6 +38,7 @@ private:
const Data::WallPaper &paper) const;
void removePaper(const Data::WallPaper &paper);
void resetForPeer();
[[nodiscard]] bool forChannel() const;
void chooseFromFile();
@@ -7,10 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/background_preview_box.h"
#include "base/unixtime.h"
#include "boxes/peers/edit_peer_color_box.h"
#include "boxes/premium_preview_box.h"
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "window/themes/window_theme.h"
#include "ui/boxes/confirm_box.h"
#include "ui/boxes/boost_box.h"
#include "ui/controls/chat_service_checkbox.h"
#include "ui/chat/chat_theme.h"
#include "ui/chat/chat_style.h"
@@ -18,13 +22,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/continuous_sliders.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
#include "ui/ui_utility.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "history/view/history_view_message.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "data/data_session.h"
@@ -33,17 +41,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h"
#include "data/data_document_resolver.h"
#include "data/data_file_origin.h"
#include "base/unixtime.h"
#include "boxes/background_preview_box.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
#include "settings/settings_common.h"
#include "data/data_peer_values.h"
#include "settings/settings_premium.h"
#include "storage/file_upload.h"
#include "storage/localimageloader.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
#include "styles/style_chat.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_settings.h"
#include <QtGui/QClipboard>
#include <QtGui/QGuiApplication>
@@ -157,6 +163,25 @@ constexpr auto kDefaultDimming = 50;
return result;
}
[[nodiscard]] Data::WallPaper Resolve(
not_null<Main::Session*> session,
const Data::WallPaper &paper,
bool dark) {
if (paper.emojiId().isEmpty()) {
return paper;
}
const auto &themes = session->data().cloudThemes();
if (const auto theme = themes.themeForEmoji(paper.emojiId())) {
using Type = Data::CloudThemeType;
const auto type = dark ? Type::Dark : Type::Light;
const auto i = theme->settings.find(type);
if (i != end(theme->settings) && i->second.paper) {
return *i->second.paper;
}
}
return paper;
}
} // namespace
struct BackgroundPreviewBox::OverridenStyle {
@@ -194,15 +219,17 @@ BackgroundPreviewBox::BackgroundPreviewBox(
? tr::lng_background_apply2(tr::now)
: tr::lng_background_text2(tr::now)),
true))
, _paper(paper)
, _paperEmojiId(paper.emojiId())
, _paper(
Resolve(&controller->session(), paper, Window::Theme::IsNightMode()))
, _media(_paper.document() ? _paper.document()->createMediaView() : nullptr)
, _radial([=](crl::time now) { radialAnimationCallback(now); })
, _appNightMode(Window::Theme::IsNightModeValue())
, _boxDarkMode(_appNightMode.current())
, _dimmingIntensity(std::clamp(paper.patternIntensity(), 0, 100))
, _dimmingIntensity(std::clamp(_paper.patternIntensity(), 0, 100))
, _dimmed(_forPeer
&& (paper.document() || paper.localThumbnail())
&& !paper.isPattern()) {
&& (_paper.document() || _paper.localThumbnail())
&& !_paper.isPattern()) {
if (_media) {
_media->thumbnailWanted(_paper.fileOrigin());
}
@@ -242,7 +269,36 @@ BackgroundPreviewBox::BackgroundPreviewBox(
BackgroundPreviewBox::~BackgroundPreviewBox() = default;
void BackgroundPreviewBox::recreate(bool dark) {
_paper = Resolve(
&_controller->session(),
Data::WallPaper::FromEmojiId(_paperEmojiId),
dark);
_media = _paper.document()
? _paper.document()->createMediaView()
: nullptr;
if (_media) {
_media->thumbnailWanted(_paper.fileOrigin());
}
_full = QImage();
_generated = _scaled = _blurred = _fadeOutThumbnail = QPixmap();
_generating = {};
generateBackground();
_paper.loadDocument();
if (const auto document = _paper.document()) {
if (document->loading()) {
_radial.start(_media->progress());
}
}
checkLoadedDocument();
updateServiceBg(_paper.backgroundColors());
update();
}
void BackgroundPreviewBox::applyDarkMode(bool dark) {
if (!_paperEmojiId.isEmpty()) {
recreate(dark);
}
const auto equals = (dark == Window::Theme::IsNightMode());
const auto &palette = (dark ? _darkPalette : _lightPalette);
if (!equals && !palette) {
@@ -293,10 +349,10 @@ void BackgroundPreviewBox::createDimmingSlider(bool dark) {
const auto equals = (dark == Window::Theme::IsNightMode());
const auto inner = Ui::CreateChild<Ui::VerticalLayout>(_dimmingContent);
inner->show();
Settings::AddSubsectionTitle(
Ui::AddSubsectionTitle(
inner,
tr::lng_background_dimming(),
style::margins(0, st::settingsSectionSkip, 0, 0),
style::margins(0, st::defaultVerticalListSkip, 0, 0),
equals ? nullptr : dark ? &_dark->subtitle : &_light->subtitle);
_dimmingSlider = inner->add(
object_ptr<Ui::MediaSlider>(
@@ -378,7 +434,7 @@ auto BackgroundPreviewBox::prepareOverridenStyle(bool dark)
.box = st::defaultBox,
.toggle = toggle,
.slider = st::defaultContinuousSlider,
.subtitle = st::settingsSubsectionTitle,
.subtitle = st::defaultSubsectionTitle,
};
result.box.button.textFg = p->lightButtonFg();
result.box.button.textFgOver = p->lightButtonFgOver();
@@ -408,6 +464,10 @@ auto BackgroundPreviewBox::prepareOverridenStyle(bool dark)
return result;
}
bool BackgroundPreviewBox::forChannel() const {
return _forPeer && _forPeer->isChannel();
}
void BackgroundPreviewBox::generateBackground() {
if (_paper.backgroundColors().empty()) {
return;
@@ -433,7 +493,9 @@ void BackgroundPreviewBox::resetTitle() {
void BackgroundPreviewBox::rebuildButtons(bool dark) {
clearButtons();
addButton(_forPeer
addButton(forChannel()
? tr::lng_background_apply_channel()
: _forPeer
? tr::lng_background_apply_button()
: tr::lng_settings_apply(), [=] { apply(); });
addButton(tr::lng_cancel(), [=] { closeBox(); });
@@ -510,6 +572,10 @@ void BackgroundPreviewBox::recreateBlurCheckbox() {
}, _blur->lifetime());
_blur->setDisabled(_paper.document() && _full.isNull());
if (_forBothOverlay) {
_forBothOverlay->raise();
}
}
void BackgroundPreviewBox::apply() {
@@ -520,7 +586,7 @@ void BackgroundPreviewBox::apply() {
}
}
void BackgroundPreviewBox::uploadForPeer() {
void BackgroundPreviewBox::uploadForPeer(bool both) {
Expects(_forPeer != nullptr);
if (_uploadId) {
@@ -579,7 +645,7 @@ void BackgroundPreviewBox::uploadForPeer() {
"Got wallPaperNoFile after account.UploadWallPaper."));
});
if (const auto paper = Data::WallPaper::Create(session, result)) {
setExistingForPeer(*paper);
setExistingForPeer(*paper, both);
}
}).send();
}, _uploadLifetime);
@@ -588,7 +654,9 @@ void BackgroundPreviewBox::uploadForPeer() {
_radial.start(_uploadProgress);
}
void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
void BackgroundPreviewBox::setExistingForPeer(
const Data::WallPaper &paper,
bool both) {
Expects(_forPeer != nullptr);
if (const auto already = _forPeer->wallPaper()) {
@@ -602,6 +670,7 @@ void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
api->request(MTPmessages_SetChatWallPaper(
MTP_flags((_fromMessageId ? Flag::f_id : Flag())
| (_fromMessageId ? Flag() : Flag::f_wallpaper)
| (both ? Flag::f_for_both : Flag())
| Flag::f_settings),
_forPeer->input,
paper.mtpInput(&_controller->session()),
@@ -615,13 +684,155 @@ void BackgroundPreviewBox::setExistingForPeer(const Data::WallPaper &paper) {
_controller->finishChatThemeEdit(_forPeer);
}
void BackgroundPreviewBox::checkLevelForChannel() {
Expects(forChannel());
const auto show = _controller->uiShow();
_forPeerLevelCheck = true;
const auto weak = Ui::MakeWeak(this);
CheckBoostLevel(show, _forPeer, [=](int level) {
if (!weak) {
return std::optional<Ui::AskBoostReason>();
}
const auto appConfig = &_forPeer->session().account().appConfig();
const auto defaultRequired = appConfig->get<int>(
"channel_wallpaper_level_min",
9);
const auto customRequired = appConfig->get<int>(
"channel_custom_wallpaper_level_min",
10);
const auto required = _paperEmojiId.isEmpty()
? customRequired
: defaultRequired;
if (level >= required) {
applyForPeer(false);
return std::optional<Ui::AskBoostReason>();
}
return std::make_optional(Ui::AskBoostReason{
Ui::AskBoostWallpaper{ required }
});
}, [=] { _forPeerLevelCheck = false; });
}
void BackgroundPreviewBox::applyForPeer() {
Expects(_forPeer != nullptr);
if (Data::IsCustomWallPaper(_paper)) {
uploadForPeer();
if (!Data::IsCustomWallPaper(_paper)) {
if (const auto already = _forPeer->wallPaper()) {
if (already->equals(_paper)) {
_controller->finishChatThemeEdit(_forPeer);
return;
}
}
}
if (forChannel()) {
checkLevelForChannel();
return;
} else if (_fromMessageId || !_forPeer->session().premiumPossible()) {
applyForPeer(false);
return;
} else if (_forBothOverlay) {
return;
}
const auto size = this->size() * style::DevicePixelRatio();
const auto bg = Images::DitherImage(
Images::BlurLargeImage(
Ui::GrabWidgetToImage(this).scaled(
size / style::ConvertScale(4),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation),
24).scaled(
size,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
_forBothOverlay = std::make_unique<Ui::FadeWrap<>>(
this,
object_ptr<Ui::RpWidget>(this));
const auto overlay = _forBothOverlay->entity();
sizeValue() | rpl::start_with_next([=](QSize size) {
_forBothOverlay->setGeometry({ QPoint(), size });
overlay->setGeometry({ QPoint(), size });
}, _forBothOverlay->lifetime());
overlay->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(overlay);
p.drawImage(0, 0, bg);
p.fillRect(clip, QColor(0, 0, 0, 64));
}, overlay->lifetime());
using namespace Ui;
const auto forMe = CreateChild<RoundButton>(
overlay,
tr::lng_background_apply_me(),
st::backgroundConfirm);
forMe->setClickedCallback([=] {
applyForPeer(false);
});
using namespace rpl::mappers;
const auto forBoth = ::Settings::CreateLockedButton(
overlay,
tr::lng_background_apply_both(
lt_user,
rpl::single(_forPeer->shortName())),
st::backgroundConfirm,
Data::AmPremiumValue(&_forPeer->session()) | rpl::map(!_1));
forBoth->setClickedCallback([=] {
if (_forPeer->session().premium()) {
applyForPeer(true);
} else {
ShowPremiumPreviewBox(
_controller->uiShow(),
PremiumPreview::Wallpapers);
}
});
const auto cancel = CreateChild<RoundButton>(
overlay,
tr::lng_cancel(),
st::backgroundConfirmCancel);
cancel->setClickedCallback([=] {
const auto raw = _forBothOverlay.release();
raw->shownValue() | rpl::filter(
!rpl::mappers::_1
) | rpl::take(1) | rpl::start_with_next(crl::guard(raw, [=] {
delete raw;
}), raw->lifetime());
raw->toggle(false, anim::type::normal);
});
forMe->setTextTransform(RoundButton::TextTransform::NoTransform);
forBoth->setTextTransform(RoundButton::TextTransform::NoTransform);
cancel->setTextTransform(RoundButton::TextTransform::NoTransform);
overlay->sizeValue(
) | rpl::start_with_next([=](QSize size) {
const auto padding = st::backgroundConfirmPadding;
const auto width = size.width()
- padding.left()
- padding.right();
const auto height = cancel->height();
auto top = size.height() - padding.bottom() - height;
cancel->setGeometry(padding.left(), top, width, height);
top -= height + padding.top();
forBoth->setGeometry(padding.left(), top, width, height);
top -= height + padding.top();
forMe->setGeometry(padding.left(), top, width, height);
}, _forBothOverlay->lifetime());
_forBothOverlay->hide(anim::type::instant);
_forBothOverlay->show(anim::type::normal);
}
void BackgroundPreviewBox::applyForPeer(bool both) {
using namespace Data;
if (forChannel() && !_paperEmojiId.isEmpty()) {
setExistingForPeer(WallPaper::FromEmojiId(_paperEmojiId), both);
} else if (IsCustomWallPaper(_paper)) {
uploadForPeer(both);
} else {
setExistingForPeer(_paper);
setExistingForPeer(_paper, both);
}
}
@@ -739,7 +950,7 @@ int BackgroundPreviewBox::textsTop() const {
- st::historyPaddingBottom
- (_service ? _service->height() : 0)
- _text1->height()
- _text2->height();
- (forChannel() ? _text2->height() : 0);
}
QRect BackgroundPreviewBox::radialRect() const {
@@ -769,10 +980,11 @@ void BackgroundPreviewBox::paintTexts(Painter &p, crl::time ms) {
context.outbg = _text1->hasOutLayout();
_text1->draw(p, context);
p.translate(0, height1);
context.outbg = _text2->hasOutLayout();
_text2->draw(p, context);
p.translate(0, height2);
if (!forChannel()) {
context.outbg = _text2->hasOutLayout();
_text2->draw(p, context);
p.translate(0, height2);
}
}
void BackgroundPreviewBox::radialAnimationCallback(crl::time now) {
@@ -872,7 +1084,9 @@ void BackgroundPreviewBox::updateServiceBg(const std::vector<QColor> &bg) {
_service = GenerateServiceItem(
delegate(),
_serviceHistory,
((_forPeer && !_fromMessageId)
(forChannel()
? tr::lng_background_other_channel(tr::now)
: (_forPeer && !_fromMessageId)
? tr::lng_background_other_info(
tr::now,
lt_user,
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
#include "base/binary_guard.h"
#include "history/admin_log/history_admin_log_item.h"
#include "history/view/history_view_element.h"
@@ -29,6 +29,8 @@ class ChatStyle;
class MediaSlider;
template <typename Widget>
class SlideWrap;
template <typename Widget>
class FadeWrap;
} // namespace Ui
struct BackgroundPreviewArgs {
@@ -66,9 +68,10 @@ private:
void apply();
void applyForPeer();
void applyForPeer(bool both);
void applyForEveryone();
void uploadForPeer();
void setExistingForPeer(const Data::WallPaper &paper);
void uploadForPeer(bool both);
void setExistingForPeer(const Data::WallPaper &paper, bool both);
void share();
void radialAnimationCallback(crl::time now);
QRect radialRect() const;
@@ -91,18 +94,24 @@ private:
void applyDarkMode(bool dark);
[[nodiscard]] OverridenStyle prepareOverridenStyle(bool dark);
[[nodiscard]] bool forChannel() const;
void checkLevelForChannel();
void recreate(bool dark);
void resetTitle();
void rebuildButtons(bool dark);
void createDimmingSlider(bool dark);
const not_null<Window::SessionController*> _controller;
PeerData * const _forPeer = nullptr;
bool _forPeerLevelCheck = false;
FullMsgId _fromMessageId;
std::unique_ptr<Ui::ChatStyle> _chatStyle;
const not_null<History*> _serviceHistory;
AdminLog::OwnedItem _service;
AdminLog::OwnedItem _text1;
AdminLog::OwnedItem _text2;
QString _paperEmojiId;
Data::WallPaper _paper;
std::shared_ptr<Data::DocumentMedia> _media;
QImage _full;
@@ -131,6 +140,8 @@ private:
float64 _uploadProgress = 0.;
rpl::lifetime _uploadLifetime;
std::unique_ptr<Ui::FadeWrap<Ui::RpWidget>> _forBothOverlay;
rpl::variable<QColor> _paletteServiceBg;
rpl::lifetime _serviceBgLifetime;
+29
View File
@@ -753,7 +753,28 @@ backgroundCheck: ServiceCheck {
color: msgServiceFg;
duration: 200;
}
backgroundConfirmPadding: margins(24px, 16px, 24px, 16px);
backgroundConfirm: RoundButton(defaultActiveButton) {
height: 44px;
textTop: 12px;
font: font(13px semibold);
}
backgroundConfirmCancel: RoundButton(backgroundConfirm) {
textFg: mediaviewSaveMsgFg;
textFgOver: mediaviewSaveMsgFg;
numbersTextFg: mediaviewSaveMsgFg;
numbersTextFgOver: mediaviewSaveMsgFg;
textBg: shadowFg;
textBgOver: shadowFg;
height: 44px;
textTop: 12px;
font: font(13px semibold);
ripple: RippleAnimation(defaultRippleAnimation) {
color: shadowFg;
}
}
urlAuthCheckbox: Checkbox(defaultBoxCheckbox) {
width: 240px;
}
@@ -906,6 +927,14 @@ sponsoredUrlButton: RoundButton(defaultActiveButton) {
}
}
requestPeerRestriction: FlatLabel(defaultFlatLabel) {
minWidth: 240px;
textFg: membersAboutLimitFg;
style: TextStyle(boxTextStyle) {
lineHeight: 22px;
}
}
requestsBoxItem: PeerListItem(peerListBoxItem) {
height: 99px;
button: OutlineButton(defaultPeerListButton) {
+1 -1
View File
@@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h"
#include "base/object_ptr.h"
#include "core/core_settings.h"
#include "core/core_settings_proxy.h"
#include "mtproto/connection_abstract.h"
#include "mtproto/mtproto_proxy_data.h"
+15 -16
View File
@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "main/main_session.h"
#include "core/application.h"
#include "core/core_settings.h"
@@ -26,7 +27,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/message_field.h"
#include "menu/menu_send.h"
#include "history/view/history_view_schedule_box.h"
#include "settings/settings_common.h"
#include "base/unique_qptr.h"
#include "base/event_filter.h"
#include "base/call_delayed.h"
@@ -34,7 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_settings.h"
namespace {
@@ -790,7 +789,7 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
using namespace Settings;
const auto session = &_controller->session();
AddSubsectionTitle(container, tr::lng_polls_create_question());
Ui::AddSubsectionTitle(container, tr::lng_polls_create_question());
const auto question = container->add(
object_ptr<Ui::InputField>(
container,
@@ -818,9 +817,9 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
- st::createPollWarningPosition.x()),
(geometry.y()
- st::createPollFieldPadding.top()
- st::settingsSubsectionTitlePadding.bottom()
- st::settingsSubsectionTitle.style.font->height
+ st::settingsSubsectionTitle.style.font->ascent
- st::defaultSubsectionTitlePadding.bottom()
- st::defaultSubsectionTitle.style.font->height
+ st::defaultSubsectionTitle.style.font->ascent
- st::createPollWarning.style.font->ascent),
geometry.width());
}, warning->lifetime());
@@ -841,8 +840,8 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
const auto inner = outer->entity();
const auto session = &_controller->session();
AddSkip(inner);
AddSubsectionTitle(inner, tr::lng_polls_solution_title());
Ui::AddSkip(inner);
Ui::AddSubsectionTitle(inner, tr::lng_polls_solution_title());
const auto solution = inner->add(
object_ptr<Ui::InputField>(
inner,
@@ -875,9 +874,9 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
- st::createPollWarningPosition.x()),
(geometry.y()
- st::createPollFieldPadding.top()
- st::settingsSubsectionTitlePadding.bottom()
- st::settingsSubsectionTitle.style.font->height
+ st::settingsSubsectionTitle.style.font->ascent
- st::defaultSubsectionTitlePadding.bottom()
- st::defaultSubsectionTitle.style.font->height
+ st::defaultSubsectionTitle.style.font->ascent
- st::createPollWarning.style.font->ascent),
geometry.width());
}, warning->lifetime());
@@ -902,13 +901,13 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
const auto container = result.data();
const auto question = setupQuestion(container);
AddDivider(container);
AddSkip(container);
Ui::AddDivider(container);
Ui::AddSkip(container);
container->add(
object_ptr<Ui::FlatLabel>(
container,
tr::lng_polls_create_options(),
st::settingsSubsectionTitle),
st::defaultSubsectionTitle),
st::createPollFieldTitlePadding);
const auto options = lifetime().make_state<Options>(
getDelegate()->outerContainer(),
@@ -939,8 +938,8 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
options->focusFirst();
}, question->lifetime());
AddSkip(container);
AddSubsectionTitle(container, tr::lng_polls_create_settings());
Ui::AddSkip(container);
Ui::AddSubsectionTitle(container, tr::lng_polls_create_settings());
const auto anonymous = (!(_disabled & PollData::Flag::PublicVotes))
? container->add(
+1 -1
View File
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
#include "api/api_common.h"
#include "data/data_poll.h"
#include "base/flags.h"
@@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#ifndef TDESKTOP_DISABLE_SPELLCHECK
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
namespace Main {
class Session;
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/abstract_box.h"
#include "ui/layers/box_content.h"
#include "ui/chat/attach/attach_prepare.h"
namespace ChatHelpers {
@@ -13,9 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/vertical_list.h"
#include "history/history.h"
#include "boxes/peer_list_controllers.h"
#include "settings/settings_common.h"
#include "settings/settings_privacy_security.h"
#include "calls/calls_instance.h"
#include "base/binary_guard.h"
@@ -233,7 +233,7 @@ Ui::FlatLabel *EditPrivacyBox::addLabel(
object_ptr<Ui::DividerLabel>(
container,
std::move(label),
st::settingsDividerLabelPadding),
st::defaultBoxDividerLabelPadding),
{ 0, topSkip, 0, 0 });
return result;
}
@@ -294,7 +294,7 @@ void EditPrivacyBox::setupContent() {
const auto button = content->add(
object_ptr<Ui::SlideWrap<Button>>(
content,
CreateButton(
object_ptr<Button>(
content,
rpl::duplicate(text),
st::settingsButtonNoIcon)));
@@ -321,7 +321,7 @@ void EditPrivacyBox::setupContent() {
content->add(std::move(above));
}
AddSubsectionTitle(
Ui::AddSubsectionTitle(
content,
_controller->optionsTitleKey(),
{ 0, st::settingsPrivacySkipTop, 0, 0 });
@@ -332,7 +332,7 @@ void EditPrivacyBox::setupContent() {
const auto warning = addLabelOrDivider(
content,
_controller->warning(),
st::settingsSectionSkip + st::settingsPrivacySkipTop);
st::defaultVerticalListSkip + st::settingsPrivacySkipTop);
if (warning) {
_controller->prepareWarningLabel(warning);
}
@@ -345,8 +345,8 @@ void EditPrivacyBox::setupContent() {
content->add(std::move(middle));
}
AddSkip(content);
AddSubsectionTitle(
Ui::AddSkip(content);
Ui::AddSubsectionTitle(
content,
tr::lng_edit_privacy_exceptions(),
{ 0, st::settingsPrivacySkipTop, 0, 0 });
@@ -355,7 +355,7 @@ void EditPrivacyBox::setupContent() {
addLabel(
content,
_controller->exceptionsDescription() | Ui::Text::ToWithEntities(),
st::settingsSectionSkip);
st::defaultVerticalListSkip);
if (auto below = _controller->setupBelowWidget(_window, content)) {
content->add(std::move(below));
@@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/filter_icons.h"
#include "ui/filter_icon_panel.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
#include "data/data_channel.h"
#include "data/data_chat_filters.h"
#include "data/data_peer.h"
@@ -515,7 +516,7 @@ not_null<Ui::SettingsButton*> AddToggledButton(
const auto toggled = container->add(
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
container,
CreateButton(
CreateButtonWithIcon(
container,
std::move(text),
st,
@@ -658,12 +659,12 @@ void EditFilterBox(
name->setFocusFast();
});
AddSkip(content);
AddDivider(content);
AddSkip(content);
AddSubsectionTitle(content, tr::lng_filters_include());
Ui::AddSkip(content);
Ui::AddDivider(content);
Ui::AddSkip(content);
Ui::AddSubsectionTitle(content, tr::lng_filters_include());
const auto includeAdd = AddButton(
const auto includeAdd = AddButtonWithIcon(
content,
tr::lng_filters_add_chats(),
st::settingsButtonActive,
@@ -676,9 +677,9 @@ void EditFilterBox(
kTypes,
&Data::ChatFilter::always);
AddSkip(content);
AddDividerText(content, tr::lng_filters_include_about());
AddSkip(content);
Ui::AddSkip(content);
Ui::AddDividerText(content, tr::lng_filters_include_about());
Ui::AddSkip(content);
auto excludeWrap = content->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
@@ -688,9 +689,9 @@ void EditFilterBox(
excludeWrap->toggleOn(state->chatlist.value() | rpl::map(!_1));
const auto excludeInner = excludeWrap->entity();
AddSubsectionTitle(excludeInner, tr::lng_filters_exclude());
Ui::AddSubsectionTitle(excludeInner, tr::lng_filters_exclude());
const auto excludeAdd = AddButton(
const auto excludeAdd = AddButtonWithIcon(
excludeInner,
tr::lng_filters_remove_chats(),
st::settingsButtonActive,
@@ -703,9 +704,9 @@ void EditFilterBox(
kExcludeTypes,
&Data::ChatFilter::never);
AddSkip(excludeInner);
AddDividerText(excludeInner, tr::lng_filters_exclude_about());
AddSkip(excludeInner);
Ui::AddSkip(excludeInner);
Ui::AddDividerText(excludeInner, tr::lng_filters_exclude_about());
Ui::AddSkip(excludeInner);
const auto collect = [=]() -> std::optional<Data::ChatFilter> {
const auto title = name->getLastText().trimmed();
@@ -726,7 +727,7 @@ void EditFilterBox(
return rules.withTitle(title);
};
AddSubsectionTitle(
Ui::AddSubsectionTitle(
content,
rpl::conditional(
state->hasLinks.value(),
@@ -806,8 +807,8 @@ void EditFilterBox(
}));
}));
}, createLink->lifetime());
AddSkip(content);
AddDividerText(
Ui::AddSkip(content);
Ui::AddDividerText(
content,
rpl::conditional(
state->hasLinks.value(),
@@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
#include "window/window_session_controller.h"
#include "styles/style_info.h"
#include "styles/style_layers.h"
@@ -140,12 +141,12 @@ void ChatFilterLinkBox(
tr::lng_group_invite_label_header(),
data.title),
style::margins(
st::settingsSubsectionTitlePadding.left(),
st::settingsSectionSkip,
st::settingsSubsectionTitlePadding.right(),
st::settingsSectionSkip * 2));
st::defaultSubsectionTitlePadding.left(),
st::defaultVerticalListSkip,
st::defaultSubsectionTitlePadding.right(),
st::defaultVerticalListSkip * 2));
labelField->setMaxLength(kMaxLinkTitleLength);
Settings::AddDivider(container);
AddDivider(container);
box->setFocusCallback([=] {
labelField->setFocusFast();
@@ -616,7 +617,7 @@ void LinkController::addLinkBlock(not_null<Ui::VerticalLayout*> container) {
&st::menuIconDelete);
return result;
};
AddSubsectionTitle(
Ui::AddSubsectionTitle(
container,
tr::lng_filters_link_subtitle(),
st::filterLinkSubsectionTitlePadding);
@@ -637,11 +638,11 @@ void LinkController::addLinkBlock(not_null<Ui::VerticalLayout*> container) {
AddCopyShareLinkButtons(container, copyLink, shareLink);
AddSkip(container, st::inviteLinkJoinedRowPadding.bottom() * 2);
Ui::AddSkip(container, st::inviteLinkJoinedRowPadding.bottom() * 2);
AddSkip(container);
Ui::AddSkip(container);
AddDivider(container);
Ui::AddDivider(container);
}
void LinkController::prepare() {
@@ -788,7 +789,7 @@ void LinkController::setupBelowWidget() {
? tr::lng_filters_link_chats_no_about()
: tr::lng_filters_link_chats_about()),
st::boxDividerLabel),
st::settingsDividerLabelPadding));
st::defaultBoxDividerLabelPadding));
}
Main::Session &LinkController::session() const {
@@ -1152,7 +1153,7 @@ void AddFilterSubtitleWithToggles(
font->width(tr::lng_filters_by_link_select(tr::now)),
font->width(tr::lng_filters_by_link_deselect(tr::now))));
}
const auto title = Settings::AddSubsectionTitle(
const auto title = Ui::AddSubsectionTitle(
container,
std::move(text),
padding);
+638 -45
View File
@@ -12,18 +12,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "base/unixtime.h"
#include "base/weak_ptr.h"
#include "boxes/peer_list_controllers.h" // ContactsBoxController.
#include "boxes/peers/prepare_short_info_box.h"
#include "boxes/peers/replace_boost_box.h" // BoostsForGift.
#include "boxes/premium_preview_box.h" // ShowPremiumPreviewBox.
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "data/data_boosts.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
#include "data/data_media_types.h" // Data::Giveaway
#include "data/data_media_types.h" // Data::GiveawayStart.
#include "data/data_peer_values.h" // Data::PeerPremiumValue.
#include "data/data_session.h"
#include "data/data_subscription_option.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
#include "info/boosts/giveaway/boost_badge.h" // InfiniteRadialAnimationWidget.
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "mainwidget.h"
#include "payments/payments_checkout_process.h"
#include "payments/payments_form.h"
#include "settings/settings_premium.h"
#include "ui/basic_click_handlers.h" // UrlClickHandler::Open.
#include "ui/boxes/boost_box.h" // StartFireworks.
@@ -33,11 +41,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/premium_top_bar.h"
#include "ui/effects/spoiler_mess.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/vertical_list.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/gradient_round_button.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/wrap/table_layout.h"
#include "window/window_peer_menu.h" // ShowChooseRecipientBox.
#include "window/window_session_controller.h"
@@ -52,6 +63,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace {
constexpr auto kDiscountDivider = 5.;
constexpr auto kUserpicsMax = size_t(3);
using GiftOption = Data::SubscriptionOption;
using GiftOptions = Data::SubscriptionOptions;
@@ -72,6 +84,137 @@ GiftOptions GiftOptionFromTL(const MTPDuserFull &data) {
return result;
}
using TagUser1 = lngtag_user;
using TagUser2 = lngtag_second_user;
using TagUser3 = lngtag_name;
[[nodiscard]] rpl::producer<TextWithEntities> ComplexAboutLabel(
const std::vector<not_null<UserData*>> &users,
tr::phrase<TagUser1> phrase1,
tr::phrase<TagUser1, TagUser2> phrase2,
tr::phrase<TagUser1, TagUser2, TagUser3> phrase3,
tr::phrase<lngtag_count, TagUser1, TagUser2, TagUser3> phraseMore) {
Expects(!users.empty());
const auto count = users.size();
const auto nameValue = [&](not_null<UserData*> user) {
return user->session().changes().peerFlagsValue(
user,
Data::PeerUpdate::Flag::Name
) | rpl::map([=] { return TextWithEntities{ user->firstName }; });
};
if (count == 1) {
return phrase1(
lt_user,
nameValue(users.front()),
Ui::Text::RichLangValue);
} else if (count == 2) {
return phrase2(
lt_user,
nameValue(users.front()),
lt_second_user,
nameValue(users[1]),
Ui::Text::RichLangValue);
} else if (count == 3) {
return phrase3(
lt_user,
nameValue(users.front()),
lt_second_user,
nameValue(users[1]),
lt_name,
nameValue(users[2]),
Ui::Text::RichLangValue);
} else {
return phraseMore(
lt_count,
rpl::single(count - kUserpicsMax) | tr::to_count(),
lt_user,
nameValue(users.front()),
lt_second_user,
nameValue(users[1]),
lt_name,
nameValue(users[2]),
Ui::Text::RichLangValue);
}
}
[[nodiscard]] not_null<Ui::RpWidget*> CircleBadge(
not_null<Ui::RpWidget*> parent,
const QString &text) {
const auto widget = Ui::CreateChild<Ui::RpWidget>(parent.get());
const auto full = Rect(st::premiumGiftsUserpicBadgeSize);
const auto inner = full - Margins(st::premiumGiftsUserpicBadgeInner);
auto gradient = QLinearGradient(
QPointF(0, full.height()),
QPointF(full.width(), 0));
gradient.setStops(Ui::Premium::GiftGradientStops());
widget->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(widget);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::boxBg);
p.drawEllipse(full);
p.setPen(Qt::NoPen);
p.setBrush(gradient);
p.drawEllipse(inner);
p.setFont(st::premiumGiftsUserpicBadgeFont);
p.setPen(st::premiumButtonFg);
p.drawText(full, text, style::al_center);
}, widget->lifetime());
widget->resize(full.size());
return widget;
}
[[nodiscard]] not_null<Ui::RpWidget*> UserpicsContainer(
not_null<Ui::RpWidget*> parent,
std::vector<not_null<UserData*>> users) {
Expects(!users.empty());
if (users.size() == 1) {
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
parent.get(),
users.front(),
st::defaultUserpicButton);
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
return userpic;
}
const auto &singleSize = st::defaultUserpicButton.size;
const auto container = Ui::CreateChild<Ui::RpWidget>(parent.get());
const auto single = singleSize.width();
const auto shift = single - st::boostReplaceUserpicsShift;
const auto maxWidth = users.size() * (single - shift) + shift;
container->resize(maxWidth, singleSize.height());
container->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto diff = (single - st::premiumGiftsUserpicButton.size.width())
/ 2;
for (auto i = 0; i < users.size(); i++) {
const auto bg = Ui::CreateChild<Ui::RpWidget>(container);
bg->resize(singleSize);
bg->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(bg);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::boxBg);
p.drawEllipse(bg->rect());
}, bg->lifetime());
bg->moveToLeft(std::max(0, i * (single - shift)), 0);
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
bg,
users[i],
st::premiumGiftsUserpicButton);
userpic->moveToLeft(diff, diff);
}
return container;
}
void GiftBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
@@ -95,12 +238,11 @@ void GiftBox(
+ st::defaultUserpicButton.size.height()));
using ColoredMiniStars = Ui::Premium::ColoredMiniStars;
const auto stars = box->lifetime().make_state<ColoredMiniStars>(top, true);
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
const auto stars = box->lifetime().make_state<ColoredMiniStars>(
top,
user,
st::defaultUserpicButton);
true);
const auto userpic = UserpicsContainer(top, { user });
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
top->widthValue(
) | rpl::start_with_next([=](int width) {
@@ -211,7 +353,7 @@ void GiftBox(
auto raw = Settings::CreateSubscribeButton({
controller,
box,
[] { return QString("gift"); },
[] { return u"gift"_q; },
state->buttonText.events(),
Ui::Premium::GiftGradientStops(),
[=] {
@@ -222,10 +364,8 @@ void GiftBox(
},
});
auto button = object_ptr<Ui::GradientButton>::fromRaw(raw);
button->resizeToWidth(boxWidth
- stButton.buttonPadding.left()
- stButton.buttonPadding.right());
box->setShowFinishedCallback([raw = button.data()]{
button->resizeToWidth(boxWidth - rect::m::sum::h(stButton.buttonPadding));
box->setShowFinishedCallback([raw = button.data()] {
raw->startGlareAnimation();
});
box->addButton(std::move(button));
@@ -239,6 +379,302 @@ void GiftBox(
}, box->lifetime());
}
void GiftsBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
std::vector<not_null<UserData*>> users,
not_null<Api::PremiumGiftCodeOptions*> api) {
Expects(!users.empty());
const auto boxWidth = st::boxWideWidth;
box->setWidth(boxWidth);
box->setNoContentMargin(true);
const auto buttonsParent = box->verticalLayout().get();
const auto session = &users.front()->session();
struct State {
rpl::event_stream<QString> buttonText;
rpl::variable<bool> confirmButtonBusy = false;
rpl::variable<bool> isPaymentComplete = false;
};
const auto state = box->lifetime().make_state<State>();
const auto userpicPadding = st::premiumGiftUserpicPadding;
const auto top = box->addRow(object_ptr<Ui::FixedHeightWidget>(
buttonsParent,
userpicPadding.top()
+ userpicPadding.bottom()
+ st::defaultUserpicButton.size.height()));
using ColoredMiniStars = Ui::Premium::ColoredMiniStars;
const auto stars = box->lifetime().make_state<ColoredMiniStars>(
top,
true);
const auto maxWithUserpic = std::min(users.size(), kUserpicsMax);
const auto userpics = UserpicsContainer(
top,
{ users.begin(), users.begin() + maxWithUserpic });
top->widthValue(
) | rpl::start_with_next([=](int width) {
userpics->moveToLeft(
(width - userpics->width()) / 2,
userpicPadding.top());
const auto center = top->rect().center();
const auto size = QSize(
userpics->width() * Ui::Premium::MiniStars::kSizeFactor,
userpics->height());
const auto ministarsRect = QRect(
QPoint(center.x() - size.width(), center.y() - size.height()),
QPoint(center.x() + size.width(), center.y() + size.height()));
stars->setPosition(ministarsRect.topLeft());
stars->setSize(ministarsRect.size());
}, userpics->lifetime());
if (const auto rest = users.size() - maxWithUserpic; rest > 0) {
const auto badge = CircleBadge(
userpics,
QChar('+') + QString::number(rest));
badge->moveToRight(0, userpics->height() - badge->height());
}
top->paintRequest(
) | rpl::start_with_next([=](const QRect &r) {
auto p = QPainter(top);
p.fillRect(r, Qt::transparent);
stars->paint(p);
}, top->lifetime());
const auto close = Ui::CreateChild<Ui::IconButton>(
buttonsParent,
st::infoTopBarClose);
close->setClickedCallback([=] { box->closeBox(); });
buttonsParent->widthValue(
) | rpl::start_with_next([=](int width) {
close->moveToRight(0, 0, width);
}, close->lifetime());
// Header.
const auto &padding = st::premiumGiftAboutPadding;
const auto available = boxWidth - padding.left() - padding.right();
const auto &stTitle = st::premiumPreviewAboutTitle;
auto titleLabel = object_ptr<Ui::FlatLabel>(
box,
rpl::conditional(
state->isPaymentComplete.value(),
tr::lng_premium_gifts_about_paid_title(),
tr::lng_premium_gift_title()),
stTitle);
titleLabel->resizeToWidth(available);
box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box,
std::move(titleLabel)),
st::premiumGiftTitlePadding);
// About.
{
const auto emoji = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::premiumGiftsBoostIcon,
QMargins(0, st::premiumGiftsUserpicBadgeInner, 0, 0),
false));
auto text = rpl::conditional(
state->isPaymentComplete.value(),
ComplexAboutLabel(
users,
tr::lng_premium_gifts_about_paid1,
tr::lng_premium_gifts_about_paid2,
tr::lng_premium_gifts_about_paid3,
tr::lng_premium_gifts_about_paid_more
) | rpl::map([count = users.size()](TextWithEntities text) {
text.append('\n');
text.append('\n');
text.append(tr::lng_premium_gifts_about_paid_below(
tr::now,
lt_count,
float64(count),
Ui::Text::RichLangValue));
return text;
}),
ComplexAboutLabel(
users,
tr::lng_premium_gifts_about_user1,
tr::lng_premium_gifts_about_user2,
tr::lng_premium_gifts_about_user3,
tr::lng_premium_gifts_about_user_more
) | rpl::map([=, count = users.size()](TextWithEntities text) {
text.append('\n');
text.append('\n');
text.append(tr::lng_premium_gifts_about_reward(
tr::now,
lt_count,
count * BoostsForGift(session),
lt_emoji,
emoji,
Ui::Text::RichLangValue));
return text;
})
);
const auto label = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box,
object_ptr<Ui::FlatLabel>(box, st::premiumPreviewAbout)),
padding)->entity();
std::move(
text
) | rpl::start_with_next([=](const TextWithEntities &t) {
using namespace Core;
label->setMarkedText(t, MarkedTextContext{ .session = session });
}, label->lifetime());
label->setTextColorOverride(stTitle.textFg->c);
label->resizeToWidth(available);
}
// List.
const auto optionsContainer = buttonsParent->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
buttonsParent,
object_ptr<Ui::VerticalLayout>(buttonsParent)));
const auto options = api->options(users.size());
const auto group = std::make_shared<Ui::RadiobuttonGroup>();
const auto groupValueChangedCallback = [=](int value) {
Expects(value < options.size() && value >= 0);
auto text = tr::lng_premium_gift_button(
tr::now,
lt_cost,
options[value].costTotal);
state->buttonText.fire(std::move(text));
};
group->setChangedCallback(groupValueChangedCallback);
Ui::Premium::AddGiftOptions(
optionsContainer->entity(),
group,
options,
st::premiumGiftOption);
optionsContainer->toggleOn(
state->isPaymentComplete.value() | rpl::map(!rpl::mappers::_1),
anim::type::instant);
// Summary.
{
{
// Will be hidden after payment.
const auto content = optionsContainer->entity();
Ui::AddSkip(content);
Ui::AddDivider(content);
Ui::AddSkip(content);
Ui::AddSubsectionTitle(
content,
tr::lng_premium_gifts_summary_subtitle());
}
const auto content = box->addRow(
object_ptr<Ui::VerticalLayout>(box),
{});
auto buttonCallback = [=](PremiumPreview section) {
stars->setPaused(true);
const auto previewBoxShown = [=](
not_null<Ui::BoxContent*> previewBox) {
previewBox->boxClosing(
) | rpl::start_with_next(crl::guard(box, [=] {
stars->setPaused(false);
}), previewBox->lifetime());
};
ShowPremiumPreviewBox(
controller->uiShow(),
section,
previewBoxShown,
true);
};
Settings::AddSummaryPremium(
content,
controller,
u"gift"_q,
std::move(buttonCallback));
}
// Footer.
{
box->addRow(
object_ptr<Ui::DividerLabel>(
box,
object_ptr<Ui::FlatLabel>(
box,
session->api().premium().statusTextValue(), // TODO.
st::premiumGiftTerms),
st::defaultBoxDividerLabelPadding),
{});
}
// Button.
const auto &stButton = st::premiumGiftBox;
box->setStyle(stButton);
auto raw = Settings::CreateSubscribeButton({
controller,
box,
[] { return u"gift"_q; },
rpl::combine(
state->buttonText.events(),
state->confirmButtonBusy.value(),
state->isPaymentComplete.value()
) | rpl::map([](const QString &text, bool busy, bool paid) {
return busy
? QString()
: paid
? tr::lng_close(tr::now)
: text;
}),
Ui::Premium::GiftGradientStops(),
});
raw->setClickedCallback([=] {
if (state->confirmButtonBusy.current()) {
return;
}
if (state->isPaymentComplete.current()) {
return box->closeBox();
}
auto invoice = api->invoice(
users.size(),
api->monthsFromPreset(group->value()));
invoice.purpose = Payments::InvoicePremiumGiftCodeUsers{ users };
state->confirmButtonBusy = true;
const auto show = box->uiShow();
const auto weak = Ui::MakeWeak(box.get());
const auto done = [=](Payments::CheckoutResult result) {
if (const auto strong = weak.data()) {
strong->window()->setFocus();
state->confirmButtonBusy = false;
if (result == Payments::CheckoutResult::Paid) {
state->isPaymentComplete = true;
Ui::StartFireworks(box->parentWidget());
}
}
};
Payments::CheckoutProcess::Start(std::move(invoice), done);
});
{
using namespace Info::Statistics;
const auto loadingAnimation = InfiniteRadialAnimationWidget(
raw,
raw->height() / 2);
AddChildToWidgetCenter(raw, loadingAnimation);
loadingAnimation->showOn(state->confirmButtonBusy.value());
}
auto button = object_ptr<Ui::GradientButton>::fromRaw(raw);
button->resizeToWidth(boxWidth - rect::m::sum::h(stButton.buttonPadding));
box->setShowFinishedCallback([raw = button.data()] {
raw->startGlareAnimation();
});
box->addButton(std::move(button));
groupValueChangedCallback(0);
}
[[nodiscard]] Data::GiftCodeLink MakeGiftCodeLink(
not_null<Main::Session*> session,
const QString &slug) {
@@ -370,18 +806,20 @@ void AddTable(
container,
st::giveawayGiftCodeTable),
st::giveawayGiftCodeTableMargin);
AddTableRow(
table,
tr::lng_gift_link_label_from(),
controller,
current.from);
if (current.to) {
if (current.from) {
AddTableRow(
table,
tr::lng_gift_link_label_from(),
controller,
current.from);
}
if (current.from && current.to) {
AddTableRow(
table,
tr::lng_gift_link_label_to(),
controller,
current.to);
} else {
} else if (current.from) {
AddTableRow(
table,
tr::lng_gift_link_label_to(),
@@ -394,7 +832,7 @@ void AddTable(
lt_duration,
GiftDurationValue(current.months) | Ui::Text::ToWithEntities(),
Ui::Text::WithEntities));
if (!skipReason) {
if (!skipReason && current.from) {
const auto reason = AddTableRow(
table,
tr::lng_gift_link_label_reason(),
@@ -439,6 +877,112 @@ void GiftPremiumValidator::cancel() {
_requestId = 0;
}
void GiftPremiumValidator::showChoosePeerBox() {
if (_manyGiftsLifetime) {
return;
}
using namespace Api;
const auto api = _manyGiftsLifetime.make_state<PremiumGiftCodeOptions>(
_controller->session().user());
const auto show = _controller->uiShow();
api->request(
) | rpl::start_with_error_done([=](const QString &error) {
show->showToast(error);
}, [=] {
const auto maxAmount = *ranges::max_element(api->availablePresets());
class Controller final : public ContactsBoxController {
public:
Controller(
not_null<Main::Session*> session,
Fn<bool(int)> checkErrorCallback)
: ContactsBoxController(session)
, _checkErrorCallback(std::move(checkErrorCallback)) {
}
protected:
std::unique_ptr<PeerListRow> createRow(
not_null<UserData*> user) override {
return !user->isSelf()
? ContactsBoxController::createRow(user)
: nullptr;
}
void rowClicked(not_null<PeerListRow*> row) override {
const auto checked = !row->checked();
if (checked
&& _checkErrorCallback
&& _checkErrorCallback(
delegate()->peerListSelectedRowsCount())) {
return;
}
delegate()->peerListSetRowChecked(row, checked);
}
private:
const Fn<bool(int)> _checkErrorCallback;
};
auto initBox = [=](not_null<PeerListBox*> peersBox) {
const auto ignoreClose = peersBox->lifetime().make_state<bool>(0);
auto process = [=] {
const auto selected = peersBox->collectSelectedRows();
const auto users = ranges::views::all(
selected
) | ranges::views::transform([](not_null<PeerData*> p) {
return p->asUser();
}) | ranges::views::filter([](UserData *u) -> bool {
return u;
}) | ranges::to<std::vector<not_null<UserData*>>>();
if (!users.empty()) {
const auto giftBox = show->show(
Box(GiftsBox, _controller, users, api));
giftBox->boxClosing(
) | rpl::start_with_next([=] {
_manyGiftsLifetime.destroy();
}, giftBox->lifetime());
}
(*ignoreClose) = true;
peersBox->closeBox();
};
peersBox->setTitle(tr::lng_premium_gift_title());
peersBox->addButton(
tr::lng_settings_gift_premium_users_confirm(),
std::move(process));
peersBox->addButton(tr::lng_cancel(), [=] {
peersBox->closeBox();
});
peersBox->boxClosing(
) | rpl::start_with_next([=] {
if (!(*ignoreClose)) {
_manyGiftsLifetime.destroy();
}
}, peersBox->lifetime());
};
auto listController = std::make_unique<Controller>(
&_controller->session(),
[=](int count) {
if (count <= maxAmount) {
return false;
}
show->showToast(tr::lng_settings_gift_premium_users_error(
tr::now,
lt_count,
maxAmount));
return true;
});
show->showBox(
Box<PeerListBox>(
std::move(listController),
std::move(initBox)),
Ui::LayerOption::KeepOther);
}, _manyGiftsLifetime);
}
void GiftPremiumValidator::showBox(not_null<UserData*> user) {
if (_requestId) {
return;
@@ -723,10 +1267,22 @@ void GiftCodePendingBox(
void ResolveGiftCode(
not_null<Window::SessionNavigation*> controller,
const QString &slug) {
const QString &slug,
PeerId fromId,
PeerId toId) {
const auto done = [=](Api::GiftCode code) {
const auto session = &controller->session();
const auto selfId = session->userPeerId();
if (!code) {
controller->showToast(tr::lng_gift_link_expired(tr::now));
} else if (!code.from && fromId == selfId) {
code.from = fromId;
code.to = toId;
const auto self = (fromId == selfId);
const auto peer = session->data().peer(self ? toId : fromId);
const auto months = code.months;
const auto parent = controller->parentController();
Settings::ShowGiftPremium(parent, peer, months, self);
} else {
controller->uiShow()->showBox(Box(GiftCodeBox, controller, slug));
}
@@ -739,8 +1295,11 @@ void ResolveGiftCode(
void GiveawayInfoBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionNavigation*> controller,
Data::Giveaway giveaway,
std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results,
Api::GiveawayInfo info) {
Expects(start || results);
using State = Api::GiveawayState;
const auto finished = (info.state == State::Finished)
|| (info.state == State::Refunded);
@@ -749,10 +1308,31 @@ void GiveawayInfoBox(
? tr::lng_prizes_end_title
: tr::lng_prizes_how_title)());
const auto first = !giveaway.channels.empty()
? giveaway.channels.front()->name()
const auto first = results
? results->channel->name()
: !start->channels.empty()
? start->channels.front()->name()
: u"channel"_q;
auto text = (finished
auto text = TextWithEntities();
if (!info.giftCode.isEmpty()) {
text.append("\n\n");
text.append(Ui::Text::Bold(tr::lng_prizes_you_won(
tr::now,
lt_cup,
QString::fromUtf8("\xf0\x9f\x8f\x86"))));
text.append("\n\n");
} else if (info.state == State::Finished) {
text.append("\n\n");
text.append(Ui::Text::Bold(tr::lng_prizes_you_didnt(tr::now)));
text.append("\n\n");
}
const auto quantity = start
? start->quantity
: (results->winnersCount + results->unclaimedCount);
const auto months = start ? start->months : results->months;
text.append((finished
? tr::lng_prizes_end_text
: tr::lng_prizes_how_text)(
tr::now,
@@ -760,18 +1340,21 @@ void GiveawayInfoBox(
tr::lng_prizes_admins(
tr::now,
lt_count,
giveaway.quantity,
quantity,
lt_channel,
Ui::Text::Bold(first),
lt_duration,
TextWithEntities{ GiftDuration(giveaway.months) },
TextWithEntities{ GiftDuration(months) },
Ui::Text::RichLangValue),
Ui::Text::RichLangValue);
const auto many = (giveaway.channels.size() > 1);
Ui::Text::RichLangValue));
const auto many = start
? (start->channels.size() > 1)
: (results->additionalPeersCount > 0);
const auto count = info.winnersCount
? info.winnersCount
: giveaway.quantity;
auto winners = giveaway.all
: quantity;
const auto all = start ? start->all : results->all;
auto winners = all
? (many
? tr::lng_prizes_winners_all_of_many
: tr::lng_prizes_winners_all_of_one)(
@@ -793,13 +1376,30 @@ void GiveawayInfoBox(
Ui::Text::Bold(
langDateTime(base::unixtime::parse(info.startDate))),
Ui::Text::RichLangValue);
const auto additionalPrize = results
? results->additionalPrize
: start->additionalPrize;
if (!additionalPrize.isEmpty()) {
text.append("\n\n").append(tr::lng_prizes_additional_added(
tr::now,
lt_count,
count,
lt_channel,
Ui::Text::Bold(first),
lt_prize,
TextWithEntities{ additionalPrize },
Ui::Text::RichLangValue));
}
const auto untilDate = start
? start->untilDate
: results->untilDate;
text.append("\n\n").append((finished
? tr::lng_prizes_end_when_finish
: tr::lng_prizes_how_when_finish)(
tr::now,
lt_date,
Ui::Text::Bold(langDayOfMonthFull(
base::unixtime::parse(giveaway.untilDate).date())),
base::unixtime::parse(untilDate).date())),
lt_winners,
winners,
Ui::Text::RichLangValue));
@@ -810,17 +1410,9 @@ void GiveawayInfoBox(
info.activatedCount,
Ui::Text::RichLangValue));
}
if (!info.giftCode.isEmpty()) {
text.append("\n\n");
text.append(tr::lng_prizes_you_won(
tr::now,
lt_cup,
QString::fromUtf8("\xf0\x9f\x8f\x86")));
} else if (info.state == State::Finished) {
text.append("\n\n");
text.append(tr::lng_prizes_you_didnt(tr::now));
} else if (info.state == State::Preparing) {
if (!info.giftCode.isEmpty()
|| info.state == State::Finished
|| info.state == State::Preparing) {
} else if (info.state != State::Refunded) {
if (info.adminChannelId) {
const auto channel = controller->session().data().channel(
@@ -858,7 +1450,7 @@ void GiveawayInfoBox(
Ui::Text::Bold(first),
lt_date,
Ui::Text::Bold(langDayOfMonthFull(
base::unixtime::parse(giveaway.untilDate).date())),
base::unixtime::parse(untilDate).date())),
Ui::Text::RichLangValue));
}
}
@@ -902,14 +1494,15 @@ void ResolveGiveawayInfo(
not_null<Window::SessionNavigation*> controller,
not_null<PeerData*> peer,
MsgId messageId,
Data::Giveaway giveaway) {
std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results) {
const auto show = [=](Api::GiveawayInfo info) {
if (!info) {
controller->showToast(
tr::lng_confirm_phone_link_invalid(tr::now));
} else {
controller->uiShow()->showBox(
Box(GiveawayInfoBox, controller, giveaway, info));
Box(GiveawayInfoBox, controller, start, results, info));
}
};
controller->session().api().premium().resolveGiveawayInfo(
+10 -3
View File
@@ -16,7 +16,8 @@ struct GiftCode;
} // namespace Api
namespace Data {
struct Giveaway;
struct GiveawayStart;
struct GiveawayResults;
} // namespace Data
namespace Ui {
@@ -33,6 +34,7 @@ public:
GiftPremiumValidator(not_null<Window::SessionController*> controller);
void showBox(not_null<UserData*> user);
void showChoosePeerBox();
void cancel();
private:
@@ -41,6 +43,8 @@ private:
mtpRequestId _requestId = 0;
rpl::lifetime _manyGiftsLifetime;
};
[[nodiscard]] rpl::producer<QString> GiftDurationValue(int months);
@@ -56,10 +60,13 @@ void GiftCodePendingBox(
const Api::GiftCode &data);
void ResolveGiftCode(
not_null<Window::SessionNavigation*> controller,
const QString &slug);
const QString &slug,
PeerId fromId = 0,
PeerId toId = 0);
void ResolveGiveawayInfo(
not_null<Window::SessionNavigation*> controller,
not_null<PeerData*> peer,
MsgId messageId,
Data::Giveaway giveaway);
std::optional<Data::GiveawayStart> start,
std::optional<Data::GiveawayResults> results);
+12 -12
View File
@@ -24,7 +24,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h"
#include "ui/text/text_options.h"
#include "ui/painter.h"
#include "ui/vertical_list.h"
#include "storage/localstorage.h"
#include "boxes/abstract_box.h"
#include "boxes/premium_preview_box.h"
#include "boxes/translate_box.h"
#include "ui/boxes/confirm_box.h"
@@ -1177,12 +1179,12 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
if (!_controller) {
return;
}
const auto translateEnabled = Settings::AddButton(
container,
tr::lng_translate_settings_show(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(Core::App().settings().translateButtonEnabled()));
const auto translateEnabled = container->add(
object_ptr<Ui::SettingsButton>(
container,
tr::lng_translate_settings_show(),
st::settingsButtonNoIcon))->toggleOn(
rpl::single(Core::App().settings().translateButtonEnabled()));
translateEnabled->toggledValue(
) | rpl::filter([](bool checked) {
@@ -1194,11 +1196,11 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
using namespace rpl::mappers;
auto premium = Data::AmPremiumValue(&_controller->session());
const auto translateChat = Settings::AddButton(
const auto translateChat = container->add(object_ptr<Ui::SettingsButton>(
container,
tr::lng_translate_settings_chat(),
st::settingsButtonNoIconLocked
)->toggleOn(rpl::merge(
))->toggleOn(rpl::merge(
rpl::combine(
Core::App().settings().translateChatEnabledValue(),
rpl::duplicate(premium),
@@ -1250,10 +1252,8 @@ void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
translateSkip->setClickedCallback([=] {
uiShow()->showBox(Ui::EditSkipTranslationLanguages());
});
Settings::AddSkip(container);
Settings::AddDividerText(
container,
tr::lng_translate_settings_about());
Ui::AddSkip(container);
Ui::AddDividerText(container, tr::lng_translate_settings_about());
}
void LanguageBox::keyPressEvent(QKeyEvent *e) {

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